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