Changeset 54530 in vbox
- Timestamp:
- Feb 26, 2015 1:54:52 PM (10 years ago)
- Location:
- trunk/src/VBox/Additions/x11
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/x11/undefined_xorg
r53547 r54530 106 106 __register_frame_info_bases 107 107 rename 108 RRC hangeOutputProperty108 RRCrtcSet 109 109 RRGetInfo 110 RRScreenSizeSet 110 111 setenv 111 112 ShadowFBInit2 … … 157 158 xf86CrtcCreate 158 159 xf86CrtcScreenInit 160 xf86CrtcSetMode 159 161 xf86CrtcSetSizeRange 160 162 xf86DestroyCursorInfoRec -
trunk/src/VBox/Additions/x11/vboxvideo/README.testing
r54173 r54530 7 7 * Dynamic resizing should work, on CentOS 6 and later Linux guests it should 8 8 work without VBoxClient running. 9 * Disabling and enabling virtual screens ( only possible as of 4.4).9 * Disabling and enabling virtual screens (VBoxManage in 4.3). 10 10 * Dynamic resizing with one of more virtual screens disabled. 11 11 * Test switching to virtual terminals and back from windowed, full screen and 12 seamless modes. 12 seamless modes (seamless currently only works properly with VBoxClient 13 running). 13 14 * Test switching directly between normal, full-screen, seamless and scaled 14 15 modes. 15 * Test enabling and disabling guest screens from the host.16 16 * execute "xprop -root | grep VBOX" after resizing a screen: VBOX_SIZE_HINTS 17 17 should be set, and VBOX_SIZE_HINTS_MISMATCH should equal 0 on CentOS 6 and 18 later. 18 later (4.4 and later). 19 * Test re-ordering the virtual screen using the native guest operating system 20 tools and make sure that mouse integration still works as expected. 21 * Test disabling and re-enabling guest screens with the native system tools. 22 * Try disabling and re-enabling mouse integration and check that capturing 23 works with multiple guest screens. 19 24 * Shutting down and re-starting a virtual machine should restore the last size 20 for all monitors (note: currently only after log-in). 25 for all monitors (note: currently only after log-in). Full shut-down, not 26 a reboot. -
trunk/src/VBox/Additions/x11/vboxvideo/getmode.c
r54084 r54530 36 36 #endif 37 37 38 #ifdef VBOXVIDEO_1339 # ifdef RT_OS_LINUX40 # include "randrstr.h"41 # include "xf86_OSproc.h"42 # include <linux/input.h>43 # ifndef EVIOCGRAB44 # define EVIOCGRAB _IOW('E', 0x90, int)45 # endif46 # ifndef KEY_SWITCHVIDEOMODE47 # define KEY_SWITCHVIDEOMODE 22748 # endif49 # include <dirent.h>50 # include <errno.h>51 # include <fcntl.h>52 # include <unistd.h>53 # endif /* RT_OS_LINUX */54 #endif /* VBOXVIDEO_13 */55 38 /************************************************************************** 56 39 * Main functions * … … 99 82 } 100 83 101 /** vboxvideo's list of standard video modes */102 struct103 {104 /** mode width */105 uint32_t cx;106 /** mode height */107 uint32_t cy;108 } vboxStandardModes[] =109 {110 { 1600, 1200 },111 { 1440, 1050 },112 { 1280, 960 },113 { 1024, 768 },114 { 800, 600 },115 { 640, 480 },116 { 0, 0 }117 };118 enum119 {120 vboxNumStdModes = sizeof(vboxStandardModes) / sizeof(vboxStandardModes[0])121 };122 123 /**124 * Returns a standard mode which the host likes. Can be called multiple125 * times with the index returned by the previous call to get a list of modes.126 * @returns the index of the mode in the list, or 0 if no more modes are127 * available128 * @param pScrn the screen information structure129 * @param pScrn->bitsPerPixel130 * if this is non-null, only modes with this BPP will be131 * returned132 * @param cIndex the index of the last mode queried, or 0 to query the133 * first mode available. Note: the first index is 1134 * @param pcx where to store the mode's width135 * @param pcy where to store the mode's height136 * @param pcBits where to store the mode's BPP137 */138 unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,139 uint32_t *pcx, uint32_t *pcy)140 {141 unsigned i;142 143 VBVXASSERT(cIndex < vboxNumStdModes,144 ("cIndex = %d, vboxNumStdModes = %d\n", cIndex,145 vboxNumStdModes));146 for (i = cIndex; i < vboxNumStdModes - 1; ++i)147 {148 uint32_t cx = vboxStandardModes[i].cx;149 uint32_t cy = vboxStandardModes[i].cy;150 151 if (pcx)152 *pcx = cx;153 if (pcy)154 *pcy = cy;155 return i + 1;156 }157 return 0;158 }159 160 84 /** 161 85 * Allocates an empty display mode and links it into the doubly linked list of … … 188 112 * of the graphics modes that we wish to support, that is: 189 113 * - A dynamic mode in first place which will be updated by the RandR code. 190 * - Several standard modes.191 114 * - Any modes that the user requested in xorg.conf/XFree86Config. 192 115 */ … … 203 126 pMode = vboxAddEmptyScreenMode(pScrn); 204 127 vboxFillDisplayMode(pScrn, pMode, NULL, 1024, 768); 205 /* Add standard modes supported by the host */ 206 for ( ; ; ) 207 { 208 cIndex = vboxNextStandardMode(pScrn, cIndex, &cx, &cy); 209 if (cIndex == 0) 210 break; 211 pMode = vboxAddEmptyScreenMode(pScrn); 212 vboxFillDisplayMode(pScrn, pMode, NULL, cx, cy); 213 } 214 /* And finally any modes specified by the user. We assume here that 215 * the mode names reflect the mode sizes. */ 128 /* Add any modes specified by the user. We assume here that the mode names 129 * reflect the mode sizes. */ 216 130 for (i = 0; pScrn->display->modes && pScrn->display->modes[i]; i++) 217 131 { … … 224 138 } 225 139 226 /** Set the initial values for the guest screen size hints by reading saved 227 * values from files. */ 228 /** @todo Actually read the files instead of setting dummies. */ 140 /** Set the initial values for the guest screen size hints to standard values 141 * in case nothing else is available. */ 229 142 void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn) 230 143 { … … 242 155 pScrn->modes->HDisplay = pVBox->pScreens[0].aPreferredSize.cx; 243 156 pScrn->modes->VDisplay = pVBox->pScreens[0].aPreferredSize.cy; 244 /* RandR 1.1 quirk: make sure that the initial resolution is always present 245 * in the mode list as RandR will always advertise a mode of the initial 246 * virtual resolution via GetScreenInfo. */ 247 pMode = vboxAddEmptyScreenMode(pScrn); 248 vboxFillDisplayMode(pScrn, pMode, NULL, pVBox->pScreens[0].aPreferredSize.cx, 249 pVBox->pScreens[0].aPreferredSize.cy); 250 } 251 252 static void updateUseHardwareCursor(VBOXPtr pVBox, uint32_t fCursorCapabilities) 157 } 158 159 static bool useHardwareCursor(uint32_t fCursorCapabilities) 253 160 { 254 161 if ( !(fCursorCapabilities & VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER) 255 162 && (fCursorCapabilities & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE)) 256 pVBox->fUseHardwareCursor = true; 257 else 258 pVBox->fUseHardwareCursor = false; 259 } 260 261 # define SIZE_HINTS_PROPERTY "VBOX_SIZE_HINTS" 262 # define MOUSE_CAPABILITIES_PROPERTY "VBOX_MOUSE_CAPABILITIES" 263 264 /** Read in information about the most recent size hints requested for the 265 * guest screens. A client application sets the hint information as a root 266 * window property. */ 267 /* TESTING: dynamic resizing and absolute pointer toggling work on old guest X servers and recent ones on Linux at the log-in screen. */ 268 /** @note we try to maximise code coverage by typically using all code paths (HGSMI and properties) in a single X session. */ 269 void VBoxUpdateSizeHints(ScrnInfoPtr pScrn) 163 return true; 164 return false; 165 } 166 167 static void compareAndMaybeSetUseHardwareCursor(VBOXPtr pVBox, uint32_t fCursorCapabilities, bool *pfChanged, bool fSet) 168 { 169 if (pVBox->fUseHardwareCursor != useHardwareCursor(fCursorCapabilities)) 170 *pfChanged = true; 171 if (fSet) 172 pVBox->fUseHardwareCursor = useHardwareCursor(fCursorCapabilities); 173 } 174 175 #define SIZE_HINTS_PROPERTY "VBOX_SIZE_HINTS" 176 #define SIZE_HINTS_MISMATCH_PROPERTY "VBOX_SIZE_HINTS_MISMATCH" 177 #define MOUSE_CAPABILITIES_PROPERTY "VBOX_MOUSE_CAPABILITIES" 178 179 #define COMPARE_AND_MAYBE_SET(pDest, src, pfChanged, fSet) \ 180 do { \ 181 if (*(pDest) != (src)) \ 182 { \ 183 if (fSet) \ 184 *(pDest) = (src); \ 185 *(pfChanged) = true; \ 186 } \ 187 } while(0) 188 189 /** Read in information about the most recent size hints and cursor 190 * capabilities requested for the guest screens from a root window property set 191 * by an X11 client. Information obtained via HGSMI takes priority. */ 192 void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate) 270 193 { 271 194 VBOXPtr pVBox = VBOXGetRec(pScrn); 272 195 size_t cModesFromProperty, cDummy; 273 int32_t *paModeHints, *pfCursorCapabilities; 274 unsigned i; 275 uint32_t fCursorCapabilities; 276 bool fOldUseHardwareCursor = pVBox->fUseHardwareCursor; 196 int32_t *paModeHints, *pfCursorCapabilities; 197 int rc; 198 unsigned i; 199 bool fChanged = false; 200 int32_t fSizeMismatch; 277 201 278 202 if (vbvxGetIntegerPropery(pScrn, SIZE_HINTS_PROPERTY, &cModesFromProperty, &paModeHints) != VINF_SUCCESS) 279 203 paModeHints = NULL; 280 if ( vbvxGetIntegerPropery(pScrn, MOUSE_CAPABILITIES_PROPERTY, &cDummy, &pfCursorCapabilities) != VINF_SUCCESS281 || cDummy != 1)282 pfCursorCapabilities = NULL;283 #ifdef VBOXVIDEO_13284 if (!pVBox->fHaveReadHGSMIModeHintData && RT_SUCCESS(VBoxHGSMIGetModeHints(&pVBox->guestCtx, pVBox->cScreens,285 pVBox->paVBVAModeHints)))286 {287 for (i = 0; i < pVBox->cScreens; ++i)288 {289 if (pVBox->paVBVAModeHints[i].magic == VBVAMODEHINT_MAGIC)290 {291 pVBox->pScreens[i].aPreferredSize.cx = pVBox->paVBVAModeHints[i].cx;292 pVBox->pScreens[i].aPreferredSize.cy = pVBox->paVBVAModeHints[i].cy;293 pVBox->pScreens[i].afConnected = pVBox->paVBVAModeHints[i].fEnabled;294 /* Do not re-read this if we have data from HGSMI. */295 if (paModeHints != NULL && i < cModesFromProperty)296 pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];297 }298 }299 }300 if (!pVBox->fHaveReadHGSMIModeHintData)301 {302 if (RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &fCursorCapabilities)))303 updateUseHardwareCursor(pVBox, fCursorCapabilities);304 else305 pVBox->fUseHardwareCursor = false;306 /* Do not re-read this if we have data from HGSMI. */307 if (pfCursorCapabilities != NULL)308 pVBox->fLastCursorCapabilitiesFromProperty = *pfCursorCapabilities;309 }310 pVBox->fHaveReadHGSMIModeHintData = true;311 #endif312 204 if (paModeHints != NULL) 313 205 for (i = 0; i < cModesFromProperty && i < pVBox->cScreens; ++i) 314 { 315 if (paModeHints[i] != 0 && paModeHints[i] != pVBox->pScreens[i].lastModeHintFromProperty) 206 if (paModeHints[i] != 0) 316 207 { 317 208 if (paModeHints[i] == -1) 318 pVBox->pScreens[i].afConnected = false;209 COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, false, &fChanged, !pVBox->fHaveHGSMIModeHints); 319 210 else 320 211 { 321 pVBox->pScreens[i].aPreferredSize.cx = paModeHints[i] >> 16; 322 pVBox->pScreens[i].aPreferredSize.cy = paModeHints[i] & 0x8fff; 323 pVBox->pScreens[i].afConnected = true; 212 COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cx, (paModeHints[i] >> 16) & 0x8fff, &fChanged, 213 !pVBox->fHaveHGSMIModeHints); 214 COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cy, paModeHints[i] & 0x8fff, &fChanged, 215 !pVBox->fHaveHGSMIModeHints); 216 COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, true, &fChanged, !pVBox->fHaveHGSMIModeHints); 324 217 } 325 pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];326 218 } 219 if ( vbvxGetIntegerPropery(pScrn, MOUSE_CAPABILITIES_PROPERTY, &cDummy, &pfCursorCapabilities) == VINF_SUCCESS 220 && cDummy == 1) 221 compareAndMaybeSetUseHardwareCursor(pVBox, *pfCursorCapabilities, &fChanged, !pVBox->fHaveHGSMIModeHints); 222 fSizeMismatch = pVBox->fHaveHGSMIModeHints && fChanged; 223 vbvxSetIntegerPropery(pScrn, SIZE_HINTS_MISMATCH_PROPERTY, 1, &fSizeMismatch, false); 224 if (pfNeedUpdate != NULL) 225 *pfNeedUpdate = !pVBox->fHaveHGSMIModeHints && fChanged; 226 } 227 228 /** Read in information about the most recent size hints and cursor 229 * capabilities requested for the guest screens from HGSMI. */ 230 void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate) 231 { 232 VBOXPtr pVBox = VBOXGetRec(pScrn); 233 int rc; 234 unsigned i; 235 bool fChanged = false; 236 uint32_t fCursorCapabilities; 237 238 if (pfNeedUpdate != NULL) 239 *pfNeedUpdate = false; 240 if (!pVBox->fHaveHGSMIModeHints) 241 return; 242 rc = VBoxHGSMIGetModeHints(&pVBox->guestCtx, pVBox->cScreens, pVBox->paVBVAModeHints); 243 VBVXASSERT(rc == VINF_SUCCESS, ("VBoxHGSMIGetModeHints failed, rc=%d.\n", rc)); 244 for (i = 0; i < pVBox->cScreens; ++i) 245 if (pVBox->paVBVAModeHints[i].magic == VBVAMODEHINT_MAGIC) 246 { 247 COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cx, pVBox->paVBVAModeHints[i].cx & 0x8fff, &fChanged, true); 248 COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cy, pVBox->paVBVAModeHints[i].cy & 0x8fff, &fChanged, true); 249 COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, RT_BOOL(pVBox->paVBVAModeHints[i].fEnabled), &fChanged, true); 327 250 } 328 if (pfCursorCapabilities != NULL && *pfCursorCapabilities != pVBox->fLastCursorCapabilitiesFromProperty) 329 { 330 updateUseHardwareCursor(pVBox, (uint32_t)*pfCursorCapabilities); 331 pVBox->fLastCursorCapabilitiesFromProperty = *pfCursorCapabilities; 332 } 333 if (pVBox->fUseHardwareCursor != fOldUseHardwareCursor) 334 vbvxReprobeCursor(pScrn); 335 } 336 337 #ifndef VBOXVIDEO_13 338 339 /** The RandR "proc" vector, which we wrap with our own in order to notice 340 * when a client sends a GetScreenInfo request. */ 341 static int (*g_pfnVBoxRandRProc)(ClientPtr) = NULL; 342 /** The swapped RandR "proc" vector. */ 343 static int (*g_pfnVBoxRandRSwappedProc)(ClientPtr) = NULL; 344 345 /* TESTING: dynamic resizing and toggling cursor integration work with older guest X servers (1.2 and older). */ 346 static void vboxRandRDispatchCore(ClientPtr pClient) 347 { 348 xRRGetScreenInfoReq *pReq = (xRRGetScreenInfoReq *)pClient->requestBuffer; 349 WindowPtr pWin; 350 ScrnInfoPtr pScrn; 351 VBOXPtr pVBox; 352 DisplayModePtr pMode; 353 354 if (pClient->req_len != sizeof(xRRGetScreenInfoReq) >> 2) 355 return; 356 pWin = (WindowPtr)SecurityLookupWindow(pReq->window, pClient, 357 SecurityReadAccess); 358 if (!pWin) 359 return; 360 pScrn = xf86Screens[pWin->drawable.pScreen->myNum]; 361 pVBox = VBOXGetRec(pScrn); 362 TRACE_LOG("pVBox->fUseHardwareCursor=%u\n", pVBox->fUseHardwareCursor); 363 VBoxUpdateSizeHints(pScrn); 364 pMode = pScrn->modes; 365 if (pScrn->currentMode == pMode) 366 pMode = pMode->next; 367 pMode->HDisplay = pVBox->pScreens[0].aPreferredSize.cx; 368 pMode->VDisplay = pVBox->pScreens[0].aPreferredSize.cy; 369 } 370 371 static int vboxRandRDispatch(ClientPtr pClient) 372 { 373 xReq *pReq = (xReq *)pClient->requestBuffer; 374 375 if (pReq->data == X_RRGetScreenInfo) 376 vboxRandRDispatchCore(pClient); 377 return g_pfnVBoxRandRProc(pClient); 378 } 379 380 static int vboxRandRSwappedDispatch(ClientPtr pClient) 381 { 382 xReq *pReq = (xReq *)pClient->requestBuffer; 383 384 if (pReq->data == X_RRGetScreenInfo) 385 vboxRandRDispatchCore(pClient); 386 return g_pfnVBoxRandRSwappedProc(pClient); 387 } 388 389 static Bool vboxRandRCreateScreenResources(ScreenPtr pScreen) 390 { 391 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 392 VBOXPtr pVBox = VBOXGetRec(pScrn); 393 ExtensionEntry *pExt; 394 395 pScreen->CreateScreenResources = pVBox->pfnCreateScreenResources; 396 if (!pScreen->CreateScreenResources(pScreen)) 397 return FALSE; 398 /* I doubt we can be loaded twice - should I fail here? */ 399 if (g_pfnVBoxRandRProc) 400 return TRUE; 401 pExt = CheckExtension(RANDR_NAME); 402 if (!pExt) 403 { 404 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 405 "RandR extension not found, disabling dynamic resizing.\n"); 406 return TRUE; 407 } 408 if ( !ProcVector[pExt->base] 409 #if !defined(XF86_VERSION_CURRENT) \ 410 || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0) 411 /* SwappedProcVector is not exported in XFree86, so we will not support 412 * swapped byte order clients. I doubt this is a big issue. */ 413 || !SwappedProcVector[pExt->base] 414 #endif 415 ) 416 FatalError("RandR \"proc\" vector not initialised\n"); 417 g_pfnVBoxRandRProc = ProcVector[pExt->base]; 418 ProcVector[pExt->base] = vboxRandRDispatch; 419 #if !defined(XF86_VERSION_CURRENT) \ 420 || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0) 421 g_pfnVBoxRandRSwappedProc = SwappedProcVector[pExt->base]; 422 SwappedProcVector[pExt->base] = vboxRandRSwappedDispatch; 423 #endif 424 return TRUE; 425 } 426 427 /** Install our private RandR hook procedure, so that we can detect 428 * GetScreenInfo requests from clients to update our dynamic mode. This works 429 * by installing a wrapper around CreateScreenResources(), which will be called 430 * after RandR is initialised. The wrapper then in turn wraps the RandR "proc" 431 * vectors with its own handlers which will get called on any client RandR 432 * request. This should not be used in conjunction with RandR 1.2 or later. 433 * A couple of points of interest in our RandR 1.1 support: 434 * * We use the first two screen modes as dynamic modes. When a new mode hint 435 * arrives we update the first of the two which is not the current mode with 436 * the new size. 437 * * RandR 1.1 always advertises a mode of the size of the initial virtual 438 * resolution via GetScreenInfo(), so we make sure that a mode of that size 439 * is always present in the list. 440 * * RandR adds each new mode it sees to an internal array, but never removes 441 * entries. This array might end up getting rather long given that we can 442 * report a lot more modes than physical hardware. 443 */ 444 void VBoxSetUpRandR11(ScreenPtr pScreen) 445 { 446 VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]); 447 448 if (!pScreen->CreateScreenResources) 449 FatalError("called to early: CreateScreenResources not yet initialised\n"); 450 pVBox->pfnCreateScreenResources = pScreen->CreateScreenResources; 451 pScreen->CreateScreenResources = vboxRandRCreateScreenResources; 452 } 453 454 #endif /* !VBOXVIDEO_13 */ 455 456 #ifdef VBOXVIDEO_13 457 # ifdef RT_OS_LINUX 458 /* TESTING: dynamic resizing works on recent Linux guest X servers at the log-in screen. */ 459 /** @note to maximise code coverage we only read data from HGSMI once, and only when responding to an ACPI event. */ 460 static void acpiEventHandler(int fd, void *pvData) 461 { 462 ScreenPtr pScreen = (ScreenPtr)pvData; 463 VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]); 464 struct input_event event; 465 ssize_t rc; 466 467 pVBox->fHaveReadHGSMIModeHintData = false; 468 RRGetInfo(pScreen 469 # if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5 470 , TRUE 471 # endif 472 ); 473 VBVXASSERT(pVBox->fHaveReadHGSMIModeHintData == true, ("fHaveReadHGSMIModeHintData not set.\n")); 474 do 475 rc = read(fd, &event, sizeof(event)); 476 while (rc > 0 || (rc == -1 && errno == EINTR)); 477 /* Why do they return EAGAIN instead of zero bytes read like everyone else does? */ 478 VBVXASSERT(rc != -1 || errno == EAGAIN, ("Reading ACPI input event failed.\n")); 479 } 480 481 void VBoxSetUpLinuxACPI(ScreenPtr pScreen) 482 { 483 VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]); 484 struct dirent *pDirent; 485 DIR *pDir; 486 int fd = -1; 487 488 if (pVBox->fdACPIDevices != -1 || pVBox->hACPIEventHandler != NULL) 489 FatalError("ACPI input file descriptor not initialised correctly.\n"); 490 pDir = opendir("/dev/input"); 491 if (pDir == NULL) 492 return; 493 for (pDirent = readdir(pDir); pDirent != NULL; pDirent = readdir(pDir)) 494 { 495 if (strncmp(pDirent->d_name, "event", sizeof("event") - 1) == 0) 496 { 497 #define BITS_PER_BLOCK (sizeof(unsigned long) * 8) 498 char szFile[64] = "/dev/input/"; 499 char szDevice[64] = ""; 500 unsigned long afKeys[KEY_MAX / BITS_PER_BLOCK]; 501 502 strncat(szFile, pDirent->d_name, sizeof(szFile) - sizeof("/dev/input/")); 503 if (fd != -1) 504 close(fd); 505 fd = open(szFile, O_RDONLY | O_NONBLOCK); 506 if ( fd == -1 507 || ioctl(fd, EVIOCGNAME(sizeof(szDevice)), szDevice) == -1 508 || strcmp(szDevice, "Video Bus") != 0) 509 continue; 510 if ( ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(afKeys)), afKeys) == -1 511 || (( afKeys[KEY_SWITCHVIDEOMODE / BITS_PER_BLOCK] 512 >> KEY_SWITCHVIDEOMODE % BITS_PER_BLOCK) & 1) == 0) 513 break; 514 if (ioctl(fd, EVIOCGRAB, (void *)1) != 0) 515 break; 516 pVBox->hACPIEventHandler 517 = xf86AddGeneralHandler(fd, acpiEventHandler, pScreen); 518 if (pVBox->hACPIEventHandler == NULL) 519 break; 520 pVBox->fdACPIDevices = fd; 521 fd = -1; 522 break; 523 #undef BITS_PER_BLOCK 524 } 525 } 526 if (fd != -1) 527 close(fd); 528 closedir(pDir); 529 } 530 531 void VBoxCleanUpLinuxACPI(ScreenPtr pScreen) 532 { 533 VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]); 534 if (pVBox->fdACPIDevices != -1) 535 close(pVBox->fdACPIDevices); 536 pVBox->fdACPIDevices = -1; 537 xf86RemoveGeneralHandler(pVBox->hACPIEventHandler); 538 pVBox->hACPIEventHandler = NULL; 539 } 540 # endif /* RT_OS_LINUX */ 541 #endif /* VBOXVIDEO_13 */ 251 rc = VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &fCursorCapabilities); 252 VBVXASSERT(rc == VINF_SUCCESS, ("Getting VBOX_VBVA_CONF32_CURSOR_CAPABILITIES failed, rc=%d.\n", rc)); 253 compareAndMaybeSetUseHardwareCursor(pVBox, fCursorCapabilities, &fChanged, true); 254 if (pfNeedUpdate != NULL) 255 *pfNeedUpdate = fChanged; 256 } 257 258 #undef COMPARE_AND_MAYBE_SET -
trunk/src/VBox/Additions/x11/vboxvideo/helpers.c
r54040 r54530 55 55 } 56 56 57 /* TESTING: if this is broken, dynamic resizing will not work on old X servers (1.2 and older). */58 57 int vbvxGetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t *pcData, int32_t **ppaData) 59 58 { … … 64 63 if (!ROOT_WINDOW(pScrn)) 65 64 return VERR_NOT_FOUND; 66 atom = MakeAtom(pszName, strlen(pszName), FALSE);65 atom = MakeAtom(pszName, strlen(pszName), TRUE); 67 66 if (atom == BAD_RESOURCE) 68 67 return VERR_NOT_FOUND; … … 76 75 *ppaData = (int32_t *)prop->data; 77 76 return VINF_SUCCESS; 77 } 78 79 void vbvxSetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t cData, int32_t *paData, Bool fSendEvent) 80 { 81 Atom property_name; 82 int i; 83 84 property_name = MakeAtom(pszName, strlen(pszName), TRUE); 85 VBVXASSERT(property_name != BAD_RESOURCE, ("Failed to set atom \"%s\"\n", pszName)); 86 ChangeWindowProperty(ROOT_WINDOW(pScrn), property_name, XA_INTEGER, 32, PropModeReplace, cData, paData, fSendEvent); 78 87 } 79 88 -
trunk/src/VBox/Additions/x11/vboxvideo/setmode.c
r53966 r54530 75 75 * size of a new framebuffer. Framebuffer sizes larger than available VRAM 76 76 * be treated as zero and passed over. */ 77 void vb oxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY)77 void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize) 78 78 { 79 79 VBOXPtr pVBox = VBOXGetRec(pScrn); 80 uint64_t cbOldFB, cbNewFB;81 80 82 cbOldFB = pVBox->cbLine * pScrn->virtualX; 83 cbNewFB = vboxLineLength(pScrn, cNewX) * cNewY; 84 if (cbOldFB > (uint64_t)pVBox->cbFBMax) 85 cbOldFB = 0; 86 if (cbNewFB > (uint64_t)pVBox->cbFBMax) 87 cbNewFB = 0; 88 memset(pVBox->base, 0, max(cbOldFB, cbNewFB)); 81 /* Assume 32BPP - this is just a sanity test. */ 82 VBVXASSERT(cbOldSize / 4 <= INT16_MAX * INT16_MAX && cbNewSize / 4 <= INT16_MAX * INT16_MAX, 83 ("cbOldSize or cbNewSize is too big.\n")); 84 if (cbOldSize > (size_t)pVBox->cbFBMax) 85 cbOldSize = pVBox->cbFBMax; 86 if (cbNewSize > (size_t)pVBox->cbFBMax) 87 cbNewSize = pVBox->cbFBMax; 88 memset(pVBox->base, 0, max(cbOldSize, cbNewSize)); 89 89 } 90 90 91 91 /** Set a graphics mode. Poke any required values into registers, do an HGSMI 92 * mode set and tell the host we support advanced graphics functions. This 93 * procedure is complicated by the fact that X.Org can implicitly disable a 94 * screen by resizing the virtual framebuffer so that the screen is no longer 95 * inside it. We have to spot and handle this. 92 * mode set and tell the host we support advanced graphics functions. 96 93 */ 97 Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,98 unsigned cHeight, int x, int y)94 void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled, 95 bool fConnected, struct vbvxFrameBuffer *pFrameBuffer) 99 96 { 100 97 VBOXPtr pVBox = VBOXGetRec(pScrn); 101 uint32_t offStart, cwReal = cWidth; 102 bool fEnabled; 98 uint32_t offStart; 103 99 uint16_t fFlags; 104 100 int rc; 105 101 106 TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, displayWidth=%d\n", 107 cDisplay, cWidth, cHeight, x, y, pScrn->displayWidth); 108 offStart = y * pVBox->cbLine + x * vboxBPP(pScrn) / 8; 109 /* Deactivate the screen if the mode - specifically the virtual width - is 110 * too large for VRAM as we sometimes have to do this - see comments in 111 * VBOXPreInit. */ 112 if ( offStart + pVBox->cbLine * cHeight > pVBox->cbFBMax 113 || pVBox->cbLine * pScrn->virtualY > pVBox->cbFBMax) 114 return FALSE; 115 /* Deactivate the screen if it is outside of the virtual framebuffer and 116 * clamp it to lie inside if it is partly outside. */ 117 if (x >= pScrn->displayWidth || x + (int) cWidth <= 0) 118 return FALSE; 119 else 120 cwReal = RT_MIN((int) cWidth, pScrn->displayWidth - x); 121 TRACE_LOG("pVBox->pScreens[%u].fCrtcEnabled=%d, fOutputEnabled=%d\n", 122 cDisplay, (int)pVBox->pScreens[cDisplay].fCrtcEnabled, 123 (int)pVBox->pScreens[cDisplay].fOutputEnabled); 102 TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, fEnabled=%d, fConnected=%d, pFrameBuffer: { x0=%d, y0=%d, cWidth=%u, cHeight=%u, cBPP=%u }\n", 103 cDisplay, cWidth, cHeight, x, y, fEnabled, fConnected, pFrameBuffer->x0, pFrameBuffer->y0, pFrameBuffer->cWidth, 104 pFrameBuffer->cHeight, pFrameBuffer->cBPP); 105 VBVXASSERT(cWidth != 0 && cHeight != 0, ("cWidth = 0 or cHeight = 0\n")); 106 offStart = (y * pFrameBuffer->cWidth + x) * pFrameBuffer->cBPP / 8; 124 107 if (cDisplay == 0) 125 VBoxVideoSetModeRegisters(cwReal, cHeight, pScrn->displayWidth, 126 vboxBPP(pScrn), 0, x, y); 127 fEnabled = pVBox->pScreens[cDisplay].fCrtcEnabled 128 && pVBox->pScreens[cDisplay].fOutputEnabled; 108 VBoxVideoSetModeRegisters(cWidth, cHeight, pFrameBuffer->cWidth, pFrameBuffer->cBPP, 0, x, y); 129 109 fFlags = VBVA_SCREEN_F_ACTIVE; 130 fFlags |= (pVBox->pScreens[cDisplay].afConnected ? 0 131 : VBVA_SCREEN_F_DISABLED); 132 VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x, y, 133 offStart, pVBox->cbLine, cwReal, cHeight, 134 fEnabled ? vboxBPP(pScrn) : 0, fFlags); 135 if (cDisplay == 0) 136 { 137 rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pVBox->pScreens[0].aScreenLocation.x, 138 0 - pVBox->pScreens[0].aScreenLocation.y, pScrn->virtualX, pScrn->virtualY); 139 if (RT_FAILURE(rc)) 140 FatalError("Failed to update the input mapping.\n"); 141 } 142 return TRUE; 110 fFlags |= (fConnected ? 0 : VBVA_SCREEN_F_DISABLED); 111 VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x - pFrameBuffer->x0, y - pFrameBuffer->y0, offStart, 112 pFrameBuffer->cWidth * pFrameBuffer->cBPP / 8, cWidth, cHeight, 113 fEnabled ? pFrameBuffer->cBPP : 0, fFlags); 114 rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pFrameBuffer->x0, 0 - pFrameBuffer->y0, pFrameBuffer->cWidth, 115 pFrameBuffer->cHeight); 116 if (RT_FAILURE(rc)) 117 FatalError("Failed to update the input mapping.\n"); 143 118 } 144 119 145 /** Resize the virtual framebuffer. After resizing we reset all modes 146 * (X.Org 1.3+) to adjust them to the new framebuffer. 147 */ 148 Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height) 120 /** Tell the virtual mouse device about the new virtual desktop size. */ 121 void vbvxSetSolarisMouseRange(int width, int height) 149 122 { 150 ScreenPtr pScreen = pScrn->pScreen; 151 PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen); 152 VBOXPtr pVBox = VBOXGetRec(pScrn); 153 uint64_t cbLine = vboxLineLength(pScrn, width); 154 int displayWidth = vboxDisplayPitch(pScrn, cbLine); 123 #ifdef RT_OS_SOLARIS 155 124 int rc; 125 int hMouse = open("/dev/mouse", O_RDWR); 156 126 157 TRACE_LOG("width=%d, height=%d\n", width, height); 158 if ( width == pScrn->virtualX 159 && height == pScrn->virtualY 160 && displayWidth == pScrn->displayWidth) 161 return TRUE; 162 if (!pPixmap) { 163 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 164 "Failed to get the screen pixmap.\n"); 165 return FALSE; 166 } 167 if (cbLine > UINT32_MAX || cbLine * height >= pVBox->cbFBMax) 127 if (hMouse >= 0) 168 128 { 169 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 170 "Unable to set up a virtual screen size of %dx%d with %lu of %d Kb of video memory available. Please increase the video memory size.\n", 171 width, height, pVBox->cbFBMax / 1024, pScrn->videoRam); 172 return FALSE; 173 } 174 pScreen->ModifyPixmapHeader(pPixmap, width, height, 175 pScrn->depth, vboxBPP(pScrn), cbLine, 176 pVBox->base); 177 vboxClearVRAM(pScrn, width, height); 178 pScrn->virtualX = width; 179 pScrn->virtualY = height; 180 pScrn->displayWidth = displayWidth; 181 pVBox->cbLine = cbLine; 182 #ifdef VBOX_DRI_OLD 183 if (pVBox->useDRI) 184 VBOXDRIUpdateStride(pScrn, pVBox); 185 #endif 186 #ifdef VBOXVIDEO_13 187 /* Write the new values to the hardware */ 188 /** @todo why is this only for VBOXVIDEO_13? */ 189 { 190 unsigned i; 191 for (i = 0; i < pVBox->cScreens; ++i) 192 VBOXSetMode(pScrn, i, pVBox->pScreens[i].aScreenLocation.cx, 193 pVBox->pScreens[i].aScreenLocation.cy, 194 pVBox->pScreens[i].aScreenLocation.x, 195 pVBox->pScreens[i].aScreenLocation.y); 129 do { 130 Ms_screen_resolution Res = { height, width }; 131 rc = ioctl(hMouse, MSIOSRESOLUTION, &Res); 132 } while ((rc != 0) && (errno == EINTR)); 133 close(hMouse); 196 134 } 197 135 #else 198 rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pVBox->pScreens[0].aScreenLocation.x, 199 0 - pVBox->pScreens[0].aScreenLocation.y, pScrn->virtualX, pScrn->virtualY); 200 if (RT_FAILURE(rc)) 201 FatalError("Failed to update the input mapping.\n"); 136 (void)width; (void)height; 202 137 #endif 203 #ifdef RT_OS_SOLARIS204 /* Tell the virtual mouse device about the new virtual desktop size. */205 {206 int rc;207 int hMouse = open("/dev/mouse", O_RDWR);208 if (hMouse >= 0)209 {210 do {211 Ms_screen_resolution Res = { height, width };212 rc = ioctl(hMouse, MSIOSRESOLUTION, &Res);213 } while ((rc != 0) && (errno == EINTR));214 close(hMouse);215 }216 }217 #endif218 return TRUE;219 138 } -
trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c
r54478 r54530 80 80 81 81 #include "fb.h" 82 #include "os.h" 82 83 83 84 #include "vboxvideo.h" 84 85 #include <VBox/VBoxGuest.h> 86 #include <VBox/Hardware/VBoxVideoVBE.h> 85 87 #include "version-generated.h" 86 88 #include "product-generated.h" … … 98 100 /* #define DPMS_SERVER 99 101 #include "extensions/dpms.h" */ 102 103 /* ShadowFB support */ 104 #include "shadowfb.h" 100 105 101 106 /* VGA hardware functions for setting and restoring text mode */ … … 145 150 static void VBOXSaveMode(ScrnInfoPtr pScrn); 146 151 static void VBOXRestoreMode(ScrnInfoPtr pScrn); 152 static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fScreenInitTime); 153 154 #ifndef XF86_SCRN_INTERFACE 155 # define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum] 156 # define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex] 157 #endif 147 158 148 159 static inline void VBOXSetRec(ScrnInfoPtr pScrn) … … 152 163 VBOXPtr pVBox = (VBOXPtr)xnfcalloc(sizeof(VBOXRec), 1); 153 164 pScrn->driverPrivate = pVBox; 154 #if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)155 pVBox->fdACPIDevices = -1;156 #endif157 165 } 158 166 } … … 262 270 #endif /* !XORG_7X */ 263 271 272 /** Resize the virtual framebuffer. */ 273 static Bool adjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height) 274 { 275 ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 276 VBOXPtr pVBox = VBOXGetRec(pScrn); 277 int adjustedWidth = pScrn->bitsPerPixel == 16 ? (width + 1) & ~1 : width; 278 int cbLine = adjustedWidth * pScrn->bitsPerPixel / 8; 279 PixmapPtr pPixmap; 280 int rc; 281 282 TRACE_LOG("width=%d, height=%d\n", width, height); 283 VBVXASSERT(width >= 0 && height >= 0, ("Invalid negative width (%d) or height (%d)\n", width, height)); 284 if (pScreen == NULL) /* Not yet initialised. */ 285 return TRUE; 286 pPixmap = pScreen->GetScreenPixmap(pScreen); 287 VBVXASSERT(pPixmap != NULL, ("Failed to get the screen pixmap.\n")); 288 if ( adjustedWidth != pPixmap->drawable.width 289 || height != pPixmap->drawable.height) 290 { 291 if (adjustedWidth > INT16_MAX || height > INT16_MAX || (unsigned)cbLine * (unsigned)height >= pVBox->cbFBMax) 292 { 293 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 294 "Virtual framebuffer %dx%d too large (%u Kb available).\n", 295 adjustedWidth, height, (unsigned) pVBox->cbFBMax / 1024); 296 return FALSE; 297 } 298 vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel, 299 adjustedWidth * height * pScrn->bitsPerPixel); 300 pScreen->ModifyPixmapHeader(pPixmap, adjustedWidth, height, pScrn->depth, pScrn->bitsPerPixel, cbLine, pVBox->base); 301 } 302 pScrn->virtualX = adjustedWidth; 303 pScrn->virtualY = height; 304 pScrn->displayWidth = adjustedWidth; 305 pVBox->cbLine = cbLine; 306 #ifdef VBOX_DRI_OLD 307 if (pVBox->useDRI) 308 VBOXDRIUpdateStride(pScrn, pVBox); 309 #endif 310 return TRUE; 311 } 312 313 /** Set a video mode to the hardware, RandR 1.1 version. Since we no longer do 314 * virtual frame buffers, adjust the screen pixmap dimensions to match. */ 315 static void setModeRandR11(ScrnInfoPtr pScrn, DisplayModePtr pMode) 316 { 317 VBOXPtr pVBox = VBOXGetRec(pScrn); 318 struct vbvxFrameBuffer frameBuffer = { 0, 0, pMode->HDisplay, pMode->VDisplay, pScrn->bitsPerPixel}; 319 320 adjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay); 321 if (pMode->HDisplay != 0 && pMode->VDisplay != 0) 322 vbvxSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay, 0, 0, true, true, &frameBuffer); 323 } 324 264 325 #ifdef VBOXVIDEO_13 265 326 /* X.org 1.3+ mode-setting support ******************************************/ 327 328 /** Set a video mode to the hardware, RandR 1.2 version. If this is the first 329 * screen, re-set the current mode for all others (the offset for the first 330 * screen is always treated as zero by the hardware, so all other screens need 331 * to be changed to compensate for any changes!). The mode to set is taken 332 * from the X.Org Crtc structure. */ 333 static void setModeRandR12(ScrnInfoPtr pScrn, unsigned cScreen) 334 { 335 VBOXPtr pVBox = VBOXGetRec(pScrn); 336 unsigned i; 337 struct vbvxFrameBuffer frameBuffer = { pVBox->pScreens[0].paCrtcs->x, pVBox->pScreens[0].paCrtcs->y, pScrn->virtualX, 338 pScrn->virtualY, pScrn->bitsPerPixel }; 339 unsigned cFirst = cScreen; 340 unsigned cLast = cScreen != 0 ? cScreen + 1 : pVBox->cScreens; 341 342 for (i = cFirst; i < cLast; ++i) 343 if (pVBox->pScreens[i].paCrtcs->mode.HDisplay != 0 && pVBox->pScreens[i].paCrtcs->mode.VDisplay != 0) 344 vbvxSetMode(pScrn, i, pVBox->pScreens[i].paCrtcs->mode.HDisplay, pVBox->pScreens[i].paCrtcs->mode.VDisplay, 345 pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y, pVBox->pScreens[i].fPowerOn, 346 pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected, &frameBuffer); 347 } 348 349 /** Wrapper around setModeRandR12() to avoid exposing non-obvious semantics. 350 */ 351 static void setAllModesRandR12(ScrnInfoPtr pScrn) 352 { 353 setModeRandR12(pScrn, 0); 354 } 266 355 267 356 /* For descriptions of these functions and structures, see … … 272 361 { 273 362 VBOXPtr pVBox = VBOXGetRec(pScrn); 363 Bool rc; 364 unsigned i; 365 274 366 TRACE_LOG("width=%d, height=%d\n", cw, ch); 275 /* Save the size in case we need to re-set it later. */276 pVBox->FBSize.cx = cw;277 pVBox->FBSize.cy = ch;278 367 /* Don't fiddle with the hardware if we are switched 279 368 * to a virtual terminal. */ … … 283 372 return TRUE; 284 373 } 285 return VBOXAdjustScreenPixmap(pScrn, cw, ch); 374 rc = adjustScreenPixmap(pScrn, cw, ch); 375 /* Power-on all screens (the server expects this) and set the new pitch to them. */ 376 for (i = 0; i < pVBox->cScreens; ++i) 377 pVBox->pScreens[i].fPowerOn = true; 378 setAllModesRandR12(pScrn); 379 vbvxSetSolarisMouseRange(cw, ch); 380 return rc; 286 381 } 287 382 … … 293 388 vbox_crtc_dpms(xf86CrtcPtr crtc, int mode) 294 389 { 295 VBOXPtr pVBox = VBOXGetRec(crtc->scrn); 390 ScrnInfoPtr pScrn = crtc->scrn; 391 VBOXPtr pVBox = VBOXGetRec(pScrn); 296 392 unsigned cDisplay = (uintptr_t)crtc->driver_private; 297 bool fEnabled = (mode != DPMSModeOff); 298 299 TRACE_LOG("cDisplay=%u, mode=%i\n", cDisplay, mode); 300 pVBox->pScreens[cDisplay].fCrtcEnabled = fEnabled; 301 /* Don't fiddle with the hardware if we are switched 302 * to a virtual terminal. */ 303 if (!crtc->scrn->vtSema) { 304 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, 305 "We do not own the active VT, exiting.\n"); 306 return; 307 } 308 if ( pVBox->pScreens[cDisplay].aScreenLocation.cx 309 && pVBox->pScreens[cDisplay].aScreenLocation.cy) 310 VBOXSetMode(crtc->scrn, cDisplay, 311 pVBox->pScreens[cDisplay].aScreenLocation.cx, 312 pVBox->pScreens[cDisplay].aScreenLocation.cy, 313 pVBox->pScreens[cDisplay].aScreenLocation.x, 314 pVBox->pScreens[cDisplay].aScreenLocation.y); 393 394 TRACE_LOG("mode=%d\n", mode); 395 pVBox->pScreens[cDisplay].fPowerOn = (mode != DPMSModeOff); 396 setModeRandR12(pScrn, cDisplay); 315 397 } 316 398 … … 345 427 TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name, 346 428 adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y); 347 pVBox->pScreens[cDisplay].fCrtcEnabled = true; 348 pVBox->pScreens[cDisplay].fOutputEnabled = true; 429 pVBox->pScreens[cDisplay].fPowerOn = true; 349 430 pVBox->pScreens[cDisplay].aScreenLocation.cx = adjusted_mode->HDisplay; 350 431 pVBox->pScreens[cDisplay].aScreenLocation.cy = adjusted_mode->VDisplay; … … 359 440 return; 360 441 } 361 VBOXSetMode(crtc->scrn, cDisplay, adjusted_mode->HDisplay, 362 adjusted_mode->VDisplay, x, y); 442 setModeRandR12(crtc->scrn, cDisplay); 363 443 } 364 444 … … 402 482 vbox_output_dpms (xf86OutputPtr output, int mode) 403 483 { 404 VBOXPtr pVBox = VBOXGetRec(output->scrn); 405 unsigned cDisplay = (uintptr_t)output->driver_private; 406 bool fEnabled = (mode == DPMSModeOn); 407 408 TRACE_LOG("cDisplay=%u, mode=%i\n", cDisplay, mode); 409 pVBox->pScreens[cDisplay].fOutputEnabled = fEnabled; 410 /* Don't fiddle with the hardware if we are switched 411 * to a virtual terminal. */ 412 if (!output->scrn->vtSema) { 413 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 414 "We do not own the active VT, exiting.\n"); 415 return; 416 } 417 if ( pVBox->pScreens[cDisplay].aScreenLocation.cx 418 && pVBox->pScreens[cDisplay].aScreenLocation.cy) 419 VBOXSetMode(output->scrn, cDisplay, 420 pVBox->pScreens[cDisplay].aScreenLocation.cx, 421 pVBox->pScreens[cDisplay].aScreenLocation.cy, 422 pVBox->pScreens[cDisplay].aScreenLocation.x, 423 pVBox->pScreens[cDisplay].aScreenLocation.y); 484 (void)output; (void)mode; 424 485 } 425 486 … … 498 559 uint32_t x, y, iScreen; 499 560 iScreen = (uintptr_t)output->driver_private; 500 VBoxUpdateSizeHints(pScrn);501 561 pMode = vbox_output_add_mode(pVBox, &pModes, NULL, pVBox->pScreens[iScreen].aPreferredSize.cx, 502 562 pVBox->pScreens[iScreen].aPreferredSize.cy, TRUE, FALSE); 503 563 VBOXEDIDSet(output, pMode); 504 /* Add standard modes supported by the host */505 for ( ; ; )506 {507 cIndex = vboxNextStandardMode(pScrn, cIndex, &x, &y);508 if (cIndex == 0)509 break;510 vbox_output_add_mode(pVBox, &pModes, NULL, x, y, FALSE, FALSE);511 }512 513 /* Also report any modes the user may have requested in the xorg.conf514 * configuration file. */515 for (i = 0; pScrn->display->modes[i] != NULL; i++)516 {517 if (2 == sscanf(pScrn->display->modes[i], "%ux%u", &x, &y))518 vbox_output_add_mode(pVBox, &pModes, pScrn->display->modes[i], x, y, FALSE, TRUE);519 }520 564 TRACE_EXIT(); 521 565 return pModes; … … 617 661 618 662 #ifndef XF86_SCRN_INTERFACE 619 # define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]620 # define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]621 663 # define SCRNINDEXAPI(pfn) pfn ## Index 622 664 static Bool VBOXScreenInitIndex(int scrnIndex, ScreenPtr pScreen, int argc, … … 889 931 890 932 /* Set the right virtual resolution. */ 891 pScrn->virtualX = pScrn-> currentMode->HDisplay;933 pScrn->virtualX = pScrn->bitsPerPixel == 16 ? (pScrn->currentMode->HDisplay + 1) & ~1 : pScrn->currentMode->HDisplay; 892 934 pScrn->virtualY = pScrn->currentMode->VDisplay; 893 935 … … 895 937 896 938 /* Needed before we initialise DRI. */ 897 p VBox->cbLine = vboxLineLength(pScrn, pScrn->virtualX);898 p Scrn->displayWidth = vboxDisplayPitch(pScrn, pVBox->cbLine);939 pScrn->displayWidth = pScrn->virtualX; 940 pVBox->cbLine = pScrn->virtualX * pScrn->bitsPerPixel / 8; 899 941 900 942 xf86PrintModes(pScrn); … … 985 1027 if (property_name == BAD_RESOURCE) 986 1028 FatalError("Failed to retrieve \"HAS_VT\" atom\n"); 1029 if (ROOT_WINDOW(pScrn) == NULL) 1030 return; 987 1031 ChangeWindowProperty(ROOT_WINDOW(pScrn), property_name, XA_INTEGER, 32, 988 1032 PropModeReplace, 1, &value, TRUE); 989 1033 } 990 1034 #endif /* SET_HAVE_VT_PROPERTY */ 1035 1036 #ifdef VBOXVIDEO_13 1037 static void getVirtualSize(ScrnInfoPtr pScrn, int *px, int *py) 1038 { 1039 VBOXPtr pVBox = VBOXGetRec(pScrn); 1040 unsigned i; 1041 1042 *px = 0; 1043 *py = 0; 1044 for (i = 0; i < pVBox->cScreens; ++i) 1045 { 1046 if (pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected) 1047 { 1048 *px += pVBox->pScreens[i].aPreferredSize.cx; 1049 *py = RT_MAX(*py, VBVXCAST(int, pVBox->pScreens[i].aPreferredSize.cy)); 1050 } 1051 } 1052 } 1053 #endif 1054 1055 static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fScreenInitTime) 1056 { 1057 VBOXPtr pVBox = VBOXGetRec(pScrn); 1058 #ifdef VBOXVIDEO_13 1059 unsigned i; 1060 int x, y; 1061 #else 1062 DisplayModePtr pNewMode; 1063 #endif 1064 1065 TRACE_LOG("fScreenInitTime=%d\n", fScreenInitTime); 1066 #ifdef VBOXVIDEO_13 1067 # if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5 1068 RRGetInfo(xf86ScrnToScreen(pScrn), TRUE); 1069 # else 1070 RRGetInfo(xf86ScrnToScreen(pScrn)); 1071 # endif 1072 getVirtualSize(pScrn, &x, &y); 1073 if (fScreenInitTime) 1074 { 1075 pScrn->virtualX = x; 1076 pScrn->virtualY = y; 1077 } 1078 else 1079 RRScreenSizeSet(xf86ScrnToScreen(pScrn), x, y, xf86ScrnToScreen(pScrn)->mmWidth, xf86ScrnToScreen(pScrn)->mmHeight); 1080 x = 0; 1081 for (i = 0; i < pVBox->cScreens; ++i) 1082 { 1083 if (fScreenInitTime) 1084 xf86CrtcSetMode(pVBox->pScreens[i].paCrtcs, pVBox->pScreens[i].paOutputs->probed_modes, RR_Rotate_0, x, 0); 1085 else 1086 RRCrtcSet(pVBox->pScreens[i].paCrtcs->randr_crtc, pVBox->pScreens[i].paOutputs->randr_output->modes[0], x, 0, 1087 RR_Rotate_0, 1, &pVBox->pScreens[i].paOutputs->randr_output); 1088 if (pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected) 1089 x += pVBox->pScreens[i].aPreferredSize.cx; 1090 } 1091 #else /* !VBOXVIDEO_13 */ 1092 pNewMode = pScrn->modes != pScrn->currentMode ? pScrn->modes : pScrn->modes->next; 1093 pNewMode->HDisplay = pVBox->pScreens[0].aPreferredSize.cx; 1094 pNewMode->VDisplay = pVBox->pScreens[0].aPreferredSize.cy; 1095 #endif 1096 vbvxReprobeCursor(pScrn); 1097 } 1098 1099 /* We update the size hints from the X11 property set by VBoxClient every time 1100 * that the X server goes to sleep (to catch the property change request). 1101 * Although this is far more often than necessary it should not have real-life 1102 * performance consequences and allows us to simplify the code quite a bit. */ 1103 static void updateSizeHintsBlockHandler(pointer pData, OSTimePtr pTimeout, pointer pReadmask) 1104 { 1105 ScrnInfoPtr pScrn = (ScrnInfoPtr)pData; 1106 VBOXPtr pVBox = VBOXGetRec(pScrn); 1107 bool fNeedUpdate; 1108 1109 (void)pTimeout; 1110 (void)pReadmask; 1111 if (!pScrn->vtSema || ROOT_WINDOW(pScrn) == NULL) 1112 return; 1113 vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, &fNeedUpdate); 1114 if (fNeedUpdate || pVBox->fForceModeUpdate) 1115 setSizesAndCursorIntegration(pScrn, false); 1116 } 1117 1118 /* We update the size hints from the host every time that the X server is woken 1119 * up by a client. Although this is far more often than necessary it should 1120 * not have real-life performance consequences and allows us to simplify the 1121 * code quite a bit. */ 1122 static void updateSizeHintsWakeupHandler(pointer pData, int i, pointer pLastSelectMask) 1123 { 1124 #ifdef VBOXVIDEO_13 1125 ScrnInfoPtr pScrn = (ScrnInfoPtr)pData; 1126 bool fNeedUpdate; 1127 1128 (void)i; 1129 (void)pLastSelectMask; 1130 if (!pScrn->vtSema || ROOT_WINDOW(pScrn) == NULL) 1131 return; 1132 vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, &fNeedUpdate); 1133 if (fNeedUpdate) 1134 setSizesAndCursorIntegration(pScrn, false); 1135 #else 1136 (void)pData; (void)i; (void)pLastSelectMask; 1137 #endif 1138 } 991 1139 992 1140 /* … … 1062 1210 pScrn->vtSema = TRUE; 1063 1211 1064 #if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX) 1065 VBoxSetUpLinuxACPI(pScreen); 1066 #endif 1067 1068 vbox_open (pScrn, pScreen, pVBox); 1212 if (!VBoxHGSMIIsSupported()) 1213 { 1214 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Graphics device too old to support.\n"); 1215 return FALSE; 1216 } 1217 vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024); 1218 pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx); 1219 pVBox->pScreens = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->pScreens)); 1220 pVBox->paVBVAModeHints = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->paVBVAModeHints)); 1221 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n", pVBox->cScreens); 1069 1222 vboxEnableVbva(pScrn); 1223 /* Set up the dirty rectangle handler. It will be added into a function 1224 * chain and gets removed when the screen is cleaned up. */ 1225 if (ShadowFBInit2(pScreen, NULL, vbvxHandleDirtyRect) != TRUE) 1226 return FALSE; 1070 1227 VBoxInitialiseSizeHints(pScrn); 1228 /* Get any screen size hints from HGSMI. Do not yet try to access X11 1229 * properties, as they are not yet set up, and nor are the clients that 1230 * might have set them. */ 1231 vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, NULL); 1071 1232 1072 1233 #ifdef VBOXVIDEO_13 … … 1104 1265 /* Set a sane minimum and maximum mode size to match what the hardware 1105 1266 * supports. */ 1106 xf86CrtcSetSizeRange(pScrn, 64, 64, 16384, 16384);1267 xf86CrtcSetSizeRange(pScrn, 64, 64, VBE_DISPI_MAX_XRES, VBE_DISPI_MAX_YRES); 1107 1268 1108 1269 /* Now create our initial CRTC/output configuration. */ … … 1112 1273 } 1113 1274 1114 /* Initialise randr 1.2 mode-setting functions and set first mode. 1115 * Note that the mode won't be usable until the server has resized the 1116 * framebuffer to something reasonable. */ 1275 /* Initialise randr 1.2 mode-setting functions. */ 1117 1276 if (!xf86CrtcScreenInit(pScreen)) { 1118 1277 return FALSE; 1119 1278 } 1120 1279 1121 if (!xf86SetDesiredModes(pScrn)) { 1280 setSizesAndCursorIntegration(pScrn, true); 1281 #else /* !VBOXVIDEO_13 */ 1282 /* set first video mode */ 1283 if (!VBOXSwitchMode(pScrn, pScrn->currentMode)) 1122 1284 return FALSE; 1123 } 1124 #else /* !VBOXVIDEO_13 */ 1125 VBoxSetUpRandR11(pScreen); 1126 /* set first video mode */ 1127 if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay, 1128 pScrn->currentMode->VDisplay, pScrn->frameX0, 1129 pScrn->frameY0)) 1130 return FALSE; 1131 /* Save the size in case we need to re-set it later. */ 1132 pVBox->FBSize.cx = pScrn->currentMode->HDisplay; 1133 pVBox->FBSize.cy = pScrn->currentMode->VDisplay; 1134 pVBox->pScreens[0].aScreenLocation.cx = pScrn->currentMode->HDisplay; 1135 pVBox->pScreens[0].aScreenLocation.cy = pScrn->currentMode->VDisplay; 1136 pVBox->pScreens[0].aScreenLocation.x = pScrn->frameX0; 1137 pVBox->pScreens[0].aScreenLocation.y = pScrn->frameY0; 1138 #endif /* !VBOXVIDEO_13 */ 1285 #endif 1286 1287 /* Register block and wake-up handlers for getting new screen size hints. */ 1288 RegisterBlockAndWakeupHandlers(updateSizeHintsBlockHandler, updateSizeHintsWakeupHandler, (pointer)pScrn); 1139 1289 1140 1290 /* software cursor */ … … 1187 1337 1188 1338 TRACE_ENTRY(); 1189 vboxClearVRAM(pScrn, 0, 0);1190 1339 #ifdef VBOX_DRI_OLD 1191 1340 if (pVBox->useDRI) … … 1198 1347 } 1199 1348 #endif 1349 vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024); 1200 1350 vboxEnableVbva(pScrn); 1201 /* Re-assert this in case we had a change request while switched out. */ 1202 if (pVBox->FBSize.cx && pVBox->FBSize.cy) 1203 VBOXAdjustScreenPixmap(pScrn, pVBox->FBSize.cx, pVBox->FBSize.cy); 1204 #ifdef VBOXVIDEO_13 1205 if (!xf86SetDesiredModes(pScrn)) 1206 return FALSE; 1207 #else 1208 if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay, 1209 pScrn->currentMode->VDisplay, pScrn->frameX0, 1210 pScrn->frameY0)) 1211 return FALSE; 1212 #endif 1351 /* Re-set video mode */ 1352 vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, NULL); 1353 vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, NULL); 1354 setSizesAndCursorIntegration(pScrn, false); 1213 1355 #ifdef SET_HAVE_VT_PROPERTY 1214 1356 updateHasVTProperty(pScrn, TRUE); … … 1230 1372 #endif 1231 1373 vboxDisableVbva(pScrn); 1232 vb oxClearVRAM(pScrn, 0, 0);1374 vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel, 0); 1233 1375 #ifdef VBOX_DRI_OLD 1234 1376 if (pVBox->useDRI) … … 1261 1403 #endif 1262 1404 vboxDisableVbva(pScrn); 1263 vb oxClearVRAM(pScrn, 0, 0);1405 vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel, 0); 1264 1406 } 1265 1407 #ifdef VBOX_DRI … … 1287 1429 1288 1430 pScreen->CloseScreen = pVBox->CloseScreen; 1289 #if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)1290 VBoxCleanUpLinuxACPI(pScreen);1291 #endif1292 1431 #ifndef XF86_SCRN_INTERFACE 1293 1432 return pScreen->CloseScreen(pScreen->myNum, pScreen); … … 1300 1439 { 1301 1440 VBOXPtr pVBox; 1302 Bool rc ;1441 Bool rc = TRUE; 1303 1442 1304 1443 TRACE_LOG("HDisplay=%d, VDisplay=%d\n", pMode->HDisplay, pMode->VDisplay); 1305 #ifndef VBOXVIDEO_131306 pVBox = VBOXGetRec(pScrn);1307 /* Save the size in case we need to re-set it later. */1308 pVBox->FBSize.cx = pMode->HDisplay;1309 pVBox->FBSize.cy = pMode->VDisplay;1310 pVBox->pScreens[0].aScreenLocation.cx = pMode->HDisplay;1311 pVBox->pScreens[0].aScreenLocation.cy = pMode->VDisplay;1312 pVBox->pScreens[0].aScreenLocation.x = pScrn->frameX0;1313 pVBox->pScreens[0].aScreenLocation.y = pScrn->frameY0;1314 #endif1315 1444 if (!pScrn->vtSema) 1316 1445 { … … 1322 1451 rc = xf86SetSingleMode(pScrn, pMode, RR_Rotate_0); 1323 1452 #else 1324 VBOXAdjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay); 1325 rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay, 1326 pScrn->frameX0, pScrn->frameY0); 1453 setModeRandR11(pScrn, pMode); 1327 1454 #endif 1328 1455 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE"); … … 1331 1458 1332 1459 static void VBOXAdjustFrame(ScrnInfoPtr pScrn, int x, int y) 1333 { 1334 VBOXPtr pVBox = VBOXGetRec(pScrn); 1335 1336 TRACE_ENTRY(); 1337 pVBox->pScreens[0].aScreenLocation.x = x; 1338 pVBox->pScreens[0].aScreenLocation.y = y; 1339 /* Don't fiddle with the hardware if we are switched 1340 * to a virtual terminal. */ 1341 if (!pScrn->vtSema) 1342 { 1343 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1344 "We do not own the active VT, exiting.\n"); 1345 return; 1346 } 1347 VBOXSetMode(pScrn, 0, pVBox->pScreens[0].aScreenLocation.cx, 1348 pVBox->pScreens[0].aScreenLocation.cy, x, y); 1349 TRACE_EXIT(); 1350 } 1460 { (void)pScrn; (void)x; (void)y; } 1351 1461 1352 1462 static void VBOXFreeScreen(ScrnInfoPtr pScrn) -
trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h
r54324 r54530 95 95 vbvxAbortServer(); \ 96 96 } 97 98 #define VBVXCAST(type, val) \ 99 ((long long)(type)(val) == (long long)(val) \ 100 && (unsigned long long)(type)(val) == (unsigned long long)(val) \ 101 ? ((type)(val)) \ 102 : (vbvxMsg("Cannot convert " #val " to " #type ".\n"), vbvxAbortServer(), 0)) 97 103 98 104 #define BOOL_STR(a) ((a) ? "TRUE" : "FALSE") … … 148 154 RTRECT2 aScreenLocation; 149 155 /** Is this CRTC enabled or in DPMS off state? */ 150 Bool fCrtcEnabled; 151 /** Is this output enabled or in DPMS low power state? */ 152 Bool fOutputEnabled; 156 Bool fPowerOn; 153 157 #ifdef VBOXVIDEO_13 154 158 /** The virtual crtcs. */ … … 165 169 /** Has this screen been enabled by the host? */ 166 170 Bool afConnected; 167 /** The last mode hint data read from the X11 property. */ 168 int32_t lastModeHintFromProperty; 171 Bool afLastConnected; 169 172 }; 170 173 … … 198 201 /** Do we currently want to use the host cursor? */ 199 202 Bool fUseHardwareCursor; 200 /** The last cursor capabilities data read from the X11 property. */201 int32_t fLastCursorCapabilitiesFromProperty;202 203 /** Number of screens attached */ 203 204 uint32_t cScreens; 204 205 /** Information about each virtual screen. */ 205 206 struct VBoxScreen *pScreens; 206 /** The last requested framebuffer size. */ 207 RTRECTSIZE FBSize; 208 #ifdef VBOXVIDEO_13 207 /** Can we get mode hint and cursor integration information from HGSMI? */ 208 bool fHaveHGSMIModeHints; 209 209 /** Array of structures for receiving mode hints. */ 210 210 VBVAMODEHINT *paVBVAModeHints; 211 # ifdef RT_OS_LINUX 212 /** Input device file descriptor for getting ACPI hot-plug events. */ 213 int fdACPIDevices; 214 /** Input handler handle for ACPI hot-plug listener. */ 215 void *hACPIEventHandler; 216 # endif 217 /** Have we read all available HGSMI mode hint data? */ 218 bool fHaveReadHGSMIModeHintData; 219 #else 220 /** The original CreateScreenResources procedure which we wrap with our own. 221 */ 222 CreateScreenResourcesProcPtr pfnCreateScreenResources; 223 #endif 211 /** Should we force a screen mode update next time the handler is called? */ 212 bool fForceModeUpdate; 224 213 /** HGSMI guest heap context */ 225 214 HGSMIGUESTCOMMANDCONTEXT guestCtx; … … 244 233 #define VBOXGetRec vbvxGetRec /* Temporary */ 245 234 extern int vbvxGetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t *pcData, int32_t **ppaData); 235 extern void vbvxSetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t cData, int32_t *paData, Bool fSendEvent); 246 236 extern void vbvxReprobeCursor(ScrnInfoPtr pScrn); 247 237 248 238 /* setmode.c */ 239 240 /** Structure describing the virtual frame buffer. It starts at the beginning 241 * of the video RAM. */ 242 struct vbvxFrameBuffer { 243 /** X offset of first screen in frame buffer. */ 244 int x0; 245 /** Y offset of first screen in frame buffer. */ 246 int y0; 247 /** Frame buffer virtual width. */ 248 unsigned cWidth; 249 /** Frame buffer virtual height. */ 250 unsigned cHeight; 251 /** Bits per pixel. */ 252 unsigned cBPP; 253 }; 254 255 extern void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize); 256 extern void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled, 257 bool fConnected, struct vbvxFrameBuffer *pFrameBuffer); 258 extern void vbvxSetSolarisMouseRange(int width, int height); 259 260 /* pointer.c */ 249 261 extern Bool vbox_cursor_init (ScreenPtr pScreen); 250 extern void vbox_open (ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox);251 262 extern void vbox_close (ScrnInfoPtr pScrn, VBOXPtr pVBox); 252 263 264 /* vbva.c */ 265 extern void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects); 266 extern void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM); 253 267 extern Bool vboxEnableVbva(ScrnInfoPtr pScrn); 254 268 extern void vboxDisableVbva(ScrnInfoPtr pScrn); 255 269 256 270 /* getmode.c */ 257 extern unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,258 uint32_t *pcx, uint32_t *pcy);259 271 extern void vboxAddModes(ScrnInfoPtr pScrn); 260 272 extern void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn); 261 extern void VBoxUpdateSizeHints(ScrnInfoPtr pScrn); 262 #ifndef VBOXVIDEO_13 263 extern void VBoxSetUpRandR11(ScreenPtr pScreen); 264 #else 265 void VBoxSetUpLinuxACPI(ScreenPtr pScreen); 266 void VBoxCleanUpLinuxACPI(ScreenPtr pScreen); 267 #endif 273 extern void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate); 274 extern void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate); 268 275 269 276 /* DRI stuff */ … … 279 286 #endif 280 287 281 /* Utilities */282 283 /** Calculate the BPP from the screen depth */284 static inline uint16_t vboxBPP(ScrnInfoPtr pScrn)285 {286 return pScrn->depth == 24 ? 32 : 16;287 }288 289 /** Calculate the scan line length for a display width */290 static inline int32_t vboxLineLength(ScrnInfoPtr pScrn, int32_t cDisplayWidth)291 {292 uint32_t cbLine = (cDisplayWidth * vboxBPP(pScrn) / 8 + 3) & ~3;293 return cbLine < INT32_MAX ? cbLine : INT32_MAX;294 }295 296 /** Calculate the display pitch from the scan line length */297 static inline int32_t vboxDisplayPitch(ScrnInfoPtr pScrn, int32_t cbLine)298 {299 return cbLine * 8 / vboxBPP(pScrn);300 }301 302 extern void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY);303 extern Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,304 unsigned cHeight, int x, int y);305 extern Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height);306 307 288 #endif /* _VBOXVIDEO_H_ */ 308 289 -
trunk/src/VBox/Additions/x11/vboxvideo/vbva.c
r53967 r54530 18 18 #include <VBox/VBoxGuestLib.h> 19 19 20 #ifndef PCIACCESS21 # include <xf86Pci.h>22 # include <Pci.h>23 #endif24 25 #include "xf86.h"26 #define NEED_XF86_TYPES27 20 #include <iprt/string.h> 28 21 #include "compiler.h" 29 30 /* ShadowFB support */31 #include "shadowfb.h"32 22 33 23 #include "vboxvideo.h" … … 51 41 * rectangles 52 42 */ 53 static void 54 vboxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects) 43 void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects) 55 44 { 56 45 VBVACMDHDR cmdHdr; … … 79 68 || aRects[i].y2 < pVBox->pScreens[j].aScreenLocation.y) 80 69 continue; 81 cmdHdr.x = (int16_t)aRects[i].x1 ;82 cmdHdr.y = (int16_t)aRects[i].y1 ;70 cmdHdr.x = (int16_t)aRects[i].x1 - pVBox->pScreens[0].aScreenLocation.x; 71 cmdHdr.y = (int16_t)aRects[i].y1 - pVBox->pScreens[0].aScreenLocation.y; 83 72 cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1); 84 73 cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1); … … 100 89 } 101 90 91 static DECLCALLBACK(void *) hgsmiEnvAlloc(void *pvEnv, HGSMISIZE cb) 92 { 93 NOREF(pvEnv); 94 return calloc(1, cb); 95 } 96 97 static DECLCALLBACK(void) hgsmiEnvFree(void *pvEnv, void *pv) 98 { 99 NOREF(pvEnv); 100 free(pv); 101 } 102 103 static HGSMIENV g_hgsmiEnv = 104 { 105 NULL, 106 hgsmiEnvAlloc, 107 hgsmiEnvFree 108 }; 109 110 /** 111 * Calculate the location in video RAM of and initialise the heap for guest to 112 * host messages. In the VirtualBox 4.3 and earlier Guest Additions this 113 * function creates the heap structures directly in guest video RAM, so it 114 * needs to be called whenever video RAM is (re-)set-up. 115 */ 116 void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM) 117 { 118 int rc; 119 uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory; 120 void *pvGuestHeapMemory; 121 122 VBoxHGSMIGetBaseMappingInfo(cbVRAM, &offVRAMBaseMapping, NULL, &offGuestHeapMemory, &cbGuestHeapMemory, NULL); 123 pvGuestHeapMemory = ((uint8_t *)pVBox->base) + offVRAMBaseMapping + offGuestHeapMemory; 124 rc = VBoxHGSMISetupGuestContext(&pVBox->guestCtx, pvGuestHeapMemory, cbGuestHeapMemory, 125 offVRAMBaseMapping + offGuestHeapMemory, &g_hgsmiEnv); 126 VBVXASSERT(RT_SUCCESS(rc), ("Failed to set up the guest-to-host message buffer heap, rc=%d\n", rc)); 127 pVBox->cbView = offVRAMBaseMapping; 128 } 129 102 130 /** Callback to fill in the view structures */ 103 131 static int … … 121 149 * @returns TRUE on success, FALSE on failure 122 150 */ 123 static Bool 124 vboxInitVbva(int scrnIndex, ScreenPtr pScreen, VBOXPtr pVBox) 125 { 126 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 151 static Bool vboxSetupVRAMVbva(VBOXPtr pVBox) 152 { 127 153 int rc = VINF_SUCCESS; 128 129 /* Why is this here? In case things break before we have found the real 130 * count? */ 131 pVBox->cScreens = 1; 132 if (!VBoxHGSMIIsSupported()) 133 { 134 xf86DrvMsg(scrnIndex, X_ERROR, "The graphics device does not seem to support HGSMI. Disableing video acceleration.\n"); 135 return FALSE; 136 } 137 138 /* Set up the dirty rectangle handler. It will be added into a function 139 * chain and gets removed when the screen is cleaned up. */ 140 if (ShadowFBInit2(pScreen, NULL, vboxHandleDirtyRect) != TRUE) 141 { 142 xf86DrvMsg(scrnIndex, X_ERROR, 143 "Unable to install dirty rectangle handler for VirtualBox graphics acceleration.\n"); 144 return FALSE; 145 } 146 return TRUE; 147 } 148 149 static DECLCALLBACK(void *) hgsmiEnvAlloc(void *pvEnv, HGSMISIZE cb) 150 { 151 NOREF(pvEnv); 152 return calloc(1, cb); 153 } 154 155 static DECLCALLBACK(void) hgsmiEnvFree(void *pvEnv, void *pv) 156 { 157 NOREF(pvEnv); 158 free(pv); 159 } 160 161 static HGSMIENV g_hgsmiEnv = 162 { 163 NULL, 164 hgsmiEnvAlloc, 165 hgsmiEnvFree 166 }; 167 168 /** 169 * Initialise VirtualBox's accelerated video extensions. 170 * 171 * @returns TRUE on success, FALSE on failure 172 */ 173 static Bool 174 vboxSetupVRAMVbva(ScrnInfoPtr pScrn, VBOXPtr pVBox) 175 { 176 int rc = VINF_SUCCESS; 177 unsigned i; 178 uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory; 179 void *pvGuestHeapMemory; 180 181 VBoxHGSMIGetBaseMappingInfo(pScrn->videoRam * 1024, &offVRAMBaseMapping, 182 NULL, &offGuestHeapMemory, &cbGuestHeapMemory, 183 NULL); 184 pvGuestHeapMemory = ((uint8_t *)pVBox->base) + offVRAMBaseMapping 185 + offGuestHeapMemory; 186 TRACE_LOG("video RAM: %u KB, guest heap offset: 0x%x, cbGuestHeapMemory: %u\n", 187 pScrn->videoRam, offVRAMBaseMapping + offGuestHeapMemory, 188 cbGuestHeapMemory); 189 rc = VBoxHGSMISetupGuestContext(&pVBox->guestCtx, pvGuestHeapMemory, 190 cbGuestHeapMemory, 191 offVRAMBaseMapping + offGuestHeapMemory, 192 &g_hgsmiEnv); 193 if (RT_FAILURE(rc)) 194 { 195 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up the guest-to-host communication context, rc=%d\n", rc); 196 return FALSE; 197 } 198 pVBox->cbView = pVBox->cbFBMax = offVRAMBaseMapping; 199 pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx); 200 pVBox->pScreens = calloc(pVBox->cScreens, sizeof(*pVBox->pScreens)); 201 if (pVBox->pScreens == NULL) 202 FatalError("Failed to allocate memory for screens array.\n"); 203 #ifdef VBOXVIDEO_13 204 pVBox->paVBVAModeHints = calloc(pVBox->cScreens, 205 sizeof(*pVBox->paVBVAModeHints)); 206 if (pVBox->paVBVAModeHints == NULL) 207 FatalError("Failed to allocate memory for mode hints array.\n"); 208 #endif 209 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n", 210 pVBox->cScreens); 154 unsigned i; 155 156 pVBox->cbFBMax = pVBox->cbView; 211 157 for (i = 0; i < pVBox->cScreens; ++i) 212 158 { … … 224 170 rc = VBoxHGSMISendViewInfo(&pVBox->guestCtx, pVBox->cScreens, 225 171 vboxFillViewInfo, (void *)pVBox); 226 if (RT_FAILURE(rc)) 227 { 228 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to send the view information to the host, rc=%d\n", rc); 229 return FALSE; 230 } 172 VBVXASSERT(RT_SUCCESS(rc), ("Failed to send the view information to the host, rc=%d\n", rc)); 231 173 return TRUE; 232 174 } 233 175 234 void 235 vbox_open(ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox) 236 { 237 TRACE_ENTRY(); 238 239 if (!vboxInitVbva(pScrn->scrnIndex, pScreen, pVBox)) 240 FatalError("failed to initialise vboxvideo graphics acceleration.\n"); 176 static bool haveHGSMIModeHintAndCursorReportingInterface(VBOXPtr pVBox) 177 { 178 uint32_t fModeHintReporting, fCursorReporting; 179 180 return RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_MODE_HINT_REPORTING, &fModeHintReporting)) 181 && RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_GUEST_CURSOR_REPORTING, &fCursorReporting)) 182 && fModeHintReporting == VINF_SUCCESS 183 && fCursorReporting == VINF_SUCCESS; 241 184 } 242 185 … … 252 195 { 253 196 bool rc = TRUE; 254 int scrnIndex = pScrn->scrnIndex;255 197 unsigned i; 256 198 VBOXPtr pVBox = pScrn->driverPrivate; 257 199 258 200 TRACE_ENTRY(); 259 if (!vboxSetupVRAMVbva(p Scrn, pVBox))201 if (!vboxSetupVRAMVbva(pVBox)) 260 202 return FALSE; 261 203 for (i = 0; i < pVBox->cScreens; ++i) … … 269 211 rc = FALSE; 270 212 } 271 if (!rc) 272 { 273 /* Request not accepted - disable for old hosts. */ 274 xf86DrvMsg(scrnIndex, X_ERROR, 275 "Failed to enable screen update reporting for at least one virtual monitor.\n"); 276 vboxDisableVbva(pScrn); 277 } 213 VBVXASSERT(rc, ("Failed to enable screen update reporting for at least one virtual monitor.\n")); 278 214 #ifdef VBOXVIDEO_13 279 # ifdef RT_OS_LINUX 280 if (rc && pVBox->hACPIEventHandler != NULL) 281 /* We ignore the return value as the fall-back should be active 282 * anyway. */ 283 VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION); 284 # endif 215 VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION); 216 pVBox->fHaveHGSMIModeHints = haveHGSMIModeHintAndCursorReportingInterface(pVBox); 285 217 #endif 286 218 return rc; … … 299 231 { 300 232 int rc; 301 int scrnIndex = pScrn->scrnIndex;302 233 unsigned i; 303 234 VBOXPtr pVBox = pScrn->driverPrivate;
Note:
See TracChangeset
for help on using the changeset viewer.