Changeset 55250 in vbox for trunk/src/VBox/Additions/x11/vboxvideo
- Timestamp:
- Apr 14, 2015 2:17:18 PM (10 years ago)
- Location:
- trunk/src/VBox/Additions/x11/vboxvideo
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/x11/vboxvideo/README.testing
r55191 r55250 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. 27 * Test power management by disabling guest screens ("xrandr --output VGA-n 28 --off") and re-enabling them ("xrandr --output VGA-n --preferred --pos XxY") 29 where X and Y are the position of the screen before disabling it. 30 * Test sending video mode hints with screen position information via 31 VBoxManage. The screen position is a hint only. The approximate position 32 should be preserved after a shut down and re-start of the guest. 33 * Test re-starting the X server after resizing all guest windows. The server 34 should not crash. -
trunk/src/VBox/Additions/x11/vboxvideo/getmode.c
r55225 r55250 38 38 #ifdef VBOXVIDEO_13 39 39 # ifdef RT_OS_LINUX 40 # include "randrstr.h"41 # include "xf86_OSproc.h"42 40 # include <linux/input.h> 43 41 # ifndef EVIOCGRAB … … 53 51 # endif /* RT_OS_LINUX */ 54 52 #endif /* VBOXVIDEO_13 */ 53 55 54 /************************************************************************** 56 55 * Main functions * … … 155 154 } 156 155 157 /** Set the initial values for the guest screen size hints by reading saved 158 * values from files. */ 159 /** @todo Actually read the files instead of setting dummies. */ 156 /** Set the initial values for the guest screen size hints to standard values 157 * in case nothing else is available. */ 160 158 void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn) 161 159 { … … 173 171 pScrn->modes->HDisplay = pVBox->pScreens[0].aPreferredSize.cx; 174 172 pScrn->modes->VDisplay = pVBox->pScreens[0].aPreferredSize.cy; 175 /* RandR 1.1 quirk: make sure that the initial resolution is always present176 * in the mode list as RandR will always advertise a mode of the initial177 * virtual resolution via GetScreenInfo. */178 pMode = vboxAddEmptyScreenMode(pScrn);179 vboxFillDisplayMode(pScrn, pMode, NULL, pVBox->pScreens[0].aPreferredSize.cx,180 pVBox->pScreens[0].aPreferredSize.cy);181 }182 183 static void updateUseHardwareCursor(VBOXPtr pVBox, uint32_t fCursorCapabilities)184 {185 if ( !(fCursorCapabilities & VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER)186 && (fCursorCapabilities & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE))187 pVBox->fUseHardwareCursor = true;188 else189 pVBox->fUseHardwareCursor = false;190 }191 192 # define SIZE_HINTS_PROPERTY "VBOX_SIZE_HINTS"193 # define MOUSE_CAPABILITIES_PROPERTY "VBOX_MOUSE_CAPABILITIES"194 195 /** Read in information about the most recent size hints requested for the196 * guest screens. A client application sets the hint information as a root197 * window property. */198 /* TESTING: dynamic resizing and absolute pointer toggling work on old guest X servers and recent ones on Linux at the log-in screen. */199 /** @note we try to maximise code coverage by typically using all code paths (HGSMI and properties) in a single X session. */200 void VBoxUpdateSizeHints(ScrnInfoPtr pScrn)201 {202 VBOXPtr pVBox = VBOXGetRec(pScrn);203 size_t cModesFromProperty, cDummy;204 int32_t *paModeHints, *pfCursorCapabilities;205 unsigned i;206 uint32_t fCursorCapabilities;207 bool fOldUseHardwareCursor = pVBox->fUseHardwareCursor;208 209 if (vbvxGetIntegerPropery(pScrn, SIZE_HINTS_PROPERTY, &cModesFromProperty, &paModeHints) != VINF_SUCCESS)210 paModeHints = NULL;211 if ( vbvxGetIntegerPropery(pScrn, MOUSE_CAPABILITIES_PROPERTY, &cDummy, &pfCursorCapabilities) != VINF_SUCCESS212 || cDummy != 1)213 pfCursorCapabilities = NULL;214 #ifdef VBOXVIDEO_13215 if (!pVBox->fHaveReadHGSMIModeHintData && RT_SUCCESS(VBoxHGSMIGetModeHints(&pVBox->guestCtx, pVBox->cScreens,216 pVBox->paVBVAModeHints)))217 {218 for (i = 0; i < pVBox->cScreens; ++i)219 {220 if (pVBox->paVBVAModeHints[i].magic == VBVAMODEHINT_MAGIC)221 {222 pVBox->pScreens[i].aPreferredSize.cx = pVBox->paVBVAModeHints[i].cx;223 pVBox->pScreens[i].aPreferredSize.cy = pVBox->paVBVAModeHints[i].cy;224 pVBox->pScreens[i].afConnected = pVBox->paVBVAModeHints[i].fEnabled;225 /* Do not re-read this if we have data from HGSMI. */226 if (paModeHints != NULL && i < cModesFromProperty)227 pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];228 }229 }230 }231 if (!pVBox->fHaveReadHGSMIModeHintData)232 {233 if (RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &fCursorCapabilities)))234 updateUseHardwareCursor(pVBox, fCursorCapabilities);235 else236 pVBox->fUseHardwareCursor = false;237 /* Do not re-read this if we have data from HGSMI. */238 if (pfCursorCapabilities != NULL)239 pVBox->fLastCursorCapabilitiesFromProperty = *pfCursorCapabilities;240 }241 pVBox->fHaveReadHGSMIModeHintData = true;242 #endif243 if (paModeHints != NULL)244 for (i = 0; i < cModesFromProperty && i < pVBox->cScreens; ++i)245 {246 if (paModeHints[i] != 0 && paModeHints[i] != pVBox->pScreens[i].lastModeHintFromProperty)247 {248 if (paModeHints[i] == -1)249 pVBox->pScreens[i].afConnected = false;250 else251 {252 pVBox->pScreens[i].aPreferredSize.cx = paModeHints[i] >> 16;253 pVBox->pScreens[i].aPreferredSize.cy = paModeHints[i] & 0x8fff;254 pVBox->pScreens[i].afConnected = true;255 }256 pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];257 }258 }259 if (pfCursorCapabilities != NULL && *pfCursorCapabilities != pVBox->fLastCursorCapabilitiesFromProperty)260 {261 updateUseHardwareCursor(pVBox, (uint32_t)*pfCursorCapabilities);262 pVBox->fLastCursorCapabilitiesFromProperty = *pfCursorCapabilities;263 }264 if (pVBox->fUseHardwareCursor != fOldUseHardwareCursor)265 vbvxReprobeCursor(pScrn);266 173 } 267 174 … … 397 304 #undef COMPARE_AND_MAYBE_SET 398 305 399 #ifndef VBOXVIDEO_13400 401 /** The RandR "proc" vector, which we wrap with our own in order to notice402 * when a client sends a GetScreenInfo request. */403 static int (*g_pfnVBoxRandRProc)(ClientPtr) = NULL;404 /** The swapped RandR "proc" vector. */405 static int (*g_pfnVBoxRandRSwappedProc)(ClientPtr) = NULL;406 407 /* TESTING: dynamic resizing and toggling cursor integration work with older guest X servers (1.2 and older). */408 static void vboxRandRDispatchCore(ClientPtr pClient)409 {410 xRRGetScreenInfoReq *pReq = (xRRGetScreenInfoReq *)pClient->requestBuffer;411 WindowPtr pWin;412 ScrnInfoPtr pScrn;413 VBOXPtr pVBox;414 DisplayModePtr pMode;415 416 if (pClient->req_len != sizeof(xRRGetScreenInfoReq) >> 2)417 return;418 pWin = (WindowPtr)SecurityLookupWindow(pReq->window, pClient,419 SecurityReadAccess);420 if (!pWin)421 return;422 pScrn = xf86Screens[pWin->drawable.pScreen->myNum];423 pVBox = VBOXGetRec(pScrn);424 TRACE_LOG("pVBox->fUseHardwareCursor=%u\n", pVBox->fUseHardwareCursor);425 VBoxUpdateSizeHints(pScrn);426 pMode = pScrn->modes;427 if (pScrn->currentMode == pMode)428 pMode = pMode->next;429 pMode->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;430 pMode->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;431 }432 433 static int vboxRandRDispatch(ClientPtr pClient)434 {435 xReq *pReq = (xReq *)pClient->requestBuffer;436 437 if (pReq->data == X_RRGetScreenInfo)438 vboxRandRDispatchCore(pClient);439 return g_pfnVBoxRandRProc(pClient);440 }441 442 static int vboxRandRSwappedDispatch(ClientPtr pClient)443 {444 xReq *pReq = (xReq *)pClient->requestBuffer;445 446 if (pReq->data == X_RRGetScreenInfo)447 vboxRandRDispatchCore(pClient);448 return g_pfnVBoxRandRSwappedProc(pClient);449 }450 451 static Bool vboxRandRCreateScreenResources(ScreenPtr pScreen)452 {453 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];454 VBOXPtr pVBox = VBOXGetRec(pScrn);455 ExtensionEntry *pExt;456 457 pScreen->CreateScreenResources = pVBox->pfnCreateScreenResources;458 if (!pScreen->CreateScreenResources(pScreen))459 return FALSE;460 /* I doubt we can be loaded twice - should I fail here? */461 if (g_pfnVBoxRandRProc)462 return TRUE;463 pExt = CheckExtension(RANDR_NAME);464 if (!pExt)465 {466 xf86DrvMsg(pScrn->scrnIndex, X_INFO,467 "RandR extension not found, disabling dynamic resizing.\n");468 return TRUE;469 }470 if ( !ProcVector[pExt->base]471 #if !defined(XF86_VERSION_CURRENT) \472 || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0)473 /* SwappedProcVector is not exported in XFree86, so we will not support474 * swapped byte order clients. I doubt this is a big issue. */475 || !SwappedProcVector[pExt->base]476 #endif477 )478 FatalError("RandR \"proc\" vector not initialised\n");479 g_pfnVBoxRandRProc = ProcVector[pExt->base];480 ProcVector[pExt->base] = vboxRandRDispatch;481 #if !defined(XF86_VERSION_CURRENT) \482 || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0)483 g_pfnVBoxRandRSwappedProc = SwappedProcVector[pExt->base];484 SwappedProcVector[pExt->base] = vboxRandRSwappedDispatch;485 #endif486 return TRUE;487 }488 489 /** Install our private RandR hook procedure, so that we can detect490 * GetScreenInfo requests from clients to update our dynamic mode. This works491 * by installing a wrapper around CreateScreenResources(), which will be called492 * after RandR is initialised. The wrapper then in turn wraps the RandR "proc"493 * vectors with its own handlers which will get called on any client RandR494 * request. This should not be used in conjunction with RandR 1.2 or later.495 * A couple of points of interest in our RandR 1.1 support:496 * * We use the first two screen modes as dynamic modes. When a new mode hint497 * arrives we update the first of the two which is not the current mode with498 * the new size.499 * * RandR 1.1 always advertises a mode of the size of the initial virtual500 * resolution via GetScreenInfo(), so we make sure that a mode of that size501 * is always present in the list.502 * * RandR adds each new mode it sees to an internal array, but never removes503 * entries. This array might end up getting rather long given that we can504 * report a lot more modes than physical hardware.505 */506 void VBoxSetUpRandR11(ScreenPtr pScreen)507 {508 VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);509 510 if (!pScreen->CreateScreenResources)511 FatalError("called to early: CreateScreenResources not yet initialised\n");512 pVBox->pfnCreateScreenResources = pScreen->CreateScreenResources;513 pScreen->CreateScreenResources = vboxRandRCreateScreenResources;514 }515 516 #endif /* !VBOXVIDEO_13 */517 518 306 #ifdef VBOXVIDEO_13 519 307 # ifdef RT_OS_LINUX 520 /* TESTING: dynamic resizing works on recent Linux guest X servers at the log-in screen. */ 521 /** @note to maximise code coverage we only read data from HGSMI once, and only when responding to an ACPI event. */ 308 /** We have this for two purposes: one is to ensure that the X server is woken 309 * up when we get a video ACPI event. Two is to grab ACPI video events to 310 * prevent gnome-settings-daemon from seeing them, as older versions ignored 311 * the time stamp and handled them at the wrong time. */ 522 312 static void acpiEventHandler(int fd, void *pvData) 523 313 { … … 527 317 ssize_t rc; 528 318 529 pVBox->fHaveReadHGSMIModeHintData = false;530 RRGetInfo(pScreen531 # if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5532 , TRUE533 # endif534 );535 VBVXASSERT(pVBox->fHaveReadHGSMIModeHintData == true, ("fHaveReadHGSMIModeHintData not set.\n"));536 319 do 537 320 rc = read(fd, &event, sizeof(event)); … … 541 324 } 542 325 543 void VBoxSetUpLinuxACPI(ScreenPtr pScreen)326 void vbvxSetUpLinuxACPI(ScreenPtr pScreen) 544 327 { 545 328 VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]); … … 591 374 } 592 375 593 void VBoxCleanUpLinuxACPI(ScreenPtr pScreen)376 void vbvxCleanUpLinuxACPI(ScreenPtr pScreen) 594 377 { 595 378 VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]); … … 602 385 # endif /* RT_OS_LINUX */ 603 386 #endif /* VBOXVIDEO_13 */ 387 -
trunk/src/VBox/Additions/x11/vboxvideo/helpers.c
r55225 r55250 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 { -
trunk/src/VBox/Additions/x11/vboxvideo/setmode.c
r55242 r55250 91 91 } 92 92 93 /** Clear the virtual framebuffer in VRAM. Optionally also clear up to the94 * size of a new framebuffer. Framebuffer sizes larger than available VRAM95 * be treated as zero and passed over. */96 void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY)97 {98 VBOXPtr pVBox = VBOXGetRec(pScrn);99 uint64_t cbOldFB, cbNewFB;100 101 cbOldFB = pVBox->cbLine * pScrn->virtualX;102 cbNewFB = vboxLineLength(pScrn, cNewX) * cNewY;103 if (cbOldFB > (uint64_t)pVBox->cbFBMax)104 cbOldFB = 0;105 if (cbNewFB > (uint64_t)pVBox->cbFBMax)106 cbNewFB = 0;107 memset(pVBox->base, 0, max(cbOldFB, cbNewFB));108 }109 110 93 /** Set a graphics mode. Poke any required values into registers, do an HGSMI 111 94 * mode set and tell the host we support advanced graphics functions. … … 140 123 } 141 124 142 /** Set a graphics mode. Poke any required values into registers, do an HGSMI143 * mode set and tell the host we support advanced graphics functions. This144 * procedure is complicated by the fact that X.Org can implicitly disable a145 * screen by resizing the virtual framebuffer so that the screen is no longer146 * inside it. We have to spot and handle this.147 */148 Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,149 unsigned cHeight, int x, int y)150 {151 VBOXPtr pVBox = VBOXGetRec(pScrn);152 uint32_t offStart, cwReal = cWidth;153 bool fEnabled;154 uint16_t fFlags;155 int rc;156 157 TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, displayWidth=%d\n",158 cDisplay, cWidth, cHeight, x, y, pScrn->displayWidth);159 offStart = y * pVBox->cbLine + x * vboxBPP(pScrn) / 8;160 /* Deactivate the screen if the mode - specifically the virtual width - is161 * too large for VRAM as we sometimes have to do this - see comments in162 * VBOXPreInit. */163 if ( offStart + pVBox->cbLine * cHeight > pVBox->cbFBMax164 || pVBox->cbLine * pScrn->virtualY > pVBox->cbFBMax)165 return FALSE;166 /* Deactivate the screen if it is outside of the virtual framebuffer and167 * clamp it to lie inside if it is partly outside. */168 if (x >= pScrn->displayWidth || x + (int) cWidth <= 0)169 return FALSE;170 else171 cwReal = RT_MIN((int) cWidth, pScrn->displayWidth - x);172 TRACE_LOG("pVBox->pScreens[%u].fCrtcEnabled=%d, fOutputEnabled=%d\n",173 cDisplay, (int)pVBox->pScreens[cDisplay].fCrtcEnabled,174 (int)pVBox->pScreens[cDisplay].fOutputEnabled);175 if (cDisplay == 0)176 VBoxVideoSetModeRegisters(cwReal, cHeight, pScrn->displayWidth,177 vboxBPP(pScrn), 0, x, y);178 fEnabled = pVBox->pScreens[cDisplay].fCrtcEnabled179 && pVBox->pScreens[cDisplay].fOutputEnabled;180 fFlags = VBVA_SCREEN_F_ACTIVE;181 fFlags |= (pVBox->pScreens[cDisplay].afConnected ? 0182 : VBVA_SCREEN_F_DISABLED);183 VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x, y,184 offStart, pVBox->cbLine, cwReal, cHeight,185 fEnabled ? vboxBPP(pScrn) : 0, fFlags);186 if (cDisplay == 0)187 {188 rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pVBox->pScreens[0].aScreenLocation.x,189 0 - pVBox->pScreens[0].aScreenLocation.y, pScrn->virtualX, pScrn->virtualY);190 if (RT_FAILURE(rc))191 FatalError("Failed to update the input mapping.\n");192 }193 return TRUE;194 }195 196 /** Resize the virtual framebuffer. After resizing we reset all modes197 * (X.Org 1.3+) to adjust them to the new framebuffer.198 */199 Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)200 {201 ScreenPtr pScreen = pScrn->pScreen;202 PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen);203 VBOXPtr pVBox = VBOXGetRec(pScrn);204 uint64_t cbLine = vboxLineLength(pScrn, width);205 int displayWidth = vboxDisplayPitch(pScrn, cbLine);206 int rc;207 208 TRACE_LOG("width=%d, height=%d\n", width, height);209 if ( width == pScrn->virtualX210 && height == pScrn->virtualY211 && displayWidth == pScrn->displayWidth)212 return TRUE;213 if (!pPixmap) {214 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,215 "Failed to get the screen pixmap.\n");216 return FALSE;217 }218 if (cbLine > UINT32_MAX || cbLine * height >= pVBox->cbFBMax)219 {220 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,221 "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",222 width, height, pVBox->cbFBMax / 1024, pScrn->videoRam);223 return FALSE;224 }225 pScreen->ModifyPixmapHeader(pPixmap, width, height,226 pScrn->depth, vboxBPP(pScrn), cbLine,227 pVBox->base);228 vboxClearVRAM(pScrn, width, height);229 pScrn->virtualX = width;230 pScrn->virtualY = height;231 pScrn->displayWidth = displayWidth;232 pVBox->cbLine = cbLine;233 #ifdef VBOX_DRI_OLD234 if (pVBox->useDRI)235 VBOXDRIUpdateStride(pScrn, pVBox);236 #endif237 #ifdef VBOXVIDEO_13238 /* Write the new values to the hardware */239 /** @todo why is this only for VBOXVIDEO_13? */240 {241 unsigned i;242 for (i = 0; i < pVBox->cScreens; ++i)243 VBOXSetMode(pScrn, i, pVBox->pScreens[i].aScreenLocation.cx,244 pVBox->pScreens[i].aScreenLocation.cy,245 pVBox->pScreens[i].aScreenLocation.x,246 pVBox->pScreens[i].aScreenLocation.y);247 }248 #else249 rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pVBox->pScreens[0].aScreenLocation.x,250 0 - pVBox->pScreens[0].aScreenLocation.y, pScrn->virtualX, pScrn->virtualY);251 if (RT_FAILURE(rc))252 FatalError("Failed to update the input mapping.\n");253 #endif254 vbvxSetSolarisMouseRange(width, height);255 return TRUE;256 }257 258 125 /** Tell the virtual mouse device about the new virtual desktop size. */ 259 126 void vbvxSetSolarisMouseRange(int width, int height) -
trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c
r55236 r55250 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) … … 262 273 #endif /* !XORG_7X */ 263 274 275 /** Resize the virtual framebuffer. */ 276 static Bool adjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height) 277 { 278 ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 279 VBOXPtr pVBox = VBOXGetRec(pScrn); 280 int adjustedWidth = pScrn->bitsPerPixel == 16 ? (width + 1) & ~1 : width; 281 int cbLine = adjustedWidth * pScrn->bitsPerPixel / 8; 282 PixmapPtr pPixmap; 283 int rc; 284 285 TRACE_LOG("width=%d, height=%d\n", width, height); 286 VBVXASSERT(width >= 0 && height >= 0, ("Invalid negative width (%d) or height (%d)\n", width, height)); 287 if (pScreen == NULL) /* Not yet initialised. */ 288 return TRUE; 289 pPixmap = pScreen->GetScreenPixmap(pScreen); 290 VBVXASSERT(pPixmap != NULL, ("Failed to get the screen pixmap.\n")); 291 TRACE_LOG("pPixmap=%p adjustedWidth=%d height=%d pScrn->depth=%d pScrn->bitsPerPixel=%d cbLine=%d pVBox->base=%p pPixmap->drawable.width=%d pPixmap->drawable.height=%d\n", 292 pPixmap, adjustedWidth, height, pScrn->depth, pScrn->bitsPerPixel, cbLine, pVBox->base, pPixmap->drawable.width, 293 pPixmap->drawable.height); 294 if ( adjustedWidth != pPixmap->drawable.width 295 || height != pPixmap->drawable.height) 296 { 297 if ( adjustedWidth > VBOX_VIDEO_MAX_VIRTUAL || height > VBOX_VIDEO_MAX_VIRTUAL 298 || (unsigned)cbLine * (unsigned)height >= pVBox->cbFBMax) 299 { 300 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 301 "Virtual framebuffer %dx%d too large. For information, video memory: %u Kb.\n", 302 adjustedWidth, height, (unsigned) pVBox->cbFBMax / 1024); 303 return FALSE; 304 } 305 vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8, 306 adjustedWidth * height * pScrn->bitsPerPixel / 8); 307 pScreen->ModifyPixmapHeader(pPixmap, adjustedWidth, height, pScrn->depth, pScrn->bitsPerPixel, cbLine, pVBox->base); 308 } 309 pScrn->displayWidth = pScrn->virtualX = adjustedWidth; 310 pScrn->virtualY = height; 311 #ifdef VBOX_DRI_OLD 312 if (pVBox->useDRI) 313 VBOXDRIUpdateStride(pScrn, pVBox); 314 #endif 315 return TRUE; 316 } 317 318 /** Set a video mode to the hardware, RandR 1.1 version. Since we no longer do 319 * virtual frame buffers, adjust the screen pixmap dimensions to match. */ 320 static void setModeRandR11(ScrnInfoPtr pScrn, DisplayModePtr pMode, bool fLimitedContext) 321 { 322 VBOXPtr pVBox = VBOXGetRec(pScrn); 323 struct vbvxFrameBuffer frameBuffer = { 0, 0, pMode->HDisplay, pMode->VDisplay, pScrn->bitsPerPixel}; 324 325 pVBox->pScreens[0].aScreenLocation.cx = pMode->HDisplay; 326 pVBox->pScreens[0].aScreenLocation.cy = pMode->VDisplay; 327 if (fLimitedContext) 328 { 329 pScrn->displayWidth = pScrn->virtualX = pMode->HDisplay; 330 pScrn->virtualY = pMode->VDisplay; 331 } 332 else 333 adjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay); 334 if (pMode->HDisplay != 0 && pMode->VDisplay != 0) 335 vbvxSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay, 0, 0, true, true, &frameBuffer); 336 pScrn->currentMode = pMode; 337 } 338 264 339 #ifdef VBOXVIDEO_13 265 340 /* X.org 1.3+ mode-setting support ******************************************/ 341 342 /** Set a video mode to the hardware, RandR 1.2 version. If this is the first 343 * screen, re-set the current mode for all others (the offset for the first 344 * screen is always treated as zero by the hardware, so all other screens need 345 * to be changed to compensate for any changes!). The mode to set is taken 346 * from the X.Org Crtc structure. */ 347 static void setModeRandR12(ScrnInfoPtr pScrn, unsigned cScreen) 348 { 349 VBOXPtr pVBox = VBOXGetRec(pScrn); 350 unsigned i; 351 struct vbvxFrameBuffer frameBuffer = { pVBox->pScreens[0].paCrtcs->x, pVBox->pScreens[0].paCrtcs->y, pScrn->virtualX, 352 pScrn->virtualY, pScrn->bitsPerPixel }; 353 unsigned cFirst = cScreen; 354 unsigned cLast = cScreen != 0 ? cScreen + 1 : pVBox->cScreens; 355 356 for (i = cFirst; i < cLast; ++i) 357 if (pVBox->pScreens[i].paCrtcs->mode.HDisplay != 0 && pVBox->pScreens[i].paCrtcs->mode.VDisplay != 0) 358 vbvxSetMode(pScrn, i, pVBox->pScreens[i].paCrtcs->mode.HDisplay, pVBox->pScreens[i].paCrtcs->mode.VDisplay, 359 pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y, pVBox->pScreens[i].fPowerOn, 360 pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected, &frameBuffer); 361 } 362 363 /** Wrapper around setModeRandR12() to avoid exposing non-obvious semantics. 364 */ 365 static void setAllModesRandR12(ScrnInfoPtr pScrn) 366 { 367 setModeRandR12(pScrn, 0); 368 } 266 369 267 370 /* For descriptions of these functions and structures, see … … 272 375 { 273 376 VBOXPtr pVBox = VBOXGetRec(pScrn); 377 Bool rc; 378 unsigned i; 379 274 380 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 381 /* Don't fiddle with the hardware if we are switched 279 382 * to a virtual terminal. */ … … 283 386 return TRUE; 284 387 } 285 return VBOXAdjustScreenPixmap(pScrn, cw, ch); 388 rc = adjustScreenPixmap(pScrn, cw, ch); 389 /* Power-on all screens (the server expects this) and set the new pitch to them. */ 390 for (i = 0; i < pVBox->cScreens; ++i) 391 pVBox->pScreens[i].fPowerOn = true; 392 setAllModesRandR12(pScrn); 393 vbvxSetSolarisMouseRange(cw, ch); 394 return rc; 286 395 } 287 396 … … 293 402 vbox_crtc_dpms(xf86CrtcPtr crtc, int mode) 294 403 { 295 VBOXPtr pVBox = VBOXGetRec(crtc->scrn); 404 ScrnInfoPtr pScrn = crtc->scrn; 405 VBOXPtr pVBox = VBOXGetRec(pScrn); 296 406 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); 407 408 TRACE_LOG("mode=%d\n", mode); 409 pVBox->pScreens[cDisplay].fPowerOn = (mode != DPMSModeOff); 410 setModeRandR12(pScrn, cDisplay); 315 411 } 316 412 … … 345 441 TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name, 346 442 adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y); 347 pVBox->pScreens[cDisplay].fCrtcEnabled = true; 348 pVBox->pScreens[cDisplay].fOutputEnabled = true; 443 pVBox->pScreens[cDisplay].fPowerOn = true; 349 444 pVBox->pScreens[cDisplay].aScreenLocation.cx = adjusted_mode->HDisplay; 350 445 pVBox->pScreens[cDisplay].aScreenLocation.cy = adjusted_mode->VDisplay; … … 359 454 return; 360 455 } 361 VBOXSetMode(crtc->scrn, cDisplay, adjusted_mode->HDisplay, 362 adjusted_mode->VDisplay, x, y); 456 setModeRandR12(crtc->scrn, cDisplay); 363 457 } 364 458 … … 402 496 vbox_output_dpms (xf86OutputPtr output, int mode) 403 497 { 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); 498 (void)output; (void)mode; 424 499 } 425 500 … … 498 573 uint32_t x, y, iScreen; 499 574 iScreen = (uintptr_t)output->driver_private; 500 VBoxUpdateSizeHints(pScrn); 501 pMode = vbox_output_add_mode(pVBox, &pModes, NULL, pVBox->pScreens[iScreen].aPreferredSize.cx, 502 pVBox->pScreens[iScreen].aPreferredSize.cy, TRUE, FALSE); 575 pMode = vbox_output_add_mode(pVBox, &pModes, NULL, 576 RT_CLAMP(pVBox->pScreens[iScreen].aPreferredSize.cx, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL), 577 RT_CLAMP(pVBox->pScreens[iScreen].aPreferredSize.cy, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL), 578 TRUE, FALSE); 579 // VBOXEDIDSet(output, pMode); 503 580 TRACE_EXIT(); 504 581 return pModes; … … 600 677 601 678 #ifndef XF86_SCRN_INTERFACE 602 # define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]603 # define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]604 679 # define SCRNINDEXAPI(pfn) pfn ## Index 605 680 static Bool VBOXScreenInitIndex(int scrnIndex, ScreenPtr pScreen, int argc, … … 872 947 873 948 /* Set the right virtual resolution. */ 874 pScrn->virtualX = pScrn-> currentMode->HDisplay;949 pScrn->virtualX = pScrn->bitsPerPixel == 16 ? (pScrn->currentMode->HDisplay + 1) & ~1 : pScrn->currentMode->HDisplay; 875 950 pScrn->virtualY = pScrn->currentMode->VDisplay; 876 951 … … 878 953 879 954 /* Needed before we initialise DRI. */ 880 pVBox->cbLine = vboxLineLength(pScrn, pScrn->virtualX); 881 pScrn->displayWidth = vboxDisplayPitch(pScrn, pVBox->cbLine); 955 pScrn->displayWidth = pScrn->virtualX; 882 956 883 957 xf86PrintModes(pScrn); … … 975 1049 #endif /* SET_HAVE_VT_PROPERTY */ 976 1050 1051 #ifdef VBOXVIDEO_13 1052 1053 static void setVirtualSizeRandR12(ScrnInfoPtr pScrn, bool fLimitedContext) 1054 { 1055 VBOXPtr pVBox = VBOXGetRec(pScrn); 1056 unsigned i; 1057 unsigned cx = 0; 1058 unsigned cy = 0; 1059 1060 for (i = 0; i < pVBox->cScreens; ++i) 1061 { 1062 if ( pVBox->fHaveHGSMIModeHints && pVBox->pScreens[i].afHaveLocation) 1063 { 1064 pVBox->pScreens[i].paCrtcs->x = pVBox->pScreens[i].aPreferredLocation.x; 1065 pVBox->pScreens[i].paCrtcs->y = pVBox->pScreens[i].aPreferredLocation.y; 1066 } 1067 if ( pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected 1068 && pVBox->pScreens[i].paCrtcs->x + pVBox->pScreens[i].aPreferredSize.cx < VBOX_VIDEO_MAX_VIRTUAL 1069 && pVBox->pScreens[i].paCrtcs->y + pVBox->pScreens[i].aPreferredSize.cy < VBOX_VIDEO_MAX_VIRTUAL) 1070 { 1071 cx = max(cx, pVBox->pScreens[i].paCrtcs->x + pVBox->pScreens[i].aPreferredSize.cx); 1072 cy = max(cy, pVBox->pScreens[i].paCrtcs->y + pVBox->pScreens[i].aPreferredSize.cy); 1073 } 1074 } 1075 if (cx != 0 && cy != 0) 1076 { 1077 if (fLimitedContext) 1078 { 1079 pScrn->virtualX = cx; 1080 pScrn->virtualY = cy; 1081 } 1082 else 1083 { 1084 TRACE_LOG("cx=%u, cy=%u\n", cx, cy); 1085 xf86ScrnToScreen(pScrn)->width = cx; 1086 xf86ScrnToScreen(pScrn)->height = cy; 1087 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 14 1088 xf86UpdateDesktopDimensions(); 1089 #elif GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 12 1090 screenInfo.width = cx; 1091 screenInfo.height = cy; 1092 #endif 1093 adjustScreenPixmap(pScrn, cx, cy); 1094 } 1095 } 1096 } 1097 1098 static void setScreenSizesRandR12(ScrnInfoPtr pScrn, bool fLimitedContext) 1099 { 1100 VBOXPtr pVBox = VBOXGetRec(pScrn); 1101 unsigned i; 1102 1103 for (i = 0; i < pVBox->cScreens; ++i) 1104 { 1105 if (!pVBox->pScreens[i].afConnected) 1106 continue; 1107 /* The Crtc can get "unset" if the screen was disconnected previously. 1108 * I couldn't find an API to re-set it which did not have side-effects. 1109 */ 1110 pVBox->pScreens[i].paOutputs->crtc = pVBox->pScreens[i].paCrtcs; 1111 xf86CrtcSetMode(pVBox->pScreens[i].paCrtcs, pVBox->pScreens[i].paOutputs->probed_modes, RR_Rotate_0, 1112 pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y); 1113 if (!fLimitedContext) 1114 RRCrtcNotify(pVBox->pScreens[i].paCrtcs->randr_crtc, pVBox->pScreens[i].paOutputs->randr_output->modes[0], 1115 pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y, RR_Rotate_0, 1116 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5 1117 NULL, 1118 #endif 1119 1, &pVBox->pScreens[i].paOutputs->randr_output); 1120 } 1121 } 1122 1123 static void setSizesRandR12(ScrnInfoPtr pScrn, bool fLimitedContext) 1124 { 1125 VBOXPtr pVBox = VBOXGetRec(pScrn); 1126 1127 # if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5 1128 RRGetInfo(xf86ScrnToScreen(pScrn), TRUE); 1129 # else 1130 RRGetInfo(xf86ScrnToScreen(pScrn)); 1131 # endif 1132 setVirtualSizeRandR12(pScrn, fLimitedContext); 1133 setScreenSizesRandR12(pScrn, fLimitedContext); 1134 if (!fLimitedContext) 1135 { 1136 RRScreenSizeNotify(xf86ScrnToScreen(pScrn)); 1137 RRTellChanged(xf86ScrnToScreen(pScrn)); 1138 } 1139 } 1140 1141 #else 1142 1143 static void setSizesRandR11(ScrnInfoPtr pScrn, bool fLimitedContext) 1144 { 1145 VBOXPtr pVBox = VBOXGetRec(pScrn); 1146 DisplayModePtr pNewMode; 1147 1148 pNewMode = pScrn->modes != pScrn->currentMode ? pScrn->modes : pScrn->modes->next; 1149 pNewMode->HDisplay = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cx, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL); 1150 pNewMode->VDisplay = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cy, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL); 1151 setModeRandR11(pScrn, pNewMode, fLimitedContext); 1152 } 1153 1154 #endif 1155 1156 static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fScreenInitTime) 1157 { 1158 VBOXPtr pVBox = VBOXGetRec(pScrn); 1159 1160 TRACE_LOG("fScreenInitTime=%d\n", (int)fScreenInitTime); 1161 #ifdef VBOXVIDEO_13 1162 setSizesRandR12(pScrn, fScreenInitTime); 1163 #else 1164 setSizesRandR11(pScrn, fScreenInitTime); 1165 #endif 1166 if (pScrn->vtSema) 1167 vbvxReprobeCursor(pScrn); 1168 } 1169 1170 /* We update the size hints from the X11 property set by VBoxClient every time 1171 * that the X server goes to sleep (to catch the property change request). 1172 * Although this is far more often than necessary it should not have real-life 1173 * performance consequences and allows us to simplify the code quite a bit. */ 1174 static void updateSizeHintsBlockHandler(pointer pData, OSTimePtr pTimeout, pointer pReadmask) 1175 { 1176 ScrnInfoPtr pScrn = (ScrnInfoPtr)pData; 1177 VBOXPtr pVBox = VBOXGetRec(pScrn); 1178 bool fNeedUpdate = false; 1179 1180 (void)pTimeout; 1181 (void)pReadmask; 1182 if (!pScrn->vtSema) 1183 return; 1184 vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, &fNeedUpdate); 1185 if (ROOT_WINDOW(pScrn) != NULL) 1186 vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, &fNeedUpdate); 1187 if (fNeedUpdate) 1188 setSizesAndCursorIntegration(pScrn, false); 1189 } 1190 977 1191 /* 978 1192 * QUOTE from the XFree86 DESIGN document: … … 1048 1262 1049 1263 #if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX) 1050 VBoxSetUpLinuxACPI(pScreen); 1051 #endif 1052 1053 vbox_open (pScrn, pScreen, pVBox); 1264 vbvxSetUpLinuxACPI(pScreen); 1265 #endif 1266 1267 if (!VBoxHGSMIIsSupported()) 1268 { 1269 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Graphics device too old to support.\n"); 1270 return FALSE; 1271 } 1272 vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024); 1273 pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx); 1274 pVBox->pScreens = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->pScreens)); 1275 pVBox->paVBVAModeHints = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->paVBVAModeHints)); 1276 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n", pVBox->cScreens); 1054 1277 vboxEnableVbva(pScrn); 1278 /* Set up the dirty rectangle handler. It will be added into a function 1279 * chain and gets removed when the screen is cleaned up. */ 1280 if (ShadowFBInit2(pScreen, NULL, vbvxHandleDirtyRect) != TRUE) 1281 return FALSE; 1055 1282 VBoxInitialiseSizeHints(pScrn); 1283 /* Get any screen size hints from HGSMI. Do not yet try to access X11 1284 * properties, as they are not yet set up, and nor are the clients that 1285 * might have set them. */ 1286 vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, NULL); 1056 1287 1057 1288 #ifdef VBOXVIDEO_13 … … 1097 1328 } 1098 1329 1099 /* Initialise randr 1.2 mode-setting functions and set first mode. 1100 * Note that the mode won't be usable until the server has resized the 1101 * framebuffer to something reasonable. */ 1330 /* Initialise randr 1.2 mode-setting functions. */ 1102 1331 if (!xf86CrtcScreenInit(pScreen)) { 1103 1332 return FALSE; 1104 1333 } 1105 1334 1106 if (!xf86SetDesiredModes(pScrn)) { 1107 return FALSE; 1108 } 1109 #else /* !VBOXVIDEO_13 */ 1110 VBoxSetUpRandR11(pScreen); 1335 #endif 1111 1336 /* set first video mode */ 1112 if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay, 1113 pScrn->currentMode->VDisplay, pScrn->frameX0, 1114 pScrn->frameY0)) 1115 return FALSE; 1116 /* Save the size in case we need to re-set it later. */ 1117 pVBox->FBSize.cx = pScrn->currentMode->HDisplay; 1118 pVBox->FBSize.cy = pScrn->currentMode->VDisplay; 1119 pVBox->pScreens[0].aScreenLocation.cx = pScrn->currentMode->HDisplay; 1120 pVBox->pScreens[0].aScreenLocation.cy = pScrn->currentMode->VDisplay; 1121 pVBox->pScreens[0].aScreenLocation.x = pScrn->frameX0; 1122 pVBox->pScreens[0].aScreenLocation.y = pScrn->frameY0; 1123 #endif /* !VBOXVIDEO_13 */ 1337 setSizesAndCursorIntegration(pScrn, true); 1338 1339 /* Register block and wake-up handlers for getting new screen size hints. */ 1340 RegisterBlockAndWakeupHandlers(updateSizeHintsBlockHandler, (WakeupHandlerProcPtr)NoopDDA, (pointer)pScrn); 1124 1341 1125 1342 /* software cursor */ … … 1182 1399 } 1183 1400 #endif 1401 vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024); 1184 1402 vboxEnableVbva(pScrn); 1185 /* Re-assert this in case we had a change request while switched out. */ 1186 if (pVBox->FBSize.cx && pVBox->FBSize.cy) 1187 VBOXAdjustScreenPixmap(pScrn, pVBox->FBSize.cx, pVBox->FBSize.cy); 1188 #ifdef VBOXVIDEO_13 1189 if (!xf86SetDesiredModes(pScrn)) 1190 return FALSE; 1191 #else 1192 if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay, 1193 pScrn->currentMode->VDisplay, pScrn->frameX0, 1194 pScrn->frameY0)) 1195 return FALSE; 1196 #endif 1403 /* Re-set video mode */ 1404 vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, NULL); 1405 vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, NULL); 1406 /* This prevents a crash in CentOS 3. I was unable to debug it to 1407 * satisfaction, partly due to the lack of symbols. My guess is that 1408 * pScrn->ModifyPixmapHeader() expects certain things to be set up when 1409 * it sees pScrn->vtSema set to true which are not quite done at this 1410 * point of the VT switch. */ 1411 pScrn->vtSema = FALSE; 1412 setSizesAndCursorIntegration(pScrn, false); 1413 pScrn->vtSema = TRUE; 1197 1414 #ifdef SET_HAVE_VT_PROPERTY 1198 1415 updateHasVTProperty(pScrn, TRUE); … … 1211 1428 #ifdef VBOXVIDEO_13 1212 1429 for (i = 0; i < pVBox->cScreens; ++i) 1213 vbox_ output_dpms(pVBox->pScreens[i].paOutputs, DPMSModeOff);1430 vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff); 1214 1431 #endif 1215 1432 vboxDisableVbva(pScrn); 1216 vb oxClearVRAM(pScrn, 0, 0);1433 vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8, 0); 1217 1434 #ifdef VBOX_DRI_OLD 1218 1435 if (pVBox->useDRI) … … 1242 1459 1243 1460 for (i = 0; i < pVBox->cScreens; ++i) 1244 vbox_ output_dpms(pVBox->pScreens[i].paOutputs, DPMSModeOff);1461 vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff); 1245 1462 #endif 1246 1463 vboxDisableVbva(pScrn); 1247 vb oxClearVRAM(pScrn, 0, 0);1464 vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8, 0); 1248 1465 } 1249 1466 #ifdef VBOX_DRI … … 1272 1489 pScreen->CloseScreen = pVBox->CloseScreen; 1273 1490 #if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX) 1274 VBoxCleanUpLinuxACPI(pScreen);1491 vbvxCleanUpLinuxACPI(pScreen); 1275 1492 #endif 1276 1493 #ifndef XF86_SCRN_INTERFACE … … 1284 1501 { 1285 1502 VBOXPtr pVBox; 1286 Bool rc ;1503 Bool rc = TRUE; 1287 1504 1288 1505 TRACE_LOG("HDisplay=%d, VDisplay=%d\n", pMode->HDisplay, pMode->VDisplay); 1289 #ifndef VBOXVIDEO_131290 pVBox = VBOXGetRec(pScrn);1291 /* Save the size in case we need to re-set it later. */1292 pVBox->FBSize.cx = pMode->HDisplay;1293 pVBox->FBSize.cy = pMode->VDisplay;1294 pVBox->pScreens[0].aScreenLocation.cx = pMode->HDisplay;1295 pVBox->pScreens[0].aScreenLocation.cy = pMode->VDisplay;1296 pVBox->pScreens[0].aScreenLocation.x = pScrn->frameX0;1297 pVBox->pScreens[0].aScreenLocation.y = pScrn->frameY0;1298 #endif1299 1506 if (!pScrn->vtSema) 1300 1507 { … … 1306 1513 rc = xf86SetSingleMode(pScrn, pMode, RR_Rotate_0); 1307 1514 #else 1308 VBOXAdjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay); 1309 rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay, 1310 pScrn->frameX0, pScrn->frameY0); 1515 setModeRandR11(pScrn, pMode, false); 1311 1516 #endif 1312 1517 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE"); … … 1315 1520 1316 1521 static void VBOXAdjustFrame(ScrnInfoPtr pScrn, int x, int y) 1317 { 1318 VBOXPtr pVBox = VBOXGetRec(pScrn); 1319 1320 TRACE_ENTRY(); 1321 pVBox->pScreens[0].aScreenLocation.x = x; 1322 pVBox->pScreens[0].aScreenLocation.y = y; 1323 /* Don't fiddle with the hardware if we are switched 1324 * to a virtual terminal. */ 1325 if (!pScrn->vtSema) 1326 { 1327 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1328 "We do not own the active VT, exiting.\n"); 1329 return; 1330 } 1331 VBOXSetMode(pScrn, 0, pVBox->pScreens[0].aScreenLocation.cx, 1332 pVBox->pScreens[0].aScreenLocation.cy, x, y); 1333 TRACE_EXIT(); 1334 } 1522 { (void)pScrn; (void)x; (void)y; } 1335 1523 1336 1524 static void VBOXFreeScreen(ScrnInfoPtr pScrn) -
trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h
r55241 r55250 55 55 #include <VBox/VBoxVideoGuest.h> 56 56 #include <VBox/VBoxVideo.h> 57 58 #ifndef VBVA_SCREEN_F_BLANK 59 # define VBVA_SCREEN_F_BLANK 0x0004 60 #endif 57 61 58 62 #ifdef DEBUG … … 151 155 RTRECT2 aScreenLocation; 152 156 /** Is this CRTC enabled or in DPMS off state? */ 153 Bool fCrtcEnabled; 154 /** Is this output enabled or in DPMS low power state? */ 155 Bool fOutputEnabled; 157 Bool fPowerOn; 156 158 #ifdef VBOXVIDEO_13 157 159 /** The virtual crtcs. */ … … 170 172 /** Has this screen been enabled by the host? */ 171 173 Bool afConnected; 172 /** The last mode hint data read from the X11 property. */173 int32_t lastModeHintFromProperty;174 174 /** Does this screen have a preferred location? */ 175 175 Bool afHaveLocation; … … 190 190 /** The size of the framebuffer and the VBVA buffers at the end of it. */ 191 191 unsigned long cbView; 192 /** The current line size in bytes */193 uint32_t cbLine;194 192 /** Whether the pre-X-server mode was a VBE mode */ 195 193 bool fSavedVBEMode; … … 205 203 /** Do we currently want to use the host cursor? */ 206 204 Bool fUseHardwareCursor; 207 /** The last cursor capabilities data read from the X11 property. */208 int32_t fLastCursorCapabilitiesFromProperty;209 205 /** Number of screens attached */ 210 206 uint32_t cScreens; 211 207 /** Information about each virtual screen. */ 212 208 struct VBoxScreen *pScreens; 213 /** The last requested framebuffer size. */214 RTRECTSIZE FBSize;215 209 /** Can we get mode hint and cursor integration information from HGSMI? */ 216 210 bool fHaveHGSMIModeHints; … … 226 220 void *hACPIEventHandler; 227 221 # endif 228 /** Have we read all available HGSMI mode hint data? */229 bool fHaveReadHGSMIModeHintData;230 #else231 /** The original CreateScreenResources procedure which we wrap with our own.232 */233 CreateScreenResourcesProcPtr pfnCreateScreenResources;234 222 #endif 235 223 /** HGSMI guest heap context */ … … 275 263 }; 276 264 265 extern void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize); 277 266 extern void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled, 278 bool fConnected, struct vbvxFrameBuffer *pFrameBuffer); 279 extern void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize); 267 bool fConnected, struct vbvxFrameBuffer *pFrameBuffer); 280 268 extern void vbvxSetSolarisMouseRange(int width, int height); 281 269 270 /* pointer.c */ 282 271 extern Bool vbox_cursor_init (ScreenPtr pScreen); 283 extern void vbox_open (ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox);284 272 extern void vbox_close (ScrnInfoPtr pScrn, VBOXPtr pVBox); 285 273 274 /* vbva.c */ 275 extern void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects); 276 extern void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM); 286 277 extern Bool vboxEnableVbva(ScrnInfoPtr pScrn); 287 278 extern void vboxDisableVbva(ScrnInfoPtr pScrn); … … 290 281 extern void vboxAddModes(ScrnInfoPtr pScrn); 291 282 extern void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn); 292 extern void VBoxUpdateSizeHints(ScrnInfoPtr pScrn); 293 #ifndef VBOXVIDEO_13 294 extern void VBoxSetUpRandR11(ScreenPtr pScreen); 295 #else 296 void VBoxSetUpLinuxACPI(ScreenPtr pScreen); 297 void VBoxCleanUpLinuxACPI(ScreenPtr pScreen); 298 #endif 283 extern void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate); 284 extern void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate); 285 extern void vbvxSetUpLinuxACPI(ScreenPtr pScreen); 286 extern void vbvxCleanUpLinuxACPI(ScreenPtr pScreen); 299 287 300 288 /* DRI stuff */ … … 305 293 extern void VBOXDRICloseScreen(ScreenPtr pScreen, VBOXPtr pVBox); 306 294 307 /* Utilities */308 309 /** Calculate the BPP from the screen depth */310 static inline uint16_t vboxBPP(ScrnInfoPtr pScrn)311 {312 return pScrn->depth == 24 ? 32 : 16;313 }314 315 /** Calculate the scan line length for a display width */316 static inline int32_t vboxLineLength(ScrnInfoPtr pScrn, int32_t cDisplayWidth)317 {318 uint32_t cbLine = (cDisplayWidth * vboxBPP(pScrn) / 8 + 3) & ~3;319 return cbLine < INT32_MAX ? cbLine : INT32_MAX;320 }321 322 /** Calculate the display pitch from the scan line length */323 static inline int32_t vboxDisplayPitch(ScrnInfoPtr pScrn, int32_t cbLine)324 {325 return cbLine * 8 / vboxBPP(pScrn);326 }327 328 extern void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY);329 extern Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,330 unsigned cHeight, int x, int y);331 extern Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height);332 333 295 #endif /* _VBOXVIDEO_H_ */ 334 296 -
trunk/src/VBox/Additions/x11/vboxvideo/vbva.c
r55191 r55250 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; 184 } 185 186 static bool hostHasScreenBlankingFlag(VBOXPtr pVBox) 187 { 188 uint32_t fScreenFlags; 189 190 return RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_SCREEN_FLAGS, &fScreenFlags)) 191 && fScreenFlags & VBVA_SCREEN_F_BLANK; 241 192 } 242 193 … … 252 203 { 253 204 bool rc = TRUE; 254 int scrnIndex = pScrn->scrnIndex;255 205 unsigned i; 256 206 VBOXPtr pVBox = pScrn->driverPrivate; 257 207 258 208 TRACE_ENTRY(); 259 if (!vboxSetupVRAMVbva(p Scrn, pVBox))209 if (!vboxSetupVRAMVbva(pVBox)) 260 210 return FALSE; 261 211 for (i = 0; i < pVBox->cScreens; ++i) … … 269 219 rc = FALSE; 270 220 } 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 } 221 VBVXASSERT(rc, ("Failed to enable screen update reporting for at least one virtual monitor.\n")); 278 222 #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 223 VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION); 224 pVBox->fHaveHGSMIModeHints = haveHGSMIModeHintAndCursorReportingInterface(pVBox); 225 pVBox->fHostHasScreenBlankingFlag = hostHasScreenBlankingFlag(pVBox); 285 226 #endif 286 227 return rc; … … 299 240 { 300 241 int rc; 301 int scrnIndex = pScrn->scrnIndex;302 242 unsigned i; 303 243 VBOXPtr pVBox = pScrn->driverPrivate;
Note:
See TracChangeset
for help on using the changeset viewer.