drmmode_display.c revision 861b9fee
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#ifdef XF86DRM_MODE 34#include <sys/ioctl.h> 35#include "micmap.h" 36#include "xf86cmap.h" 37#include "radeon.h" 38#include "radeon_reg.h" 39#include "radeon_drm.h" 40#include "sarea.h" 41 42#include "drmmode_display.h" 43 44/* DPMS */ 45#ifdef HAVE_XEXTPROTO_71 46#include <X11/extensions/dpmsconst.h> 47#else 48#define DPMS_SERVER 49#include <X11/extensions/dpms.h> 50#endif 51 52static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn, 53 int width, int height, 54 int depth, int bpp, 55 int pitch, int tiling, 56 struct radeon_bo *bo, struct radeon_surface *psurf) 57{ 58 RADEONInfoPtr info = RADEONPTR(pScrn); 59 ScreenPtr pScreen = pScrn->pScreen; 60 PixmapPtr pixmap; 61 struct radeon_surface *surface; 62 63 pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0); 64 if (!pixmap) 65 return NULL; 66 67 if (!(*pScreen->ModifyPixmapHeader)(pixmap, width, height, 68 depth, bpp, pitch, NULL)) { 69 return NULL; 70 } 71 72 exaMoveInPixmap(pixmap); 73 radeon_set_pixmap_bo(pixmap, bo); 74 if (info->ChipFamily >= CHIP_FAMILY_R600) { 75 surface = radeon_get_pixmap_surface(pixmap); 76 if (surface && psurf) 77 *surface = *psurf; 78 else if (surface) { 79 memset(surface, 0, sizeof(struct radeon_surface)); 80 surface->npix_x = width; 81 surface->npix_y = height; 82 surface->npix_z = 1; 83 surface->blk_w = 1; 84 surface->blk_h = 1; 85 surface->blk_d = 1; 86 surface->array_size = 1; 87 surface->last_level = 0; 88 surface->bpe = bpp / 8; 89 surface->nsamples = 1; 90 surface->flags = RADEON_SURF_SCANOUT; 91 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); 92 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); 93 if (tiling & RADEON_TILING_MICRO) { 94 surface->flags = RADEON_SURF_CLR(surface->flags, MODE); 95 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 96 } 97 if (tiling & RADEON_TILING_MACRO) { 98 surface->flags = RADEON_SURF_CLR(surface->flags, MODE); 99 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 100 } 101 if (radeon_surface_best(info->surf_man, surface)) { 102 return NULL; 103 } 104 if (radeon_surface_init(info->surf_man, surface)) { 105 return NULL; 106 } 107 } 108 } 109 110 return pixmap; 111} 112 113static void drmmode_destroy_bo_pixmap(PixmapPtr pixmap) 114{ 115 ScreenPtr pScreen = pixmap->drawable.pScreen; 116 117 (*pScreen->DestroyPixmap)(pixmap); 118} 119 120static void 121drmmode_ConvertFromKMode(ScrnInfoPtr scrn, 122 drmModeModeInfo *kmode, 123 DisplayModePtr mode) 124{ 125 memset(mode, 0, sizeof(DisplayModeRec)); 126 mode->status = MODE_OK; 127 128 mode->Clock = kmode->clock; 129 130 mode->HDisplay = kmode->hdisplay; 131 mode->HSyncStart = kmode->hsync_start; 132 mode->HSyncEnd = kmode->hsync_end; 133 mode->HTotal = kmode->htotal; 134 mode->HSkew = kmode->hskew; 135 136 mode->VDisplay = kmode->vdisplay; 137 mode->VSyncStart = kmode->vsync_start; 138 mode->VSyncEnd = kmode->vsync_end; 139 mode->VTotal = kmode->vtotal; 140 mode->VScan = kmode->vscan; 141 142 mode->Flags = kmode->flags; //& FLAG_BITS; 143 mode->name = strdup(kmode->name); 144 145 if (kmode->type & DRM_MODE_TYPE_DRIVER) 146 mode->type = M_T_DRIVER; 147 if (kmode->type & DRM_MODE_TYPE_PREFERRED) 148 mode->type |= M_T_PREFERRED; 149 xf86SetModeCrtc (mode, scrn->adjustFlags); 150} 151 152static void 153drmmode_ConvertToKMode(ScrnInfoPtr scrn, 154 drmModeModeInfo *kmode, 155 DisplayModePtr mode) 156{ 157 memset(kmode, 0, sizeof(*kmode)); 158 159 kmode->clock = mode->Clock; 160 kmode->hdisplay = mode->HDisplay; 161 kmode->hsync_start = mode->HSyncStart; 162 kmode->hsync_end = mode->HSyncEnd; 163 kmode->htotal = mode->HTotal; 164 kmode->hskew = mode->HSkew; 165 166 kmode->vdisplay = mode->VDisplay; 167 kmode->vsync_start = mode->VSyncStart; 168 kmode->vsync_end = mode->VSyncEnd; 169 kmode->vtotal = mode->VTotal; 170 kmode->vscan = mode->VScan; 171 172 kmode->flags = mode->Flags; //& FLAG_BITS; 173 if (mode->name) 174 strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN); 175 kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; 176 177} 178 179static void 180drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode) 181{ 182 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 183// drmmode_ptr drmmode = drmmode_crtc->drmmode; 184 185 drmmode_crtc->dpms_mode = mode; 186 187#if 0 188 /* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */ 189 if (mode == DPMSModeOff) { 190// drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 191// 0, 0, 0, NULL, 0, NULL); 192 } 193#endif 194} 195 196static PixmapPtr 197create_pixmap_for_fbcon(drmmode_ptr drmmode, 198 ScrnInfoPtr pScrn, int fbcon_id) 199{ 200 PixmapPtr pixmap = NULL; 201 struct radeon_bo *bo; 202 drmModeFBPtr fbcon; 203 struct drm_gem_flink flink; 204 205 fbcon = drmModeGetFB(drmmode->fd, fbcon_id); 206 if (fbcon == NULL) 207 return NULL; 208 209 if (fbcon->depth != pScrn->depth || 210 fbcon->width != pScrn->virtualX || 211 fbcon->height != pScrn->virtualY) 212 goto out_free_fb; 213 214 flink.handle = fbcon->handle; 215 if (ioctl(drmmode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) { 216 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 217 "Couldn't flink fbcon handle\n"); 218 goto out_free_fb; 219 } 220 221 bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0); 222 if (bo == NULL) { 223 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 224 "Couldn't allocate bo for fbcon handle\n"); 225 goto out_free_fb; 226 } 227 228 pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height, 229 fbcon->depth, fbcon->bpp, 230 fbcon->pitch, 0, bo, NULL); 231 radeon_bo_unref(bo); 232out_free_fb: 233 drmModeFreeFB(fbcon); 234 return pixmap; 235} 236 237void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) 238{ 239 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 240 RADEONInfoPtr info = RADEONPTR(pScrn); 241 PixmapPtr src, dst; 242 ScreenPtr pScreen = pScrn->pScreen; 243 int fbcon_id = 0; 244 int i; 245 int pitch; 246 uint32_t tiling_flags = 0; 247 Bool ret; 248 249 if (info->accelOn == FALSE) 250 goto fallback; 251 252 for (i = 0; i < xf86_config->num_crtc; i++) { 253 drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[i]->driver_private; 254 255 if (drmmode_crtc->mode_crtc->buffer_id) 256 fbcon_id = drmmode_crtc->mode_crtc->buffer_id; 257 } 258 259 if (!fbcon_id) 260 goto fallback; 261 262 src = create_pixmap_for_fbcon(drmmode, pScrn, fbcon_id); 263 if (!src) 264 goto fallback; 265 266 if (info->allowColorTiling) { 267 if (info->ChipFamily >= CHIP_FAMILY_R600) { 268 if (info->allowColorTiling2D) { 269 tiling_flags |= RADEON_TILING_MACRO; 270 } else { 271 tiling_flags |= RADEON_TILING_MICRO; 272 } 273 } else 274 tiling_flags |= RADEON_TILING_MACRO; 275 } 276 277 pitch = RADEON_ALIGN(pScrn->displayWidth, 278 drmmode_get_pitch_align(pScrn, info->CurrentLayout.pixel_bytes, tiling_flags)) * 279 info->CurrentLayout.pixel_bytes; 280 281 dst = drmmode_create_bo_pixmap(pScrn, pScrn->virtualX, 282 pScrn->virtualY, pScrn->depth, 283 pScrn->bitsPerPixel, pitch, 284 tiling_flags, info->front_bo, &info->front_surface); 285 if (!dst) 286 goto out_free_src; 287 288 ret = info->accel_state->exa->PrepareCopy (src, dst, 289 -1, -1, GXcopy, FB_ALLONES); 290 if (!ret) 291 goto out_free_src; 292 info->accel_state->exa->Copy (dst, 0, 0, 0, 0, 293 pScrn->virtualX, pScrn->virtualY); 294 info->accel_state->exa->DoneCopy (dst); 295 radeon_cs_flush_indirect(pScrn); 296 297#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10 298 pScreen->canDoBGNoneRoot = TRUE; 299#endif 300 drmmode_destroy_bo_pixmap(dst); 301 out_free_src: 302 drmmode_destroy_bo_pixmap(src); 303 return; 304 305fallback: 306 /* map and memset the bo */ 307 if (radeon_bo_map(info->front_bo, 1)) 308 return; 309 310 memset(info->front_bo->ptr, 0x00, info->front_bo->size); 311 radeon_bo_unmap(info->front_bo); 312} 313 314static Bool 315drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, 316 Rotation rotation, int x, int y) 317{ 318 ScrnInfoPtr pScrn = crtc->scrn; 319 RADEONInfoPtr info = RADEONPTR(pScrn); 320 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 321 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 322 drmmode_ptr drmmode = drmmode_crtc->drmmode; 323 int saved_x, saved_y; 324 Rotation saved_rotation; 325 DisplayModeRec saved_mode; 326 uint32_t *output_ids; 327 int output_count = 0; 328 Bool ret = TRUE; 329 int i; 330 int fb_id; 331 drmModeModeInfo kmode; 332 int pitch; 333 uint32_t tiling_flags = 0; 334 int height; 335 336 if (info->allowColorTiling) { 337 if (info->ChipFamily >= CHIP_FAMILY_R600) 338 tiling_flags |= RADEON_TILING_MICRO; 339 else 340 tiling_flags |= RADEON_TILING_MACRO; 341 } 342 343 pitch = RADEON_ALIGN(pScrn->displayWidth, drmmode_get_pitch_align(pScrn, info->CurrentLayout.pixel_bytes, tiling_flags)) * 344 info->CurrentLayout.pixel_bytes; 345 height = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags)); 346 if (info->ChipFamily >= CHIP_FAMILY_R600) { 347 pitch = info->front_surface.level[0].pitch_bytes; 348 } 349 350 if (drmmode->fb_id == 0) { 351 ret = drmModeAddFB(drmmode->fd, 352 pScrn->virtualX, height, 353 pScrn->depth, pScrn->bitsPerPixel, 354 pitch, 355 info->front_bo->handle, 356 &drmmode->fb_id); 357 if (ret < 0) { 358 ErrorF("failed to add fb\n"); 359 return FALSE; 360 } 361 } 362 363 saved_mode = crtc->mode; 364 saved_x = crtc->x; 365 saved_y = crtc->y; 366 saved_rotation = crtc->rotation; 367 368 if (mode) { 369 crtc->mode = *mode; 370 crtc->x = x; 371 crtc->y = y; 372 crtc->rotation = rotation; 373#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,5,99,0,0) 374 crtc->transformPresent = FALSE; 375#endif 376 } 377 378 output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); 379 if (!output_ids) { 380 ret = FALSE; 381 goto done; 382 } 383 384 if (mode) { 385 for (i = 0; i < xf86_config->num_output; i++) { 386 xf86OutputPtr output = xf86_config->output[i]; 387 drmmode_output_private_ptr drmmode_output; 388 389 if (output->crtc != crtc) 390 continue; 391 392 drmmode_output = output->driver_private; 393 output_ids[output_count] = drmmode_output->mode_output->connector_id; 394 output_count++; 395 } 396 397 if (!xf86CrtcRotate(crtc)) { 398 goto done; 399 } 400#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0) 401 crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, 402 crtc->gamma_blue, crtc->gamma_size); 403#endif 404 405 drmmode_ConvertToKMode(crtc->scrn, &kmode, mode); 406 407 fb_id = drmmode->fb_id; 408 if (drmmode_crtc->rotate_fb_id) { 409 fb_id = drmmode_crtc->rotate_fb_id; 410 x = y = 0; 411 } 412 ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 413 fb_id, x, y, output_ids, output_count, &kmode); 414 if (ret) 415 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, 416 "failed to set mode: %s", strerror(-ret)); 417 else 418 ret = TRUE; 419 420 if (crtc->scrn->pScreen) 421 xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen); 422 /* go through all the outputs and force DPMS them back on? */ 423 for (i = 0; i < xf86_config->num_output; i++) { 424 xf86OutputPtr output = xf86_config->output[i]; 425 426 if (output->crtc != crtc) 427 continue; 428 429 output->funcs->dpms(output, DPMSModeOn); 430 } 431 } 432 433 if (pScrn->pScreen && 434 !xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) 435#ifdef HAVE_XF86_CURSOR_RESET_CURSOR 436 xf86CursorResetCursor(pScrn->pScreen); 437#else 438 xf86_reload_cursors(pScrn->pScreen); 439#endif 440 441done: 442 if (!ret) { 443 crtc->x = saved_x; 444 crtc->y = saved_y; 445 crtc->rotation = saved_rotation; 446 crtc->mode = saved_mode; 447 } 448#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3 449 else 450 crtc->active = TRUE; 451#endif 452 453 return ret; 454} 455 456static void 457drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg) 458{ 459 460} 461 462static void 463drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) 464{ 465 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 466 drmmode_ptr drmmode = drmmode_crtc->drmmode; 467 468 drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); 469} 470 471static void 472drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) 473{ 474 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 475 int i; 476 uint32_t *ptr; 477 478 /* cursor should be mapped already */ 479 ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr); 480 481 for (i = 0; i < 64 * 64; i++) 482 ptr[i] = cpu_to_le32(image[i]); 483} 484 485 486static void 487drmmode_hide_cursor (xf86CrtcPtr crtc) 488{ 489 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 490 drmmode_ptr drmmode = drmmode_crtc->drmmode; 491 492 drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 64, 64); 493 494} 495 496static void 497drmmode_show_cursor (xf86CrtcPtr crtc) 498{ 499 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 500 drmmode_ptr drmmode = drmmode_crtc->drmmode; 501 uint32_t handle = drmmode_crtc->cursor_bo->handle; 502 503 drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64); 504} 505 506static void * 507drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) 508{ 509 ScrnInfoPtr pScrn = crtc->scrn; 510 RADEONInfoPtr info = RADEONPTR(pScrn); 511 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 512 drmmode_ptr drmmode = drmmode_crtc->drmmode; 513 int size; 514 struct radeon_bo *rotate_bo; 515 int ret; 516 unsigned long rotate_pitch; 517 int base_align; 518 519 /* rotation requires acceleration */ 520 if (info->r600_shadow_fb) { 521 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 522 "Rotation requires acceleration!\n"); 523 return NULL; 524 } 525 526 rotate_pitch = 527 RADEON_ALIGN(width, drmmode_get_pitch_align(crtc->scrn, drmmode->cpp, 0)) * drmmode->cpp; 528 height = RADEON_ALIGN(height, drmmode_get_height_align(crtc->scrn, 0)); 529 base_align = drmmode_get_base_align(crtc->scrn, drmmode->cpp, 0); 530 size = RADEON_ALIGN(rotate_pitch * height, RADEON_GPU_PAGE_SIZE); 531 532 rotate_bo = radeon_bo_open(drmmode->bufmgr, 0, size, base_align, RADEON_GEM_DOMAIN_VRAM, 0); 533 if (rotate_bo == NULL) 534 return NULL; 535 536 radeon_bo_map(rotate_bo, 1); 537 538 ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth, 539 crtc->scrn->bitsPerPixel, rotate_pitch, 540 rotate_bo->handle, 541 &drmmode_crtc->rotate_fb_id); 542 if (ret) { 543 ErrorF("failed to add rotate fb\n"); 544 } 545 546 drmmode_crtc->rotate_bo = rotate_bo; 547 return drmmode_crtc->rotate_bo->ptr; 548} 549 550static PixmapPtr 551drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) 552{ 553 ScrnInfoPtr pScrn = crtc->scrn; 554 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 555 drmmode_ptr drmmode = drmmode_crtc->drmmode; 556 unsigned long rotate_pitch; 557 PixmapPtr rotate_pixmap; 558 559 if (!data) 560 data = drmmode_crtc_shadow_allocate (crtc, width, height); 561 562 rotate_pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0)) * drmmode->cpp; 563 564 rotate_pixmap = drmmode_create_bo_pixmap(pScrn, 565 width, height, 566 pScrn->depth, 567 pScrn->bitsPerPixel, 568 rotate_pitch, 569 0, drmmode_crtc->rotate_bo, NULL); 570 if (rotate_pixmap == NULL) { 571 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 572 "Couldn't allocate shadow pixmap for rotated CRTC\n"); 573 } 574 return rotate_pixmap; 575 576} 577 578static void 579drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) 580{ 581 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 582 drmmode_ptr drmmode = drmmode_crtc->drmmode; 583 584 if (rotate_pixmap) 585 drmmode_destroy_bo_pixmap(rotate_pixmap); 586 587 if (data) { 588 drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id); 589 drmmode_crtc->rotate_fb_id = 0; 590 radeon_bo_unmap(drmmode_crtc->rotate_bo); 591 radeon_bo_unref(drmmode_crtc->rotate_bo); 592 drmmode_crtc->rotate_bo = NULL; 593 } 594 595} 596 597static void 598drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green, 599 uint16_t *blue, int size) 600{ 601 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 602 drmmode_ptr drmmode = drmmode_crtc->drmmode; 603 604 drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 605 size, red, green, blue); 606} 607 608static const xf86CrtcFuncsRec drmmode_crtc_funcs = { 609 .dpms = drmmode_crtc_dpms, 610 .set_mode_major = drmmode_set_mode_major, 611 .set_cursor_colors = drmmode_set_cursor_colors, 612 .set_cursor_position = drmmode_set_cursor_position, 613 .show_cursor = drmmode_show_cursor, 614 .hide_cursor = drmmode_hide_cursor, 615 .load_cursor_argb = drmmode_load_cursor_argb, 616 617 .gamma_set = drmmode_crtc_gamma_set, 618 .shadow_create = drmmode_crtc_shadow_create, 619 .shadow_allocate = drmmode_crtc_shadow_allocate, 620 .shadow_destroy = drmmode_crtc_shadow_destroy, 621 .destroy = NULL, /* XXX */ 622}; 623 624int drmmode_get_crtc_id(xf86CrtcPtr crtc) 625{ 626 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 627 return drmmode_crtc->hw_id; 628} 629 630void drmmode_crtc_hw_id(xf86CrtcPtr crtc) 631{ 632 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 633 ScrnInfoPtr pScrn = crtc->scrn; 634 RADEONInfoPtr info = RADEONPTR(pScrn); 635 struct drm_radeon_info ginfo; 636 int r; 637 uint32_t tmp; 638 639 memset(&ginfo, 0, sizeof(ginfo)); 640 ginfo.request = 0x4; 641 tmp = drmmode_crtc->mode_crtc->crtc_id; 642 ginfo.value = (uintptr_t)&tmp; 643 r = drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); 644 if (r) { 645 drmmode_crtc->hw_id = -1; 646 return; 647 } 648 drmmode_crtc->hw_id = tmp; 649} 650 651static void 652drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) 653{ 654 xf86CrtcPtr crtc; 655 drmmode_crtc_private_ptr drmmode_crtc; 656 657 crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs); 658 if (crtc == NULL) 659 return; 660 661 drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); 662 drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]); 663 drmmode_crtc->drmmode = drmmode; 664 crtc->driver_private = drmmode_crtc; 665 drmmode_crtc_hw_id(crtc); 666 667 return; 668} 669 670static xf86OutputStatus 671drmmode_output_detect(xf86OutputPtr output) 672{ 673 /* go to the hw and retrieve a new output struct */ 674 drmmode_output_private_ptr drmmode_output = output->driver_private; 675 drmmode_ptr drmmode = drmmode_output->drmmode; 676 xf86OutputStatus status; 677 drmModeFreeConnector(drmmode_output->mode_output); 678 679 drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id); 680 681 switch (drmmode_output->mode_output->connection) { 682 case DRM_MODE_CONNECTED: 683 status = XF86OutputStatusConnected; 684 break; 685 case DRM_MODE_DISCONNECTED: 686 status = XF86OutputStatusDisconnected; 687 break; 688 default: 689 case DRM_MODE_UNKNOWNCONNECTION: 690 status = XF86OutputStatusUnknown; 691 break; 692 } 693 return status; 694} 695 696static Bool 697drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) 698{ 699 return MODE_OK; 700} 701 702static DisplayModePtr 703drmmode_output_get_modes(xf86OutputPtr output) 704{ 705 drmmode_output_private_ptr drmmode_output = output->driver_private; 706 drmModeConnectorPtr koutput = drmmode_output->mode_output; 707 drmmode_ptr drmmode = drmmode_output->drmmode; 708 int i; 709 DisplayModePtr Modes = NULL, Mode; 710 drmModePropertyPtr props; 711 xf86MonPtr mon = NULL; 712 713 /* look for an EDID property */ 714 for (i = 0; i < koutput->count_props; i++) { 715 props = drmModeGetProperty(drmmode->fd, koutput->props[i]); 716 if (props && (props->flags & DRM_MODE_PROP_BLOB)) { 717 if (!strcmp(props->name, "EDID")) { 718 if (drmmode_output->edid_blob) 719 drmModeFreePropertyBlob(drmmode_output->edid_blob); 720 drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]); 721 } 722 drmModeFreeProperty(props); 723 } 724 } 725 726 if (drmmode_output->edid_blob) { 727 mon = xf86InterpretEDID(output->scrn->scrnIndex, 728 drmmode_output->edid_blob->data); 729 if (mon && drmmode_output->edid_blob->length > 128) 730 mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA; 731 } 732 xf86OutputSetEDID(output, mon); 733 734 /* modes should already be available */ 735 for (i = 0; i < koutput->count_modes; i++) { 736 Mode = xnfalloc(sizeof(DisplayModeRec)); 737 738 drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode); 739 Modes = xf86ModesAdd(Modes, Mode); 740 741 } 742 return Modes; 743} 744 745static void 746drmmode_output_destroy(xf86OutputPtr output) 747{ 748 drmmode_output_private_ptr drmmode_output = output->driver_private; 749 int i; 750 751 if (drmmode_output->edid_blob) 752 drmModeFreePropertyBlob(drmmode_output->edid_blob); 753 for (i = 0; i < drmmode_output->num_props; i++) { 754 drmModeFreeProperty(drmmode_output->props[i].mode_prop); 755 free(drmmode_output->props[i].atoms); 756 } 757 for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) { 758 drmModeFreeEncoder(drmmode_output->mode_encoders[i]); 759 free(drmmode_output->mode_encoders); 760 } 761 free(drmmode_output->props); 762 drmModeFreeConnector(drmmode_output->mode_output); 763 free(drmmode_output); 764 output->driver_private = NULL; 765} 766 767static void 768drmmode_output_dpms(xf86OutputPtr output, int mode) 769{ 770 drmmode_output_private_ptr drmmode_output = output->driver_private; 771 drmModeConnectorPtr koutput = drmmode_output->mode_output; 772 drmmode_ptr drmmode = drmmode_output->drmmode; 773 774 drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id, 775 drmmode_output->dpms_enum_id, mode); 776 return; 777} 778 779 780static Bool 781drmmode_property_ignore(drmModePropertyPtr prop) 782{ 783 if (!prop) 784 return TRUE; 785 /* ignore blob prop */ 786 if (prop->flags & DRM_MODE_PROP_BLOB) 787 return TRUE; 788 /* ignore standard property */ 789 if (!strcmp(prop->name, "EDID") || 790 !strcmp(prop->name, "DPMS")) 791 return TRUE; 792 793 return FALSE; 794} 795 796static void 797drmmode_output_create_resources(xf86OutputPtr output) 798{ 799 drmmode_output_private_ptr drmmode_output = output->driver_private; 800 drmModeConnectorPtr mode_output = drmmode_output->mode_output; 801 drmmode_ptr drmmode = drmmode_output->drmmode; 802 drmModePropertyPtr drmmode_prop; 803 int i, j, err; 804 805 drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec)); 806 if (!drmmode_output->props) 807 return; 808 809 drmmode_output->num_props = 0; 810 for (i = 0, j = 0; i < mode_output->count_props; i++) { 811 drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]); 812 if (drmmode_property_ignore(drmmode_prop)) { 813 drmModeFreeProperty(drmmode_prop); 814 continue; 815 } 816 drmmode_output->props[j].mode_prop = drmmode_prop; 817 drmmode_output->props[j].value = mode_output->prop_values[i]; 818 drmmode_output->num_props++; 819 j++; 820 } 821 822 for (i = 0; i < drmmode_output->num_props; i++) { 823 drmmode_prop_ptr p = &drmmode_output->props[i]; 824 drmmode_prop = p->mode_prop; 825 826 if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) { 827 INT32 range[2]; 828 INT32 value = p->value; 829 830 p->num_atoms = 1; 831 p->atoms = calloc(p->num_atoms, sizeof(Atom)); 832 if (!p->atoms) 833 continue; 834 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); 835 range[0] = drmmode_prop->values[0]; 836 range[1] = drmmode_prop->values[1]; 837 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], 838 FALSE, TRUE, 839 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, 840 2, range); 841 if (err != 0) { 842 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 843 "RRConfigureOutputProperty error, %d\n", err); 844 } 845 err = RRChangeOutputProperty(output->randr_output, p->atoms[0], 846 XA_INTEGER, 32, PropModeReplace, 1, &value, FALSE, TRUE); 847 if (err != 0) { 848 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 849 "RRChangeOutputProperty error, %d\n", err); 850 } 851 } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) { 852 p->num_atoms = drmmode_prop->count_enums + 1; 853 p->atoms = calloc(p->num_atoms, sizeof(Atom)); 854 if (!p->atoms) 855 continue; 856 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); 857 for (j = 1; j <= drmmode_prop->count_enums; j++) { 858 struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1]; 859 p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE); 860 } 861 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], 862 FALSE, FALSE, 863 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, 864 p->num_atoms - 1, (INT32 *)&p->atoms[1]); 865 if (err != 0) { 866 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 867 "RRConfigureOutputProperty error, %d\n", err); 868 } 869 for (j = 0; j < drmmode_prop->count_enums; j++) 870 if (drmmode_prop->enums[j].value == p->value) 871 break; 872 /* there's always a matching value */ 873 err = RRChangeOutputProperty(output->randr_output, p->atoms[0], 874 XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE); 875 if (err != 0) { 876 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 877 "RRChangeOutputProperty error, %d\n", err); 878 } 879 } 880 } 881} 882 883static Bool 884drmmode_output_set_property(xf86OutputPtr output, Atom property, 885 RRPropertyValuePtr value) 886{ 887 drmmode_output_private_ptr drmmode_output = output->driver_private; 888 drmmode_ptr drmmode = drmmode_output->drmmode; 889 int i; 890 891 for (i = 0; i < drmmode_output->num_props; i++) { 892 drmmode_prop_ptr p = &drmmode_output->props[i]; 893 894 if (p->atoms[0] != property) 895 continue; 896 897 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) { 898 uint32_t val; 899 900 if (value->type != XA_INTEGER || value->format != 32 || 901 value->size != 1) 902 return FALSE; 903 val = *(uint32_t *)value->data; 904 905 drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, 906 p->mode_prop->prop_id, (uint64_t)val); 907 return TRUE; 908 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { 909 Atom atom; 910 const char *name; 911 int j; 912 913 if (value->type != XA_ATOM || value->format != 32 || value->size != 1) 914 return FALSE; 915 memcpy(&atom, value->data, 4); 916 name = NameForAtom(atom); 917 918 /* search for matching name string, then set its value down */ 919 for (j = 0; j < p->mode_prop->count_enums; j++) { 920 if (!strcmp(p->mode_prop->enums[j].name, name)) { 921 drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, 922 p->mode_prop->prop_id, p->mode_prop->enums[j].value); 923 return TRUE; 924 } 925 } 926 } 927 } 928 929 return TRUE; 930} 931 932static Bool 933drmmode_output_get_property(xf86OutputPtr output, Atom property) 934{ 935 return TRUE; 936} 937 938static const xf86OutputFuncsRec drmmode_output_funcs = { 939 .dpms = drmmode_output_dpms, 940 .create_resources = drmmode_output_create_resources, 941#ifdef RANDR_12_INTERFACE 942 .set_property = drmmode_output_set_property, 943 .get_property = drmmode_output_get_property, 944#endif 945#if 0 946 947 .save = drmmode_crt_save, 948 .restore = drmmode_crt_restore, 949 .mode_fixup = drmmode_crt_mode_fixup, 950 .prepare = drmmode_output_prepare, 951 .mode_set = drmmode_crt_mode_set, 952 .commit = drmmode_output_commit, 953#endif 954 .detect = drmmode_output_detect, 955 .mode_valid = drmmode_output_mode_valid, 956 957 .get_modes = drmmode_output_get_modes, 958 .destroy = drmmode_output_destroy 959}; 960 961static int subpixel_conv_table[7] = { 0, SubPixelUnknown, 962 SubPixelHorizontalRGB, 963 SubPixelHorizontalBGR, 964 SubPixelVerticalRGB, 965 SubPixelVerticalBGR, 966 SubPixelNone }; 967 968const char *output_names[] = { "None", 969 "VGA", 970 "DVI", 971 "DVI", 972 "DVI", 973 "Composite", 974 "S-video", 975 "LVDS", 976 "CTV", 977 "DIN", 978 "DisplayPort", 979 "HDMI", 980 "HDMI", 981 "TV", 982 "eDP" 983}; 984 985static void 986drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dvi, int *num_hdmi) 987{ 988 RADEONInfoPtr info = RADEONPTR(pScrn); 989 xf86OutputPtr output; 990 drmModeConnectorPtr koutput; 991 drmModeEncoderPtr *kencoders = NULL; 992 drmmode_output_private_ptr drmmode_output; 993 drmModePropertyPtr props; 994 char name[32]; 995 int i; 996 const char *s; 997 998 koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]); 999 if (!koutput) 1000 return; 1001 1002 kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders); 1003 if (!kencoders) { 1004 goto out_free_encoders; 1005 } 1006 1007 for (i = 0; i < koutput->count_encoders; i++) { 1008 kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]); 1009 if (!kencoders[i]) { 1010 goto out_free_encoders; 1011 } 1012 } 1013 1014 /* need to do smart conversion here for compat with non-kms ATI driver */ 1015 if (koutput->connector_type_id == 1) { 1016 switch(koutput->connector_type) { 1017 case DRM_MODE_CONNECTOR_DVII: 1018 case DRM_MODE_CONNECTOR_DVID: 1019 case DRM_MODE_CONNECTOR_DVIA: 1020 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_dvi); 1021 (*num_dvi)++; 1022 break; 1023 case DRM_MODE_CONNECTOR_HDMIA: 1024 case DRM_MODE_CONNECTOR_HDMIB: 1025 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_hdmi); 1026 (*num_hdmi)++; 1027 break; 1028 case DRM_MODE_CONNECTOR_VGA: 1029 case DRM_MODE_CONNECTOR_DisplayPort: 1030 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1); 1031 break; 1032 default: 1033 snprintf(name, 32, "%s", output_names[koutput->connector_type]); 1034 break; 1035 } 1036 } else { 1037 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1); 1038 } 1039 1040 if (xf86IsEntityShared(pScrn->entityList[0])) { 1041 if ((s = xf86GetOptValString(info->Options, OPTION_ZAPHOD_HEADS))) { 1042 if (!RADEONZaphodStringMatches(pScrn, s, name)) 1043 goto out_free_encoders; 1044 } else { 1045 if (info->IsPrimary && (num != 0)) 1046 goto out_free_encoders; 1047 else if (info->IsSecondary && (num != 1)) 1048 goto out_free_encoders; 1049 } 1050 } 1051 1052 output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name); 1053 if (!output) { 1054 goto out_free_encoders; 1055 } 1056 1057 drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1); 1058 if (!drmmode_output) { 1059 xf86OutputDestroy(output); 1060 goto out_free_encoders; 1061 } 1062 1063 drmmode_output->output_id = drmmode->mode_res->connectors[num]; 1064 drmmode_output->mode_output = koutput; 1065 drmmode_output->mode_encoders = kencoders; 1066 drmmode_output->drmmode = drmmode; 1067 output->mm_width = koutput->mmWidth; 1068 output->mm_height = koutput->mmHeight; 1069 1070 output->subpixel_order = subpixel_conv_table[koutput->subpixel]; 1071 output->interlaceAllowed = TRUE; 1072 output->doubleScanAllowed = TRUE; 1073 output->driver_private = drmmode_output; 1074 1075 output->possible_crtcs = 0xffffffff; 1076 for (i = 0; i < koutput->count_encoders; i++) { 1077 output->possible_crtcs &= kencoders[i]->possible_crtcs; 1078 } 1079 /* work out the possible clones later */ 1080 output->possible_clones = 0; 1081 1082 for (i = 0; i < koutput->count_props; i++) { 1083 props = drmModeGetProperty(drmmode->fd, koutput->props[i]); 1084 if (props && (props->flags & DRM_MODE_PROP_ENUM)) { 1085 if (!strcmp(props->name, "DPMS")) { 1086 drmmode_output->dpms_enum_id = koutput->props[i]; 1087 drmModeFreeProperty(props); 1088 break; 1089 } 1090 drmModeFreeProperty(props); 1091 } 1092 } 1093 1094 return; 1095out_free_encoders: 1096 if (kencoders){ 1097 for (i = 0; i < koutput->count_encoders; i++) 1098 drmModeFreeEncoder(kencoders[i]); 1099 free(kencoders); 1100 } 1101 drmModeFreeConnector(koutput); 1102 1103} 1104 1105uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output) 1106{ 1107 drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout; 1108 int i; 1109 xf86OutputPtr clone_output; 1110 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1111 int index_mask = 0; 1112 1113 if (drmmode_output->enc_clone_mask == 0) 1114 return index_mask; 1115 1116 for (i = 0; i < xf86_config->num_output; i++) { 1117 clone_output = xf86_config->output[i]; 1118 clone_drmout = clone_output->driver_private; 1119 if (output == clone_output) 1120 continue; 1121 1122 if (clone_drmout->enc_mask == 0) 1123 continue; 1124 if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask) 1125 index_mask |= (1 << i); 1126 } 1127 return index_mask; 1128} 1129 1130 1131static void 1132drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode) 1133{ 1134 int i, j; 1135 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1136 1137 for (i = 0; i < xf86_config->num_output; i++) { 1138 xf86OutputPtr output = xf86_config->output[i]; 1139 drmmode_output_private_ptr drmmode_output; 1140 1141 drmmode_output = output->driver_private; 1142 drmmode_output->enc_clone_mask = 0xff; 1143 /* and all the possible encoder clones for this output together */ 1144 for (j = 0; j < drmmode_output->mode_output->count_encoders; j++) 1145 { 1146 int k; 1147 for (k = 0; k < drmmode->mode_res->count_encoders; k++) { 1148 if (drmmode->mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id) 1149 drmmode_output->enc_mask |= (1 << k); 1150 } 1151 1152 drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones; 1153 } 1154 } 1155 1156 for (i = 0; i < xf86_config->num_output; i++) { 1157 xf86OutputPtr output = xf86_config->output[i]; 1158 output->possible_clones = find_clones(scrn, output); 1159 } 1160} 1161 1162/* returns height alignment in pixels */ 1163int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling) 1164{ 1165 RADEONInfoPtr info = RADEONPTR(scrn); 1166 int height_align = 1; 1167 1168 if (info->ChipFamily >= CHIP_FAMILY_R600) { 1169 if (tiling & RADEON_TILING_MACRO) 1170 height_align = info->num_channels * 8; 1171 else if (tiling & RADEON_TILING_MICRO) 1172 height_align = 8; 1173 else 1174 height_align = 8; 1175 } else { 1176 if (tiling) 1177 height_align = 16; 1178 else 1179 height_align = 1; 1180 } 1181 return height_align; 1182} 1183 1184/* returns pitch alignment in pixels */ 1185int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling) 1186{ 1187 RADEONInfoPtr info = RADEONPTR(scrn); 1188 int pitch_align = 1; 1189 1190 if (info->ChipFamily >= CHIP_FAMILY_R600) { 1191 if (tiling & RADEON_TILING_MACRO) { 1192 /* general surface requirements */ 1193 pitch_align = MAX(info->num_banks, 1194 (((info->group_bytes / 8) / bpe) * info->num_banks)) * 8; 1195 /* further restrictions for scanout */ 1196 pitch_align = MAX(info->num_banks * 8, pitch_align); 1197 } else if (tiling & RADEON_TILING_MICRO) { 1198 /* general surface requirements */ 1199 pitch_align = MAX(8, (info->group_bytes / (8 * bpe))); 1200 /* further restrictions for scanout */ 1201 pitch_align = MAX(info->group_bytes / bpe, pitch_align); 1202 } else { 1203 if (info->have_tiling_info) 1204 /* linear aligned requirements */ 1205 pitch_align = MAX(64, info->group_bytes / bpe); 1206 else 1207 /* default to 512 elements if we don't know the real 1208 * group size otherwise the kernel may reject the CS 1209 * if the group sizes don't match as the pitch won't 1210 * be aligned properly. 1211 */ 1212 pitch_align = 512; 1213 } 1214 } else { 1215 /* general surface requirements */ 1216 if (tiling) 1217 pitch_align = 256 / bpe; 1218 else 1219 pitch_align = 64; 1220 } 1221 return pitch_align; 1222} 1223 1224/* returns base alignment in bytes */ 1225int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling) 1226{ 1227 RADEONInfoPtr info = RADEONPTR(scrn); 1228 int pixel_align = drmmode_get_pitch_align(scrn, bpe, tiling); 1229 int height_align = drmmode_get_height_align(scrn, tiling); 1230 int base_align = RADEON_GPU_PAGE_SIZE; 1231 1232 if (info->ChipFamily >= CHIP_FAMILY_R600) { 1233 if (tiling & RADEON_TILING_MACRO) 1234 base_align = MAX(info->num_banks * info->num_channels * 8 * 8 * bpe, 1235 pixel_align * bpe * height_align); 1236 else { 1237 if (info->have_tiling_info) 1238 base_align = info->group_bytes; 1239 else 1240 /* default to 512 if we don't know the real 1241 * group size otherwise the kernel may reject the CS 1242 * if the group sizes don't match as the base won't 1243 * be aligned properly. 1244 */ 1245 base_align = 512; 1246 } 1247 } 1248 return base_align; 1249} 1250 1251static Bool 1252drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) 1253{ 1254 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1255 drmmode_crtc_private_ptr 1256 drmmode_crtc = xf86_config->crtc[0]->driver_private; 1257 drmmode_ptr drmmode = drmmode_crtc->drmmode; 1258 RADEONInfoPtr info = RADEONPTR(scrn); 1259 struct radeon_bo *old_front = NULL; 1260 Bool ret; 1261 ScreenPtr screen = xf86ScrnToScreen(scrn); 1262 uint32_t old_fb_id; 1263 int i, pitch, old_width, old_height, old_pitch; 1264 int screen_size; 1265 int cpp = info->CurrentLayout.pixel_bytes; 1266 struct radeon_bo *front_bo; 1267 struct radeon_surface surface; 1268 struct radeon_surface *psurface; 1269 uint32_t tiling_flags = 0, base_align; 1270 PixmapPtr ppix = screen->GetScreenPixmap(screen); 1271 void *fb_shadow; 1272 1273 if (scrn->virtualX == width && scrn->virtualY == height) 1274 return TRUE; 1275 1276 front_bo = info->front_bo; 1277 radeon_cs_flush_indirect(scrn); 1278 1279 if (front_bo) 1280 radeon_bo_wait(front_bo); 1281 1282 if (info->allowColorTiling) { 1283 if (info->ChipFamily >= CHIP_FAMILY_R600) { 1284 if (info->allowColorTiling2D) { 1285 tiling_flags |= RADEON_TILING_MACRO; 1286 } else { 1287 tiling_flags |= RADEON_TILING_MICRO; 1288 } 1289 } else 1290 tiling_flags |= RADEON_TILING_MACRO; 1291 } 1292 1293 pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp; 1294 height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags)); 1295 screen_size = RADEON_ALIGN(pitch * height, RADEON_GPU_PAGE_SIZE); 1296 base_align = 4096; 1297 if (info->ChipFamily >= CHIP_FAMILY_R600) { 1298 memset(&surface, 0, sizeof(struct radeon_surface)); 1299 surface.npix_x = width; 1300 surface.npix_y = height; 1301 surface.npix_z = 1; 1302 surface.blk_w = 1; 1303 surface.blk_h = 1; 1304 surface.blk_d = 1; 1305 surface.array_size = 1; 1306 surface.last_level = 0; 1307 surface.bpe = cpp; 1308 surface.nsamples = 1; 1309 surface.flags = RADEON_SURF_SCANOUT; 1310 surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); 1311 surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); 1312 if (tiling_flags & RADEON_TILING_MICRO) { 1313 surface.flags = RADEON_SURF_CLR(surface.flags, MODE); 1314 surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 1315 } 1316 if (tiling_flags & RADEON_TILING_MACRO) { 1317 surface.flags = RADEON_SURF_CLR(surface.flags, MODE); 1318 surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 1319 } 1320 if (radeon_surface_best(info->surf_man, &surface)) { 1321 return FALSE; 1322 } 1323 if (radeon_surface_init(info->surf_man, &surface)) { 1324 return FALSE; 1325 } 1326 screen_size = surface.bo_size; 1327 base_align = surface.bo_alignment; 1328 pitch = surface.level[0].pitch_bytes; 1329 tiling_flags = 0; 1330 switch (surface.level[0].mode) { 1331 case RADEON_SURF_MODE_2D: 1332 tiling_flags |= RADEON_TILING_MACRO; 1333 tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT; 1334 tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT; 1335 tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT; 1336 tiling_flags |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT; 1337 break; 1338 case RADEON_SURF_MODE_1D: 1339 tiling_flags |= RADEON_TILING_MICRO; 1340 break; 1341 default: 1342 break; 1343 } 1344 info->front_surface = surface; 1345 } 1346 1347 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1348 "Allocate new frame buffer %dx%d stride %d\n", 1349 width, height, pitch / cpp); 1350 1351 old_width = scrn->virtualX; 1352 old_height = scrn->virtualY; 1353 old_pitch = scrn->displayWidth; 1354 old_fb_id = drmmode->fb_id; 1355 old_front = info->front_bo; 1356 1357 scrn->virtualX = width; 1358 scrn->virtualY = height; 1359 scrn->displayWidth = pitch / cpp; 1360 1361 info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align, RADEON_GEM_DOMAIN_VRAM, 0); 1362 if (!info->front_bo) 1363 goto fail; 1364 1365#if X_BYTE_ORDER == X_BIG_ENDIAN 1366 switch (cpp) { 1367 case 4: 1368 tiling_flags |= RADEON_TILING_SWAP_32BIT; 1369 break; 1370 case 2: 1371 tiling_flags |= RADEON_TILING_SWAP_16BIT; 1372 break; 1373 } 1374#endif 1375 if (tiling_flags) 1376 radeon_bo_set_tiling(info->front_bo, tiling_flags, pitch); 1377 1378 ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth, 1379 scrn->bitsPerPixel, pitch, 1380 info->front_bo->handle, 1381 &drmmode->fb_id); 1382 if (ret) 1383 goto fail; 1384 1385 if (!info->r600_shadow_fb) { 1386 radeon_set_pixmap_bo(ppix, info->front_bo); 1387 psurface = radeon_get_pixmap_surface(ppix); 1388 *psurface = info->front_surface; 1389 screen->ModifyPixmapHeader(ppix, 1390 width, height, -1, -1, pitch, NULL); 1391 } else { 1392 if (radeon_bo_map(info->front_bo, 1)) 1393 goto fail; 1394 fb_shadow = calloc(1, screen_size); 1395 if (fb_shadow == NULL) 1396 goto fail; 1397 free(info->fb_shadow); 1398 info->fb_shadow = fb_shadow; 1399 screen->ModifyPixmapHeader(ppix, 1400 width, height, -1, -1, pitch, 1401 info->fb_shadow); 1402 } 1403#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,9,99,1,0) 1404 scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr; 1405#endif 1406 1407 for (i = 0; i < xf86_config->num_crtc; i++) { 1408 xf86CrtcPtr crtc = xf86_config->crtc[i]; 1409 1410 if (!crtc->enabled) 1411 continue; 1412 1413 drmmode_set_mode_major(crtc, &crtc->mode, 1414 crtc->rotation, crtc->x, crtc->y); 1415 } 1416 1417 if (old_fb_id) 1418 drmModeRmFB(drmmode->fd, old_fb_id); 1419 if (old_front) 1420 radeon_bo_unref(old_front); 1421 1422 radeon_kms_update_vram_limit(scrn, screen_size); 1423 return TRUE; 1424 1425 fail: 1426 if (info->front_bo) 1427 radeon_bo_unref(info->front_bo); 1428 info->front_bo = old_front; 1429 scrn->virtualX = old_width; 1430 scrn->virtualY = old_height; 1431 scrn->displayWidth = old_pitch; 1432 drmmode->fb_id = old_fb_id; 1433 1434 return FALSE; 1435} 1436 1437static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { 1438 drmmode_xf86crtc_resize 1439}; 1440 1441static void 1442drmmode_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec, 1443 unsigned int tv_usec, void *event_data) 1444{ 1445 radeon_dri2_frame_event_handler(frame, tv_sec, tv_usec, event_data); 1446} 1447 1448static void 1449drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec, 1450 unsigned int tv_usec, void *event_data) 1451{ 1452 drmmode_flipevtcarrier_ptr flipcarrier = event_data; 1453 drmmode_flipdata_ptr flipdata = flipcarrier->flipdata; 1454 drmmode_ptr drmmode = flipdata->drmmode; 1455 1456 /* Is this the event whose info shall be delivered to higher level? */ 1457 if (flipcarrier->dispatch_me) { 1458 /* Yes: Cache msc, ust for later delivery. */ 1459 flipdata->fe_frame = frame; 1460 flipdata->fe_tv_sec = tv_sec; 1461 flipdata->fe_tv_usec = tv_usec; 1462 } 1463 free(flipcarrier); 1464 1465 /* Last crtc completed flip? */ 1466 flipdata->flip_count--; 1467 if (flipdata->flip_count > 0) 1468 return; 1469 1470 /* Release framebuffer */ 1471 drmModeRmFB(drmmode->fd, flipdata->old_fb_id); 1472 1473 if (flipdata->event_data == NULL) 1474 return; 1475 1476 /* Deliver cached msc, ust from reference crtc to flip event handler */ 1477 radeon_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec, 1478 flipdata->fe_tv_usec, flipdata->event_data); 1479 1480 free(flipdata); 1481} 1482 1483 1484#if HAVE_NOTIFY_FD 1485static void drmmode_notify_fd(int fd, int notify, void *data) 1486{ 1487 drmmode_ptr drmmode = data; 1488 1489 drmHandleEvent(fd, &drmmode->event_context); 1490} 1491#else 1492static void 1493drm_wakeup_handler(pointer data, int err, pointer p) 1494{ 1495 drmmode_ptr drmmode = data; 1496 fd_set *read_mask = p; 1497 1498 if (err >= 0 && FD_ISSET(drmmode->fd, read_mask)) { 1499 drmHandleEvent(drmmode->fd, &drmmode->event_context); 1500 } 1501} 1502#endif 1503 1504Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) 1505{ 1506 xf86CrtcConfigPtr xf86_config; 1507 int i, num_dvi = 0, num_hdmi = 0; 1508 1509 xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs); 1510 xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1511 1512 drmmode->scrn = pScrn; 1513 drmmode->cpp = cpp; 1514 drmmode->mode_res = drmModeGetResources(drmmode->fd); 1515 if (!drmmode->mode_res) 1516 return FALSE; 1517 1518 xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height); 1519 for (i = 0; i < drmmode->mode_res->count_crtcs; i++) 1520 if (!xf86IsEntityShared(pScrn->entityList[0]) || pScrn->confScreen->device->screen == i) 1521 drmmode_crtc_init(pScrn, drmmode, i); 1522 1523 for (i = 0; i < drmmode->mode_res->count_connectors; i++) 1524 drmmode_output_init(pScrn, drmmode, i, &num_dvi, &num_hdmi); 1525 1526 /* workout clones */ 1527 drmmode_clones_init(pScrn, drmmode); 1528 1529 xf86InitialConfiguration(pScrn, TRUE); 1530 1531 drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION; 1532 drmmode->event_context.vblank_handler = drmmode_vblank_handler; 1533 drmmode->event_context.page_flip_handler = drmmode_flip_handler; 1534 1535 return TRUE; 1536} 1537 1538void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode) 1539{ 1540 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1541 RADEONInfoPtr info = RADEONPTR(pScrn); 1542 1543 if (pRADEONEnt->fd_wakeup_registered != serverGeneration && 1544 info->dri->pKernelDRMVersion->version_minor >= 4) { 1545#if HAVE_NOTIFY_FD 1546 SetNotifyFd(drmmode->fd, drmmode_notify_fd, X_NOTIFY_READ, drmmode); 1547#else 1548 AddGeneralSocket(drmmode->fd); 1549 RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, 1550 drm_wakeup_handler, drmmode); 1551#endif 1552 pRADEONEnt->fd_wakeup_registered = serverGeneration; 1553 } 1554} 1555 1556Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr) 1557{ 1558 drmmode->bufmgr = bufmgr; 1559 return TRUE; 1560} 1561 1562 1563 1564void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo) 1565{ 1566 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1567 xf86CrtcPtr crtc = xf86_config->crtc[id]; 1568 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1569 1570 drmmode_crtc->cursor_bo = bo; 1571} 1572 1573void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y) 1574{ 1575 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 1576 xf86OutputPtr output = config->output[config->compat_output]; 1577 xf86CrtcPtr crtc = output->crtc; 1578 1579 if (crtc && crtc->enabled) { 1580 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, 1581 x, y); 1582 } 1583} 1584 1585Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode) 1586{ 1587 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 1588 int c; 1589 1590 drmmode_copy_fb(pScrn, drmmode); 1591 1592 for (c = 0; c < config->num_crtc; c++) { 1593 xf86CrtcPtr crtc = config->crtc[c]; 1594 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1595 xf86OutputPtr output = NULL; 1596 int o; 1597 1598 /* Skip disabled CRTCs */ 1599 if (!crtc->enabled) { 1600 drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 1601 0, 0, 0, NULL, 0, NULL); 1602 continue; 1603 } 1604 1605 if (config->output[config->compat_output]->crtc == crtc) 1606 output = config->output[config->compat_output]; 1607 else 1608 { 1609 for (o = 0; o < config->num_output; o++) 1610 if (config->output[o]->crtc == crtc) 1611 { 1612 output = config->output[o]; 1613 break; 1614 } 1615 } 1616 /* paranoia */ 1617 if (!output) 1618 continue; 1619 1620 /* Mark that we'll need to re-set the mode for sure */ 1621 memset(&crtc->mode, 0, sizeof(crtc->mode)); 1622 if (!crtc->desiredMode.CrtcHDisplay) 1623 { 1624 DisplayModePtr mode = xf86OutputFindClosestMode (output, pScrn->currentMode); 1625 1626 if (!mode) 1627 return FALSE; 1628 crtc->desiredMode = *mode; 1629 crtc->desiredRotation = RR_Rotate_0; 1630 crtc->desiredX = 0; 1631 crtc->desiredY = 0; 1632 } 1633 1634 if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation, 1635 crtc->desiredX, crtc->desiredY)) 1636 return FALSE; 1637 } 1638 return TRUE; 1639} 1640 1641static void drmmode_load_palette(ScrnInfoPtr pScrn, int numColors, 1642 int *indices, LOCO *colors, VisualPtr pVisual) 1643{ 1644 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1645 uint16_t lut_r[256], lut_g[256], lut_b[256]; 1646 int index, j, i; 1647 int c; 1648 1649 for (c = 0; c < xf86_config->num_crtc; c++) { 1650 xf86CrtcPtr crtc = xf86_config->crtc[c]; 1651 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1652 1653 for (i = 0 ; i < 256; i++) { 1654 lut_r[i] = drmmode_crtc->lut_r[i] << 6; 1655 lut_g[i] = drmmode_crtc->lut_g[i] << 6; 1656 lut_b[i] = drmmode_crtc->lut_b[i] << 6; 1657 } 1658 1659 switch(pScrn->depth) { 1660 case 15: 1661 for (i = 0; i < numColors; i++) { 1662 index = indices[i]; 1663 for (j = 0; j < 8; j++) { 1664 lut_r[index * 8 + j] = colors[index].red << 6; 1665 lut_g[index * 8 + j] = colors[index].green << 6; 1666 lut_b[index * 8 + j] = colors[index].blue << 6; 1667 } 1668 } 1669 break; 1670 case 16: 1671 for (i = 0; i < numColors; i++) { 1672 index = indices[i]; 1673 1674 if (i <= 31) { 1675 for (j = 0; j < 8; j++) { 1676 lut_r[index * 8 + j] = colors[index].red << 6; 1677 lut_b[index * 8 + j] = colors[index].blue << 6; 1678 } 1679 } 1680 1681 for (j = 0; j < 4; j++) { 1682 lut_g[index * 4 + j] = colors[index].green << 6; 1683 } 1684 } 1685 break; 1686 default: 1687 for (i = 0; i < numColors; i++) { 1688 index = indices[i]; 1689 lut_r[index] = colors[index].red << 6; 1690 lut_g[index] = colors[index].green << 6; 1691 lut_b[index] = colors[index].blue << 6; 1692 } 1693 break; 1694 } 1695 1696 /* Make the change through RandR */ 1697#ifdef RANDR_12_INTERFACE 1698 if (crtc->randr_crtc) 1699 RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); 1700 else 1701#endif 1702 crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); 1703 } 1704} 1705 1706Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn) 1707{ 1708 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 1709 "Initializing kms color map\n"); 1710 if (!miCreateDefColormap(pScreen)) 1711 return FALSE; 1712 /* all radeons support 10 bit CLUTs */ 1713 if (!xf86HandleColormaps(pScreen, 256, 10, 1714 drmmode_load_palette, NULL, 1715 CMAP_PALETTED_TRUECOLOR 1716#if 0 /* This option messes up text mode! (eich@suse.de) */ 1717 | CMAP_LOAD_EVEN_IF_OFFSCREEN 1718#endif 1719 | CMAP_RELOAD_ON_MODE_SWITCH)) 1720 return FALSE; 1721 return TRUE; 1722} 1723 1724#ifdef HAVE_LIBUDEV 1725static void 1726drmmode_handle_uevents(int fd, void *closure) 1727{ 1728 drmmode_ptr drmmode = closure; 1729 ScrnInfoPtr scrn = drmmode->scrn; 1730 struct udev_device *dev; 1731 dev = udev_monitor_receive_device(drmmode->uevent_monitor); 1732 if (!dev) 1733 return; 1734 1735 RRGetInfo(xf86ScrnToScreen(scrn), TRUE); 1736 udev_device_unref(dev); 1737} 1738#endif 1739 1740void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode) 1741{ 1742#ifdef HAVE_LIBUDEV 1743 struct udev *u; 1744 struct udev_monitor *mon; 1745 1746 u = udev_new(); 1747 if (!u) 1748 return; 1749 mon = udev_monitor_new_from_netlink(u, "udev"); 1750 if (!mon) { 1751 udev_unref(u); 1752 return; 1753 } 1754 1755 if (udev_monitor_filter_add_match_subsystem_devtype(mon, 1756 "drm", 1757 "drm_minor") < 0 || 1758 udev_monitor_enable_receiving(mon) < 0) { 1759 udev_monitor_unref(mon); 1760 udev_unref(u); 1761 return; 1762 } 1763 1764 drmmode->uevent_handler = 1765 xf86AddGeneralHandler(udev_monitor_get_fd(mon), 1766 drmmode_handle_uevents, 1767 drmmode); 1768 1769 drmmode->uevent_monitor = mon; 1770#endif 1771} 1772 1773void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode) 1774{ 1775#ifdef HAVE_LIBUDEV 1776 if (drmmode->uevent_handler) { 1777 struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor); 1778 xf86RemoveGeneralHandler(drmmode->uevent_handler); 1779 1780 udev_monitor_unref(drmmode->uevent_monitor); 1781 udev_unref(u); 1782 } 1783#endif 1784} 1785 1786Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id) 1787{ 1788 RADEONInfoPtr info = RADEONPTR(scrn); 1789 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 1790 drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private; 1791 drmmode_ptr drmmode = drmmode_crtc->drmmode; 1792 unsigned int pitch; 1793 int i, old_fb_id; 1794 uint32_t tiling_flags = 0; 1795 int height, emitted = 0; 1796 drmmode_flipdata_ptr flipdata; 1797 drmmode_flipevtcarrier_ptr flipcarrier; 1798 1799 if (info->allowColorTiling) { 1800 if (info->ChipFamily >= CHIP_FAMILY_R600) 1801 tiling_flags |= RADEON_TILING_MICRO; 1802 else 1803 tiling_flags |= RADEON_TILING_MACRO; 1804 } 1805 1806 pitch = RADEON_ALIGN(scrn->displayWidth, drmmode_get_pitch_align(scrn, info->CurrentLayout.pixel_bytes, tiling_flags)) * 1807 info->CurrentLayout.pixel_bytes; 1808 height = RADEON_ALIGN(scrn->virtualY, drmmode_get_height_align(scrn, tiling_flags)); 1809 if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) { 1810 pitch = info->front_surface.level[0].pitch_bytes; 1811 } 1812 1813 /* 1814 * Create a new handle for the back buffer 1815 */ 1816 old_fb_id = drmmode->fb_id; 1817 if (drmModeAddFB(drmmode->fd, scrn->virtualX, height, 1818 scrn->depth, scrn->bitsPerPixel, pitch, 1819 new_front->handle, &drmmode->fb_id)) 1820 goto error_out; 1821 1822 flipdata = calloc(1, sizeof(drmmode_flipdata_rec)); 1823 if (!flipdata) { 1824 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1825 "flip queue: data alloc failed.\n"); 1826 goto error_undo; 1827 } 1828 /* 1829 * Queue flips on all enabled CRTCs 1830 * Note that if/when we get per-CRTC buffers, we'll have to update this. 1831 * Right now it assumes a single shared fb across all CRTCs, with the 1832 * kernel fixing up the offset of each CRTC as necessary. 1833 * 1834 * Also, flips queued on disabled or incorrectly configured displays 1835 * may never complete; this is a configuration error. 1836 */ 1837 1838 flipdata->event_data = data; 1839 flipdata->drmmode = drmmode; 1840 1841 for (i = 0; i < config->num_crtc; i++) { 1842 if (!config->crtc[i]->enabled) 1843 continue; 1844 1845 flipdata->flip_count++; 1846 drmmode_crtc = config->crtc[i]->driver_private; 1847 1848 flipcarrier = calloc(1, sizeof(drmmode_flipevtcarrier_rec)); 1849 if (!flipcarrier) { 1850 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1851 "flip queue: carrier alloc failed.\n"); 1852 if (emitted == 0) 1853 free(flipdata); 1854 goto error_undo; 1855 } 1856 1857 /* Only the reference crtc will finally deliver its page flip 1858 * completion event. All other crtc's events will be discarded. 1859 */ 1860 flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id); 1861 flipcarrier->flipdata = flipdata; 1862 1863 if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 1864 drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipcarrier)) { 1865 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1866 "flip queue failed: %s\n", strerror(errno)); 1867 free(flipcarrier); 1868 if (emitted == 0) 1869 free(flipdata); 1870 goto error_undo; 1871 } 1872 emitted++; 1873 } 1874 1875 flipdata->old_fb_id = old_fb_id; 1876 return TRUE; 1877 1878error_undo: 1879 drmModeRmFB(drmmode->fd, drmmode->fb_id); 1880 drmmode->fb_id = old_fb_id; 1881 1882error_out: 1883 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", 1884 strerror(errno)); 1885 return FALSE; 1886} 1887 1888#endif 1889