1/* 2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 3 * Copyright 2011 VMWare, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 * 27 * Author: Alan Hourihane <alanh@tungstengraphics.com> 28 * Author: Jakob Bornecrantz <wallbraker@gmail.com> 29 * Author: Thomas Hellstrom <thellstrom@vmware.com> 30 */ 31 32#ifdef HAVE_CONFIG_H 33#include "config.h" 34#endif 35 36#include <unistd.h> 37#include <fcntl.h> 38#include "xorg-server.h" 39#include "xf86.h" 40#include "xf86_OSproc.h" 41#include "compiler.h" 42#include "xf86Pci.h" 43#include "mipointer.h" 44#include "micmap.h" 45#include <X11/extensions/randr.h> 46#include "fb.h" 47#include "edid.h" 48#include "xf86i2c.h" 49#include "xf86Crtc.h" 50#include "miscstruct.h" 51#include "dixstruct.h" 52#include "xf86cmap.h" 53#include "xf86xv.h" 54#include "xorgVersion.h" 55#ifndef XSERVER_LIBPCIACCESS 56#error "libpciaccess needed" 57#endif 58 59#include <pciaccess.h> 60 61#ifdef XSERVER_PLATFORM_BUS 62#include "xf86platformBus.h" 63#endif 64 65#include "vmwgfx_driver.h" 66 67#include <saa.h> 68#include "vmwgfx_saa.h" 69#include "../src/vmware_bootstrap.h" 70#include "../src/vmware_common.h" 71#include "vmwgfx_hosted.h" 72#include "common_compat.h" 73 74/* 75 * We can't incude svga_types.h due to conflicting types for Bool. 76 */ 77typedef int64_t int64; 78typedef uint64_t uint64; 79 80typedef int32_t int32; 81typedef uint32_t uint32; 82 83typedef int16_t int16; 84typedef uint16_t uint16; 85 86typedef int8_t int8; 87typedef uint8_t uint8; 88#include "../src/svga_reg.h" 89 90#define XA_VERSION_MINOR_REQUIRED 0 91#define XA_VERSION_MAJOR_REQUIRED 1 92#define XA_VERSION_MAJOR_COMPAT 2 93 94#define DRM_VERSION_MAJOR_REQUIRED 2 95#define DRM_VERSION_MINOR_REQUIRED 3 96 97/* 98 * Some macros to deal with function wrapping. 99 */ 100#define vmwgfx_wrap(priv, real, mem, func) {\ 101 (priv)->saved_##mem = (real)->mem; \ 102 (real)->mem = func; \ 103} 104 105#define vmwgfx_unwrap(priv, real, mem) {\ 106 (real)->mem = (priv)->saved_##mem; \ 107} 108 109#define vmwgfx_swap(priv, real, mem) {\ 110 void *tmp = (priv)->saved_##mem; \ 111 (priv)->saved_##mem = (real)->mem; \ 112 (real)->mem = tmp; \ 113} 114 115/* 116 * Functions and symbols exported to Xorg via pointers. 117 */ 118 119static Bool drv_pre_init(ScrnInfoPtr pScrn, int flags); 120static Bool drv_screen_init(SCREEN_INIT_ARGS_DECL); 121static Bool drv_switch_mode(SWITCH_MODE_ARGS_DECL); 122static void drv_adjust_frame(ADJUST_FRAME_ARGS_DECL); 123static Bool drv_enter_vt(VT_FUNC_ARGS_DECL); 124static void drv_leave_vt(VT_FUNC_ARGS_DECL); 125static void drv_free_screen(FREE_SCREEN_ARGS_DECL); 126static ModeStatus drv_valid_mode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, 127 int flags); 128 129extern void xorg_tracker_set_functions(ScrnInfoPtr scrn); 130 131void 132vmwgfx_hookup(ScrnInfoPtr pScrn) 133{ 134 pScrn->PreInit = drv_pre_init; 135 pScrn->ScreenInit = drv_screen_init; 136 pScrn->SwitchMode = drv_switch_mode; 137 pScrn->FreeScreen = drv_free_screen; 138 pScrn->ValidMode = drv_valid_mode; 139} 140 141void 142vmwgfx_modify_flags(uint32_t *flags) 143{ 144 *flags &= ~(HW_IO); 145 vmwgfx_hosted_modify_flags(flags); 146} 147/* 148 * Internal function definitions 149 */ 150 151static Bool drv_close_screen(CLOSE_SCREEN_ARGS_DECL); 152 153/* 154 * Internal functions 155 */ 156 157static Bool 158drv_get_rec(ScrnInfoPtr pScrn) 159{ 160 if (pScrn->driverPrivate) 161 return TRUE; 162 163 pScrn->driverPrivate = xnfcalloc(1, sizeof(modesettingRec)); 164 165 return TRUE; 166} 167 168static void 169drv_free_rec(ScrnInfoPtr pScrn) 170{ 171 if (!pScrn) 172 return; 173 174 if (!pScrn->driverPrivate) 175 return; 176 177 free(pScrn->driverPrivate); 178 179 pScrn->driverPrivate = NULL; 180} 181 182static void 183drv_probe_ddc(ScrnInfoPtr pScrn, int _index) 184{ 185 ConfiguredMonitor = NULL; 186} 187 188static Bool 189drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height) 190{ 191 modesettingPtr ms = modesettingPTR(pScrn); 192 ScreenPtr pScreen = pScrn->pScreen; 193 int old_width, old_height; 194 PixmapPtr rootPixmap; 195 196 if (width == pScrn->virtualX && height == pScrn->virtualY) 197 return TRUE; 198 199 if (ms->check_fb_size) { 200 size_t size = width*(pScrn->bitsPerPixel / 8) * height + 1024; 201 202 if (size > ms->max_fb_size) { 203 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 204 "Requested framebuffer size %dx%dx%d will not fit " 205 "in display memory.\n", 206 width, height, pScrn->bitsPerPixel); 207 return FALSE; 208 } 209 } 210 211 old_width = pScrn->virtualX; 212 old_height = pScrn->virtualY; 213 pScrn->virtualX = width; 214 pScrn->virtualY = height; 215 216 /* ms->create_front_buffer will remove the old front buffer */ 217 218 rootPixmap = pScreen->GetScreenPixmap(pScreen); 219 vmwgfx_disable_scanout(pScrn); 220 if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL)) 221 goto error_modify; 222 223 pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8); 224 225 xf86SetDesiredModes(pScrn); 226 return TRUE; 227 228 /* 229 * FIXME: Try out this error recovery path and fix problems. 230 231 */ 232 //error_create: 233 if (!pScreen->ModifyPixmapHeader(rootPixmap, old_width, old_height, -1, -1, -1, NULL)) 234 FatalError("failed to resize rootPixmap error path\n"); 235 236 pScrn->displayWidth = rootPixmap->devKind / 237 (rootPixmap->drawable.bitsPerPixel / 8); 238 239 240error_modify: 241 pScrn->virtualX = old_width; 242 pScrn->virtualY = old_height; 243 244 if (xf86SetDesiredModes(pScrn)) 245 return FALSE; 246 247 FatalError("failed to setup old framebuffer\n"); 248 return FALSE; 249} 250 251static const xf86CrtcConfigFuncsRec crtc_config_funcs = { 252 .resize = drv_crtc_resize 253}; 254 255static Bool vmwgfx_use_server_fd(modesettingPtr ms) 256{ 257#ifdef XF86_PDEV_SERVER_FD 258 return ms->platform_dev && (ms->platform_dev->flags & XF86_PDEV_SERVER_FD); 259#else 260 return FALSE; 261#endif 262} 263 264static Bool 265drv_init_drm(ScrnInfoPtr pScrn) 266{ 267 modesettingPtr ms = modesettingPTR(pScrn); 268 269 /* deal with server regeneration */ 270 if (ms->fd < 0) { 271 272 ms->fd = vmwgfx_hosted_drm_fd(ms->hdriver, ms->hosted, ms->PciInfo); 273 274#ifdef ODEV_ATTRIB_FD 275 if (ms->fd < 0 && vmwgfx_use_server_fd(ms)) 276 ms->fd = xf86_get_platform_device_int_attrib(ms->platform_dev, 277 ODEV_ATTRIB_FD, -1); 278#endif 279 280 if (ms->fd < 0) { 281 282 char bus_id[64]; 283 284 snprintf(bus_id, sizeof(bus_id), "PCI:%d:%d:%d", 285 ((ms->PciInfo->domain << 8) | ms->PciInfo->bus), 286 ms->PciInfo->dev, ms->PciInfo->func 287 ); 288 289 ms->fd = drmOpen("vmwgfx", bus_id); 290 ms->isMaster = TRUE; 291 292 } 293 294 if (ms->fd >= 0) { 295 drmVersionPtr ver = drmGetVersion(ms->fd); 296 297 if (ver == NULL) { 298 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 299 "Could not determine DRM version.\n"); 300 return FALSE; 301 } 302 303 ms->drm_major = ver->version_major; 304 ms->drm_minor = ver->version_minor; 305 ms->drm_patch = ver->version_patchlevel; 306 307 drmFreeVersion(ver); 308 return TRUE; 309 } 310 311 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 312 "Failed to open drm.\n"); 313 314 return FALSE; 315 } 316 317 return TRUE; 318} 319 320/** 321 * vmwgfx_set_topology - Set the GUI topology according to an option string 322 * 323 * @pScrn: Pointer to a ScrnInfo struct. 324 * @topology: String containing the topology description. 325 * @info: Info describing the option used to invoke this function. 326 * 327 * This function reads a GUI topology according from @topology, and 328 * calls into the kernel to set that topology. 329 */ 330static Bool 331vmwgfx_set_topology(ScrnInfoPtr pScrn, const char *topology, const char *info) 332{ 333 modesettingPtr ms = modesettingPTR(pScrn); 334 unsigned int num_outputs; 335 xXineramaScreenInfo *screen_info; 336 struct drm_vmw_rect *rects; 337 int ret; 338 unsigned int i; 339 340 screen_info = VMWAREParseTopologyString(pScrn, topology, &num_outputs, 341 info); 342 343 if (screen_info == NULL) 344 return FALSE; 345 346 rects = calloc(num_outputs, sizeof(*rects)); 347 if (rects == NULL) { 348 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 349 "Failed to allocate topology data.\n"); 350 goto out_no_rects; 351 } 352 353 for(i = 0; i < num_outputs; ++i) { 354 rects[i].x = screen_info[i].x_org; 355 rects[i].y = screen_info[i].y_org; 356 rects[i].w = screen_info[i].width; 357 rects[i].h = screen_info[i].height; 358 } 359 360 ret = vmwgfx_update_gui_layout(ms->fd, num_outputs, rects); 361 free(rects); 362 free(screen_info); 363 364 return (ret == 0); 365 366 out_no_rects: 367 free(screen_info); 368 return FALSE; 369} 370 371 372static Bool 373vmwgfx_pre_init_mode(ScrnInfoPtr pScrn, int flags) 374{ 375 modesettingPtr ms = modesettingPTR(pScrn); 376 Bool ret = TRUE; 377 378 ms->from_dp = (xf86GetOptValBool(ms->Options, OPTION_DIRECT_PRESENTS, 379 &ms->direct_presents)) ? 380 X_CONFIG : X_DEFAULT; 381 382 ms->from_hwp = (xf86GetOptValBool(ms->Options, OPTION_HW_PRESENTS, 383 &ms->only_hw_presents)) ? 384 X_CONFIG : X_DEFAULT; 385 386 /* Allocate an xf86CrtcConfig */ 387 xf86CrtcConfigInit(pScrn, &crtc_config_funcs); 388 389 /* get max width and height */ 390 { 391 drmModeResPtr res; 392 int max_width, max_height; 393 394 res = drmModeGetResources(ms->fd); 395 max_width = res->max_width; 396 max_height = res->max_height; 397 398 xf86CrtcSetSizeRange(pScrn, res->min_width, 399 res->min_height, max_width, max_height); 400 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 401 "Min width %d, Max Width %d.\n", 402 res->min_width, max_width); 403 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 404 "Min height %d, Max Height %d.\n", 405 res->min_height, max_height); 406 drmModeFreeResources(res); 407 } 408 409 ms->SWCursor = FALSE; 410 if (!xf86ReturnOptValBool(ms->Options, OPTION_HW_CURSOR, TRUE)) { 411 ms->SWCursor = TRUE; 412 } 413 414 if (xf86IsOptionSet(ms->Options, OPTION_GUI_LAYOUT)) { 415 CONST_ABI_18_0 char *topology = 416 xf86GetOptValString(ms->Options, OPTION_GUI_LAYOUT); 417 418 ret = FALSE; 419 if (topology) { 420 ret = vmwgfx_set_topology(pScrn, topology, "gui"); 421 free((void *)topology); 422 } 423 424 } else if (xf86IsOptionSet(ms->Options, OPTION_STATIC_XINERAMA)) { 425 CONST_ABI_18_0 char *topology = 426 xf86GetOptValString(ms->Options, OPTION_STATIC_XINERAMA); 427 428 ret = FALSE; 429 if (topology) { 430 ret = vmwgfx_set_topology(pScrn, topology, "static Xinerama"); 431 free((void *)topology); 432 } 433 } 434 435 if (!ret) 436 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Falied parsing or setting " 437 "gui topology from config file.\n"); 438 439 xorg_crtc_init(pScrn); 440 xorg_output_init(pScrn); 441 442 if (!xf86InitialConfiguration(pScrn, TRUE)) { 443 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); 444 goto out_modes; 445 } 446 447 if (pScrn->modes == NULL) { 448 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No available modes.\n"); 449 goto out_modes; 450 } 451 452 pScrn->currentMode = pScrn->modes; 453 454 return TRUE; 455 456 out_modes: 457 return FALSE; 458} 459 460static Bool 461drv_pre_init(ScrnInfoPtr pScrn, int flags) 462{ 463 modesettingPtr ms; 464 rgb defaultWeight = { 0, 0, 0 }; 465 Gamma zeros = { 0.0, 0.0, 0.0 }; 466 EntityInfoPtr pEnt; 467 uint64_t cap; 468 469 if (pScrn->numEntities != 1) 470 return FALSE; 471 472 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 473 474 if (flags & PROBE_DETECT) { 475 drv_probe_ddc(pScrn, pEnt->index); 476 return TRUE; 477 } 478 479 pScrn->driverPrivate = NULL; 480 481 /* Allocate driverPrivate */ 482 if (!drv_get_rec(pScrn)) { 483 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 484 "Failed to allocate driver private.\n"); 485 } 486 487 ms = modesettingPTR(pScrn); 488 ms->pEnt = pEnt; 489 490 pScrn->displayWidth = 640; /* default it */ 491 492 ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index); 493 if (!ms->PciInfo) { 494 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 495 "Incorrect bus for device.\n"); 496 goto out_err_bus; 497 } 498 499#ifdef XSERVER_PLATFORM_BUS 500 if (pEnt->location.type == BUS_PLATFORM) 501 ms->platform_dev = pEnt->location.id.plat; 502#endif 503 504 xf86SetPrimInitDone(pScrn->entityList[0]); 505 506 ms->hdriver = vmwgfx_hosted_detect(); 507 ms->hosted = vmwgfx_hosted_create(ms->hdriver, pScrn); 508 if (ms->hdriver && !ms->hosted) { 509 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 510 "Failed to set up compositor hosted environment.\n"); 511 goto out_err_bus; 512 } 513 514 pScrn->monitor = pScrn->confScreen->monitor; 515 pScrn->progClock = TRUE; 516 pScrn->rgbBits = 8; 517 518 if (!xf86SetDepthBpp 519 (pScrn, 0, 0, 0, 520 PreferConvert24to32 | SupportConvert24to32 | Support32bppFb)) { 521 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set depth and bpp.\n"); 522 goto out_err_bus; 523 } 524 525 if (!vmwgfx_hosted_pre_init(ms->hdriver, ms->hosted, flags)) 526 goto out_err_bus; 527 528 ms->fd = -1; 529 if (!drv_init_drm(pScrn)) 530 goto out_no_drm; 531 532 if (ms->drm_major != DRM_VERSION_MAJOR_REQUIRED || 533 ms->drm_minor < DRM_VERSION_MINOR_REQUIRED) { 534 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 535 "DRM driver version is %d.%d.%d\n", 536 ms->drm_major, ms->drm_minor, ms->drm_patch); 537 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 538 "But KMS- and 3D functionality needs at least " 539 "%d.%d.0 to work.\n", 540 DRM_VERSION_MAJOR_REQUIRED, 541 DRM_VERSION_MINOR_REQUIRED); 542 goto out_drm_version; 543 } else { 544 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 545 "DRM driver version is %d.%d.%d\n", 546 ms->drm_major, ms->drm_minor, ms->drm_patch); 547 } 548 549 ms->has_screen_targets = ms->drm_major > 2 || 550 (ms->drm_major == 2 && ms->drm_minor >= 7); 551 ms->has_screen_targets = (ms->has_screen_targets && 552 !vmwgfx_get_param(ms->fd, 553 DRM_VMW_PARAM_SCREEN_TARGET, 554 &cap) && 555 cap != 0); 556 557 ms->check_fb_size = (vmwgfx_max_fb_size(ms->fd, &ms->max_fb_size) == 0); 558 559 switch (pScrn->depth) { 560 case 15: 561 case 16: 562 case 24: 563 break; 564 default: 565 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 566 "Given depth (%d) is not supported with KMS enabled.\n", 567 pScrn->depth); 568 goto out_depth; 569 } 570 xf86PrintDepthBpp(pScrn); 571 572 if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 573 goto out_depth; 574 if (!xf86SetDefaultVisual(pScrn, -1)) 575 goto out_depth; 576 577 /* Process the options */ 578 xf86CollectOptions(pScrn, NULL); 579 if (!(ms->Options = VMWARECopyOptions())) 580 goto out_depth; 581 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options); 582 583 ms->accelerate_render = TRUE; 584 ms->from_render = xf86GetOptValBool(ms->Options, OPTION_RENDER_ACCEL, 585 &ms->accelerate_render) ? 586 X_CONFIG : X_PROBED; 587 588 ms->rendercheck = FALSE; 589 ms->from_rendercheck = xf86GetOptValBool(ms->Options, OPTION_RENDERCHECK, 590 &ms->rendercheck) ? 591 X_CONFIG : X_DEFAULT; 592 593 ms->enable_dri = ms->accelerate_render; 594 ms->from_dri = xf86GetOptValBool(ms->Options, OPTION_DRI, 595 &ms->enable_dri) ? 596 X_CONFIG : X_PROBED; 597 598 ms->direct_presents = FALSE; 599 ms->only_hw_presents = FALSE; 600 ms->SWCursor = TRUE; 601 if (!vmwgfx_is_hosted(ms->hdriver)) { 602 if (!vmwgfx_pre_init_mode(pScrn, flags)) 603 goto out_modes; 604 } else { 605 ms->from_dp = X_CONFIG; 606 ms->from_hwp = X_CONFIG; 607 } 608 609 xf86SetDpi(pScrn, 0, 0); 610 611 if (!xf86SetGamma(pScrn, zeros)) { 612 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set gamma.\n"); 613 goto out_modes; 614 } 615 616 /* Load the required sub modules */ 617 if (!xf86LoadSubModule(pScrn, "fb")) { 618 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load fb module.\n"); 619 goto out_modes; 620 } 621 622 if (!xf86LoadSubModule(pScrn, "dri2")) { 623 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load dri2 module.\n"); 624 goto out_modes; 625 } 626 627#ifdef DRI3 628 if (!xf86LoadSubModule(pScrn, "dri3")) { 629 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load dri3 module.\n"); 630 goto out_modes; 631 } 632#endif 633 634 return TRUE; 635 636 out_modes: 637 free(ms->Options); 638 out_depth: 639 out_drm_version: 640 if (!vmwgfx_is_hosted(ms->hdriver) && !vmwgfx_use_server_fd(ms)) 641 close(ms->fd); 642 out_no_drm: 643 vmwgfx_hosted_destroy(ms->hdriver, ms->hosted); 644 out_err_bus: 645 drv_free_rec(pScrn); 646 return FALSE; 647 648} 649 650static Bool 651vmwgfx_scanout_update(int drm_fd, int fb_id, RegionPtr dirty) 652{ 653 BoxPtr clips = REGION_RECTS(dirty); 654 unsigned int num_clips = REGION_NUM_RECTS(dirty); 655 unsigned int alloc_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS); 656 drmModeClip *rects, *r; 657 int i, ret; 658 659 if (num_clips == 0) 660 return TRUE; 661 662 rects = malloc(alloc_clips * sizeof(*rects)); 663 if (!rects) { 664 LogMessage(X_ERROR, "Failed to alloc cliprects for scanout update.\n"); 665 return FALSE; 666 } 667 668 while (num_clips > 0) { 669 unsigned int cur_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS); 670 671 memset(rects, 0, alloc_clips * sizeof(*rects)); 672 673 for (i = 0, r = rects; i < cur_clips; ++i, ++r, ++clips) { 674 r->x1 = clips->x1; 675 r->y1 = clips->y1; 676 r->x2 = clips->x2; 677 r->y2 = clips->y2; 678 } 679 680 ret = drmModeDirtyFB(drm_fd, fb_id, rects, cur_clips); 681 if (ret) { 682 LogMessage(X_ERROR, "%s: failed to send dirty (%i, %s)\n", 683 __func__, ret, strerror(-ret)); 684 return FALSE; 685 } 686 687 num_clips -= cur_clips; 688 } 689 690 free(rects); 691 692 return TRUE; 693} 694 695static Bool 696vmwgfx_scanout_present(ScreenPtr pScreen, int drm_fd, 697 struct vmwgfx_saa_pixmap *vpix, 698 RegionPtr dirty) 699{ 700 uint32_t handle; 701 unsigned int dummy; 702 703 if (!REGION_NOTEMPTY(pScreen, dirty)) 704 return TRUE; 705 706 if (!vpix->hw) { 707 LogMessage(X_ERROR, "No surface to present from.\n"); 708 return FALSE; 709 } 710 711 if (_xa_surface_handle(vpix->hw, &handle, &dummy) != 0) { 712 LogMessage(X_ERROR, "Could not get present surface handle.\n"); 713 return FALSE; 714 } 715 716 if (vmwgfx_present(drm_fd, vpix->fb_id, 0, 0, dirty, handle) != 0) { 717 LogMessage(X_ERROR, "Failed present kernel call.\n"); 718 return FALSE; 719 } 720 721 return TRUE; 722} 723 724void xorg_flush(ScreenPtr pScreen) 725{ 726 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 727 modesettingPtr ms = modesettingPTR(pScrn); 728 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 729 PixmapPtr pixmap = NULL; 730 struct vmwgfx_saa_pixmap *vpix; 731 int i; 732 xf86CrtcPtr crtc; 733 PixmapPtr *pixmaps = calloc(config->num_crtc, sizeof(*pixmaps)); 734 unsigned int num_scanout = 0; 735 unsigned int j; 736 737 if (!pixmaps) { 738 LogMessage(X_ERROR, "Failed memory allocation during screen " 739 "update.\n"); 740 return; 741 } 742 743 /* 744 * Get an array of pixmaps from which we scan out. 745 */ 746 for (i=0; i<config->num_crtc; ++i) { 747 crtc = config->crtc[i]; 748 if (crtc->enabled) { 749 pixmap = crtc_get_scanout(crtc); 750 if (pixmap) { 751 752 /* 753 * Remove duplicates. 754 */ 755 for (j=0; j<num_scanout; ++j) { 756 if (pixmap == pixmaps[j]) 757 break; 758 } 759 760 if (j == num_scanout) 761 pixmaps[num_scanout++] = pixmap; 762 } 763 } 764 } 765 766 if (!num_scanout) 767 return; 768 769 for (j=0; j<num_scanout; ++j) { 770 pixmap = pixmaps[j]; 771 vpix = vmwgfx_saa_pixmap(pixmap); 772 773 if (vpix->fb_id != -1) { 774 if (vpix->pending_update) { 775 if (vpix->scanout_hw && 776 REGION_NOTEMPTY(pscreen, vpix->pending_update)) { 777 (void) vmwgfx_hw_accel_validate(pixmap, 0, XA_FLAG_SCANOUT, 778 0, NULL); 779 REGION_UNION(pScreen, vpix->pending_present, 780 vpix->pending_present, vpix->pending_update); 781 } else 782 (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id, 783 vpix->pending_update); 784 REGION_EMPTY(pScreen, vpix->pending_update); 785 } 786 if (vpix->pending_present) { 787 if (vpix->scanout_hw) 788 (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id, 789 vpix->pending_present); 790 else 791 (void) vmwgfx_scanout_present(pScreen, ms->fd, vpix, 792 vpix->pending_present); 793 REGION_EMPTY(pScreen, vpix->pending_present); 794 } 795 } 796 } 797 free(pixmaps); 798} 799 800static void drv_block_handler(BLOCKHANDLER_ARGS_DECL) 801{ 802 SCREEN_PTR(arg); 803 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen)); 804 805 vmwgfx_swap(ms, pScreen, BlockHandler); 806 pScreen->BlockHandler(BLOCKHANDLER_ARGS); 807 vmwgfx_swap(ms, pScreen, BlockHandler); 808 809 if (vmwgfx_is_hosted(ms->hdriver)) 810 vmwgfx_hosted_post_damage(ms->hdriver, ms->hosted); 811 else 812 xorg_flush(pScreen); 813} 814 815static Bool 816drv_create_screen_resources(ScreenPtr pScreen) 817{ 818 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 819 modesettingPtr ms = modesettingPTR(pScrn); 820 Bool ret; 821 822 vmwgfx_swap(ms, pScreen, CreateScreenResources); 823 ret = pScreen->CreateScreenResources(pScreen); 824 vmwgfx_swap(ms, pScreen, CreateScreenResources); 825 if (!ret) 826 return ret; 827 828 drv_adjust_frame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 829 vmwgfx_uevent_init(pScrn, ms); 830 831 return drv_enter_vt(VT_FUNC_ARGS); 832} 833 834static Bool 835drv_set_master(ScrnInfoPtr pScrn) 836{ 837 modesettingPtr ms = modesettingPTR(pScrn); 838 839 if (!vmwgfx_is_hosted(ms->hdriver) && !vmwgfx_use_server_fd(ms) && 840 !ms->isMaster && drmSetMaster(ms->fd) != 0) { 841 if (errno == EINVAL) { 842 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 843 "drmSetMaster failed: 2.6.29 or newer kernel required for " 844 "multi-server DRI\n"); 845 } else { 846 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 847 "drmSetMaster failed: %s\n", strerror(errno)); 848 } 849 return FALSE; 850 } 851 852 ms->isMaster = TRUE; 853 return TRUE; 854} 855 856/** 857 * vmwgfx_use_hw_cursor_argb - wrapper around hw argb cursor check. 858 * 859 * screen: Pointer to the current screen metadata. 860 * cursor: Pointer to the current cursor metadata. 861 * 862 * In addition to the default test, also check whether we might be 863 * needing more than one hw cursor (which we don't support). 864 */ 865static Bool 866vmwgfx_use_hw_cursor_argb(ScreenPtr screen, CursorPtr cursor) 867{ 868 ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 869 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 870 xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; 871 modesettingPtr ms = modesettingPTR(pScrn); 872 Bool ret; 873 874 vmwgfx_swap(ms, cursor_info, UseHWCursorARGB); 875 ret = cursor_info->UseHWCursorARGB(screen, cursor); 876 vmwgfx_swap(ms, cursor_info, UseHWCursorARGB); 877 if (!ret) 878 return FALSE; 879 880 /* 881 * If there is a chance we might need two cursors, 882 * revert to sw cursor. 883 */ 884 return !vmwgfx_output_explicit_overlap(pScrn); 885} 886 887/** 888 * vmwgfx_use_hw_cursor - wrapper around hw cursor check. 889 * 890 * screen: Pointer to the current screen metadata. 891 * cursor: Pointer to the current cursor metadata. 892 * 893 * In addition to the default test, also check whether we might be 894 * needing more than one hw cursor (which we don't support). 895 */ 896static Bool 897vmwgfx_use_hw_cursor(ScreenPtr screen, CursorPtr cursor) 898{ 899 ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 900 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 901 xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; 902 modesettingPtr ms = modesettingPTR(pScrn); 903 Bool ret; 904 905 vmwgfx_swap(ms, cursor_info, UseHWCursor); 906 ret = cursor_info->UseHWCursor(screen, cursor); 907 vmwgfx_swap(ms, cursor_info, UseHWCursor); 908 if (!ret) 909 return FALSE; 910 911 /* 912 * If there is a chance we might need two simultaneous cursors, 913 * revert to sw cursor. 914 */ 915 return !vmwgfx_output_explicit_overlap(pScrn); 916} 917 918/** 919 * vmwgfx_wrap_use_hw_cursor - Wrap functions that check for hw cursor 920 * support. 921 * 922 * pScrn: Pointer to current screen info. 923 * 924 * Enables the device-specific hw cursor support check functions. 925 */ 926static void vmwgfx_wrap_use_hw_cursor(ScrnInfoPtr pScrn) 927{ 928 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 929 xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; 930 modesettingPtr ms = modesettingPTR(pScrn); 931 932 vmwgfx_wrap(ms, cursor_info, UseHWCursor, vmwgfx_use_hw_cursor); 933 vmwgfx_wrap(ms, cursor_info, UseHWCursorARGB, vmwgfx_use_hw_cursor_argb); 934} 935 936 937static void drv_load_palette(ScrnInfoPtr pScrn, int numColors, 938 int *indices, LOCO *colors, VisualPtr pVisual) 939{ 940 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 941 modesettingPtr ms = modesettingPTR(pScrn); 942 int _index, j, i; 943 int c; 944 945 switch(pScrn->depth) { 946 case 15: 947 for (i = 0; i < numColors; i++) { 948 _index = indices[i]; 949 for (j = 0; j < 8; j++) { 950 ms->lut_r[_index * 8 + j] = colors[_index].red << 8; 951 ms->lut_g[_index * 8 + j] = colors[_index].green << 8; 952 ms->lut_b[_index * 8 + j] = colors[_index].blue << 8; 953 } 954 } 955 break; 956 case 16: 957 for (i = 0; i < numColors; i++) { 958 _index = indices[i]; 959 960 if (_index < 32) { 961 for (j = 0; j < 8; j++) { 962 ms->lut_r[_index * 8 + j] = colors[_index].red << 8; 963 ms->lut_b[_index * 8 + j] = colors[_index].blue << 8; 964 } 965 } 966 967 for (j = 0; j < 4; j++) { 968 ms->lut_g[_index * 4 + j] = colors[_index].green << 8; 969 } 970 } 971 break; 972 default: 973 for (i = 0; i < numColors; i++) { 974 _index = indices[i]; 975 ms->lut_r[_index] = colors[_index].red << 8; 976 ms->lut_g[_index] = colors[_index].green << 8; 977 ms->lut_b[_index] = colors[_index].blue << 8; 978 } 979 break; 980 } 981 982 for (c = 0; c < xf86_config->num_crtc; c++) { 983 xf86CrtcPtr crtc = xf86_config->crtc[c]; 984 985 /* Make the change through RandR */ 986#ifdef RANDR_12_INTERFACE 987 if (crtc->randr_crtc) 988 RRCrtcGammaSet(crtc->randr_crtc, ms->lut_r, ms->lut_g, ms->lut_b); 989 else 990#endif 991 crtc->funcs->gamma_set(crtc, ms->lut_r, ms->lut_g, ms->lut_b, 256); 992 } 993} 994 995 996static Bool 997drv_screen_init(SCREEN_INIT_ARGS_DECL) 998{ 999 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1000 modesettingPtr ms = modesettingPTR(pScrn); 1001 VisualPtr visual; 1002 1003 if (!drv_set_master(pScrn)) 1004 return FALSE; 1005 1006 pScrn->pScreen = pScreen; 1007 1008 /* HW dependent - FIXME */ 1009 pScrn->displayWidth = pScrn->virtualX; 1010 1011 miClearVisualTypes(); 1012 1013 if (!miSetVisualTypes(pScrn->depth, 1014 miGetDefaultVisualMask(pScrn->depth), 1015 pScrn->rgbBits, pScrn->defaultVisual)) 1016 return FALSE; 1017 1018 if (!miSetPixmapDepths()) 1019 return FALSE; 1020 1021 pScrn->memPhysBase = 0; 1022 pScrn->fbOffset = 0; 1023 1024 if (!fbScreenInit(pScreen, NULL, 1025 pScrn->virtualX, pScrn->virtualY, 1026 pScrn->xDpi, pScrn->yDpi, 1027 pScrn->displayWidth, pScrn->bitsPerPixel)) 1028 return FALSE; 1029 1030 if (pScrn->bitsPerPixel > 8) { 1031 /* Fixup RGB ordering */ 1032 visual = pScreen->visuals + pScreen->numVisuals; 1033 while (--visual >= pScreen->visuals) { 1034 if ((visual->class | DynamicClass) == DirectColor) { 1035 visual->offsetRed = pScrn->offset.red; 1036 visual->offsetGreen = pScrn->offset.green; 1037 visual->offsetBlue = pScrn->offset.blue; 1038 visual->redMask = pScrn->mask.red; 1039 visual->greenMask = pScrn->mask.green; 1040 visual->blueMask = pScrn->mask.blue; 1041 } 1042 } 1043 } 1044 1045 fbPictureInit(pScreen, NULL, 0); 1046 1047 vmwgfx_wrap(ms, pScreen, BlockHandler, drv_block_handler); 1048 vmwgfx_wrap(ms, pScreen, CreateScreenResources, 1049 drv_create_screen_resources); 1050 1051 xf86SetBlackWhitePixels(pScreen); 1052 1053 ms->autoLayout = TRUE; 1054 vmw_ctrl_ext_init(pScrn); 1055 1056 if (ms->accelerate_render) { 1057 /* 1058 * Some versions of the Gallium loader close our drm file 1059 * descriptor if xa_tracker_create() fails (typically 2D VMs.) 1060 * While this is mostly fixed everywhere we implement a 1061 * workaround to avoid tracking down the same bug again and again 1062 * on those setups where this is not fixed in mesa. 1063 */ 1064 1065 int tmp_fd = dup(ms->fd); 1066 long flags = fcntl(ms->fd, F_GETFD); 1067 1068 ms->xat = xa_tracker_create(ms->fd); 1069 if (fcntl(ms->fd, F_GETFD) == -1) { 1070 if (tmp_fd == -1 || flags == -1 || fcntl(tmp_fd, F_SETFD, flags)) { 1071 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1072 "XA closed our DRM file descriptor. Giving up.\n"); 1073 return FALSE; 1074 } 1075 ms->fd = tmp_fd; 1076 } else { 1077 close(tmp_fd); 1078 } 1079 1080 if (!ms->xat) { 1081 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1082 "Failed to initialize Gallium3D Xa. " 1083 "No render acceleration available.\n"); 1084 ms->from_render = X_PROBED; 1085 } else { 1086 int major, minor, patch; 1087 1088 xa_tracker_version(&major, &minor, &patch); 1089 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1090 "Gallium3D XA version: %d.%d.%d.\n", 1091 major, minor, patch); 1092 1093 if (major < XA_VERSION_MAJOR_REQUIRED || 1094 major > XA_VERSION_MAJOR_COMPAT || 1095 (major == XA_VERSION_MAJOR_REQUIRED && 1096 minor < XA_VERSION_MINOR_REQUIRED)) { 1097 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1098 "Expecting %d.%d.x >= XA version < %d.0.0.\n", 1099 XA_VERSION_MAJOR_REQUIRED, 1100 XA_VERSION_MINOR_REQUIRED, 1101 XA_VERSION_MAJOR_COMPAT + 1); 1102 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1103 "No render acceleration available.\n"); 1104 xa_tracker_destroy(ms->xat); 1105 ms->xat = NULL; 1106 ms->from_render = X_PROBED; 1107 } 1108#ifdef DRI3 1109 if (major == VMW_XA_VERSION_MAJOR_DRI3 && 1110 minor >= VMW_XA_VERSION_MINOR_DRI3) { 1111 ms->xa_dri3 = TRUE; 1112 } else { 1113 ms->xa_dri3 = FALSE; 1114 LogMessage(X_WARNING, 1115 "Gallium3D XA version insufficient for dri3.\n"); 1116 } 1117#endif 1118 } 1119 if (ms->xat == NULL && ms->rendercheck) { 1120 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1121 "Turning off renercheck mode.\n"); 1122 ms->rendercheck = FALSE; 1123 ms->from_rendercheck = X_PROBED; 1124 } 1125 } 1126 1127 if (vmwgfx_is_hosted(ms->hdriver) && !ms->xat) { 1128 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1129 "Can't run hosted without XA. Giving up.\n"); 1130 return FALSE; 1131 } 1132 1133 if (!vmwgfx_saa_init(pScreen, ms->fd, ms->xat, &xorg_flush, 1134 ms->direct_presents, 1135 ms->only_hw_presents, 1136 ms->rendercheck, 1137 ms->has_screen_targets)) { 1138 FatalError("Failed to initialize SAA.\n"); 1139 } 1140 1141 ms->dri2_available = FALSE; 1142#ifdef DRI3 1143 ms->dri3_available = FALSE; 1144#endif 1145 if (ms->enable_dri) { 1146 if (ms->xat) { 1147 ms->dri2_available = xorg_dri2_init(pScreen); 1148 if (!ms->dri2_available) 1149 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1150 "Failed to initialize direct rendering DRI2.\n"); 1151#ifdef DRI3 1152 if (ms->xa_dri3) { 1153 ms->dri3_available = vmwgfx_dri3_init(pScreen); 1154 if (!ms->dri3_available) 1155 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1156 "Failed to initialize direct rendering DRI3.\n"); 1157 } 1158#endif /* DRI3 */ 1159 } else { 1160 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1161 "Skipped initialization of direct rendering due " 1162 "to lack of render acceleration.\n"); 1163 ms->from_dri = X_PROBED; 1164 } 1165 } 1166 1167 xf86DrvMsg(pScrn->scrnIndex, ms->from_render, "Render acceleration is %s.\n", 1168 (ms->xat != NULL) ? "enabled" : "disabled"); 1169 1170 xf86DrvMsg(pScrn->scrnIndex, ms->from_rendercheck, 1171 "Rendercheck mode is %s.\n", 1172 (ms->rendercheck) ? "enabled" : "disabled"); 1173 1174 xf86DrvMsg(pScrn->scrnIndex, ms->from_dri, 1175 "Direct rendering (DRI2 3D) is %s.\n", 1176 (ms->dri2_available) ? "enabled" : "disabled"); 1177#ifdef DRI3 1178 xf86DrvMsg(pScrn->scrnIndex, ms->from_dri, 1179 "Direct rendering (DRI3 3D) is %s.\n", 1180 (ms->dri3_available) ? "enabled" : "disabled"); 1181#endif 1182 if (ms->xat != NULL) { 1183 xf86DrvMsg(pScrn->scrnIndex, ms->from_dp, "Direct presents are %s.\n", 1184 (ms->direct_presents) ? "enabled" : "disabled"); 1185 if (ms->only_hw_presents) 1186 xf86DrvMsg(pScrn->scrnIndex, ms->from_hwp, "Hardware only presents " 1187 "are enabled.\n"); 1188 else 1189 xf86DrvMsg(pScrn->scrnIndex, ms->from_hwp, "Hardware only presents " 1190 "are %s.\n", 1191 (ms->has_screen_targets) ? "automatic per scanout" : 1192 "disabled"); 1193 } 1194 1195 xf86SetBackingStore(pScreen); 1196 xf86SetSilkenMouse(pScreen); 1197 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1198 1199 if (!vmwgfx_hosted_screen_init(ms->hdriver, ms->hosted, pScreen)) { 1200 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1201 "Failed hosted Screen init. Giving up.\n"); 1202 return FALSE; 1203 } 1204 1205 /* Need to extend HWcursor support to handle mask interleave */ 1206 if (!ms->SWCursor) { 1207 xf86_cursors_init(pScreen, 64, 64, 1208 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 1209 HARDWARE_CURSOR_ARGB | 1210 HARDWARE_CURSOR_UPDATE_UNHIDDEN); 1211 vmwgfx_wrap_use_hw_cursor(pScrn); 1212 } 1213 1214 /* Must force it before EnterVT, so we are in control of VT and 1215 * later memory should be bound when allocating, e.g rotate_mem */ 1216 pScrn->vtSema = TRUE; 1217 1218 pScreen->SaveScreen = xf86SaveScreen; 1219 vmwgfx_wrap(ms, pScreen, CloseScreen, drv_close_screen); 1220 1221 if (!xf86CrtcScreenInit(pScreen)) 1222 return FALSE; 1223 1224 if (!miCreateDefColormap(pScreen)) 1225 return FALSE; 1226 if (!xf86HandleColormaps(pScreen, 256, 8, drv_load_palette, NULL, 1227 CMAP_PALETTED_TRUECOLOR | 1228 CMAP_RELOAD_ON_MODE_SWITCH)) 1229 return FALSE; 1230 1231 xf86DPMSInit(pScreen, xf86DPMSSet, 0); 1232 1233 if (serverGeneration == 1) 1234 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1235 1236 1237 vmwgfx_wrap(ms, pScrn, EnterVT, drv_enter_vt); 1238 vmwgfx_wrap(ms, pScrn, LeaveVT, drv_leave_vt); 1239 vmwgfx_wrap(ms, pScrn, AdjustFrame, drv_adjust_frame); 1240 1241 /* 1242 * Must be called _after_ function wrapping. 1243 */ 1244 xorg_xv_init(pScreen); 1245 1246 return TRUE; 1247} 1248 1249static void 1250drv_adjust_frame(ADJUST_FRAME_ARGS_DECL) 1251{ 1252 SCRN_INFO_PTR(arg); 1253 modesettingPtr ms = modesettingPTR(pScrn); 1254 xf86CrtcConfigPtr config; 1255 xf86OutputPtr output; 1256 xf86CrtcPtr crtc; 1257 1258 if (vmwgfx_is_hosted(ms->hdriver)) 1259 return; 1260 1261 config = XF86_CRTC_CONFIG_PTR(pScrn); 1262 output = config->output[config->compat_output]; 1263 crtc = output->crtc; 1264 1265 if (crtc && crtc->enabled) { 1266 // crtc->funcs->set_mode_major(crtc, pScrn->currentMode, 1267 // RR_Rotate_0, x, y); 1268 crtc->x = output->initial_x + x; 1269 crtc->y = output->initial_y + y; 1270 } 1271} 1272 1273static void 1274drv_free_screen(FREE_SCREEN_ARGS_DECL) 1275{ 1276 SCRN_INFO_PTR(arg); 1277 modesettingPtr ms = modesettingPTR(pScrn); 1278 1279 vmwgfx_hosted_destroy(ms->hdriver, ms->hosted); 1280 drv_free_rec(pScrn); 1281} 1282 1283static void 1284drv_leave_vt(VT_FUNC_ARGS_DECL) 1285{ 1286 SCRN_INFO_PTR(arg); 1287 modesettingPtr ms = modesettingPTR(pScrn); 1288 1289 if (!vmwgfx_is_hosted(ms->hdriver)) { 1290 vmwgfx_cursor_bypass(ms->fd, 0, 0); 1291 vmwgfx_disable_scanout(pScrn); 1292 } 1293 1294 vmwgfx_saa_drop_master(pScrn->pScreen); 1295 1296 if (!vmwgfx_is_hosted(ms->hdriver) && !vmwgfx_use_server_fd(ms) && 1297 drmDropMaster(ms->fd)) 1298 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1299 "drmDropMaster failed: %s\n", strerror(errno)); 1300 ms->isMaster = FALSE; 1301 pScrn->vtSema = FALSE; 1302} 1303 1304/* 1305 * This gets called when gaining control of the VT, and from ScreenInit(). 1306 */ 1307static Bool 1308drv_enter_vt(VT_FUNC_ARGS_DECL) 1309{ 1310 SCRN_INFO_PTR(arg); 1311 modesettingPtr ms = modesettingPTR(pScrn); 1312 1313 if (!drv_set_master(pScrn)) 1314 return FALSE; 1315 1316 vmwgfx_saa_set_master(pScrn->pScreen); 1317 1318 if (!vmwgfx_is_hosted(ms->hdriver) && !xf86SetDesiredModes(pScrn)) 1319 return FALSE; 1320 1321 return TRUE; 1322} 1323 1324static Bool 1325drv_switch_mode(SWITCH_MODE_ARGS_DECL) 1326{ 1327 SCRN_INFO_PTR(arg); 1328 1329 return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 1330} 1331 1332static Bool 1333drv_close_screen(CLOSE_SCREEN_ARGS_DECL) 1334{ 1335 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1336 modesettingPtr ms = modesettingPTR(pScrn); 1337 Bool ret; 1338 1339 if (ms->cursor) { 1340 FreeCursor(ms->cursor, None); 1341 ms->cursor = NULL; 1342 } 1343 1344 if (ms->dri2_available) 1345 xorg_dri2_close(pScreen); 1346 1347 if (pScrn->vtSema) 1348 pScrn->LeaveVT(VT_FUNC_ARGS); 1349 1350 vmwgfx_uevent_fini(pScrn, ms); 1351 vmw_xv_close(pScreen); 1352 1353 pScrn->vtSema = FALSE; 1354 1355 vmwgfx_unwrap(ms, pScrn, EnterVT); 1356 vmwgfx_unwrap(ms, pScrn, LeaveVT); 1357 vmwgfx_unwrap(ms, pScrn, AdjustFrame); 1358 vmwgfx_unwrap(ms, pScreen, CloseScreen); 1359 vmwgfx_hosted_screen_close(ms->hdriver, ms->hosted); 1360 vmwgfx_unwrap(ms, pScreen, BlockHandler); 1361 vmwgfx_unwrap(ms, pScreen, CreateScreenResources); 1362 1363 ret = (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS); 1364 1365 if (ms->xat) 1366 xa_tracker_destroy(ms->xat); 1367 1368 return ret; 1369} 1370 1371static ModeStatus 1372drv_valid_mode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 1373{ 1374 return MODE_OK; 1375} 1376 1377/* vim: set sw=4 ts=8 sts=4: */ 1378