summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/VBox/Devices/Graphics/DevVGA-SVGA.cpp38
1 files changed, 36 insertions, 2 deletions
diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
index c199b618..ea34efa2 100644
--- a/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
+++ b/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
@@ -1655,6 +1655,22 @@ int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC)
VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0];
Assert(pScreen->idScreen == 0);
+
+ if ( pScreen->cWidth == VMSVGA_VAL_UNINITIALIZED
+ || pScreen->cHeight == VMSVGA_VAL_UNINITIALIZED
+ || pScreen->cBpp == VMSVGA_VAL_UNINITIALIZED)
+ {
+ /* Do not apply the change if the guest has not finished updating registers.
+ * This is necessary in order to make a full mode change, including freeing
+ * pvScreenBitmap buffers for screen 0 if necessary.
+ */
+ return VINF_SUCCESS;
+ }
+
+ /* Remember screen bitmap buffers to be freed. */
+ void * apvOldScreenBitmap[RT_ELEMENTS(pSVGAState->aScreens)];
+ RT_ZERO(apvOldScreenBitmap);
+
pScreen->fDefined = true;
pScreen->fModified = true;
pScreen->fuScreen = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
@@ -1665,6 +1681,11 @@ int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC)
pScreen->cWidth = pThis->svga.uWidth;
pScreen->cHeight = pThis->svga.uHeight;
pScreen->cBpp = pThis->svga.uBpp;
+ pScreen->cDpi = 0; /* GFB mode does not support dpi. */
+ /* GFB mode uses the guest VRAM. The screen bitmap must be deallocated after 'vmsvgaR3VBVAResize'. */
+ apvOldScreenBitmap[0] = pScreen->pvScreenBitmap;
+ /* Set pvScreenBitmap to zero because if it is not, then vmsvgaR3VBVAResize uses it as VRAM address. */
+ pScreen->pvScreenBitmap = 0;
for (unsigned iScreen = 1; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
{
@@ -1674,8 +1695,21 @@ int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC)
{
pScreen->fModified = true;
pScreen->fDefined = false;
+
+#ifdef VBOX_WITH_VMSVGA3D
+ if (RT_LIKELY(pThis->svga.f3DEnabled))
+ vmsvga3dDestroyScreen(pThisCC, pScreen);
+#endif
+ apvOldScreenBitmap[iScreen] = pScreen->pvScreenBitmap;
+ pScreen->pvScreenBitmap = 0;
}
}
+
+ vmsvgaR3VBVAResize(pThis, pThisCC);
+
+ /* Deallocate screen bitmaps for all screens because GFB mode uses the guest VRAM. */
+ for (unsigned iScreen = 0; iScreen < RT_ELEMENTS(apvOldScreenBitmap); ++iScreen)
+ RTMemFree(apvOldScreenBitmap[iScreen]);
}
else
{
@@ -1686,9 +1720,9 @@ int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC)
pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED;
pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
pThis->svga.uBpp = pThis->svga.uHostBpp;
- }
- vmsvgaR3VBVAResize(pThis, pThisCC);
+ vmsvgaR3VBVAResize(pThis, pThisCC);
+ }
/* Last stuff. For the VGA device screenshot. */
pThis->last_bpp = pSVGAState->aScreens[0].cBpp;