drmmode_display.c revision b338b52f
1/* 2 * Copyright © 2007 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Dave Airlie <airlied@redhat.com> 25 * 26 */ 27 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#include <errno.h> 33#include <sys/ioctl.h> 34#include <time.h> 35#include "cursorstr.h" 36#include "damagestr.h" 37#include "inputstr.h" 38#include "list.h" 39#include "micmap.h" 40#include "mipointrst.h" 41#include "xf86cmap.h" 42#include "xf86Priv.h" 43#include "radeon.h" 44#include "radeon_bo_helper.h" 45#include "radeon_glamor.h" 46#include "radeon_reg.h" 47 48#include <dri.h> 49 50#include "drmmode_display.h" 51 52/* DPMS */ 53#ifdef HAVE_XEXTPROTO_71 54#include <X11/extensions/dpmsconst.h> 55#else 56#define DPMS_SERVER 57#include <X11/extensions/dpms.h> 58#endif 59 60#define DEFAULT_NOMINAL_FRAME_RATE 60 61 62#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 22 63#define HAVE_NOTIFY_FD 1 64#endif 65 66static Bool 67drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height); 68 69static Bool 70RADEONZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name) 71{ 72 int i = 0; 73 char s1[20]; 74 75 do { 76 switch(*s) { 77 case ',': 78 s1[i] = '\0'; 79 i = 0; 80 if (strcmp(s1, output_name) == 0) 81 return TRUE; 82 break; 83 case ' ': 84 case '\t': 85 case '\n': 86 case '\r': 87 break; 88 default: 89 s1[i] = *s; 90 i++; 91 break; 92 } 93 } while(*s++); 94 95 s1[i] = '\0'; 96 if (strcmp(s1, output_name) == 0) 97 return TRUE; 98 99 return FALSE; 100} 101 102 103static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn, 104 int width, int height, 105 int depth, int bpp, 106 int pitch, 107 struct radeon_buffer *bo) 108{ 109 RADEONInfoPtr info = RADEONPTR(pScrn); 110 ScreenPtr pScreen = pScrn->pScreen; 111 PixmapPtr pixmap; 112 113 pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 114 RADEON_CREATE_PIXMAP_SCANOUT); 115 if (!pixmap) 116 return NULL; 117 118 if (!(*pScreen->ModifyPixmapHeader)(pixmap, width, height, 119 depth, bpp, pitch, NULL)) { 120 goto fail; 121 } 122 123 if (!info->use_glamor) 124 exaMoveInPixmap(pixmap); 125 126 if (!radeon_set_pixmap_bo(pixmap, bo)) 127 goto fail; 128 129 if (info->surf_man && !info->use_glamor) { 130 struct radeon_surface *surface = radeon_get_pixmap_surface(pixmap); 131 132 if (!radeon_surface_initialize(info, surface, width, height, bpp / 8, 133 radeon_get_pixmap_tiling_flags(pixmap), 0)) 134 goto fail; 135 } 136 137 if (!info->use_glamor || 138 radeon_glamor_create_textured_pixmap(pixmap, bo)) 139 return pixmap; 140 141fail: 142 pScreen->DestroyPixmap(pixmap); 143 return NULL; 144} 145 146static void drmmode_destroy_bo_pixmap(PixmapPtr pixmap) 147{ 148 ScreenPtr pScreen = pixmap->drawable.pScreen; 149 150 (*pScreen->DestroyPixmap)(pixmap); 151} 152 153static void 154drmmode_ConvertFromKMode(ScrnInfoPtr scrn, 155 drmModeModeInfo *kmode, 156 DisplayModePtr mode) 157{ 158 memset(mode, 0, sizeof(DisplayModeRec)); 159 mode->status = MODE_OK; 160 161 mode->Clock = kmode->clock; 162 163 mode->HDisplay = kmode->hdisplay; 164 mode->HSyncStart = kmode->hsync_start; 165 mode->HSyncEnd = kmode->hsync_end; 166 mode->HTotal = kmode->htotal; 167 mode->HSkew = kmode->hskew; 168 169 mode->VDisplay = kmode->vdisplay; 170 mode->VSyncStart = kmode->vsync_start; 171 mode->VSyncEnd = kmode->vsync_end; 172 mode->VTotal = kmode->vtotal; 173 mode->VScan = kmode->vscan; 174 175 mode->Flags = kmode->flags; //& FLAG_BITS; 176 mode->name = strdup(kmode->name); 177 178 if (kmode->type & DRM_MODE_TYPE_DRIVER) 179 mode->type = M_T_DRIVER; 180 if (kmode->type & DRM_MODE_TYPE_PREFERRED) 181 mode->type |= M_T_PREFERRED; 182 xf86SetModeCrtc (mode, scrn->adjustFlags); 183} 184 185static void 186drmmode_ConvertToKMode(ScrnInfoPtr scrn, 187 drmModeModeInfo *kmode, 188 DisplayModePtr mode) 189{ 190 memset(kmode, 0, sizeof(*kmode)); 191 192 kmode->clock = mode->Clock; 193 kmode->hdisplay = mode->HDisplay; 194 kmode->hsync_start = mode->HSyncStart; 195 kmode->hsync_end = mode->HSyncEnd; 196 kmode->htotal = mode->HTotal; 197 kmode->hskew = mode->HSkew; 198 199 kmode->vdisplay = mode->VDisplay; 200 kmode->vsync_start = mode->VSyncStart; 201 kmode->vsync_end = mode->VSyncEnd; 202 kmode->vtotal = mode->VTotal; 203 kmode->vscan = mode->VScan; 204 205 kmode->flags = mode->Flags; //& FLAG_BITS; 206 if (mode->name) 207 strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN); 208 kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; 209 210} 211 212/* 213 * Utility helper for drmWaitVBlank 214 */ 215Bool 216drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type, 217 uint32_t target_seq, unsigned long signal, uint64_t *ust, 218 uint32_t *result_seq) 219{ 220 int crtc_id = drmmode_get_crtc_id(crtc); 221 ScrnInfoPtr scrn = crtc->scrn; 222 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 223 drmVBlank vbl; 224 225 if (crtc_id == 1) 226 type |= DRM_VBLANK_SECONDARY; 227 else if (crtc_id > 1) 228 type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) & 229 DRM_VBLANK_HIGH_CRTC_MASK; 230 231 vbl.request.type = type; 232 vbl.request.sequence = target_seq; 233 vbl.request.signal = signal; 234 235 if (drmWaitVBlank(pRADEONEnt->fd, &vbl) != 0) 236 return FALSE; 237 238 if (ust) 239 *ust = (uint64_t)vbl.reply.tval_sec * 1000000 + 240 vbl.reply.tval_usec; 241 if (result_seq) 242 *result_seq = vbl.reply.sequence; 243 244 return TRUE; 245} 246 247/* 248 * Retrieves present time in microseconds that is compatible 249 * with units used by vblank timestamps. Depending on the kernel 250 * version and DRM kernel module configuration, the vblank 251 * timestamp can either be in real time or monotonic time 252 */ 253int drmmode_get_current_ust(int drm_fd, CARD64 *ust) 254{ 255 uint64_t cap_value; 256 int ret; 257 struct timespec now; 258 259 ret = drmGetCap(drm_fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap_value); 260 if (ret || !cap_value) 261 /* old kernel or drm_timestamp_monotonic turned off */ 262 ret = clock_gettime(CLOCK_REALTIME, &now); 263 else 264 ret = clock_gettime(CLOCK_MONOTONIC, &now); 265 if (ret) 266 return ret; 267 *ust = ((CARD64)now.tv_sec * 1000000) + ((CARD64)now.tv_nsec / 1000); 268 return 0; 269} 270 271/* 272 * Get current frame count and frame count timestamp of the crtc. 273 */ 274int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc) 275{ 276 ScrnInfoPtr scrn = crtc->scrn; 277 uint32_t seq; 278 279 if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, ust, &seq)) { 280 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 281 "get vblank counter failed: %s\n", strerror(errno)); 282 return -1; 283 } 284 285 *msc = seq; 286 287 return Success; 288} 289 290static void 291drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode) 292{ 293 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 294 ScrnInfoPtr scrn = crtc->scrn; 295 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 296 CARD64 ust; 297 int ret; 298 299 if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) { 300 uint32_t seq; 301 302 radeon_drm_wait_pending_flip(crtc); 303 304 /* 305 * On->Off transition: record the last vblank time, 306 * sequence number and frame period. 307 */ 308 if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, &ust, 309 &seq)) 310 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 311 "%s cannot get last vblank counter\n", 312 __func__); 313 else { 314 CARD64 nominal_frame_rate, pix_in_frame; 315 316 drmmode_crtc->dpms_last_ust = ust; 317 drmmode_crtc->dpms_last_seq = seq; 318 nominal_frame_rate = crtc->mode.Clock; 319 nominal_frame_rate *= 1000; 320 pix_in_frame = crtc->mode.HTotal * crtc->mode.VTotal; 321 if (nominal_frame_rate == 0 || pix_in_frame == 0) 322 nominal_frame_rate = DEFAULT_NOMINAL_FRAME_RATE; 323 else 324 nominal_frame_rate /= pix_in_frame; 325 drmmode_crtc->dpms_last_fps = nominal_frame_rate; 326 } 327 328 drmmode_crtc->dpms_mode = mode; 329 radeon_drm_queue_handle_deferred(crtc); 330 } else if (drmmode_crtc->dpms_mode != DPMSModeOn && mode == DPMSModeOn) { 331 /* 332 * Off->On transition: calculate and accumulate the 333 * number of interpolated vblanks while we were in Off state 334 */ 335 ret = drmmode_get_current_ust(pRADEONEnt->fd, &ust); 336 if (ret) 337 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 338 "%s cannot get current time\n", __func__); 339 else if (drmmode_crtc->dpms_last_ust) { 340 CARD64 time_elapsed, delta_seq; 341 time_elapsed = ust - drmmode_crtc->dpms_last_ust; 342 delta_seq = time_elapsed * drmmode_crtc->dpms_last_fps; 343 delta_seq /= 1000000; 344 drmmode_crtc->interpolated_vblanks += delta_seq; 345 346 } 347 348 drmmode_crtc->dpms_mode = DPMSModeOn; 349 } 350} 351 352static void 353drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode) 354{ 355 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 356 RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); 357 358 /* Disable unused CRTCs */ 359 if (!crtc->enabled || mode != DPMSModeOn) { 360 drmmode_do_crtc_dpms(crtc, DPMSModeOff); 361 drmModeSetCrtc(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 362 0, 0, 0, NULL, 0, NULL); 363 drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL); 364 } else if (drmmode_crtc->dpms_mode != DPMSModeOn) 365 crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, 366 crtc->x, crtc->y); 367} 368 369static PixmapPtr 370create_pixmap_for_fbcon(drmmode_ptr drmmode, 371 ScrnInfoPtr pScrn, int fbcon_id) 372{ 373 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 374 RADEONInfoPtr info = RADEONPTR(pScrn); 375 PixmapPtr pixmap = info->fbcon_pixmap; 376 struct radeon_buffer *bo = NULL; 377 drmModeFBPtr fbcon; 378 struct drm_gem_flink flink; 379 380 if (pixmap) 381 return pixmap; 382 383 fbcon = drmModeGetFB(pRADEONEnt->fd, fbcon_id); 384 if (!fbcon) 385 return NULL; 386 387 if (fbcon->depth != pScrn->depth || 388 fbcon->width != pScrn->virtualX || 389 fbcon->height != pScrn->virtualY) 390 goto out_free_fb; 391 392 flink.handle = fbcon->handle; 393 if (ioctl(pRADEONEnt->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) { 394 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 395 "Couldn't flink fbcon handle\n"); 396 goto out_free_fb; 397 } 398 399 bo = calloc(1, sizeof(struct radeon_buffer)); 400 if (!bo) { 401 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 402 "Couldn't allocate BO for fbcon handle\n"); 403 goto out_free_fb; 404 } 405 bo->ref_count = 1; 406 407 bo->bo.radeon = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0); 408 if (!bo->bo.radeon) { 409 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 410 "Couldn't open BO for fbcon handle\n"); 411 goto out_free_fb; 412 } 413 414 pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height, 415 fbcon->depth, fbcon->bpp, fbcon->pitch, 416 bo); 417 info->fbcon_pixmap = pixmap; 418out_free_fb: 419 radeon_buffer_unref(&bo); 420 drmModeFreeFB(fbcon); 421 return pixmap; 422} 423 424static void 425destroy_pixmap_for_fbcon(ScrnInfoPtr pScrn) 426{ 427 RADEONInfoPtr info = RADEONPTR(pScrn); 428 429 /* XXX: The current GPUVM support in the kernel doesn't allow removing 430 * the virtual address range for this BO, so we need to keep around 431 * the pixmap to avoid breaking glamor with GPUVM 432 * 433 * Similarly, need to keep around the pixmap with current glamor, to 434 * avoid issues due to a GEM handle lifetime conflict between us and 435 * Mesa 436 */ 437 if (info->use_glamor && 438 (info->ChipFamily >= CHIP_FAMILY_CAYMAN || 439 xorgGetVersion() >= XORG_VERSION_NUMERIC(1,19,99,1,0))) 440 return; 441 442 if (info->fbcon_pixmap) 443 pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap); 444 info->fbcon_pixmap = NULL; 445} 446 447void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) 448{ 449 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 450 RADEONInfoPtr info = RADEONPTR(pScrn); 451 ScreenPtr pScreen = pScrn->pScreen; 452 PixmapPtr src, dst = pScreen->GetScreenPixmap(pScreen); 453 struct drmmode_fb *fb = radeon_pixmap_get_fb(dst); 454 int fbcon_id = 0; 455 Bool force; 456 GCPtr gc; 457 int i; 458 459 for (i = 0; i < xf86_config->num_crtc; i++) { 460 drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[i]->driver_private; 461 462 if (drmmode_crtc->mode_crtc->buffer_id) 463 fbcon_id = drmmode_crtc->mode_crtc->buffer_id; 464 } 465 466 if (!fbcon_id) 467 return; 468 469 if (fbcon_id == fb->handle) { 470 /* in some rare case there might be no fbcon and we might already 471 * be the one with the current fb to avoid a false deadlck in 472 * kernel ttm code just do nothing as anyway there is nothing 473 * to do 474 */ 475 return; 476 } 477 478 src = create_pixmap_for_fbcon(drmmode, pScrn, fbcon_id); 479 if (!src) 480 return; 481 482 gc = GetScratchGC(pScrn->depth, pScreen); 483 ValidateGC(&dst->drawable, gc); 484 485 force = info->accel_state->force; 486 info->accel_state->force = TRUE; 487 (*gc->ops->CopyArea)(&src->drawable, &dst->drawable, gc, 0, 0, 488 pScrn->virtualX, pScrn->virtualY, 0, 0); 489 info->accel_state->force = force; 490 491 FreeScratchGC(gc); 492 493 pScreen->canDoBGNoneRoot = TRUE; 494 destroy_pixmap_for_fbcon(pScrn); 495 return; 496} 497 498void 499drmmode_crtc_scanout_destroy(drmmode_ptr drmmode, 500 struct drmmode_scanout *scanout) 501{ 502 if (scanout->pixmap) { 503 drmmode_destroy_bo_pixmap(scanout->pixmap); 504 scanout->pixmap = NULL; 505 } 506 507 radeon_buffer_unref(&scanout->bo); 508} 509 510void 511drmmode_crtc_scanout_free(xf86CrtcPtr crtc) 512{ 513 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 514 515 if (drmmode_crtc->scanout_update_pending) { 516 radeon_drm_wait_pending_flip(crtc); 517 radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending); 518 drmmode_crtc->scanout_update_pending = 0; 519 radeon_drm_queue_handle_deferred(crtc); 520 } 521 522 drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, 523 &drmmode_crtc->scanout[0]); 524 drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, 525 &drmmode_crtc->scanout[1]); 526 527 if (drmmode_crtc->scanout_damage) 528 DamageDestroy(drmmode_crtc->scanout_damage); 529} 530 531PixmapPtr 532drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout, 533 int width, int height) 534{ 535 ScrnInfoPtr pScrn = crtc->scrn; 536 RADEONInfoPtr info = RADEONPTR(pScrn); 537 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 538 drmmode_ptr drmmode = drmmode_crtc->drmmode; 539 struct radeon_surface surface; 540 uint32_t tiling = RADEON_CREATE_PIXMAP_TILING_MACRO; 541 int pitch; 542 543 if (scanout->pixmap) { 544 if (scanout->width == width && scanout->height == height) 545 return scanout->pixmap; 546 547 drmmode_crtc_scanout_destroy(drmmode, scanout); 548 } 549 550 if (info->ChipFamily >= CHIP_FAMILY_R600) 551 tiling |= RADEON_CREATE_PIXMAP_TILING_MICRO; 552 scanout->bo = radeon_alloc_pixmap_bo(pScrn, width, height, pScrn->depth, 553 tiling, pScrn->bitsPerPixel, 554 &pitch, &surface, &tiling); 555 if (!scanout->bo) { 556 ErrorF("failed to create CRTC scanout BO\n"); 557 return NULL; 558 } 559 560 scanout->pixmap = drmmode_create_bo_pixmap(pScrn, 561 width, height, 562 pScrn->depth, 563 pScrn->bitsPerPixel, 564 pitch, scanout->bo); 565 if (!scanout->pixmap) { 566 ErrorF("failed to create CRTC scanout pixmap\n"); 567 goto error; 568 } 569 570 if (radeon_pixmap_get_fb(scanout->pixmap)) { 571 scanout->width = width; 572 scanout->height = height; 573 } else { 574 ErrorF("failed to create CRTC scanout FB\n"); 575error: 576 drmmode_crtc_scanout_destroy(drmmode, scanout); 577 } 578 579 return scanout->pixmap; 580} 581 582static void 583radeon_screen_damage_report(DamagePtr damage, RegionPtr region, void *closure) 584{ 585 drmmode_crtc_private_ptr drmmode_crtc = closure; 586 587 if (drmmode_crtc->ignore_damage) { 588 RegionEmpty(&damage->damage); 589 drmmode_crtc->ignore_damage = FALSE; 590 return; 591 } 592 593 /* Only keep track of the extents */ 594 RegionUninit(&damage->damage); 595 damage->damage.data = NULL; 596} 597 598static void 599drmmode_screen_damage_destroy(DamagePtr damage, void *closure) 600{ 601 drmmode_crtc_private_ptr drmmode_crtc = closure; 602 603 drmmode_crtc->scanout_damage = NULL; 604 RegionUninit(&drmmode_crtc->scanout_last_region); 605} 606 607static Bool 608drmmode_can_use_hw_cursor(xf86CrtcPtr crtc) 609{ 610 RADEONInfoPtr info = RADEONPTR(crtc->scrn); 611 612 /* Check for Option "SWcursor" */ 613 if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) 614 return FALSE; 615 616 /* Fall back to SW cursor if the CRTC is transformed */ 617 if (crtc->transformPresent) 618 return FALSE; 619 620#if XF86_CRTC_VERSION < 7 621 /* Xorg doesn't correctly handle cursor position transform in the 622 * rotation case 623 */ 624 if (crtc->driverIsPerformingTransform && 625 (crtc->rotation & 0xf) != RR_Rotate_0) 626 return FALSE; 627#endif 628 629 /* HW cursor not supported with RandR 1.4 multihead up to 1.18.99.901 */ 630 if (xorgGetVersion() <= XORG_VERSION_NUMERIC(1,18,99,901,0) && 631 !xorg_list_is_empty(&crtc->scrn->pScreen->pixmap_dirty_list)) 632 return FALSE; 633 634 return TRUE; 635} 636 637static void 638drmmode_crtc_update_tear_free(xf86CrtcPtr crtc) 639{ 640 RADEONInfoPtr info = RADEONPTR(crtc->scrn); 641 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 642 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 643 int i; 644 645 drmmode_crtc->tear_free = FALSE; 646 647 for (i = 0; i < xf86_config->num_output; i++) { 648 xf86OutputPtr output = xf86_config->output[i]; 649 drmmode_output_private_ptr drmmode_output = output->driver_private; 650 651 if (output->crtc != crtc) 652 continue; 653 654 if (drmmode_output->tear_free == 1 || 655 (drmmode_output->tear_free == 2 && 656 (crtc->scrn->pScreen->isGPU || 657 info->shadow_primary || 658 crtc->transformPresent || crtc->rotation != RR_Rotate_0))) { 659 drmmode_crtc->tear_free = TRUE; 660 return; 661 } 662 } 663} 664 665#if XF86_CRTC_VERSION < 7 666#define XF86DriverTransformOutput TRUE 667#define XF86DriverTransformNone FALSE 668#endif 669 670static Bool 671drmmode_handle_transform(xf86CrtcPtr crtc) 672{ 673 Bool ret; 674 675#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0) 676 crtc->driverIsPerformingTransform = XF86DriverTransformOutput; 677#else 678 crtc->driverIsPerformingTransform = !crtc->transformPresent && 679 (crtc->rotation & 0xf) == RR_Rotate_0; 680#endif 681 682 ret = xf86CrtcRotate(crtc); 683 684 crtc->driverIsPerformingTransform &= ret && crtc->transform_in_use; 685 686 return ret; 687} 688 689 690static void 691drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode, 692 unsigned scanout_id, struct drmmode_fb **fb, 693 int *x, int *y) 694{ 695 ScrnInfoPtr scrn = crtc->scrn; 696 ScreenPtr screen = scrn->pScreen; 697 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 698 699 if (drmmode_crtc->tear_free && 700 !drmmode_crtc->scanout[1].pixmap) { 701 RegionPtr region; 702 BoxPtr box; 703 704 drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1], 705 mode->HDisplay, 706 mode->VDisplay); 707 region = &drmmode_crtc->scanout_last_region; 708 RegionUninit(region); 709 region->data = NULL; 710 box = RegionExtents(region); 711 box->x1 = crtc->x; 712 box->y1 = crtc->y; 713 box->x2 = crtc->x + mode->HDisplay; 714 box->y2 = crtc->y + mode->VDisplay; 715 } 716 717 if (scanout_id != drmmode_crtc->scanout_id) { 718 PixmapDirtyUpdatePtr dirty = NULL; 719 720 xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, 721 ent) { 722 if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { 723 dirty->slave_dst = 724 drmmode_crtc->scanout[scanout_id].pixmap; 725 break; 726 } 727 } 728 729 if (!drmmode_crtc->tear_free) { 730 GCPtr gc = GetScratchGC(scrn->depth, screen); 731 732 ValidateGC(&drmmode_crtc->scanout[0].pixmap->drawable, gc); 733 gc->ops->CopyArea(&drmmode_crtc->scanout[1].pixmap->drawable, 734 &drmmode_crtc->scanout[0].pixmap->drawable, 735 gc, 0, 0, mode->HDisplay, mode->VDisplay, 736 0, 0); 737 FreeScratchGC(gc); 738 radeon_finish(scrn, drmmode_crtc->scanout[0].bo); 739 } 740 } 741 742 *fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); 743 *x = *y = 0; 744 drmmode_crtc->scanout_id = scanout_id; 745} 746 747 748static void 749drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode, 750 unsigned scanout_id, struct drmmode_fb **fb, int *x, 751 int *y) 752{ 753 ScrnInfoPtr scrn = crtc->scrn; 754 ScreenPtr screen = scrn->pScreen; 755 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 756 757 drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[scanout_id], 758 mode->HDisplay, mode->VDisplay); 759 if (drmmode_crtc->tear_free) { 760 drmmode_crtc_scanout_create(crtc, 761 &drmmode_crtc->scanout[scanout_id ^ 1], 762 mode->HDisplay, mode->VDisplay); 763 } 764 765 if (drmmode_crtc->scanout[scanout_id].pixmap && 766 (!drmmode_crtc->tear_free || 767 drmmode_crtc->scanout[scanout_id ^ 1].pixmap)) { 768 BoxRec extents = { .x1 = 0, .y1 = 0, 769 .x2 = scrn->virtualX, .y2 = scrn->virtualY }; 770 771 if (!drmmode_crtc->scanout_damage) { 772 drmmode_crtc->scanout_damage = 773 DamageCreate(radeon_screen_damage_report, 774 drmmode_screen_damage_destroy, 775 DamageReportRawRegion, 776 TRUE, screen, drmmode_crtc); 777 DamageRegister(&screen->root->drawable, 778 drmmode_crtc->scanout_damage); 779 } 780 781 *fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); 782 *x = *y = 0; 783 784 if (radeon_scanout_do_update(crtc, scanout_id, 785 screen->GetWindowPixmap(screen->root), 786 extents)) { 787 RegionEmpty(DamageRegion(drmmode_crtc->scanout_damage)); 788 radeon_finish(scrn, drmmode_crtc->scanout[scanout_id].bo); 789 790 if (!drmmode_crtc->flip_pending) { 791 radeon_drm_abort_entry(drmmode_crtc-> 792 scanout_update_pending); 793 } 794 } 795 } 796} 797 798static void 799drmmode_crtc_gamma_do_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green, 800 uint16_t *blue, int size) 801{ 802 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 803 RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); 804 805 drmModeCrtcSetGamma(pRADEONEnt->fd, 806 drmmode_crtc->mode_crtc->crtc_id, size, red, green, 807 blue); 808} 809 810Bool 811drmmode_set_mode(xf86CrtcPtr crtc, struct drmmode_fb *fb, DisplayModePtr mode, 812 int x, int y) 813{ 814 ScrnInfoPtr scrn = crtc->scrn; 815 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 816 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 817 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 818 uint32_t *output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); 819 int output_count = 0; 820 drmModeModeInfo kmode; 821 Bool ret; 822 int i; 823 824 if (!output_ids) 825 return FALSE; 826 827 for (i = 0; i < xf86_config->num_output; i++) { 828 xf86OutputPtr output = xf86_config->output[i]; 829 drmmode_output_private_ptr drmmode_output = output->driver_private; 830 831 if (output->crtc != crtc) 832 continue; 833 834 output_ids[output_count] = drmmode_output->mode_output->connector_id; 835 output_count++; 836 } 837 838 drmmode_ConvertToKMode(scrn, &kmode, mode); 839 840 ret = drmModeSetCrtc(pRADEONEnt->fd, 841 drmmode_crtc->mode_crtc->crtc_id, 842 fb->handle, x, y, output_ids, 843 output_count, &kmode) == 0; 844 845 if (ret) { 846 drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, fb); 847 } else { 848 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 849 "failed to set mode: %s\n", strerror(errno)); 850 } 851 852 free(output_ids); 853 return ret; 854} 855 856static Bool 857drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, 858 Rotation rotation, int x, int y) 859{ 860 ScrnInfoPtr pScrn = crtc->scrn; 861 ScreenPtr pScreen = pScrn->pScreen; 862 RADEONInfoPtr info = RADEONPTR(pScrn); 863 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 864 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 865 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 866 Bool handle_deferred = FALSE; 867 unsigned scanout_id = 0; 868 drmmode_ptr drmmode = drmmode_crtc->drmmode; 869 int saved_x, saved_y; 870 Rotation saved_rotation; 871 DisplayModeRec saved_mode; 872 Bool ret = FALSE; 873 uint32_t handle; 874 int i; 875 struct drmmode_fb *fb = NULL; 876 877 /* The root window contents may be undefined before the WindowExposures 878 * hook is called for it, so bail if we get here before that 879 */ 880 if (pScreen->WindowExposures == RADEONWindowExposures_oneshot) 881 return FALSE; 882 883 saved_mode = crtc->mode; 884 saved_x = crtc->x; 885 saved_y = crtc->y; 886 saved_rotation = crtc->rotation; 887 888 if (mode) { 889 crtc->mode = *mode; 890 crtc->x = x; 891 crtc->y = y; 892 crtc->rotation = rotation; 893 894 if (!drmmode_handle_transform(crtc)) 895 goto done; 896 897 drmmode_crtc_update_tear_free(crtc); 898 if (drmmode_crtc->tear_free) 899 scanout_id = drmmode_crtc->scanout_id; 900 else 901 drmmode_crtc->scanout_id = 0; 902 903 if (drmmode_crtc->prime_scanout_pixmap) { 904 drmmode_crtc_prime_scanout_update(crtc, mode, scanout_id, 905 &fb, &x, &y); 906 } else if (drmmode_crtc->rotate.pixmap) { 907 fb = radeon_pixmap_get_fb(drmmode_crtc->rotate.pixmap); 908 x = y = 0; 909 910 } else if (!pScreen->isGPU && 911 (drmmode_crtc->tear_free || 912 crtc->driverIsPerformingTransform || 913 info->shadow_primary)) { 914 drmmode_crtc_scanout_update(crtc, mode, scanout_id, 915 &fb, &x, &y); 916 } 917 918 if (!fb) 919 fb = radeon_pixmap_get_fb(pScreen->GetWindowPixmap(pScreen->root)); 920 if (!fb) { 921 if (info->front_buffer->flags & RADEON_BO_FLAGS_GBM) { 922 handle = gbm_bo_get_handle(info->front_buffer->bo.gbm).u32; 923 } else { 924 handle = info->front_buffer->bo.radeon->handle; 925 } 926 fb = radeon_fb_create(pScrn, pRADEONEnt->fd, 927 pScrn->virtualX, pScrn->virtualY, 928 pScrn->displayWidth * info->pixel_bytes, 929 handle); 930 /* Prevent refcnt of ad-hoc FBs from reaching 2 */ 931 drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL); 932 drmmode_crtc->fb = fb; 933 } 934 if (!fb) { 935 ErrorF("failed to add FB for modeset\n"); 936 goto done; 937 } 938 939 radeon_drm_wait_pending_flip(crtc); 940 handle_deferred = TRUE; 941 942 if (!drmmode_set_mode(crtc, fb, mode, x, y)) 943 goto done; 944 945 ret = TRUE; 946 947 if (pScreen) 948 xf86CrtcSetScreenSubpixelOrder(pScreen); 949 950 drmmode_crtc->need_modeset = FALSE; 951 952 /* go through all the outputs and force DPMS them back on? */ 953 for (i = 0; i < xf86_config->num_output; i++) { 954 xf86OutputPtr output = xf86_config->output[i]; 955 956 if (output->crtc != crtc) 957 continue; 958 959 output->funcs->dpms(output, DPMSModeOn); 960 } 961 } 962 963 /* Compute index of this CRTC into xf86_config->crtc */ 964 for (i = 0; i < xf86_config->num_crtc; i++) { 965 if (xf86_config->crtc[i] != crtc) 966 continue; 967 968 if (!crtc->enabled || drmmode_can_use_hw_cursor(crtc)) 969 info->hwcursor_disabled &= ~(1 << i); 970 else 971 info->hwcursor_disabled |= 1 << i; 972 973 break; 974 } 975 976#ifndef HAVE_XF86_CURSOR_RESET_CURSOR 977 if (!info->hwcursor_disabled) 978 xf86_reload_cursors(pScreen); 979#endif 980 981done: 982 if (!ret) { 983 crtc->x = saved_x; 984 crtc->y = saved_y; 985 crtc->rotation = saved_rotation; 986 crtc->mode = saved_mode; 987 } else { 988 crtc->active = TRUE; 989 990 if (drmmode_crtc->scanout[scanout_id].pixmap && 991 fb != radeon_pixmap_get_fb(drmmode_crtc-> 992 scanout[scanout_id].pixmap)) { 993 drmmode_crtc_scanout_free(crtc); 994 } else if (!drmmode_crtc->tear_free) { 995 drmmode_crtc_scanout_destroy(drmmode, 996 &drmmode_crtc->scanout[1]); 997 } 998 } 999 1000 if (handle_deferred) 1001 radeon_drm_queue_handle_deferred(crtc); 1002 1003 return ret; 1004} 1005 1006static void 1007drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg) 1008{ 1009 1010} 1011 1012static void 1013drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) 1014{ 1015 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1016 RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); 1017 1018#if XF86_CRTC_VERSION < 7 1019 if (crtc->driverIsPerformingTransform) { 1020 x += crtc->x; 1021 y += crtc->y; 1022 xf86CrtcTransformCursorPos(crtc, &x, &y); 1023 } 1024#endif 1025 1026 drmmode_crtc->cursor_x = x; 1027 drmmode_crtc->cursor_y = y; 1028 1029 drmModeMoveCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); 1030} 1031 1032#if XF86_CRTC_VERSION < 7 1033 1034static int 1035drmmode_cursor_src_offset(Rotation rotation, int width, int height, 1036 int x_dst, int y_dst) 1037{ 1038 int t; 1039 1040 switch (rotation & 0xf) { 1041 case RR_Rotate_90: 1042 t = x_dst; 1043 x_dst = height - y_dst - 1; 1044 y_dst = t; 1045 break; 1046 case RR_Rotate_180: 1047 x_dst = width - x_dst - 1; 1048 y_dst = height - y_dst - 1; 1049 break; 1050 case RR_Rotate_270: 1051 t = x_dst; 1052 x_dst = y_dst; 1053 y_dst = width - t - 1; 1054 break; 1055 } 1056 1057 if (rotation & RR_Reflect_X) 1058 x_dst = width - x_dst - 1; 1059 if (rotation & RR_Reflect_Y) 1060 y_dst = height - y_dst - 1; 1061 1062 return y_dst * height + x_dst; 1063} 1064 1065#endif 1066 1067static Bool 1068drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool *premultiplied, 1069 Bool *apply_gamma) 1070{ 1071 uint32_t alpha = *argb >> 24; 1072 uint32_t rgb[3]; 1073 int i; 1074 1075 if (premultiplied) { 1076#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 18, 4, 0, 0) 1077 if (alpha == 0 && (*argb & 0xffffff) != 0) { 1078 /* Doesn't look like premultiplied alpha */ 1079 *premultiplied = FALSE; 1080 return FALSE; 1081 } 1082#endif 1083 1084 if (!(*apply_gamma)) 1085 return TRUE; 1086 1087 if (*argb > (alpha | alpha << 8 | alpha << 16 | alpha << 24)) { 1088 /* Un-premultiplied R/G/B would overflow gamma LUT, 1089 * don't apply gamma correction 1090 */ 1091 *apply_gamma = FALSE; 1092 return FALSE; 1093 } 1094 } 1095 1096 if (!alpha) { 1097 *argb = 0; 1098 return TRUE; 1099 } 1100 1101 /* Extract RGB */ 1102 for (i = 0; i < 3; i++) 1103 rgb[i] = (*argb >> (i * 8)) & 0xff; 1104 1105 if (premultiplied) { 1106 /* Un-premultiply alpha */ 1107 for (i = 0; i < 3; i++) 1108 rgb[i] = rgb[i] * 0xff / alpha; 1109 } 1110 1111 if (*apply_gamma) { 1112 rgb[0] = crtc->gamma_blue[rgb[0]] >> 8; 1113 rgb[1] = crtc->gamma_green[rgb[1]] >> 8; 1114 rgb[2] = crtc->gamma_red[rgb[2]] >> 8; 1115 } 1116 1117 /* Premultiply alpha */ 1118 for (i = 0; i < 3; i++) 1119 rgb[i] = rgb[i] * alpha / 0xff; 1120 1121 *argb = alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0]; 1122 return TRUE; 1123} 1124 1125static void 1126drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) 1127{ 1128 ScrnInfoPtr pScrn = crtc->scrn; 1129 RADEONInfoPtr info = RADEONPTR(pScrn); 1130 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1131 unsigned id = drmmode_crtc->cursor_id; 1132 Bool premultiplied = TRUE; 1133 Bool apply_gamma = TRUE; 1134 uint32_t argb; 1135 uint32_t *ptr; 1136 1137 if (drmmode_crtc->cursor && 1138 XF86_CRTC_CONFIG_PTR(pScrn)->cursor != drmmode_crtc->cursor) 1139 id ^= 1; 1140 1141 /* cursor should be mapped already */ 1142 ptr = (uint32_t *)(drmmode_crtc->cursor_bo[id]->ptr); 1143 1144 if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32) 1145 apply_gamma = FALSE; 1146 1147#if XF86_CRTC_VERSION < 7 1148 if (crtc->driverIsPerformingTransform) { 1149 uint32_t cursor_w = info->cursor_w, cursor_h = info->cursor_h; 1150 int dstx, dsty; 1151 int srcoffset; 1152 1153retry_transform: 1154 for (dsty = 0; dsty < cursor_h; dsty++) { 1155 for (dstx = 0; dstx < cursor_w; dstx++) { 1156 srcoffset = drmmode_cursor_src_offset(crtc->rotation, 1157 cursor_w, 1158 cursor_h, 1159 dstx, dsty); 1160 argb = image[srcoffset]; 1161 if (!drmmode_cursor_pixel(crtc, &argb, &premultiplied, 1162 &apply_gamma)) 1163 goto retry_transform; 1164 1165 ptr[dsty * info->cursor_w + dstx] = cpu_to_le32(argb); 1166 } 1167 } 1168 } else 1169#endif 1170 { 1171 uint32_t cursor_size = info->cursor_w * info->cursor_h; 1172 int i; 1173 1174retry: 1175 for (i = 0; i < cursor_size; i++) { 1176 argb = image[i]; 1177 if (!drmmode_cursor_pixel(crtc, &argb, &premultiplied, 1178 &apply_gamma)) 1179 goto retry; 1180 1181 ptr[i] = cpu_to_le32(argb); 1182 } 1183 } 1184 1185 if (id != drmmode_crtc->cursor_id) { 1186 drmmode_crtc->cursor_id = id; 1187 crtc->funcs->show_cursor(crtc); 1188 } 1189} 1190 1191#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0) 1192 1193static Bool drmmode_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 * image) 1194{ 1195 if (!drmmode_can_use_hw_cursor(crtc)) 1196 return FALSE; 1197 1198 drmmode_load_cursor_argb(crtc, image); 1199 return TRUE; 1200} 1201 1202#endif 1203 1204static void 1205drmmode_hide_cursor (xf86CrtcPtr crtc) 1206{ 1207 ScrnInfoPtr pScrn = crtc->scrn; 1208 RADEONInfoPtr info = RADEONPTR(pScrn); 1209 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1210 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1211 1212 drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 1213 info->cursor_w, info->cursor_h); 1214 drmmode_crtc->cursor = NULL; 1215} 1216 1217static void 1218drmmode_show_cursor (xf86CrtcPtr crtc) 1219{ 1220 ScrnInfoPtr pScrn = crtc->scrn; 1221 RADEONInfoPtr info = RADEONPTR(pScrn); 1222 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1223 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1224 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1225 CursorPtr cursor = xf86_config->cursor; 1226 int xhot = cursor->bits->xhot; 1227 int yhot = cursor->bits->yhot; 1228 static Bool use_set_cursor2 = TRUE; 1229 struct drm_mode_cursor2 arg; 1230 1231 drmmode_crtc->cursor = xf86_config->cursor; 1232 1233 memset(&arg, 0, sizeof(arg)); 1234 1235 arg.handle = drmmode_crtc->cursor_bo[drmmode_crtc->cursor_id]->handle; 1236 arg.flags = DRM_MODE_CURSOR_BO; 1237 arg.crtc_id = drmmode_crtc->mode_crtc->crtc_id; 1238 arg.width = info->cursor_w; 1239 arg.height = info->cursor_h; 1240 1241 if (crtc->rotation != RR_Rotate_0 && 1242 crtc->rotation != (RR_Rotate_180 | RR_Reflect_X | 1243 RR_Reflect_Y)) { 1244 int t; 1245 1246 /* Reflect & rotate hotspot position */ 1247 if (crtc->rotation & RR_Reflect_X) 1248 xhot = info->cursor_w - xhot - 1; 1249 if (crtc->rotation & RR_Reflect_Y) 1250 yhot = info->cursor_h - yhot - 1; 1251 1252 switch (crtc->rotation & 0xf) { 1253 case RR_Rotate_90: 1254 t = xhot; 1255 xhot = yhot; 1256 yhot = info->cursor_w - t - 1; 1257 break; 1258 case RR_Rotate_180: 1259 xhot = info->cursor_w - xhot - 1; 1260 yhot = info->cursor_h - yhot - 1; 1261 break; 1262 case RR_Rotate_270: 1263 t = xhot; 1264 xhot = info->cursor_h - yhot - 1; 1265 yhot = t; 1266 } 1267 } 1268 1269 if (xhot != drmmode_crtc->cursor_xhot || yhot != drmmode_crtc->cursor_yhot) { 1270 arg.flags |= DRM_MODE_CURSOR_MOVE; 1271 arg.x = drmmode_crtc->cursor_x += drmmode_crtc->cursor_xhot - xhot; 1272 arg.y = drmmode_crtc->cursor_y += drmmode_crtc->cursor_yhot - yhot; 1273 drmmode_crtc->cursor_xhot = xhot; 1274 drmmode_crtc->cursor_yhot = yhot; 1275 } 1276 1277 if (use_set_cursor2) { 1278 int ret; 1279 1280 arg.hot_x = xhot; 1281 arg.hot_y = yhot; 1282 1283 ret = drmIoctl(pRADEONEnt->fd, DRM_IOCTL_MODE_CURSOR2, &arg); 1284 if (ret == -EINVAL) 1285 use_set_cursor2 = FALSE; 1286 else 1287 return; 1288 } 1289 1290 drmIoctl(pRADEONEnt->fd, DRM_IOCTL_MODE_CURSOR, &arg); 1291} 1292 1293/* Xorg expects a non-NULL return value from drmmode_crtc_shadow_allocate, and 1294 * passes that back to drmmode_crtc_scanout_create; it doesn't use it for 1295 * anything else. 1296 */ 1297static void * 1298drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) 1299{ 1300 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1301 1302 if (!drmmode_crtc_scanout_create(crtc, &drmmode_crtc->rotate, width, 1303 height)) 1304 return NULL; 1305 1306 return (void*)~0UL; 1307} 1308 1309static PixmapPtr 1310drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) 1311{ 1312 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1313 1314 if (!data) { 1315 drmmode_crtc_scanout_create(crtc, &drmmode_crtc->rotate, width, 1316 height); 1317 } 1318 1319 return drmmode_crtc->rotate.pixmap; 1320} 1321 1322static void 1323drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) 1324{ 1325 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1326 drmmode_ptr drmmode = drmmode_crtc->drmmode; 1327 1328 drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->rotate); 1329} 1330 1331static void 1332drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green, 1333 uint16_t *blue, int size) 1334{ 1335 ScrnInfoPtr scrn = crtc->scrn; 1336 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1337 RADEONInfoPtr info = RADEONPTR(scrn); 1338 int i; 1339 1340 drmmode_crtc_gamma_do_set(crtc, red, green, blue, size); 1341 1342 /* Compute index of this CRTC into xf86_config->crtc */ 1343 for (i = 0; xf86_config->crtc[i] != crtc; i++) {} 1344 1345 if (info->hwcursor_disabled & (1 << i)) 1346 return; 1347 1348#ifdef HAVE_XF86_CURSOR_RESET_CURSOR 1349 xf86CursorResetCursor(scrn->pScreen); 1350#else 1351 xf86_reload_cursors(scrn->pScreen); 1352#endif 1353} 1354 1355static Bool 1356drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) 1357{ 1358 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1359 unsigned scanout_id = drmmode_crtc->scanout_id; 1360 ScreenPtr screen = crtc->scrn->pScreen; 1361 PixmapDirtyUpdatePtr dirty; 1362 1363 xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) { 1364 if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { 1365 PixmapStopDirtyTracking(dirty->src, dirty->slave_dst); 1366 break; 1367 } 1368 } 1369 1370 drmmode_crtc_scanout_free(crtc); 1371 drmmode_crtc->prime_scanout_pixmap = NULL; 1372 1373 if (!ppix) 1374 return TRUE; 1375 1376 if (!drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[0], 1377 ppix->drawable.width, 1378 ppix->drawable.height)) 1379 return FALSE; 1380 1381 if (drmmode_crtc->tear_free && 1382 !drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1], 1383 ppix->drawable.width, 1384 ppix->drawable.height)) { 1385 drmmode_crtc_scanout_free(crtc); 1386 return FALSE; 1387 } 1388 1389 drmmode_crtc->prime_scanout_pixmap = ppix; 1390 1391#ifdef HAS_DIRTYTRACKING_DRAWABLE_SRC 1392 PixmapStartDirtyTracking(&ppix->drawable, 1393 drmmode_crtc->scanout[scanout_id].pixmap, 1394 0, 0, 0, 0, RR_Rotate_0); 1395#elif defined(HAS_DIRTYTRACKING_ROTATION) 1396 PixmapStartDirtyTracking(ppix, drmmode_crtc->scanout[scanout_id].pixmap, 1397 0, 0, 0, 0, RR_Rotate_0); 1398#elif defined(HAS_DIRTYTRACKING2) 1399 PixmapStartDirtyTracking2(ppix, drmmode_crtc->scanout[scanout_id].pixmap, 1400 0, 0, 0, 0); 1401#else 1402 PixmapStartDirtyTracking(ppix, drmmode_crtc->scanout[scanout_id].pixmap, 0, 0); 1403#endif 1404 return TRUE; 1405} 1406 1407static xf86CrtcFuncsRec drmmode_crtc_funcs = { 1408 .dpms = drmmode_crtc_dpms, 1409 .set_mode_major = drmmode_set_mode_major, 1410 .set_cursor_colors = drmmode_set_cursor_colors, 1411 .set_cursor_position = drmmode_set_cursor_position, 1412 .show_cursor = drmmode_show_cursor, 1413 .hide_cursor = drmmode_hide_cursor, 1414 .load_cursor_argb = drmmode_load_cursor_argb, 1415#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0) 1416 .load_cursor_argb_check = drmmode_load_cursor_argb_check, 1417#endif 1418 1419 .gamma_set = drmmode_crtc_gamma_set, 1420 .shadow_create = drmmode_crtc_shadow_create, 1421 .shadow_allocate = drmmode_crtc_shadow_allocate, 1422 .shadow_destroy = drmmode_crtc_shadow_destroy, 1423 .destroy = NULL, /* XXX */ 1424 .set_scanout_pixmap = drmmode_set_scanout_pixmap, 1425}; 1426 1427int drmmode_get_crtc_id(xf86CrtcPtr crtc) 1428{ 1429 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1430 return drmmode_crtc->hw_id; 1431} 1432 1433void drmmode_crtc_hw_id(xf86CrtcPtr crtc) 1434{ 1435 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1436 RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); 1437 struct drm_radeon_info ginfo; 1438 int r; 1439 uint32_t tmp; 1440 1441 memset(&ginfo, 0, sizeof(ginfo)); 1442 ginfo.request = 0x4; 1443 tmp = drmmode_crtc->mode_crtc->crtc_id; 1444 ginfo.value = (uintptr_t)&tmp; 1445 r = drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); 1446 if (r) { 1447 drmmode_crtc->hw_id = -1; 1448 return; 1449 } 1450 drmmode_crtc->hw_id = tmp; 1451} 1452 1453static unsigned int 1454drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num) 1455{ 1456 xf86CrtcPtr crtc; 1457 drmmode_crtc_private_ptr drmmode_crtc; 1458 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1459 RADEONInfoPtr info = RADEONPTR(pScrn); 1460 1461 crtc = xf86CrtcCreate(pScrn, &info->drmmode_crtc_funcs); 1462 if (!crtc) 1463 return 0; 1464 1465 drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); 1466 drmmode_crtc->mode_crtc = drmModeGetCrtc(pRADEONEnt->fd, mode_res->crtcs[num]); 1467 drmmode_crtc->drmmode = drmmode; 1468 drmmode_crtc->dpms_mode = DPMSModeOff; 1469 crtc->driver_private = drmmode_crtc; 1470 drmmode_crtc_hw_id(crtc); 1471 1472 /* Mark num'th crtc as in use on this device. */ 1473 pRADEONEnt->assigned_crtcs |= (1 << num); 1474 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 1475 "Allocated crtc nr. %d to this screen.\n", num); 1476 1477 return 1; 1478} 1479 1480/* 1481 * Update all of the property values for an output 1482 */ 1483static void 1484drmmode_output_update_properties(xf86OutputPtr output) 1485{ 1486 drmmode_output_private_ptr drmmode_output = output->driver_private; 1487 int i, j, k; 1488 int err; 1489 drmModeConnectorPtr koutput; 1490 1491 /* Use the most recently fetched values from the kernel */ 1492 koutput = drmmode_output->mode_output; 1493 1494 if (!koutput) 1495 return; 1496 1497 for (i = 0; i < drmmode_output->num_props; i++) { 1498 drmmode_prop_ptr p = &drmmode_output->props[i]; 1499 1500 for (j = 0; j < koutput->count_props; j++) { 1501 if (koutput->props[j] != p->mode_prop->prop_id) 1502 continue; 1503 1504 /* Check to see if the property value has changed */ 1505 if (koutput->prop_values[j] == p->value) 1506 break; 1507 1508 p->value = koutput->prop_values[j]; 1509 1510 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) { 1511 INT32 value = p->value; 1512 1513 err = RRChangeOutputProperty(output->randr_output, 1514 p->atoms[0], XA_INTEGER, 1515 32, PropModeReplace, 1, 1516 &value, FALSE, TRUE); 1517 if (err != 0) { 1518 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1519 "RRChangeOutputProperty error, %d\n", 1520 err); 1521 } 1522 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { 1523 for (k = 0; k < p->mode_prop->count_enums; k++) { 1524 if (p->mode_prop->enums[k].value == p->value) 1525 break; 1526 } 1527 if (k < p->mode_prop->count_enums) { 1528 err = RRChangeOutputProperty(output->randr_output, 1529 p->atoms[0], XA_ATOM, 1530 32, PropModeReplace, 1, 1531 &p->atoms[k + 1], FALSE, 1532 TRUE); 1533 if (err != 0) { 1534 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1535 "RRChangeOutputProperty error, %d\n", 1536 err); 1537 } 1538 } 1539 } 1540 1541 break; 1542 } 1543 } 1544} 1545 1546static xf86OutputStatus 1547drmmode_output_detect(xf86OutputPtr output) 1548{ 1549 /* go to the hw and retrieve a new output struct */ 1550 drmmode_output_private_ptr drmmode_output = output->driver_private; 1551 RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); 1552 xf86OutputStatus status; 1553 drmModeFreeConnector(drmmode_output->mode_output); 1554 1555 drmmode_output->mode_output = 1556 drmModeGetConnector(pRADEONEnt->fd, drmmode_output->output_id); 1557 if (!drmmode_output->mode_output) { 1558 drmmode_output->output_id = -1; 1559 return XF86OutputStatusDisconnected; 1560 } 1561 1562 drmmode_output_update_properties(output); 1563 1564 switch (drmmode_output->mode_output->connection) { 1565 case DRM_MODE_CONNECTED: 1566 status = XF86OutputStatusConnected; 1567 break; 1568 case DRM_MODE_DISCONNECTED: 1569 status = XF86OutputStatusDisconnected; 1570 break; 1571 default: 1572 case DRM_MODE_UNKNOWNCONNECTION: 1573 status = XF86OutputStatusUnknown; 1574 break; 1575 } 1576 return status; 1577} 1578 1579static Bool 1580drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) 1581{ 1582 return MODE_OK; 1583} 1584 1585static void 1586drmmode_output_attach_tile(xf86OutputPtr output) 1587{ 1588#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1, 17, 99, 901, 0) 1589 drmmode_output_private_ptr drmmode_output = output->driver_private; 1590 drmModeConnectorPtr koutput = drmmode_output->mode_output; 1591 RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); 1592 struct xf86CrtcTileInfo tile_info, *set = NULL; 1593 int i; 1594 1595 if (!koutput) { 1596 xf86OutputSetTile(output, NULL); 1597 return; 1598 } 1599 1600 /* look for a TILE property */ 1601 for (i = 0; i < koutput->count_props; i++) { 1602 drmModePropertyPtr props; 1603 props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[i]); 1604 if (!props) 1605 continue; 1606 1607 if (!(props->flags & DRM_MODE_PROP_BLOB)) { 1608 drmModeFreeProperty(props); 1609 continue; 1610 } 1611 1612 if (!strcmp(props->name, "TILE")) { 1613 drmModeFreePropertyBlob(drmmode_output->tile_blob); 1614 drmmode_output->tile_blob = 1615 drmModeGetPropertyBlob(pRADEONEnt->fd, 1616 koutput->prop_values[i]); 1617 } 1618 drmModeFreeProperty(props); 1619 } 1620 if (drmmode_output->tile_blob) { 1621 if (xf86OutputParseKMSTile(drmmode_output->tile_blob->data, 1622 drmmode_output->tile_blob->length, 1623 &tile_info) == TRUE) 1624 set = &tile_info; 1625 } 1626 xf86OutputSetTile(output, set); 1627#endif 1628} 1629 1630static int 1631koutput_get_prop_idx(int fd, drmModeConnectorPtr koutput, 1632 int type, const char *name) 1633{ 1634 int idx = -1; 1635 1636 for (int i = 0; i < koutput->count_props; i++) { 1637 drmModePropertyPtr prop = drmModeGetProperty(fd, koutput->props[i]); 1638 1639 if (!prop) 1640 continue; 1641 1642 if (drm_property_type_is(prop, type) && !strcmp(prop->name, name)) 1643 idx = i; 1644 1645 drmModeFreeProperty(prop); 1646 1647 if (idx > -1) 1648 break; 1649 } 1650 1651 return idx; 1652} 1653 1654static int 1655koutput_get_prop_id(int fd, drmModeConnectorPtr koutput, 1656 int type, const char *name) 1657{ 1658 int idx = koutput_get_prop_idx(fd, koutput, type, name); 1659 1660 return (idx > -1) ? koutput->props[idx] : -1; 1661} 1662 1663static drmModePropertyBlobPtr 1664koutput_get_prop_blob(int fd, drmModeConnectorPtr koutput, const char *name) 1665{ 1666 drmModePropertyBlobPtr blob = NULL; 1667 int idx = koutput_get_prop_idx(fd, koutput, DRM_MODE_PROP_BLOB, name); 1668 1669 if (idx > -1) 1670 blob = drmModeGetPropertyBlob(fd, koutput->prop_values[idx]); 1671 1672 return blob; 1673} 1674 1675static DisplayModePtr 1676drmmode_output_get_modes(xf86OutputPtr output) 1677{ 1678 drmmode_output_private_ptr drmmode_output = output->driver_private; 1679 drmModeConnectorPtr koutput = drmmode_output->mode_output; 1680 RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); 1681 int i; 1682 DisplayModePtr Modes = NULL, Mode; 1683 xf86MonPtr mon = NULL; 1684 1685 if (!koutput) 1686 return NULL; 1687 1688 drmModeFreePropertyBlob(drmmode_output->edid_blob); 1689 1690 /* look for an EDID property */ 1691 drmmode_output->edid_blob = 1692 koutput_get_prop_blob(pRADEONEnt->fd, koutput, "EDID"); 1693 1694 if (drmmode_output->edid_blob) { 1695 mon = xf86InterpretEDID(output->scrn->scrnIndex, 1696 drmmode_output->edid_blob->data); 1697 if (mon && drmmode_output->edid_blob->length > 128) 1698 mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA; 1699 } 1700 xf86OutputSetEDID(output, mon); 1701 1702 drmmode_output_attach_tile(output); 1703 1704 /* modes should already be available */ 1705 for (i = 0; i < koutput->count_modes; i++) { 1706 Mode = xnfalloc(sizeof(DisplayModeRec)); 1707 1708 drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode); 1709 Modes = xf86ModesAdd(Modes, Mode); 1710 1711 } 1712 return Modes; 1713} 1714 1715static void 1716drmmode_output_destroy(xf86OutputPtr output) 1717{ 1718 drmmode_output_private_ptr drmmode_output = output->driver_private; 1719 int i; 1720 1721 drmModeFreePropertyBlob(drmmode_output->edid_blob); 1722#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1, 17, 99, 901, 0) 1723 drmModeFreePropertyBlob(drmmode_output->tile_blob); 1724#endif 1725 1726 for (i = 0; i < drmmode_output->num_props; i++) { 1727 drmModeFreeProperty(drmmode_output->props[i].mode_prop); 1728 free(drmmode_output->props[i].atoms); 1729 } 1730 for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) { 1731 drmModeFreeEncoder(drmmode_output->mode_encoders[i]); 1732 } 1733 free(drmmode_output->mode_encoders); 1734 free(drmmode_output->props); 1735 drmModeFreeConnector(drmmode_output->mode_output); 1736 free(drmmode_output); 1737 output->driver_private = NULL; 1738} 1739 1740static void 1741drmmode_output_dpms(xf86OutputPtr output, int mode) 1742{ 1743 drmmode_output_private_ptr drmmode_output = output->driver_private; 1744 xf86CrtcPtr crtc = output->crtc; 1745 drmModeConnectorPtr koutput = drmmode_output->mode_output; 1746 RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); 1747 1748 if (!koutput) 1749 return; 1750 1751 if (mode != DPMSModeOn && crtc) 1752 drmmode_do_crtc_dpms(crtc, mode); 1753 1754 drmModeConnectorSetProperty(pRADEONEnt->fd, koutput->connector_id, 1755 drmmode_output->dpms_enum_id, mode); 1756 1757 if (mode == DPMSModeOn && crtc) { 1758 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1759 1760 if (drmmode_crtc->need_modeset) 1761 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x, 1762 crtc->y); 1763 else 1764 drmmode_do_crtc_dpms(crtc, mode); 1765 } 1766} 1767 1768 1769static Bool 1770drmmode_property_ignore(drmModePropertyPtr prop) 1771{ 1772 if (!prop) 1773 return TRUE; 1774 /* ignore blob prop */ 1775 if (prop->flags & DRM_MODE_PROP_BLOB) 1776 return TRUE; 1777 /* ignore standard property */ 1778 if (!strcmp(prop->name, "EDID") || 1779 !strcmp(prop->name, "DPMS")) 1780 return TRUE; 1781 1782 return FALSE; 1783} 1784 1785static void 1786drmmode_output_create_resources(xf86OutputPtr output) 1787{ 1788 RADEONInfoPtr info = RADEONPTR(output->scrn); 1789 drmmode_output_private_ptr drmmode_output = output->driver_private; 1790 drmModeConnectorPtr mode_output = drmmode_output->mode_output; 1791 RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); 1792 drmModePropertyPtr drmmode_prop, tearfree_prop; 1793 int i, j, err; 1794 Atom name; 1795 1796 /* Create CONNECTOR_ID property */ 1797 name = MakeAtom("CONNECTOR_ID", 12, TRUE); 1798 if (name != BAD_RESOURCE) { 1799 INT32 value = mode_output->connector_id; 1800 1801 err = RRConfigureOutputProperty(output->randr_output, name, 1802 FALSE, FALSE, TRUE, 1, &value); 1803 if (err != Success) { 1804 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1805 "RRConfigureOutputProperty error, %d\n", err); 1806 } 1807 1808 err = RRChangeOutputProperty(output->randr_output, name, 1809 XA_INTEGER, 32, PropModeReplace, 1, 1810 &value, FALSE, FALSE); 1811 if (err != Success) { 1812 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1813 "RRChangeOutputProperty error, %d\n", err); 1814 } 1815 } 1816 1817 drmmode_output->props = calloc(mode_output->count_props + 1, sizeof(drmmode_prop_rec)); 1818 if (!drmmode_output->props) 1819 return; 1820 1821 drmmode_output->num_props = 0; 1822 for (i = 0, j = 0; i < mode_output->count_props; i++) { 1823 drmmode_prop = drmModeGetProperty(pRADEONEnt->fd, mode_output->props[i]); 1824 if (drmmode_property_ignore(drmmode_prop)) { 1825 drmModeFreeProperty(drmmode_prop); 1826 continue; 1827 } 1828 drmmode_output->props[j].mode_prop = drmmode_prop; 1829 drmmode_output->props[j].value = mode_output->prop_values[i]; 1830 drmmode_output->num_props++; 1831 j++; 1832 } 1833 1834 /* Userspace-only property for TearFree */ 1835 tearfree_prop = calloc(1, sizeof(*tearfree_prop)); 1836 tearfree_prop->flags = DRM_MODE_PROP_ENUM; 1837 strcpy(tearfree_prop->name, "TearFree"); 1838 tearfree_prop->count_enums = 3; 1839 tearfree_prop->enums = calloc(tearfree_prop->count_enums, 1840 sizeof(*tearfree_prop->enums)); 1841 strcpy(tearfree_prop->enums[0].name, "off"); 1842 strcpy(tearfree_prop->enums[1].name, "on"); 1843 tearfree_prop->enums[1].value = 1; 1844 strcpy(tearfree_prop->enums[2].name, "auto"); 1845 tearfree_prop->enums[2].value = 2; 1846 drmmode_output->props[j].mode_prop = tearfree_prop; 1847 drmmode_output->props[j].value = info->tear_free; 1848 drmmode_output->tear_free = info->tear_free; 1849 drmmode_output->num_props++; 1850 1851 for (i = 0; i < drmmode_output->num_props; i++) { 1852 drmmode_prop_ptr p = &drmmode_output->props[i]; 1853 drmmode_prop = p->mode_prop; 1854 1855 if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) { 1856 INT32 range[2]; 1857 INT32 value = p->value; 1858 1859 p->num_atoms = 1; 1860 p->atoms = calloc(p->num_atoms, sizeof(Atom)); 1861 if (!p->atoms) 1862 continue; 1863 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); 1864 range[0] = drmmode_prop->values[0]; 1865 range[1] = drmmode_prop->values[1]; 1866 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], 1867 FALSE, TRUE, 1868 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, 1869 2, range); 1870 if (err != 0) { 1871 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1872 "RRConfigureOutputProperty error, %d\n", err); 1873 } 1874 err = RRChangeOutputProperty(output->randr_output, p->atoms[0], 1875 XA_INTEGER, 32, PropModeReplace, 1, &value, FALSE, TRUE); 1876 if (err != 0) { 1877 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1878 "RRChangeOutputProperty error, %d\n", err); 1879 } 1880 } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) { 1881 p->num_atoms = drmmode_prop->count_enums + 1; 1882 p->atoms = calloc(p->num_atoms, sizeof(Atom)); 1883 if (!p->atoms) 1884 continue; 1885 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); 1886 for (j = 1; j <= drmmode_prop->count_enums; j++) { 1887 struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1]; 1888 p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE); 1889 } 1890 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], 1891 FALSE, FALSE, 1892 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, 1893 p->num_atoms - 1, (INT32 *)&p->atoms[1]); 1894 if (err != 0) { 1895 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1896 "RRConfigureOutputProperty error, %d\n", err); 1897 } 1898 for (j = 0; j < drmmode_prop->count_enums; j++) 1899 if (drmmode_prop->enums[j].value == p->value) 1900 break; 1901 /* there's always a matching value */ 1902 err = RRChangeOutputProperty(output->randr_output, p->atoms[0], 1903 XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE); 1904 if (err != 0) { 1905 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1906 "RRChangeOutputProperty error, %d\n", err); 1907 } 1908 } 1909 } 1910} 1911 1912static void 1913drmmode_output_set_tear_free(RADEONEntPtr pRADEONEnt, 1914 drmmode_output_private_ptr drmmode_output, 1915 xf86CrtcPtr crtc, int tear_free) 1916{ 1917 if (drmmode_output->tear_free == tear_free) 1918 return; 1919 1920 drmmode_output->tear_free = tear_free; 1921 1922 if (crtc) { 1923 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, 1924 crtc->x, crtc->y); 1925 } 1926} 1927 1928static Bool 1929drmmode_output_set_property(xf86OutputPtr output, Atom property, 1930 RRPropertyValuePtr value) 1931{ 1932 drmmode_output_private_ptr drmmode_output = output->driver_private; 1933 RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); 1934 int i; 1935 1936 for (i = 0; i < drmmode_output->num_props; i++) { 1937 drmmode_prop_ptr p = &drmmode_output->props[i]; 1938 1939 if (p->atoms[0] != property) 1940 continue; 1941 1942 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) { 1943 uint32_t val; 1944 1945 if (value->type != XA_INTEGER || value->format != 32 || 1946 value->size != 1) 1947 return FALSE; 1948 val = *(uint32_t *)value->data; 1949 1950 drmModeConnectorSetProperty(pRADEONEnt->fd, drmmode_output->output_id, 1951 p->mode_prop->prop_id, (uint64_t)val); 1952 return TRUE; 1953 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { 1954 Atom atom; 1955 const char *name; 1956 int j; 1957 1958 if (value->type != XA_ATOM || value->format != 32 || value->size != 1) 1959 return FALSE; 1960 memcpy(&atom, value->data, 4); 1961 if (!(name = NameForAtom(atom))) 1962 return FALSE; 1963 1964 /* search for matching name string, then set its value down */ 1965 for (j = 0; j < p->mode_prop->count_enums; j++) { 1966 if (!strcmp(p->mode_prop->enums[j].name, name)) { 1967 if (i == (drmmode_output->num_props - 1)) { 1968 drmmode_output_set_tear_free(pRADEONEnt, drmmode_output, 1969 output->crtc, j); 1970 } else { 1971 drmModeConnectorSetProperty(pRADEONEnt->fd, 1972 drmmode_output->output_id, 1973 p->mode_prop->prop_id, 1974 p->mode_prop->enums[j].value); 1975 } 1976 1977 return TRUE; 1978 } 1979 } 1980 } 1981 } 1982 1983 return TRUE; 1984} 1985 1986static Bool 1987drmmode_output_get_property(xf86OutputPtr output, Atom property) 1988{ 1989 return TRUE; 1990} 1991 1992static const xf86OutputFuncsRec drmmode_output_funcs = { 1993 .dpms = drmmode_output_dpms, 1994 .create_resources = drmmode_output_create_resources, 1995 .set_property = drmmode_output_set_property, 1996 .get_property = drmmode_output_get_property, 1997 .detect = drmmode_output_detect, 1998 .mode_valid = drmmode_output_mode_valid, 1999 2000 .get_modes = drmmode_output_get_modes, 2001 .destroy = drmmode_output_destroy 2002}; 2003 2004static int subpixel_conv_table[7] = { 0, SubPixelUnknown, 2005 SubPixelHorizontalRGB, 2006 SubPixelHorizontalBGR, 2007 SubPixelVerticalRGB, 2008 SubPixelVerticalBGR, 2009 SubPixelNone }; 2010 2011const char *output_names[] = { "None", 2012 "VGA", 2013 "DVI", 2014 "DVI", 2015 "DVI", 2016 "Composite", 2017 "S-video", 2018 "LVDS", 2019 "CTV", 2020 "DIN", 2021 "DisplayPort", 2022 "HDMI", 2023 "HDMI", 2024 "TV", 2025 "eDP" 2026}; 2027 2028#define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0])) 2029 2030static xf86OutputPtr find_output(ScrnInfoPtr pScrn, int id) 2031{ 2032 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 2033 int i; 2034 for (i = 0; i < xf86_config->num_output; i++) { 2035 xf86OutputPtr output = xf86_config->output[i]; 2036 drmmode_output_private_ptr drmmode_output; 2037 2038 drmmode_output = output->driver_private; 2039 if (drmmode_output->output_id == id) 2040 return output; 2041 } 2042 return NULL; 2043} 2044 2045static int parse_path_blob(drmModePropertyBlobPtr path_blob, int *conn_base_id, char **path) 2046{ 2047 char *conn; 2048 char conn_id[5]; 2049 int id, len; 2050 char *blob_data; 2051 2052 if (!path_blob) 2053 return -1; 2054 2055 blob_data = path_blob->data; 2056 /* we only handle MST paths for now */ 2057 if (strncmp(blob_data, "mst:", 4)) 2058 return -1; 2059 2060 conn = strchr(blob_data + 4, '-'); 2061 if (!conn) 2062 return -1; 2063 len = conn - (blob_data + 4); 2064 if (len + 1 > 5) 2065 return -1; 2066 memcpy(conn_id, blob_data + 4, len); 2067 conn_id[len] = '\0'; 2068 id = strtoul(conn_id, NULL, 10); 2069 2070 *conn_base_id = id; 2071 2072 *path = conn + 1; 2073 return 0; 2074} 2075 2076static void 2077drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name, 2078 drmModePropertyBlobPtr path_blob, int *num_dvi, int *num_hdmi) 2079{ 2080 xf86OutputPtr output; 2081 int conn_id; 2082 char *extra_path; 2083 2084 output = NULL; 2085 if (parse_path_blob(path_blob, &conn_id, &extra_path) == 0) 2086 output = find_output(pScrn, conn_id); 2087 if (output) { 2088 snprintf(name, 32, "%s-%s", output->name, extra_path); 2089 } else { 2090 if (koutput->connector_type >= NUM_OUTPUT_NAMES) { 2091 snprintf(name, 32, "Unknown%d-%d", koutput->connector_type, 2092 koutput->connector_type_id - 1); 2093 } else if (pScrn->is_gpu) { 2094 snprintf(name, 32, "%s-%d-%d", 2095 output_names[koutput->connector_type], pScrn->scrnIndex - GPU_SCREEN_OFFSET + 1, 2096 koutput->connector_type_id - 1); 2097 } else { 2098 /* need to do smart conversion here for compat with non-kms ATI driver */ 2099 if (koutput->connector_type_id == 1) { 2100 switch(koutput->connector_type) { 2101 case DRM_MODE_CONNECTOR_DVII: 2102 case DRM_MODE_CONNECTOR_DVID: 2103 case DRM_MODE_CONNECTOR_DVIA: 2104 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_dvi); 2105 (*num_dvi)++; 2106 break; 2107 case DRM_MODE_CONNECTOR_HDMIA: 2108 case DRM_MODE_CONNECTOR_HDMIB: 2109 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_hdmi); 2110 (*num_hdmi)++; 2111 break; 2112 case DRM_MODE_CONNECTOR_VGA: 2113 case DRM_MODE_CONNECTOR_DisplayPort: 2114 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], 2115 koutput->connector_type_id - 1); 2116 break; 2117 default: 2118 snprintf(name, 32, "%s", output_names[koutput->connector_type]); 2119 break; 2120 } 2121 } else { 2122 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], 2123 koutput->connector_type_id - 1); 2124 } 2125 } 2126 } 2127} 2128 2129static unsigned int 2130drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, int *num_dvi, int *num_hdmi, int dynamic) 2131{ 2132 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 2133 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2134 RADEONInfoPtr info = RADEONPTR(pScrn); 2135 xf86OutputPtr output; 2136 drmModeConnectorPtr koutput; 2137 drmModeEncoderPtr *kencoders = NULL; 2138 drmmode_output_private_ptr drmmode_output; 2139 drmModePropertyBlobPtr path_blob = NULL; 2140#if XF86_CRTC_VERSION >= 8 2141 Bool nonDesktop = FALSE; 2142#endif 2143 char name[32]; 2144 int i; 2145 const char *s; 2146 2147 koutput = drmModeGetConnector(pRADEONEnt->fd, mode_res->connectors[num]); 2148 if (!koutput) 2149 return 0; 2150 2151 path_blob = koutput_get_prop_blob(pRADEONEnt->fd, koutput, "PATH"); 2152 2153#if XF86_CRTC_VERSION >= 8 2154 i = koutput_get_prop_idx(pRADEONEnt->fd, koutput, DRM_MODE_PROP_RANGE, 2155 "non-desktop"); 2156 if (i >= 0) 2157 nonDesktop = koutput->prop_values[i] != 0; 2158#endif 2159 2160 kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders); 2161 if (!kencoders) { 2162 goto out_free_encoders; 2163 } 2164 2165 for (i = 0; i < koutput->count_encoders; i++) { 2166 kencoders[i] = drmModeGetEncoder(pRADEONEnt->fd, koutput->encoders[i]); 2167 if (!kencoders[i]) { 2168 goto out_free_encoders; 2169 } 2170 } 2171 2172 drmmode_create_name(pScrn, koutput, name, path_blob, num_dvi, num_hdmi); 2173 if (path_blob) 2174 drmModeFreePropertyBlob(path_blob); 2175 2176 if (path_blob && dynamic) { 2177 /* See if we have an output with this name already 2178 * and hook stuff up. 2179 */ 2180 for (i = 0; i < xf86_config->num_output; i++) { 2181 output = xf86_config->output[i]; 2182 2183 if (strncmp(output->name, name, 32)) 2184 continue; 2185 2186 drmmode_output = output->driver_private; 2187 drmmode_output->output_id = mode_res->connectors[num]; 2188 drmmode_output->mode_output = koutput; 2189#if XF86_CRTC_VERSION >= 8 2190 output->non_desktop = nonDesktop; 2191#endif 2192 for (i = 0; i < koutput->count_encoders; i++) 2193 drmModeFreeEncoder(kencoders[i]); 2194 free(kencoders); 2195 return 0; 2196 } 2197 } 2198 2199 if (xf86IsEntityShared(pScrn->entityList[0])) { 2200 if ((s = xf86GetOptValString(info->Options, OPTION_ZAPHOD_HEADS))) { 2201 if (!RADEONZaphodStringMatches(pScrn, s, name)) 2202 goto out_free_encoders; 2203 } else { 2204 if (info->instance_id != num) 2205 goto out_free_encoders; 2206 } 2207 } 2208 2209 output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name); 2210 if (!output) { 2211 goto out_free_encoders; 2212 } 2213 2214 drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1); 2215 if (!drmmode_output) { 2216 xf86OutputDestroy(output); 2217 goto out_free_encoders; 2218 } 2219 2220 drmmode_output->output_id = mode_res->connectors[num]; 2221 drmmode_output->mode_output = koutput; 2222 drmmode_output->mode_encoders = kencoders; 2223 drmmode_output->drmmode = drmmode; 2224 output->mm_width = koutput->mmWidth; 2225 output->mm_height = koutput->mmHeight; 2226 2227 output->subpixel_order = subpixel_conv_table[koutput->subpixel]; 2228 output->interlaceAllowed = TRUE; 2229 output->doubleScanAllowed = TRUE; 2230 output->driver_private = drmmode_output; 2231#if XF86_CRTC_VERSION >= 8 2232 output->non_desktop = nonDesktop; 2233#endif 2234 2235 output->possible_crtcs = 0xffffffff; 2236 for (i = 0; i < koutput->count_encoders; i++) { 2237 output->possible_crtcs &= kencoders[i]->possible_crtcs; 2238 } 2239 /* work out the possible clones later */ 2240 output->possible_clones = 0; 2241 2242 drmmode_output->dpms_enum_id = 2243 koutput_get_prop_id(pRADEONEnt->fd, koutput, DRM_MODE_PROP_ENUM, 2244 "DPMS"); 2245 2246 if (dynamic) { 2247 output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output); 2248 drmmode_output_create_resources(output); 2249 } 2250 2251 return 1; 2252out_free_encoders: 2253 if (kencoders){ 2254 for (i = 0; i < koutput->count_encoders; i++) 2255 drmModeFreeEncoder(kencoders[i]); 2256 free(kencoders); 2257 } 2258 drmModeFreeConnector(koutput); 2259 return 0; 2260} 2261 2262uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output) 2263{ 2264 drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout; 2265 int i; 2266 xf86OutputPtr clone_output; 2267 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 2268 int index_mask = 0; 2269 2270 if (drmmode_output->enc_clone_mask == 0) 2271 return index_mask; 2272 2273 for (i = 0; i < xf86_config->num_output; i++) { 2274 clone_output = xf86_config->output[i]; 2275 clone_drmout = clone_output->driver_private; 2276 if (output == clone_output) 2277 continue; 2278 2279 if (clone_drmout->enc_mask == 0) 2280 continue; 2281 if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask) 2282 index_mask |= (1 << i); 2283 } 2284 return index_mask; 2285} 2286 2287 2288static void 2289drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, drmModeResPtr mode_res) 2290{ 2291 int i, j; 2292 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 2293 2294 for (i = 0; i < xf86_config->num_output; i++) { 2295 xf86OutputPtr output = xf86_config->output[i]; 2296 drmmode_output_private_ptr drmmode_output; 2297 2298 drmmode_output = output->driver_private; 2299 drmmode_output->enc_clone_mask = 0xff; 2300 /* and all the possible encoder clones for this output together */ 2301 for (j = 0; j < drmmode_output->mode_output->count_encoders; j++) 2302 { 2303 int k; 2304 for (k = 0; k < mode_res->count_encoders; k++) { 2305 if (mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id) 2306 drmmode_output->enc_mask |= (1 << k); 2307 } 2308 2309 drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones; 2310 } 2311 } 2312 2313 for (i = 0; i < xf86_config->num_output; i++) { 2314 xf86OutputPtr output = xf86_config->output[i]; 2315 output->possible_clones = find_clones(scrn, output); 2316 } 2317} 2318 2319/* returns height alignment in pixels */ 2320int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling) 2321{ 2322 RADEONInfoPtr info = RADEONPTR(scrn); 2323 int height_align = 1; 2324 2325 if (info->ChipFamily >= CHIP_FAMILY_R600) { 2326 if (tiling & RADEON_TILING_MACRO) 2327 height_align = info->num_channels * 8; 2328 else if (tiling & RADEON_TILING_MICRO) 2329 height_align = 8; 2330 else 2331 height_align = 8; 2332 } else { 2333 if (tiling & RADEON_TILING_MICRO_SQUARE) 2334 height_align = 32; 2335 else if (tiling) 2336 height_align = 16; 2337 else 2338 height_align = 1; 2339 } 2340 return height_align; 2341} 2342 2343/* returns pitch alignment in pixels */ 2344int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling) 2345{ 2346 RADEONInfoPtr info = RADEONPTR(scrn); 2347 int pitch_align = 1; 2348 2349 if (info->ChipFamily >= CHIP_FAMILY_R600) { 2350 if (tiling & RADEON_TILING_MACRO) { 2351 /* general surface requirements */ 2352 pitch_align = MAX(info->num_banks, 2353 (((info->group_bytes / 8) / bpe) * info->num_banks)) * 8; 2354 /* further restrictions for scanout */ 2355 pitch_align = MAX(info->num_banks * 8, pitch_align); 2356 } else if (tiling & RADEON_TILING_MICRO) { 2357 /* general surface requirements */ 2358 pitch_align = MAX(8, (info->group_bytes / (8 * bpe))); 2359 /* further restrictions for scanout */ 2360 pitch_align = MAX(info->group_bytes / bpe, pitch_align); 2361 } else { 2362 if (info->have_tiling_info) 2363 /* linear aligned requirements */ 2364 pitch_align = MAX(64, info->group_bytes / bpe); 2365 else 2366 /* default to 512 elements if we don't know the real 2367 * group size otherwise the kernel may reject the CS 2368 * if the group sizes don't match as the pitch won't 2369 * be aligned properly. 2370 */ 2371 pitch_align = 512; 2372 } 2373 } else { 2374 /* general surface requirements */ 2375 if (tiling) 2376 pitch_align = 256 / bpe; 2377 else 2378 pitch_align = 64; 2379 } 2380 return pitch_align; 2381} 2382 2383/* returns base alignment in bytes */ 2384int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling) 2385{ 2386 RADEONInfoPtr info = RADEONPTR(scrn); 2387 int pixel_align = drmmode_get_pitch_align(scrn, bpe, tiling); 2388 int height_align = drmmode_get_height_align(scrn, tiling); 2389 int base_align = RADEON_GPU_PAGE_SIZE; 2390 2391 if (info->ChipFamily >= CHIP_FAMILY_R600) { 2392 if (tiling & RADEON_TILING_MACRO) 2393 base_align = MAX(info->num_banks * info->num_channels * 8 * 8 * bpe, 2394 pixel_align * bpe * height_align); 2395 else { 2396 if (info->have_tiling_info) 2397 base_align = info->group_bytes; 2398 else 2399 /* default to 512 if we don't know the real 2400 * group size otherwise the kernel may reject the CS 2401 * if the group sizes don't match as the base won't 2402 * be aligned properly. 2403 */ 2404 base_align = 512; 2405 } 2406 } 2407 return base_align; 2408} 2409 2410static Bool 2411drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) 2412{ 2413 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 2414 RADEONInfoPtr info = RADEONPTR(scrn); 2415 struct radeon_buffer *old_front = NULL; 2416 ScreenPtr screen = xf86ScrnToScreen(scrn); 2417 int i, pitch, old_width, old_height, old_pitch; 2418 int usage = CREATE_PIXMAP_USAGE_BACKING_PIXMAP; 2419 int cpp = info->pixel_bytes; 2420 uint32_t tiling_flags; 2421 PixmapPtr ppix = screen->GetScreenPixmap(screen); 2422 void *fb_shadow; 2423 2424 if (scrn->virtualX == width && scrn->virtualY == height) 2425 return TRUE; 2426 2427 if (width > xf86_config->maxWidth || height > xf86_config->maxHeight) { 2428 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 2429 "Xorg tried resizing screen to %dx%d, but maximum " 2430 "supported is %dx%d\n", width, height, 2431 xf86_config->maxWidth, xf86_config->maxHeight); 2432 return FALSE; 2433 } 2434 2435 if (info->allowColorTiling && !info->shadow_primary) { 2436 if (info->ChipFamily < CHIP_FAMILY_R600 || info->allowColorTiling2D) 2437 usage |= RADEON_CREATE_PIXMAP_TILING_MACRO; 2438 else 2439 usage |= RADEON_CREATE_PIXMAP_TILING_MICRO; 2440 } 2441 2442 xf86DrvMsg(scrn->scrnIndex, X_INFO, "Allocate new frame buffer %dx%d\n", 2443 width, height); 2444 2445 old_width = scrn->virtualX; 2446 old_height = scrn->virtualY; 2447 old_pitch = scrn->displayWidth; 2448 old_front = info->front_buffer; 2449 2450 scrn->virtualX = width; 2451 scrn->virtualY = height; 2452 2453 info->front_buffer = radeon_alloc_pixmap_bo(scrn, scrn->virtualX, 2454 scrn->virtualY, scrn->depth, 2455 usage, scrn->bitsPerPixel, 2456 &pitch, 2457 &info->front_surface, 2458 &tiling_flags); 2459 if (!info->front_buffer) 2460 goto fail; 2461 2462 scrn->displayWidth = pitch / cpp; 2463 2464 if (!info->use_glamor) { 2465#if X_BYTE_ORDER == X_BIG_ENDIAN 2466 switch (cpp) { 2467 case 4: 2468 tiling_flags |= RADEON_TILING_SWAP_32BIT; 2469 break; 2470 case 2: 2471 tiling_flags |= RADEON_TILING_SWAP_16BIT; 2472 break; 2473 } 2474 if (info->ChipFamily < CHIP_FAMILY_R600 && 2475 info->r600_shadow_fb && tiling_flags) 2476 tiling_flags |= RADEON_TILING_SURFACE; 2477#endif 2478 if (tiling_flags) 2479 radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch); 2480 } 2481 2482 if (!info->r600_shadow_fb) { 2483 if (info->surf_man && !info->use_glamor) 2484 *radeon_get_pixmap_surface(ppix) = info->front_surface; 2485 screen->ModifyPixmapHeader(ppix, 2486 width, height, -1, -1, pitch, NULL); 2487 } else { 2488 if (radeon_bo_map(info->front_buffer->bo.radeon, 1)) 2489 goto fail; 2490 fb_shadow = calloc(1, pitch * scrn->virtualY); 2491 if (!fb_shadow) 2492 goto fail; 2493 free(info->fb_shadow); 2494 info->fb_shadow = fb_shadow; 2495 screen->ModifyPixmapHeader(ppix, 2496 width, height, -1, -1, pitch, 2497 info->fb_shadow); 2498 } 2499 2500 if (info->use_glamor) 2501 radeon_glamor_create_screen_resources(scrn->pScreen); 2502 2503 if (!info->r600_shadow_fb) { 2504 if (!radeon_set_pixmap_bo(ppix, info->front_buffer)) 2505 goto fail; 2506 } 2507 2508 radeon_pixmap_clear(ppix); 2509 radeon_finish(scrn, info->front_buffer); 2510 2511 for (i = 0; i < xf86_config->num_crtc; i++) { 2512 xf86CrtcPtr crtc = xf86_config->crtc[i]; 2513 2514 if (!crtc->enabled) 2515 continue; 2516 2517 drmmode_set_mode_major(crtc, &crtc->mode, 2518 crtc->rotation, crtc->x, crtc->y); 2519 } 2520 2521 radeon_buffer_unref(&old_front); 2522 2523 radeon_kms_update_vram_limit(scrn, pitch * scrn->virtualY); 2524 return TRUE; 2525 2526 fail: 2527 radeon_buffer_unref(&info->front_buffer); 2528 info->front_buffer = old_front; 2529 scrn->virtualX = old_width; 2530 scrn->virtualY = old_height; 2531 scrn->displayWidth = old_pitch; 2532 2533 return FALSE; 2534} 2535 2536static void 2537drmmode_validate_leases(ScrnInfoPtr scrn) 2538{ 2539#ifdef XF86_LEASE_VERSION 2540 ScreenPtr screen = scrn->pScreen; 2541 rrScrPrivPtr scr_priv = rrGetScrPriv(screen); 2542 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 2543 drmModeLesseeListPtr lessees; 2544 RRLeasePtr lease, next; 2545 int l; 2546 2547 /* We can't talk to the kernel about leases when VT switched */ 2548 if (!scrn->vtSema) 2549 return; 2550 2551 lessees = drmModeListLessees(pRADEONEnt->fd); 2552 if (!lessees) 2553 return; 2554 2555 xorg_list_for_each_entry_safe(lease, next, &scr_priv->leases, list) { 2556 drmmode_lease_private_ptr lease_private = lease->devPrivate; 2557 2558 for (l = 0; l < lessees->count; l++) { 2559 if (lessees->lessees[l] == lease_private->lessee_id) 2560 break; 2561 } 2562 2563 /* check to see if the lease has gone away */ 2564 if (l == lessees->count) { 2565 free(lease_private); 2566 lease->devPrivate = NULL; 2567 xf86CrtcLeaseTerminated(lease); 2568 } 2569 } 2570 2571 free(lessees); 2572#endif 2573} 2574 2575#ifdef XF86_LEASE_VERSION 2576 2577static int 2578drmmode_create_lease(RRLeasePtr lease, int *fd) 2579{ 2580 ScreenPtr screen = lease->screen; 2581 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 2582 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 2583 drmmode_lease_private_ptr lease_private; 2584 int noutput = lease->numOutputs; 2585 int ncrtc = lease->numCrtcs; 2586 uint32_t *objects; 2587 size_t nobjects; 2588 int lease_fd; 2589 int c, o; 2590 int i; 2591 2592 nobjects = ncrtc + noutput; 2593 if (nobjects == 0 || nobjects > (SIZE_MAX / 4) || 2594 ncrtc > (SIZE_MAX - noutput)) 2595 return BadValue; 2596 2597 lease_private = calloc(1, sizeof (drmmode_lease_private_rec)); 2598 if (!lease_private) 2599 return BadAlloc; 2600 2601 objects = malloc(nobjects * 4); 2602 if (!objects) { 2603 free(lease_private); 2604 return BadAlloc; 2605 } 2606 2607 i = 0; 2608 2609 /* Add CRTC ids */ 2610 for (c = 0; c < ncrtc; c++) { 2611 xf86CrtcPtr crtc = lease->crtcs[c]->devPrivate; 2612 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 2613 2614 objects[i++] = drmmode_crtc->mode_crtc->crtc_id; 2615 } 2616 2617 /* Add connector ids */ 2618 for (o = 0; o < noutput; o++) { 2619 xf86OutputPtr output = lease->outputs[o]->devPrivate; 2620 drmmode_output_private_ptr drmmode_output = output->driver_private; 2621 2622 objects[i++] = drmmode_output->mode_output->connector_id; 2623 } 2624 2625 /* call kernel to create lease */ 2626 assert (i == nobjects); 2627 2628 lease_fd = drmModeCreateLease(pRADEONEnt->fd, objects, nobjects, 0, 2629 &lease_private->lessee_id); 2630 2631 free(objects); 2632 2633 if (lease_fd < 0) { 2634 free(lease_private); 2635 return BadMatch; 2636 } 2637 2638 lease->devPrivate = lease_private; 2639 2640 xf86CrtcLeaseStarted(lease); 2641 2642 *fd = lease_fd; 2643 return Success; 2644} 2645 2646static void 2647drmmode_terminate_lease(RRLeasePtr lease) 2648{ 2649 drmmode_lease_private_ptr lease_private = lease->devPrivate; 2650 ScreenPtr screen = lease->screen; 2651 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 2652 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 2653 2654 if (drmModeRevokeLease(pRADEONEnt->fd, lease_private->lessee_id) == 0) { 2655 free(lease_private); 2656 lease->devPrivate = NULL; 2657 xf86CrtcLeaseTerminated(lease); 2658 } 2659} 2660 2661#endif // XF86_LEASE_VERSION 2662 2663static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { 2664 .resize = drmmode_xf86crtc_resize, 2665#ifdef XF86_LEASE_VERSION 2666 .create_lease = drmmode_create_lease, 2667 .terminate_lease = drmmode_terminate_lease 2668#endif 2669}; 2670 2671static void 2672drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data) 2673{ 2674 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 2675 RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); 2676 drmmode_flipdata_ptr flipdata = event_data; 2677 int crtc_id = drmmode_get_crtc_id(crtc); 2678 struct drmmode_fb **fb = &flipdata->fb[crtc_id]; 2679 2680 if (drmmode_crtc->flip_pending == *fb) { 2681 drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, 2682 NULL); 2683 } 2684 drmmode_fb_reference(pRADEONEnt->fd, fb, NULL); 2685 2686 if (--flipdata->flip_count == 0) { 2687 if (!flipdata->fe_crtc) 2688 flipdata->fe_crtc = crtc; 2689 flipdata->abort(flipdata->fe_crtc, flipdata->event_data); 2690 free(flipdata); 2691 } 2692} 2693 2694static void 2695drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *event_data) 2696{ 2697 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 2698 RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); 2699 drmmode_flipdata_ptr flipdata = event_data; 2700 int crtc_id = drmmode_get_crtc_id(crtc); 2701 struct drmmode_fb **fb = &flipdata->fb[crtc_id]; 2702 2703 /* Is this the event whose info shall be delivered to higher level? */ 2704 if (crtc == flipdata->fe_crtc) { 2705 /* Yes: Cache msc, ust for later delivery. */ 2706 flipdata->fe_frame = frame; 2707 flipdata->fe_usec = usec; 2708 } 2709 2710 if (*fb) { 2711 if (drmmode_crtc->flip_pending == *fb) { 2712 drmmode_fb_reference(pRADEONEnt->fd, 2713 &drmmode_crtc->flip_pending, NULL); 2714 } 2715 drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, *fb); 2716 drmmode_fb_reference(pRADEONEnt->fd, fb, NULL); 2717 } 2718 2719 if (--flipdata->flip_count == 0) { 2720 /* Deliver MSC & UST from reference/current CRTC to flip event 2721 * handler 2722 */ 2723 if (flipdata->fe_crtc) 2724 flipdata->handler(flipdata->fe_crtc, flipdata->fe_frame, 2725 flipdata->fe_usec, flipdata->event_data); 2726 else 2727 flipdata->handler(crtc, frame, usec, flipdata->event_data); 2728 2729 free(flipdata); 2730 } 2731} 2732 2733 2734#if HAVE_NOTIFY_FD 2735static void 2736drm_notify_fd(int fd, int ready, void *data) 2737#else 2738static void 2739drm_wakeup_handler(pointer data, int err, pointer p) 2740#endif 2741{ 2742 drmmode_ptr drmmode = data; 2743 RADEONEntPtr pRADEONEnt = RADEONEntPriv(drmmode->scrn); 2744 2745#if !HAVE_NOTIFY_FD 2746 fd_set *read_mask = p; 2747 2748 if (err >= 0 && FD_ISSET(pRADEONEnt->fd, read_mask)) 2749#endif 2750 { 2751 radeon_drm_handle_event(pRADEONEnt->fd, &drmmode->event_context); 2752 } 2753} 2754 2755static Bool drmmode_probe_page_flip_target(RADEONEntPtr pRADEONEnt) 2756{ 2757#ifdef DRM_CAP_PAGE_FLIP_TARGET 2758 uint64_t cap_value; 2759 2760 return drmGetCap(pRADEONEnt->fd, DRM_CAP_PAGE_FLIP_TARGET, 2761 &cap_value) == 0 && cap_value != 0; 2762#else 2763 return FALSE; 2764#endif 2765} 2766 2767static int 2768drmmode_page_flip(RADEONEntPtr pRADEONEnt, 2769 drmmode_crtc_private_ptr drmmode_crtc, int fb_id, 2770 uint32_t flags, uintptr_t drm_queue_seq) 2771{ 2772 flags |= DRM_MODE_PAGE_FLIP_EVENT; 2773 return drmModePageFlip(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 2774 fb_id, flags, (void*)drm_queue_seq); 2775} 2776 2777int 2778drmmode_page_flip_target_absolute(RADEONEntPtr pRADEONEnt, 2779 drmmode_crtc_private_ptr drmmode_crtc, 2780 int fb_id, uint32_t flags, 2781 uintptr_t drm_queue_seq, uint32_t target_msc) 2782{ 2783#ifdef DRM_MODE_PAGE_FLIP_TARGET 2784 if (pRADEONEnt->has_page_flip_target) { 2785 flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE; 2786 return drmModePageFlipTarget(pRADEONEnt->fd, 2787 drmmode_crtc->mode_crtc->crtc_id, 2788 fb_id, flags, (void*)drm_queue_seq, 2789 target_msc); 2790 } 2791#endif 2792 2793 return drmmode_page_flip(pRADEONEnt, drmmode_crtc, fb_id, flags, 2794 drm_queue_seq); 2795} 2796 2797int 2798drmmode_page_flip_target_relative(RADEONEntPtr pRADEONEnt, 2799 drmmode_crtc_private_ptr drmmode_crtc, 2800 int fb_id, uint32_t flags, 2801 uintptr_t drm_queue_seq, uint32_t target_msc) 2802{ 2803#ifdef DRM_MODE_PAGE_FLIP_TARGET 2804 if (pRADEONEnt->has_page_flip_target) { 2805 flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_PAGE_FLIP_TARGET_RELATIVE; 2806 return drmModePageFlipTarget(pRADEONEnt->fd, 2807 drmmode_crtc->mode_crtc->crtc_id, 2808 fb_id, flags, (void*)drm_queue_seq, 2809 target_msc); 2810 } 2811#endif 2812 2813 return drmmode_page_flip(pRADEONEnt, drmmode_crtc, fb_id, flags, 2814 drm_queue_seq); 2815} 2816 2817Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) 2818{ 2819 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2820 RADEONInfoPtr info = RADEONPTR(pScrn); 2821 int i, num_dvi = 0, num_hdmi = 0; 2822 drmModeResPtr mode_res; 2823 unsigned int crtcs_needed = 0; 2824 unsigned int crtcs_got = 0; 2825 char *bus_id_string, *provider_name; 2826 2827 xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs); 2828 2829 drmmode->scrn = pScrn; 2830 mode_res = drmModeGetResources(pRADEONEnt->fd); 2831 if (!mode_res) 2832 return FALSE; 2833 2834 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 2835 "Initializing outputs ...\n"); 2836 for (i = 0; i < mode_res->count_connectors; i++) 2837 crtcs_needed += drmmode_output_init(pScrn, drmmode, mode_res, 2838 i, &num_dvi, &num_hdmi, 0); 2839 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 2840 "%d crtcs needed for screen.\n", crtcs_needed); 2841 2842 /* Need per-screen drmmode_crtc_funcs, based on our global template, 2843 * so we can disable some functions, depending on screen settings. 2844 */ 2845 info->drmmode_crtc_funcs = drmmode_crtc_funcs; 2846 2847 if (info->r600_shadow_fb) { 2848 /* Rotation requires hardware acceleration */ 2849 info->drmmode_crtc_funcs.shadow_allocate = NULL; 2850 info->drmmode_crtc_funcs.shadow_create = NULL; 2851 info->drmmode_crtc_funcs.shadow_destroy = NULL; 2852 } 2853 2854 /* Hw gamma lut's are currently bypassed by the hw at color depth 30, 2855 * so spare the server the effort to compute and update the cluts. 2856 */ 2857 if (pScrn->depth == 30) 2858 info->drmmode_crtc_funcs.gamma_set = NULL; 2859 2860 drmmode->count_crtcs = mode_res->count_crtcs; 2861 xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width, mode_res->max_height); 2862 2863 for (i = 0; i < mode_res->count_crtcs; i++) { 2864 if (!xf86IsEntityShared(pScrn->entityList[0]) || 2865 (crtcs_got < crtcs_needed && 2866 !(pRADEONEnt->assigned_crtcs & (1 << i)))) 2867 crtcs_got += drmmode_crtc_init(pScrn, drmmode, mode_res, i); 2868 } 2869 2870 /* All ZaphodHeads outputs provided with matching crtcs? */ 2871 if (crtcs_got < crtcs_needed) { 2872 if (crtcs_got == 0) { 2873 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2874 "No ZaphodHeads CRTC available, needed %u\n", 2875 crtcs_needed); 2876 return FALSE; 2877 } 2878 2879 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2880 "%d ZaphodHeads crtcs unavailable. Some outputs will stay off.\n", 2881 crtcs_needed); 2882 } 2883 2884 /* workout clones */ 2885 drmmode_clones_init(pScrn, drmmode, mode_res); 2886 2887 bus_id_string = DRICreatePCIBusID(info->PciInfo); 2888 XNFasprintf(&provider_name, "%s @ %s", pScrn->chipset, bus_id_string); 2889 free(bus_id_string); 2890 xf86ProviderSetup(pScrn, NULL, provider_name); 2891 free(provider_name); 2892 2893 xf86InitialConfiguration(pScrn, TRUE); 2894 2895 pRADEONEnt->has_page_flip_target = drmmode_probe_page_flip_target(pRADEONEnt); 2896 2897 drmModeFreeResources(mode_res); 2898 return TRUE; 2899} 2900 2901void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode) 2902{ 2903 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2904 RADEONInfoPtr info = RADEONPTR(pScrn); 2905 2906 if (info->dri2.pKernelDRMVersion->version_minor < 4) 2907 return; 2908 2909 info->drmmode_inited = TRUE; 2910 if (pRADEONEnt->fd_wakeup_registered != serverGeneration) { 2911#if HAVE_NOTIFY_FD 2912 SetNotifyFd(pRADEONEnt->fd, drm_notify_fd, X_NOTIFY_READ, 2913 &info->drmmode); 2914#else 2915 AddGeneralSocket(pRADEONEnt->fd); 2916 RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, 2917 drm_wakeup_handler, 2918 &info->drmmode); 2919#endif 2920 pRADEONEnt->fd_wakeup_registered = serverGeneration; 2921 pRADEONEnt->fd_wakeup_ref = 1; 2922 } else 2923 pRADEONEnt->fd_wakeup_ref++; 2924} 2925 2926void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode) 2927{ 2928 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 2929 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2930 RADEONInfoPtr info = RADEONPTR(pScrn); 2931 int c; 2932 2933 if (info->dri2.pKernelDRMVersion->version_minor < 4 || !info->drmmode_inited) 2934 return; 2935 2936 for (c = 0; c < config->num_crtc; c++) 2937 drmmode_crtc_scanout_free(config->crtc[c]); 2938 2939 if (pRADEONEnt->fd_wakeup_registered == serverGeneration && 2940 !--pRADEONEnt->fd_wakeup_ref) { 2941#if HAVE_NOTIFY_FD 2942 RemoveNotifyFd(pRADEONEnt->fd); 2943#else 2944 RemoveGeneralSocket(pRADEONEnt->fd); 2945 RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, 2946 drm_wakeup_handler, pScrn); 2947#endif 2948 } 2949} 2950 2951 2952Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr) 2953{ 2954 drmmode->bufmgr = bufmgr; 2955 return TRUE; 2956} 2957 2958 2959static void drmmode_sprite_do_set_cursor(struct radeon_device_priv *device_priv, 2960 ScrnInfoPtr scrn, int x, int y) 2961{ 2962 RADEONInfoPtr info = RADEONPTR(scrn); 2963 CursorPtr cursor = device_priv->cursor; 2964 Bool sprite_visible = device_priv->sprite_visible; 2965 2966 if (cursor) { 2967 x -= cursor->bits->xhot; 2968 y -= cursor->bits->yhot; 2969 2970 device_priv->sprite_visible = 2971 x < scrn->virtualX && y < scrn->virtualY && 2972 (x + cursor->bits->width > 0) && 2973 (y + cursor->bits->height > 0); 2974 } else { 2975 device_priv->sprite_visible = FALSE; 2976 } 2977 2978 info->sprites_visible += device_priv->sprite_visible - sprite_visible; 2979} 2980 2981static void drmmode_sprite_set_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, 2982 CursorPtr pCursor, int x, int y) 2983{ 2984 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 2985 RADEONInfoPtr info = RADEONPTR(scrn); 2986 struct radeon_device_priv *device_priv = 2987 dixLookupScreenPrivate(&pDev->devPrivates, 2988 &radeon_device_private_key, pScreen); 2989 2990 device_priv->cursor = pCursor; 2991 drmmode_sprite_do_set_cursor(device_priv, scrn, x, y); 2992 2993 info->SpriteFuncs->SetCursor(pDev, pScreen, pCursor, x, y); 2994} 2995 2996static void drmmode_sprite_move_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, 2997 int x, int y) 2998{ 2999 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 3000 RADEONInfoPtr info = RADEONPTR(scrn); 3001 struct radeon_device_priv *device_priv = 3002 dixLookupScreenPrivate(&pDev->devPrivates, 3003 &radeon_device_private_key, pScreen); 3004 3005 drmmode_sprite_do_set_cursor(device_priv, scrn, x, y); 3006 3007 info->SpriteFuncs->MoveCursor(pDev, pScreen, x, y); 3008} 3009 3010static Bool drmmode_sprite_realize_realize_cursor(DeviceIntPtr pDev, 3011 ScreenPtr pScreen, 3012 CursorPtr pCursor) 3013{ 3014 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 3015 RADEONInfoPtr info = RADEONPTR(scrn); 3016 3017 return info->SpriteFuncs->RealizeCursor(pDev, pScreen, pCursor); 3018} 3019 3020static Bool drmmode_sprite_realize_unrealize_cursor(DeviceIntPtr pDev, 3021 ScreenPtr pScreen, 3022 CursorPtr pCursor) 3023{ 3024 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 3025 RADEONInfoPtr info = RADEONPTR(scrn); 3026 3027 return info->SpriteFuncs->UnrealizeCursor(pDev, pScreen, pCursor); 3028} 3029 3030static Bool drmmode_sprite_device_cursor_initialize(DeviceIntPtr pDev, 3031 ScreenPtr pScreen) 3032{ 3033 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 3034 RADEONInfoPtr info = RADEONPTR(scrn); 3035 3036 return info->SpriteFuncs->DeviceCursorInitialize(pDev, pScreen); 3037} 3038 3039static void drmmode_sprite_device_cursor_cleanup(DeviceIntPtr pDev, 3040 ScreenPtr pScreen) 3041{ 3042 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 3043 RADEONInfoPtr info = RADEONPTR(scrn); 3044 3045 info->SpriteFuncs->DeviceCursorCleanup(pDev, pScreen); 3046} 3047 3048miPointerSpriteFuncRec drmmode_sprite_funcs = { 3049 .RealizeCursor = drmmode_sprite_realize_realize_cursor, 3050 .UnrealizeCursor = drmmode_sprite_realize_unrealize_cursor, 3051 .SetCursor = drmmode_sprite_set_cursor, 3052 .MoveCursor = drmmode_sprite_move_cursor, 3053 .DeviceCursorInitialize = drmmode_sprite_device_cursor_initialize, 3054 .DeviceCursorCleanup = drmmode_sprite_device_cursor_cleanup, 3055}; 3056 3057 3058void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y) 3059{ 3060 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 3061 xf86OutputPtr output = config->output[config->compat_output]; 3062 xf86CrtcPtr crtc = output->crtc; 3063 3064 if (crtc && crtc->enabled) { 3065 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, 3066 x, y); 3067 } 3068} 3069 3070Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, 3071 Bool set_hw) 3072{ 3073 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 3074 unsigned num_desired = 0, num_on = 0; 3075 int c; 3076 3077 /* First, disable all unused CRTCs */ 3078 if (set_hw) { 3079 for (c = 0; c < config->num_crtc; c++) { 3080 xf86CrtcPtr crtc = config->crtc[c]; 3081 3082 /* Skip disabled CRTCs */ 3083 if (crtc->enabled) 3084 continue; 3085 3086 drmmode_crtc_dpms(crtc, DPMSModeOff); 3087 } 3088 } 3089 3090 /* Then, try setting the chosen mode on each CRTC */ 3091 for (c = 0; c < config->num_crtc; c++) { 3092 xf86CrtcPtr crtc = config->crtc[c]; 3093 xf86OutputPtr output = NULL; 3094 int o; 3095 3096 if (!crtc->enabled) 3097 continue; 3098 3099 if (config->output[config->compat_output]->crtc == crtc) 3100 output = config->output[config->compat_output]; 3101 else 3102 { 3103 for (o = 0; o < config->num_output; o++) 3104 if (config->output[o]->crtc == crtc) 3105 { 3106 output = config->output[o]; 3107 break; 3108 } 3109 } 3110 /* paranoia */ 3111 if (!output) 3112 continue; 3113 3114 num_desired++; 3115 3116 /* Mark that we'll need to re-set the mode for sure */ 3117 memset(&crtc->mode, 0, sizeof(crtc->mode)); 3118 if (!crtc->desiredMode.CrtcHDisplay) 3119 { 3120 DisplayModePtr mode = xf86OutputFindClosestMode (output, pScrn->currentMode); 3121 3122 if (!mode) { 3123 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3124 "Failed to find mode for CRTC %d\n", c); 3125 continue; 3126 } 3127 crtc->desiredMode = *mode; 3128 crtc->desiredRotation = RR_Rotate_0; 3129 crtc->desiredX = 0; 3130 crtc->desiredY = 0; 3131 } 3132 3133 if (set_hw) { 3134 if (crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, 3135 crtc->desiredRotation, 3136 crtc->desiredX, 3137 crtc->desiredY)) { 3138 num_on++; 3139 } else { 3140 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3141 "Failed to set mode on CRTC %d\n", c); 3142 RRCrtcSet(crtc->randr_crtc, NULL, crtc->x, crtc->y, 3143 crtc->rotation, 0, NULL); 3144 } 3145 } else { 3146 crtc->mode = crtc->desiredMode; 3147 crtc->rotation = crtc->desiredRotation; 3148 crtc->x = crtc->desiredX; 3149 crtc->y = crtc->desiredY; 3150 if (drmmode_handle_transform(crtc)) 3151 num_on++; 3152 } 3153 } 3154 3155 if (num_on == 0 && num_desired > 0) { 3156 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to enable any CRTC\n"); 3157 return FALSE; 3158 } 3159 3160 /* Validate leases on VT re-entry */ 3161 if (dixPrivateKeyRegistered(rrPrivKey)) 3162 drmmode_validate_leases(pScrn); 3163 3164 return TRUE; 3165} 3166 3167Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn) 3168{ 3169 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 3170 int i; 3171 3172 if (xf86_config->num_crtc) { 3173 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 3174 "Initializing kms color map\n"); 3175 if (!miCreateDefColormap(pScreen)) 3176 return FALSE; 3177 3178 /* All radeons support 10 bit CLUTs. They get bypassed at depth 30. */ 3179 if (pScrn->depth != 30) { 3180 if (!xf86HandleColormaps(pScreen, 256, 10, NULL, NULL, 3181 CMAP_PALETTED_TRUECOLOR 3182 | CMAP_RELOAD_ON_MODE_SWITCH)) 3183 return FALSE; 3184 3185 for (i = 0; i < xf86_config->num_crtc; i++) { 3186 xf86CrtcPtr crtc = xf86_config->crtc[i]; 3187 3188 drmmode_crtc_gamma_do_set(crtc, crtc->gamma_red, 3189 crtc->gamma_green, 3190 crtc->gamma_blue, 3191 crtc->gamma_size); 3192 } 3193 } 3194 } 3195 3196 return TRUE; 3197} 3198 3199static Bool 3200drmmode_find_output(ScrnInfoPtr scrn, int output_id, int *num_dvi, 3201 int *num_hdmi) 3202{ 3203 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 3204 int i; 3205 3206 for (i = 0; i < config->num_output; i++) { 3207 xf86OutputPtr output = config->output[i]; 3208 drmmode_output_private_ptr drmmode_output = output->driver_private; 3209 3210 if (drmmode_output->output_id == output_id) { 3211 switch(drmmode_output->mode_output->connector_type) { 3212 case DRM_MODE_CONNECTOR_DVII: 3213 case DRM_MODE_CONNECTOR_DVID: 3214 case DRM_MODE_CONNECTOR_DVIA: 3215 (*num_dvi)++; 3216 break; 3217 case DRM_MODE_CONNECTOR_HDMIA: 3218 case DRM_MODE_CONNECTOR_HDMIB: 3219 (*num_hdmi)++; 3220 break; 3221 } 3222 3223 return TRUE; 3224 } 3225 } 3226 3227 return FALSE; 3228} 3229 3230void 3231radeon_mode_hotplug(ScrnInfoPtr scrn, drmmode_ptr drmmode) 3232{ 3233 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 3234 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 3235 drmModeResPtr mode_res; 3236 int i, j; 3237 Bool found; 3238 Bool changed = FALSE; 3239 int num_dvi = 0, num_hdmi = 0; 3240 3241 /* Try to re-set the mode on all the connectors with a BAD link-state: 3242 * This may happen if a link degrades and a new modeset is necessary, using 3243 * different link-training parameters. If the kernel found that the current 3244 * mode is not achievable anymore, it should have pruned the mode before 3245 * sending the hotplug event. Try to re-set the currently-set mode to keep 3246 * the display alive, this will fail if the mode has been pruned. 3247 * In any case, we will send randr events for the Desktop Environment to 3248 * deal with it, if it wants to. 3249 */ 3250 for (i = 0; i < config->num_output; i++) { 3251 xf86OutputPtr output = config->output[i]; 3252 xf86CrtcPtr crtc = output->crtc; 3253 drmmode_output_private_ptr drmmode_output = output->driver_private; 3254 3255 drmmode_output_detect(output); 3256 3257 if (!crtc || !drmmode_output->mode_output) 3258 continue; 3259 3260 /* Get an updated view of the properties for the current connector and 3261 * look for the link-status property 3262 */ 3263 for (j = 0; j < drmmode_output->num_props; j++) { 3264 drmmode_prop_ptr p = &drmmode_output->props[j]; 3265 3266 if (!strcmp(p->mode_prop->name, "link-status")) { 3267 if (p->value != DRM_MODE_LINK_STATUS_BAD) 3268 break; 3269 3270 /* the connector got a link failure, re-set the current mode */ 3271 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, 3272 crtc->x, crtc->y); 3273 3274 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 3275 "hotplug event: connector %u's link-state is BAD, " 3276 "tried resetting the current mode. You may be left" 3277 "with a black screen if this fails...\n", 3278 drmmode_output->mode_output->connector_id); 3279 3280 break; 3281 } 3282 } 3283 } 3284 3285 mode_res = drmModeGetResources(pRADEONEnt->fd); 3286 if (!mode_res) 3287 goto out; 3288 3289restart_destroy: 3290 for (i = 0; i < config->num_output; i++) { 3291 xf86OutputPtr output = config->output[i]; 3292 drmmode_output_private_ptr drmmode_output = output->driver_private; 3293 found = FALSE; 3294 for (j = 0; j < mode_res->count_connectors; j++) { 3295 if (mode_res->connectors[j] == drmmode_output->output_id) { 3296 found = TRUE; 3297 break; 3298 } 3299 } 3300 if (found) 3301 continue; 3302 3303 drmModeFreeConnector(drmmode_output->mode_output); 3304 drmmode_output->mode_output = NULL; 3305 drmmode_output->output_id = -1; 3306 3307 changed = TRUE; 3308 if (drmmode->delete_dp_12_displays) { 3309 RROutputDestroy(output->randr_output); 3310 xf86OutputDestroy(output); 3311 goto restart_destroy; 3312 } 3313 } 3314 3315 /* find new output ids we don't have outputs for */ 3316 for (i = 0; i < mode_res->count_connectors; i++) { 3317 for (j = 0; j < pRADEONEnt->num_scrns; j++) { 3318 if (drmmode_find_output(pRADEONEnt->scrn[j], 3319 mode_res->connectors[i], 3320 &num_dvi, &num_hdmi)) 3321 break; 3322 } 3323 3324 if (j < pRADEONEnt->num_scrns) 3325 continue; 3326 3327 if (drmmode_output_init(scrn, drmmode, mode_res, i, &num_dvi, 3328 &num_hdmi, 1) != 0) 3329 changed = TRUE; 3330 } 3331 3332 /* Check to see if a lessee has disappeared */ 3333 drmmode_validate_leases(scrn); 3334 3335 if (changed) { 3336#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0) 3337 RRSetChanged(xf86ScrnToScreen(scrn)); 3338#else 3339 rrScrPrivPtr rrScrPriv = rrGetScrPriv(scrn->pScreen); 3340 rrScrPriv->changed = TRUE; 3341#endif 3342 RRTellChanged(xf86ScrnToScreen(scrn)); 3343 } 3344 3345 drmModeFreeResources(mode_res); 3346out: 3347 RRGetInfo(xf86ScrnToScreen(scrn), TRUE); 3348} 3349#ifdef HAVE_LIBUDEV 3350static void 3351drmmode_handle_uevents(int fd, void *closure) 3352{ 3353 drmmode_ptr drmmode = closure; 3354 ScrnInfoPtr scrn = drmmode->scrn; 3355 struct udev_device *dev; 3356 Bool received = FALSE; 3357 struct timeval tv = { 0, 0 }; 3358 fd_set readfd; 3359 3360 FD_ZERO(&readfd); 3361 FD_SET(fd, &readfd); 3362 3363 while (select(fd + 1, &readfd, NULL, NULL, &tv) > 0 && 3364 FD_ISSET(fd, &readfd)) { 3365 /* select() ensured that this will not block */ 3366 dev = udev_monitor_receive_device(drmmode->uevent_monitor); 3367 if (dev) { 3368 udev_device_unref(dev); 3369 received = TRUE; 3370 } 3371 } 3372 3373 if (received) 3374 radeon_mode_hotplug(scrn, drmmode); 3375} 3376#endif 3377 3378void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode) 3379{ 3380#ifdef HAVE_LIBUDEV 3381 struct udev *u; 3382 struct udev_monitor *mon; 3383 3384 u = udev_new(); 3385 if (!u) 3386 return; 3387 mon = udev_monitor_new_from_netlink(u, "udev"); 3388 if (!mon) { 3389 udev_unref(u); 3390 return; 3391 } 3392 3393 if (udev_monitor_filter_add_match_subsystem_devtype(mon, 3394 "drm", 3395 "drm_minor") < 0 || 3396 udev_monitor_enable_receiving(mon) < 0) { 3397 udev_monitor_unref(mon); 3398 udev_unref(u); 3399 return; 3400 } 3401 3402 drmmode->uevent_handler = 3403 xf86AddGeneralHandler(udev_monitor_get_fd(mon), 3404 drmmode_handle_uevents, 3405 drmmode); 3406 3407 drmmode->uevent_monitor = mon; 3408#endif 3409} 3410 3411void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode) 3412{ 3413#ifdef HAVE_LIBUDEV 3414 if (drmmode->uevent_handler) { 3415 struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor); 3416 xf86RemoveGeneralHandler(drmmode->uevent_handler); 3417 3418 udev_monitor_unref(drmmode->uevent_monitor); 3419 udev_unref(u); 3420 } 3421#endif 3422} 3423 3424Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, 3425 PixmapPtr new_front, uint64_t id, void *data, 3426 xf86CrtcPtr ref_crtc, radeon_drm_handler_proc handler, 3427 radeon_drm_abort_proc abort, 3428 enum drmmode_flip_sync flip_sync, 3429 uint32_t target_msc) 3430{ 3431 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 3432 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 3433 xf86CrtcPtr crtc = NULL; 3434 drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private; 3435 int crtc_id; 3436 uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0; 3437 drmmode_flipdata_ptr flipdata; 3438 Bool handle_deferred = FALSE; 3439 uintptr_t drm_queue_seq = 0; 3440 struct drmmode_fb *fb; 3441 int i = 0; 3442 3443 flipdata = calloc(1, sizeof(*flipdata) + drmmode_crtc->drmmode->count_crtcs * 3444 sizeof(flipdata->fb[0])); 3445 if (!flipdata) { 3446 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 3447 "flip queue: data alloc failed.\n"); 3448 goto error; 3449 } 3450 3451 fb = radeon_pixmap_get_fb(new_front); 3452 if (!fb) { 3453 ErrorF("Failed to get FB for flip\n"); 3454 goto error; 3455 } 3456 3457 /* 3458 * Queue flips on all enabled CRTCs 3459 * Note that if/when we get per-CRTC buffers, we'll have to update this. 3460 * Right now it assumes a single shared fb across all CRTCs, with the 3461 * kernel fixing up the offset of each CRTC as necessary. 3462 * 3463 * Also, flips queued on disabled or incorrectly configured displays 3464 * may never complete; this is a configuration error. 3465 */ 3466 3467 flipdata->event_data = data; 3468 flipdata->handler = handler; 3469 flipdata->abort = abort; 3470 flipdata->fe_crtc = ref_crtc; 3471 3472 for (i = 0; i < config->num_crtc; i++) { 3473 crtc = config->crtc[i]; 3474 drmmode_crtc = crtc->driver_private; 3475 crtc_id = drmmode_get_crtc_id(crtc); 3476 3477 if (!drmmode_crtc_can_flip(crtc) || 3478 (drmmode_crtc->tear_free && crtc != ref_crtc)) 3479 continue; 3480 3481 flipdata->flip_count++; 3482 3483 drm_queue_seq = radeon_drm_queue_alloc(crtc, client, id, 3484 flipdata, 3485 drmmode_flip_handler, 3486 drmmode_flip_abort, 3487 TRUE); 3488 if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { 3489 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 3490 "Allocating DRM queue event entry failed.\n"); 3491 goto error; 3492 } 3493 3494 if (drmmode_crtc->tear_free) { 3495 BoxRec extents = { .x1 = 0, .y1 = 0, 3496 .x2 = new_front->drawable.width, 3497 .y2 = new_front->drawable.height }; 3498 int scanout_id = drmmode_crtc->scanout_id ^ 1; 3499 3500 if (flip_sync == FLIP_ASYNC) { 3501 if (!drmmode_wait_vblank(crtc, 3502 DRM_VBLANK_RELATIVE | 3503 DRM_VBLANK_EVENT, 3504 0, drm_queue_seq, 3505 NULL, NULL)) 3506 goto flip_error; 3507 goto next; 3508 } 3509 3510 drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[crtc_id], 3511 radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); 3512 if (!flipdata->fb[crtc_id]) { 3513 ErrorF("Failed to get FB for TearFree flip\n"); 3514 goto error; 3515 } 3516 3517 radeon_scanout_do_update(crtc, scanout_id, new_front, 3518 extents); 3519 radeon_cs_flush_indirect(crtc->scrn); 3520 3521 if (drmmode_crtc->scanout_update_pending) { 3522 radeon_drm_wait_pending_flip(crtc); 3523 handle_deferred = TRUE; 3524 radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending); 3525 drmmode_crtc->scanout_update_pending = 0; 3526 } 3527 } else { 3528 drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[crtc_id], fb); 3529 } 3530 3531 if (crtc == ref_crtc) { 3532 if (drmmode_page_flip_target_absolute(pRADEONEnt, 3533 drmmode_crtc, 3534 flipdata->fb[crtc_id]->handle, 3535 flip_flags, 3536 drm_queue_seq, 3537 target_msc) != 0) 3538 goto flip_error; 3539 } else { 3540 if (drmmode_page_flip_target_relative(pRADEONEnt, 3541 drmmode_crtc, 3542 flipdata->fb[crtc_id]->handle, 3543 flip_flags, 3544 drm_queue_seq, 0) != 0) 3545 goto flip_error; 3546 } 3547 3548 if (drmmode_crtc->tear_free) { 3549 drmmode_crtc->scanout_id ^= 1; 3550 drmmode_crtc->ignore_damage = TRUE; 3551 } 3552 3553 drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, 3554 flipdata->fb[crtc_id]); 3555 3556 next: 3557 drm_queue_seq = 0; 3558 } 3559 3560 if (handle_deferred) 3561 radeon_drm_queue_handle_deferred(ref_crtc); 3562 if (flipdata->flip_count > 0) 3563 return TRUE; 3564 3565flip_error: 3566 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed: %s\n", 3567 strerror(errno)); 3568 3569error: 3570 if (drm_queue_seq) 3571 radeon_drm_abort_entry(drm_queue_seq); 3572 else if (crtc) 3573 drmmode_flip_abort(crtc, flipdata); 3574 else { 3575 abort(NULL, data); 3576 free(flipdata); 3577 } 3578 3579 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", 3580 strerror(errno)); 3581 if (handle_deferred) 3582 radeon_drm_queue_handle_deferred(ref_crtc); 3583 return FALSE; 3584} 3585