Changeset 2106
- Timestamp:
- 04/16/07 17:25:48 (2 years ago)
- Files:
-
- trunk/include/VBox/err.h (modified) (1 diff)
- trunk/include/VBox/pdm.h (modified) (5 diffs)
- trunk/src/VBox/Devices/Graphics/DevVGA.cpp (modified) (27 diffs)
- trunk/src/VBox/Devices/Graphics/DevVGA.h (modified) (1 diff)
- trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp (modified) (1 diff)
- trunk/src/VBox/Frontends/VBoxBFE/DisplayImpl.cpp (modified) (9 diffs)
- trunk/src/VBox/Frontends/VBoxBFE/DisplayImpl.h (modified) (4 diffs)
- trunk/src/VBox/Main/DisplayImpl.cpp (modified) (13 diffs)
- trunk/src/VBox/Main/include/DisplayImpl.h (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/include/VBox/err.h
r1857 r2106 1031 1031 * The format or bit count of the custom mode value is invalid. */ 1032 1032 #define VERR_VGA_INVALID_CUSTOM_MODE (-3500) 1033 /** The display connector is resizing. */ 1034 #define VINF_VGA_RESIZE_IN_PROGRESS (3501) 1033 1035 /** @} */ 1034 1036 trunk/include/VBox/pdm.h
r2040 r2106 655 655 * while doing so. 656 656 * 657 * @returns VBox status code. 657 658 * @param pInterface Pointer to this interface. 658 659 * @thread The emulation thread. 659 660 */ 660 DECLR3CALLBACKMEMBER( void, pfnUpdateDisplay,(PPDMIDISPLAYPORT pInterface));661 DECLR3CALLBACKMEMBER(int, pfnUpdateDisplay,(PPDMIDISPLAYPORT pInterface)); 661 662 662 663 /** … … 666 667 * PDMIDISPLAYCONNECTOR interface and calles PDMIDISPLAYCONNECTOR::pfnUpdateRect(). 667 668 * 669 * @returns VBox status code. 668 670 * @param pInterface Pointer to this interface. 669 671 * @thread The emulation thread. 670 672 */ 671 DECLR3CALLBACKMEMBER( void, pfnUpdateDisplayAll,(PPDMIDISPLAYPORT pInterface));673 DECLR3CALLBACKMEMBER(int, pfnUpdateDisplayAll,(PPDMIDISPLAYPORT pInterface)); 672 674 673 675 /** … … 749 751 750 752 /** 751 * Setup guest physical VRAM to use the provided page aligned 752 * memory buffer as the guest VRAM, may be equal to current guest VRAM. 753 * 754 * @returns VBox status code. 753 * Inform the VGA device whether the Display is directly using the guest VRAM and there is no need 754 * to render the VRAM to the framebuffer memory. 755 * 755 756 * @param pInterface Pointer to this interface. 756 * @param pvBuffer Page aligned address. NULL for removing previously set buffer. 757 * @param cbBuffer Size of buffer. Must be equal to a whole number of pages. 757 * @param fRender Whether the VRAM content must be rendered to the framebuffer. 758 758 * @thread The emulation thread. 759 759 */ 760 DECLR3CALLBACKMEMBER( int, pfnSetupVRAM,(PPDMIDISPLAYPORT pInterface, void *pvBuffer, uint32_t cbBuffer));760 DECLR3CALLBACKMEMBER(void, pfnSetRenderVRAM,(PPDMIDISPLAYPORT pInterface, bool fRender)); 761 761 } PDMIDISPLAYPORT; 762 762 … … 774 774 * This is called when the resolution changes. This usually happens on 775 775 * request from the guest os, but may also happen as the result of a reset. 776 * 776 * If the callback returns VINF_VGA_RESIZE_IN_PROGRESS, the caller (VGA device) 777 * must not access the connector and return. 778 * 779 * @returns VINF_SUCCESS if the framebuffer resize was completed, 780 * VINF_VGA_RESIZE_IN_PROGRESS if resize takes time and not yet finished. 777 781 * @param pInterface Pointer to this interface. 778 782 * @param cBits Color depth (bits per pixel) of the new video mode. 779 * @param pvVRAM Address of guest VRAM.783 * @param pvVRAM Address of the guest VRAM. 780 784 * @param cbLine Size in bytes of a single scan line. 781 785 * @param cx New display width. … … 783 787 * @thread The emulation thread. 784 788 */ 785 DECLR3CALLBACKMEMBER( void, pfnResize,(PPDMIDISPLAYCONNECTOR pInterface, uint32_t cBits, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy));789 DECLR3CALLBACKMEMBER(int, pfnResize,(PPDMIDISPLAYCONNECTOR pInterface, uint32_t cBits, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy)); 786 790 787 791 /** trunk/src/VBox/Devices/Graphics/DevVGA.cpp
r2079 r2106 1406 1406 * - flashing 1407 1407 */ 1408 #ifndef VBOX 1408 1409 static void vga_draw_text(VGAState *s, int full_update) 1410 #else 1411 static int vga_draw_text(VGAState *s, int full_update) 1412 #endif /* !VBOX */ 1409 1413 { 1410 1414 int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr; … … 1484 1488 if ((height * width) > CH_ATTR_SIZE) { 1485 1489 /* better than nothing: exit if transient size is too big */ 1490 #ifndef VBOX 1486 1491 return; 1492 #else 1493 return VINF_SUCCESS; 1494 #endif /* VBOX */ 1487 1495 } 1488 1496 … … 1493 1501 #ifndef VBOX 1494 1502 dpy_resize(s->ds, s->last_scr_width, s->last_scr_height); 1495 #else /* VBOX */1496 /* For text modes the external memory buffer can not be used, so bpp and cbLine are 0 here. */1497 s->pDrv->pfnResize(s->pDrv, 0, NULL, 0, s->last_scr_width, s->last_scr_height);1498 #endif /* VBOX */1499 1503 s->last_width = width; 1500 1504 s->last_height = height; … … 1502 1506 s->last_cw = cw; 1503 1507 full_update = 1; 1508 #else /* VBOX */ 1509 /* For text modes the direct use of guest VRAM is not implemented, so bpp and cbLine are 0 here. */ 1510 int rc = s->pDrv->pfnResize(s->pDrv, 0, NULL, 0, s->last_scr_width, s->last_scr_height); 1511 s->last_width = width; 1512 s->last_height = height; 1513 s->last_ch = cheight; 1514 s->last_cw = cw; 1515 full_update = 1; 1516 if (rc == VINF_VGA_RESIZE_IN_PROGRESS) 1517 return rc; 1518 AssertRC(rc); 1519 #endif /* VBOX */ 1504 1520 } 1505 1521 cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr; … … 1612 1628 s1 += line_offset; 1613 1629 } 1630 #ifdef VBOX 1631 return VINF_SUCCESS; 1632 #endif /* VBOX */ 1614 1633 } 1615 1634 … … 1744 1763 { 1745 1764 const unsigned cBits = s->get_bpp(s); 1746 #if 0 /** @todo kill the nasty resize deadlocks! */1747 int rc = s->pDrv->pfnResize(s->pDrv, cBits, s->CTXSUFF(vram_ptr), s->line_offset, cx, cy);1748 if (rc == VINF_VGA_RESIZE_IN_PROGRESS)1749 return rc;1750 AssertRC(rc);1751 #else1752 1765 /** @todo r=sunlover: If the guest changes VBE_DISPI_INDEX_X_OFFSET, VBE_DISPI_INDEX_Y_OFFSET 1753 1766 * registers, then the third parameter of the following call should be 1754 1767 * probably 's->CTXSUFF(vram_ptr) + s->vbe_start_addr'. 1755 1768 */ 1756 s->pDrv->pfnResize(s->pDrv, cBits, s->CTXSUFF(vram_ptr), s->line_offset, cx, cy); 1757 #endif 1769 int rc = s->pDrv->pfnResize(s->pDrv, cBits, s->CTXSUFF(vram_ptr), s->line_offset, cx, cy); 1758 1770 1759 1771 /* last stuff */ … … 1764 1776 s->last_height = cy; 1765 1777 1778 if (rc == VINF_VGA_RESIZE_IN_PROGRESS) 1779 return rc; 1780 AssertRC(rc); 1781 1766 1782 /* update palette */ 1767 1783 switch (s->pDrv->cBits) … … 1784 1800 * graphic modes 1785 1801 */ 1802 #ifndef VBOX 1786 1803 static void vga_draw_graphic(VGAState *s, int full_update) 1804 #else 1805 static int vga_draw_graphic(VGAState *s, int full_update) 1806 #endif /* !VBOX */ 1787 1807 { 1788 1808 int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask; … … 1875 1895 || height != (int)s->last_height 1876 1896 || s->get_bpp(s) != (int)s->last_bpp 1877 || offsets_changed) { 1878 if (vga_resize_graphic(s, disp_width, height, v) != VINF_SUCCESS) 1879 return; 1897 || offsets_changed) 1898 { 1899 int rc = vga_resize_graphic(s, disp_width, height, v); 1900 if (rc != VINF_SUCCESS) /* Return any rc, particularly VINF_VGA_RESIZE_IN_PROGRESS, to the caller. */ 1901 return rc; 1880 1902 full_update = 1; 1881 1903 } … … 1900 1922 * programming of the virtual hardware ports. Just return. 1901 1923 */ 1902 if (bwidth == 0) return ;1924 if (bwidth == 0) return VINF_SUCCESS; 1903 1925 #endif /* VBOX */ 1904 1926 y_start = -1; … … 1957 1979 vga_draw_line(s, d, s->vram_ptr + addr, width); 1958 1980 #else /* VBOX */ 1959 if (s-> pvExtVRAMHC != s->pDrv->pu8Data) /* Only if external VRAM was not setup. */1981 if (s->fRenderVRAM) 1960 1982 vga_draw_line(s, d, s->CTXSUFF(vram_ptr) + addr, width); 1961 1983 #endif /* VBOX */ … … 2007 2029 } 2008 2030 memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4); 2031 #ifdef VBOX 2032 return VINF_SUCCESS; 2033 #endif /* VBOX */ 2009 2034 } 2010 2035 … … 2062 2087 void vga_update_display(void) 2063 2088 { 2064 #ifdef DEBUG_sunlover2065 LogFlow(("vga_update_display"));2066 #endif /* DEBUG_sunlover */2067 2068 2089 VGAState *s = vga_state; 2069 2090 #else /* VBOX */ 2070 static void vga_update_display(PVGASTATE s) 2071 { 2091 static int vga_update_display(PVGASTATE s) 2092 { 2093 int rc = VINF_SUCCESS; 2072 2094 #endif /* VBOX */ 2073 2095 int full_update, graphic_mode; … … 2112 2134 switch(graphic_mode) { 2113 2135 case GMODE_TEXT: 2136 #ifdef VBOX 2137 rc = 2138 #endif /* VBOX */ 2114 2139 vga_draw_text(s, full_update); 2115 2140 break; 2116 2141 case GMODE_GRAPH: 2142 #ifdef VBOX 2143 rc = 2144 #endif /* VBOX */ 2117 2145 vga_draw_graphic(s, full_update); 2118 2146 break; … … 2123 2151 } 2124 2152 } 2153 #ifdef VBOX 2154 return rc; 2155 #endif /* VBOX */ 2125 2156 } 2126 2157 … … 3522 3553 * @thread The emulation thread. 3523 3554 */ 3524 static DECLCALLBACK(void) vgaDummyResize(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy) 3525 { 3555 static DECLCALLBACK(int) vgaDummyResize(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy) 3556 { 3557 return VINF_SUCCESS; 3526 3558 } 3527 3559 … … 3572 3604 * @see PDMIKEYBOARDPORT::pfnUpdateDisplay() for details. 3573 3605 */ 3574 static DECLCALLBACK( void) vgaPortUpdateDisplay(PPDMIDISPLAYPORT pInterface)3606 static DECLCALLBACK(int) vgaPortUpdateDisplay(PPDMIDISPLAYPORT pInterface) 3575 3607 { 3576 3608 PVGASTATE pData = IDISPLAYPORT_2_VGASTATE(pInterface); … … 3583 3615 /* This should be called only in non VBVA mode. */ 3584 3616 3585 vga_update_display(pData); 3617 int rc = vga_update_display(pData); 3618 if (rc != VINF_SUCCESS) 3619 return rc; 3586 3620 3587 3621 if (pData->fHaveDirtyBits) … … 3591 3625 pData->fHaveDirtyBits = false; 3592 3626 } 3627 3628 return VINF_SUCCESS; 3593 3629 } 3594 3630 … … 3600 3636 * @see PDMIKEYBOARDPORT::pfnUpdateDisplayAll() for details. 3601 3637 */ 3602 static DECLCALLBACK( void) vgaPortUpdateDisplayAll(PPDMIDISPLAYPORT pInterface)3638 static DECLCALLBACK(int) vgaPortUpdateDisplayAll(PPDMIDISPLAYPORT pInterface) 3603 3639 { 3604 3640 PVGASTATE pData = IDISPLAYPORT_2_VGASTATE(pInterface); … … 3612 3648 3613 3649 pData->graphic_mode = -1; /* force full update */ 3614 vga_update_display(pData);3650 return vga_update_display(pData); 3615 3651 } 3616 3652 … … 3660 3696 static DECLCALLBACK(int) vgaPortSnapshot(PPDMIDISPLAYPORT pInterface, void *pvData, size_t cbData, uint32_t *pcx, uint32_t *pcy, size_t *pcbData) 3661 3697 { 3698 /* @todo r=sunlover: replace the method with a direct VRAM rendering like in vgaPortUpdateDisplayRect. */ 3662 3699 PPDMIDISPLAYCONNECTOR pConnector; 3663 3700 PDMIDISPLAYCONNECTOR Connector; … … 3713 3750 3714 3751 /* make the snapshot. */ 3715 vga_update_display(pData); 3752 int rc = vga_update_display(pData); 3753 if (rc != VINF_SUCCESS) 3754 return rc; 3716 3755 3717 3756 /* restore */ … … 3843 3882 3844 3883 /* Check if there is something to do at all. */ 3845 if ( s->pvExtVRAMHC == s->pDrv->pu8Data)3884 if (!s->fRenderVRAM) 3846 3885 { 3847 3886 /* The framebuffer uses the guest VRAM directly. */ 3848 3887 #ifdef DEBUG_sunlover 3849 LogFlow(("vgaPortUpdateDisplayRect: nothing to do : s->pvExtVRAMHC %p, s->pDrv->pu8Data %p\n", s->pvExtVRAMHC, s->pDrv->pu8Data));3888 LogFlow(("vgaPortUpdateDisplayRect: nothing to do fRender is false.\n")); 3850 3889 #endif /* DEBUG_sunlover */ 3851 3890 return; … … 3944 3983 * This is true because coordinates were verified. 3945 3984 */ 3946 pu8Src = s-> pvExtVRAMHC? (uint8_t *)s->pvExtVRAMHC: s->vram_ptrHC;3985 pu8Src = s->vram_ptrHC; 3947 3986 pu8Src += u32OffsetSrc + y * cbLineSrc + x * cbPixelSrc; 3948 3987 … … 3965 4004 } 3966 4005 3967 static DECLCALLBACK(int) vgaPortSetupVRAM (PPDMIDISPLAYPORT pInterface, void *pvBuffer, uint32_t cbBuffer) 3968 { 3969 int rc = VINF_SUCCESS; 4006 static DECLCALLBACK(void) vgaPortSetRenderVRAM(PPDMIDISPLAYPORT pInterface, bool fRender) 4007 { 3970 4008 PVGASTATE s = IDISPLAYPORT_2_VGASTATE(pInterface); 3971 PPDMDEVINS pDevIns; 3972 PVM pVM; 3973 3974 uint32_t u32OverlayOffset = 0; 3975 3976 LogFlow(("vgaPortSetupVRAM: pvBuffer = %p, cbBuffer = 0x%08X, s->vram_ptrHC = %p\n", pvBuffer, cbBuffer, s->vram_ptrHC)); 3977 3978 /* Check input values, Main::Display rely on that. */ 3979 if (ALIGNP(pvBuffer, PAGE_SIZE) != pvBuffer) 3980 { 3981 LogFlow(("vgaPortSetupVRAM: Not aligned address.\n")); 3982 return VERR_INVALID_PARAMETER; 3983 } 3984 3985 pDevIns = s->pDevInsHC; 3986 Assert(pDevIns); 3987 3988 pVM = PDMDevHlpGetVM(pDevIns); 3989 Assert(pVM); 3990 3991 if (s->pvExtVRAMHC != NULL) 3992 { 3993 if (s->pvExtVRAMHC != s->vram_ptrHC) 3994 { 3995 /* @todo */ 3996 AssertMsgFailed(("Too early to call SetupVRAM with external VRAM\n")); 3997 3998 /* Remove existing overlay mapping. */ 3999 // MMR3PPhysUnregisterOverlay (pVM, s->GCPhysVRAM, u32OverlayOffset, s->pvExtVRAMHC, s->cbExtVRAM); 4000 4001 /* Copy the content of the external VRAM to the device VRAM. */ 4002 memcpy (s->vram_ptrHC + u32OverlayOffset, s->pvExtVRAMHC, s->cbExtVRAM); 4003 } 4004 4005 s->pvExtVRAMHC = NULL; 4006 s->cbExtVRAM = 0; 4007 } 4008 4009 if (pvBuffer == NULL) 4010 { 4011 /* Resetting VRAM to use only vga device allocated memory. */ 4012 Assert (cbBuffer == 0); 4013 return VINF_SUCCESS; 4014 } 4015 4016 if (pvBuffer == s->vram_ptrHC) 4017 { 4018 /* Caller will use the guest VRAM directly. Do nothing. Ignore cbBuffer. */ 4019 cbBuffer = 0; 4020 rc = VINF_SUCCESS; 4021 } 4022 else 4023 { 4024 /* Register new overlay. */ 4025 4026 /* @todo */ 4027 AssertMsgFailed(("Too early to call SetupVRAM with external VRAM\n")); 4028 4029 cbBuffer = RT_ALIGN_32(cbBuffer, PAGE_SIZE); 4030 4031 // rc = MMR3PhysRegisterOverlay(pVM, s->GCPhysVRAM, u32OverlayOffset, pvBuffer, cbBuffer, "FBVRam"); 4032 } 4033 4034 if (VBOX_SUCCESS (rc)) 4035 { 4036 s->pvExtVRAMHC = pvBuffer; 4037 s->cbExtVRAM = cbBuffer; 4038 } 4039 4040 return rc; 4009 4010 LogFlow(("vgaPortSetRenderVRAM: fRender = %d\n", fRender)); 4011 4012 s->fRenderVRAM = fRender; 4041 4013 } 4042 4014 … … 4575 4547 pData->Port.pfnDisplayBlt = vgaPortDisplayBlt; 4576 4548 pData->Port.pfnUpdateDisplayRect= vgaPortUpdateDisplayRect; 4577 pData->Port.pfnSet upVRAM = vgaPortSetupVRAM;4549 pData->Port.pfnSetRenderVRAM = vgaPortSetRenderVRAM; 4578 4550 4579 4551 trunk/src/VBox/Devices/Graphics/DevVGA.h
r2079 r2106 281 281 uint32_t Padding0; /* May be removed if more data is added */ 282 282 283 /** Size of the buffer*/ 284 uint32_t cbExtVRAM; 285 /** Address of external video memory buffer overlaying VRAM. */ 286 R3PTRTYPE(void *) pvExtVRAMHC; 287 #if HC_ARCH_BITS ==32 288 uint32_t Alignment0; 289 #endif 283 /** Whether to render the guest VRAM to the framebuffer memory. False only for some LFB modes. */ 284 uint32_t fRenderVRAM; 290 285 291 286 /** The PCI device. */ trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp
r1931 r2106 235 235 GEN_CHECK_OFF(VGASTATE, RefreshTimer); 236 236 GEN_CHECK_OFF(VGASTATE, cMilliesRefreshInterval); 237 GEN_CHECK_OFF(VGASTATE, pvExtVRAMHC); 238 GEN_CHECK_OFF(VGASTATE, cbExtVRAM); 237 GEN_CHECK_OFF(VGASTATE, fRenderVRAM); 239 238 GEN_CHECK_OFF(VGASTATE, Dev); 240 239 GEN_CHECK_OFF(VGASTATE, StatGCMemoryRead); trunk/src/VBox/Frontends/VBoxBFE/DisplayImpl.cpp
r1550 r2106 93 93 mcbVbvaPartial = 0; 94 94 95 RTSemEventMultiCreate(&mResizeSem);96 95 RTSemEventMultiCreate(&mUpdateSem); 97 96 98 97 // reset the event sems 99 RTSemEventMultiReset(mResizeSem);100 98 RTSemEventMultiReset(mUpdateSem); 101 99 … … 105 103 mInternalFramebuffer = true; 106 104 mFramebufferOpened = false; 105 106 mu32ResizeStatus = ResizeStatus_Void; 107 107 } 108 108 … … 110 110 { 111 111 mFramebuffer = 0; 112 RTSemEventMultiDestroy(mResizeSem);113 112 RTSemEventMultiDestroy(mUpdateSem); 114 113 } … … 124 123 * @param h New display height 125 124 */ 126 voidVMDisplay::handleDisplayResize (int w, int h)125 int VMDisplay::handleDisplayResize (int w, int h) 127 126 { 128 127 LogFlow(("VMDisplay::handleDisplayResize(): w=%d, h=%d\n", w, h)); … … 130 129 // if there is no Framebuffer, this call is not interesting 131 130 if (mFramebuffer == NULL) 132 return; 133 134 // callback into the Framebuffer to notify it 131 return VINF_SUCCESS; 132 133 /* Atomically set the resize status before calling the framebuffer. The new InProgress status will 134 * disable access to the VGA device by the EMT thread. 135 */ 136 bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_InProgress, ResizeStatus_Void); 137 AssertRelease(f);NOREF(f); 138 139 // callback into the Framebuffer to notify it 135 140 BOOL finished; 136 141 137 142 mFramebuffer->Lock(); 138 139 /* Reset the event here. It could be signalled before it gets to after 'if (!finished)' */140 RTSemEventMultiReset(mResizeSem);141 143 142 144 mFramebuffer->RequestResize(w, h, &finished); … … 150 152 */ 151 153 152 /// @todo is this compatible with VBOX_NEXT_STEP? 153 // the framebuffer needs more time to process 154 // the event so we have to halt the VM until it's done 155 RTSemEventMultiWait(mResizeSem, RT_INDEFINITE_WAIT); 156 } 157 158 updateDisplayData(); 159 160 mFramebuffer->Unlock(); 161 return; 154 return VINF_VGA_RESIZE_IN_PROGRESS; 155 } 156 157 /* Set the status so the 'handleResizeCompleted' would work. */ 158 f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_UpdateDisplayData, ResizeStatus_InProgress); 159 AssertRelease(f);NOREF(f); 160 161 /* The method also unlocks the framebuffer. */ 162 handleResizeCompletedEMT(); 163 164 return VINF_SUCCESS; 165 } 166 167 /** 168 * Framebuffer has been resized. 169 * Read the new display data and unlock the framebuffer. 170 * 171 * @thread EMT 172 */ 173 void VMDisplay::handleResizeCompletedEMT (void) 174 { 175 LogFlowFunc(("\n")); 176 if (mFramebuffer) 177 { 178 /* Framebuffer has completed the resize. Update the connector data. */ 179 updateDisplayData(); 180 181 mpDrv->pUpPort->pfnSetRenderVRAM (mpDrv->pUpPort, true); 182 183 /* Unlock framebuffer. */ 184 mFramebuffer->Unlock(); 185 } 186 187 /* Go into non resizing state. */ 188 bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_Void, ResizeStatus_UpdateDisplayData); 189 AssertRelease(f);NOREF(f); 162 190 } 163 191 … … 176 204 return E_FAIL; 177 205 178 /* The framebuffer can already be locked by the thread waiting for completion; due to recent 179 * changes when calling the VGA device. We don't really need to lock it here, so just don't 180 * bother. 181 */ 182 //mFramebuffer->Lock(); 183 // signal our semaphore 184 RTSemEventMultiSignal(mResizeSem); 185 //mFramebuffer->Unlock(); 206 /* Set the flag indicating that the resize has completed and display data need to be updated. */ 207 bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_UpdateDisplayData, ResizeStatus_InProgress); 208 AssertRelease(f);NOREF(f); 186 209 187 210 return S_OK; … … 423 446 * @param cy New height in pixels. 424 447 */ 425 DECLCALLBACK( void) VMDisplay::displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy)448 DECLCALLBACK(int) VMDisplay::displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy) 426 449 { 427 450 PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface); 428 451 429 452 // forward call to instance handler 430 pDrv->pDisplay->handleDisplayResize(cx, cy);453 return pDrv->pDisplay->handleDisplayResize(cx, cy); 431 454 } 432 455 … … 465 488 466 489 VMDisplay *pDisplay = pDrv->pDisplay; 490 491 uint32_t u32ResizeStatus = pDisplay->mu32ResizeStatus; 492 493 if (u32ResizeStatus == ResizeStatus_UpdateDisplayData) 494 { 495 #ifdef DEBUG_sunlover 496 LogFlowFunc (("ResizeStatus_UpdateDisplayData\n")); 497 #endif /* DEBUG_sunlover */ 498 /* The framebuffer was resized and display data need to be updated. */ 499 pDisplay->handleResizeCompletedEMT (); 500 /* Continue with normal processing because the status here is ResizeStatus_Void. */ 501 Assert (pDisplay->mu32ResizeStatus == ResizeStatus_Void); 502 } 503 else if (u32ResizeStatus == ResizeStatus_InProgress) 504 { 505 #ifdef DEBUG_sunlover 506 LogFlowFunc (("ResizeStatus_InProcess\n")); 507 #endif /* DEBUG_sunlover */ 508 /* The framebuffer is being resized. Do not call the VGA device back. Immediately return. */ 509 return; 510 } 467 511 468 512 if (pDisplay->mfPendingVideoAccelEnable) trunk/src/VBox/Frontends/VBoxBFE/DisplayImpl.h
r1550 r2106 39 39 40 40 // public methods only for internal purposes 41 voidhandleDisplayResize (int w, int h);41 int handleDisplayResize (int w, int h); 42 42 void handleDisplayUpdate (int x, int y, int cx, int cy); 43 43 … … 67 67 static DECLCALLBACK(void*) drvQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface); 68 68 static DECLCALLBACK(int) drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle); 69 static DECLCALLBACK( void)displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy);69 static DECLCALLBACK(int) displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy); 70 70 static DECLCALLBACK(void) displayUpdateCallback(PPDMIDISPLAYCONNECTOR pInterface, 71 71 uint32_t x, uint32_t y, uint32_t cx, uint32_t cy); … … 82 82 83 83 ULONG mSupportedAccelOps; 84 RTSEMEVENTMULTI mResizeSem;85 84 RTSEMEVENTMULTI mUpdateSem; 86 85 … … 97 96 bool vbvaFetchCmd (struct _VBVACMDHDR **ppHdr, uint32_t *pcbCmd); 98 97 void vbvaReleaseCmd (struct _VBVACMDHDR *pHdr, int32_t cbCmd); 98 99 void VMDisplay::handleResizeCompletedEMT (void); 100 volatile uint32_t mu32ResizeStatus; 101 102 enum { 103 ResizeStatus_Void, 104 ResizeStatus_InProgress, 105 ResizeStatus_UpdateDisplayData 106 }; 99 107 }; 100 108 trunk/src/VBox/Main/DisplayImpl.cpp
r1904 r2106 83 83 mpVMMDev = NULL; 84 84 mfVMMDevInited = false; 85 RTSemEventMultiCreate(&mResizeSem);86 85 RTSemEventMultiCreate(&mUpdateSem); 87 86 … … 92 91 mLastHeight = 0; 93 92 93 mu32ResizeStatus = ResizeStatus_Void; 94 94 95 return S_OK; 95 96 } … … 123 124 124 125 /* reset the event sems */ 125 RTSemEventMultiReset(mResizeSem);126 126 RTSemEventMultiReset(mUpdateSem); 127 127 … … 151 151 152 152 mFramebuffer.setNull(); 153 RTSemEventMultiDestroy(mResizeSem);154 153 RTSemEventMultiDestroy(mUpdateSem); 155 154 … … 187 186 ///////////////////////////////////////////////////////////////////////////// 188 187 189 void Display::callFramebufferResize (FramebufferPixelFormat_T pixelFormat, void *pvVRAM, uint32_t cbLine, int w, int h) 190 { 191 Assert (!mFramebuffer.isNull()); 188 /** 189 * @thread EMT 190 */ 191 static int callFramebufferResize (IFramebuffer *pFramebuffer, FramebufferPixelFormat_T pixelFormat, void *pvVRAM, uint32_t cbLine, int w, int h) 192 { 193 Assert (pFramebuffer); 192 194 193 195 /* Call the framebuffer to try and set required pixelFormat. */ 194 196 BOOL finished = TRUE; 195 197 196 /* Reset the event here. It could be signalled before it gets to after 'if (!finished)' */ 197 RTSemEventMultiReset(mResizeSem); 198 199 mFramebuffer->RequestResize (pixelFormat, (BYTE *) pvVRAM, cbLine, w, h, &finished); 198 pFramebuffer->RequestResize (pixelFormat, (BYTE *) pvVRAM, cbLine, w, h, &finished); 200 199 201 200 if (!finished) 202 201 { 203 202 LogFlowFunc (("External framebuffer wants us to wait!\n")); 204 205 /* Note: The previously obtained framebuffer lock is preserved. 206 * The EMT keeps the lock until the resize process completes. 207 */ 208 209 /* The framebuffer needs more time to process 210 * the event so we have to halt the VM until it's done. 211 */ 212 RTSemEventMultiWait(mResizeSem, RT_INDEFINITE_WAIT); /** @todo r=bird: this is a serious deadlock point, where EMT is stuck while the main thread is doing VMR3Req for some reason. */ 213 } 203 return VINF_VGA_RESIZE_IN_PROGRESS; 204 } 205 206 return VINF_SUCCESS; 214 207 } 215 208 216 209 /** 217 210 * Handles display resize event. 211 * Disables access to VGA device; 212 * calls the framebuffer RequestResize method; 213 * if framebuffer resizes synchronously, 214 * updates the display connector data and enables access to the VGA device. 218 215 * 219 216 * @param w New display width … … 222 219 * @thread EMT 223 220 */ 224 voidDisplay::handleDisplayResize (uint32_t bpp, void *pvVRAM, uint32_t cbLine, int w, int h)221 int Display::handleDisplayResize (uint32_t bpp, void *pvVRAM, uint32_t cbLine, int w, int h) 225 222 { 226 223 LogRel (("Display::handleDisplayResize(): pvVRAM=%p w=%d h=%d bpp=%d cbLine=0x%X\n", … … 230 227 if (mFramebuffer.isNull()) 231 228 { 232 return ;229 return VINF_SUCCESS; 233 230 } 234 231 … … 249 246 } 250 247 248 /* Atomically set the resize status before calling the framebuffer. The new InProgress status will 249 * disable access to the VGA device by the EMT thread. 250 */ 251 bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_InProgress, ResizeStatus_Void); 252 AssertRelease(f);NOREF(f); 253 254 /* The framebuffer is locked in the state. 255 * The lock is kept, because the framebuffer is in undefined state. 256 */ 251 257 mFramebuffer->Lock(); 252 258 253 callFramebufferResize (pixelFormat, pvVRAM, cbLine, w, h); 254 255 /* Indicated whether the FB should be set to a default format in case something went wrong. */ 256 bool fResetFormat = false; 257 258 /* Check the framebuffer pixel format. */ 259 FramebufferPixelFormat_T newPixelFormat; 260 261 mFramebuffer->COMGETTER(PixelFormat) (&newPixelFormat); 262 263 if (newPixelFormat == FramebufferPixelFormat_PixelFormatDefault) 264 { 265 mpDrv->pUpPort->pfnSetupVRAM (mpDrv->pUpPort, NULL, 0); 266 } 267 else 268 { 269 Assert(pixelFormat == newPixelFormat); 270 271 /* Framebuffer successfully set the requested format. */ 272 BYTE *address; 273 mFramebuffer->COMGETTER(Address) (&address); 274 275 ULONG lineSize; 276 mFramebuffer->COMGETTER(LineSize) (&lineSize); 277 Assert(lineSize == cbLine); 278 279 /* Trust Framebuffer implementation that it allocated a buffer, 280 * which size is a multiple of PAGE_SIZE. 259 int rc = callFramebufferResize (mFramebuffer, pixelFormat, pvVRAM, cbLine, w, h); 260 if (rc == VINF_VGA_RESIZE_IN_PROGRESS) 261 { 262 /* Immediately return to the caller. ResizeCompleted will be called back by the 263 * GUI thread. The ResizeCompleted callback will change the resize status from 264 * InProgress to UpdateDisplayData. The latter status will be checked by the 265 * display timer callback on EMT and all required adjustments will be done there. 281 266 */ 282 uint32_t cbBuffer = cbLine * h; 283 284 int rc = mpDrv->pUpPort->pfnSetupVRAM (mpDrv->pUpPort, address, cbBuffer); 285 286 if (VBOX_FAILURE(rc)) 287 { 288 LogFlowFunc (("pfnSetupVRAM returns %Vrc\n", rc)); 289 fResetFormat = true; 290 } 267 return rc; 268 } 269 270 /* Set the status so the 'handleResizeCompleted' would work. */ 271 f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_UpdateDisplayData, ResizeStatus_InProgress); 272 AssertRelease(f);NOREF(f); 273 274 /* The method also unlocks the framebuffer. */ 275 handleResizeCompletedEMT(); 276 277 return VINF_SUCCESS; 278 } 279 280 /** 281 * Framebuffer has been resized. 282 * Read the new display data and unlock the framebuffer. 283 * 284 * @thread EMT 285 */ 286 void Display::handleResizeCompletedEMT (void) 287 { 288 LogFlowFunc(("\n")); 289 if (!mFramebuffer.isNull()) 290 { 291 /* Framebuffer has completed the resize. Update the connector data. */ 292 updateDisplayData(); 293 294 /* Check the framebuffer pixel format to setup the rendering in VGA device. */ 295 FramebufferPixelFormat_T newPixelFormat; 296 297 mFramebuffer->COMGETTER(PixelFormat) (&newPixelFormat); 298 299 mpDrv->pUpPort->pfnSetRenderVRAM (mpDrv->pUpPort, newPixelFormat == FramebufferPixelFormat_PixelFormatDefault); 300 301 /* Unlock framebuffer. */ 302 mFramebuffer->Unlock(); 303 } 291 304 292 305 #ifdef DEBUG_sunlover 293 if (!stam)294 {295 /* protect mpVM */296 Console::SafeVMPtr pVM (mParent);297 AssertComRC (pVM.rc());298 299 STAM_REG(pVM, &StatDisplayRefresh, STAMTYPE_PROFILE, "/PROF/Display/Refresh", STAMUNIT_TICKS_PER_CALL, "Time spent in EMT for display updates.");300 stam = 1;301 }306 if (!stam) 307 { 308 /* protect mpVM */ 309 Console::SafeVMPtr pVM (mParent); 310 AssertComRC (pVM.rc()); 311 312 STAM_REG(pVM, &StatDisplayRefresh, STAMTYPE_PROFILE, "/PROF/Display/Refresh", STAMUNIT_TICKS_PER_CALL, "Time spent in EMT for display updates."); 313 stam = 1; 314 } 302 315 #endif /* DEBUG_sunlover */ 303 } 304 305 if (fResetFormat) 306 { 307 callFramebufferResize (FramebufferPixelFormat_PixelFormatDefault, NULL, 0, w, h); 308 } 309 310 updateDisplayData(); 311 316 317 /* Inform VRDP server about the change of display parameters. */ 312 318 LogFlowFunc (("Calling VRDP\n")); 313 314 319 mParent->consoleVRDPServer()->SendResize(); 315 320 316 mFramebuffer->Unlock();317 318 return;321 /* Go into non resizing state. */ 322 bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_Void, ResizeStatus_UpdateDisplayData); 323 AssertRelease(f);NOREF(f); 319 324 } 320 325 … … 612 617 613 618 /* Update entire display. */ 614 mpDrv->pUpPort->pfnUpdateDisplayAll(mpDrv->pUpPort); 619 if (mu32ResizeStatus == ResizeStatus_Void) 620 { 621 mpDrv->pUpPort->pfnUpdateDisplayAll(mpDrv->pUpPort); 622 } 615 623 616 624 /* Everything OK. VBVA status can be changed. */ … … 1534 1542 "for external framebuffers")); 1535 1543 1536 /* signal our semaphore */ 1537 RTSemEventMultiSignal(mResizeSem); 1544 /* Set the flag indicating that the resize has completed and display data need to be updated. */ 1545 bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_UpdateDisplayData, ResizeStatus_InProgress); 1546 AssertRelease(f);NOREF(f); 1538 1547 1539 1548 return S_OK; … … 1720 1729 * @see PDMIDISPLAYCONNECTOR::pfnResize 1721 1730 */ 1722 DECLCALLBACK( void) Display::displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface,1723 uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy)1731 DECLCALLBACK(int) Display::displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, 1732 uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy) 1724 1733 { 1725 1734 PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface); … … 1728 1737 bpp, pvVRAM, cbLine, cx, cy)); 1729 1738 1730 pDrv->pDisplay->handleDisplayResize(bpp, pvVRAM, cbLine, cx, cy);1739 return pDrv->pDisplay->handleDisplayResize(bpp, pvVRAM, cbLine, cx, cy); 1731 1740 } 1732 1741 … … 1773 1782 1774 1783 Display *pDisplay = pDrv->pDisplay; 1784 1785 /* Check the resize status. The status can be checked normally because 1786 * the status affects only the EMT. 1787 */ 1788 uint32_t u32ResizeStatus = pDisplay->mu32ResizeStatus; 1789 1790 if (u32ResizeStatus == ResizeStatus_UpdateDisplayData) 1791 { 1792 LogFlowFunc (("ResizeStatus_UpdateDisplayData\n")); 1793 /* The framebuffer was resized and display data need to be updated. */ 1794 pDisplay->handleResizeCompletedEMT (); 1795 /* Continue with normal processing because the status here is ResizeStatus_Void. */ 1796 Assert (pDisplay->mu32ResizeStatus == ResizeStatus_Void); 1797 } 1798 else if (u32ResizeStatus == ResizeStatus_InProgress) 1799 { 1800 /* The framebuffer is being resized. Do not call the VGA device back. Immediately return. */ 1801 LogFlowFunc (("ResizeStatus_InProcess\n")); 1802 return; 1803 } 1775 1804 1776 1805 if (pDisplay->mFramebuffer.isNull()) trunk/src/VBox/Main/include/DisplayImpl.h
r470 r2106 59 59 60 60 // public methods only for internal purposes 61 voidhandleDisplayResize (uint32_t bpp, void *pvVRAM, uint32_t cbLine, int w, int h);61 int handleDisplayResize (uint32_t bpp, void *pvVRAM, uint32_t cbLine, int w, int h); 62 62 void handleDisplayUpdate (int x, int y, int cx, int cy); 63 63 IFramebuffer *getFramebuffer() … … 140 140 static DECLCALLBACK(int) drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle); 141 141 static DECLCALLBACK(void) drvDestruct(PPDMDRVINS pDrvIns); 142 static DECLCALLBACK( void)displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy);142 static DECLCALLBACK(int) displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy); 143 143 static DECLCALLBACK(void) displayUpdateCallback(PPDMIDISPLAYCONNECTOR pInterface, 144 144 uint32_t x, uint32_t y, uint32_t cx, uint32_t cy); … … 159 159 /** bitmask of acceleration operations supported by current framebuffer */ 160 160 ULONG mSupportedAccelOps; 161 RTSEMEVENTMULTI mResizeSem;162 161 RTSEMEVENTMULTI mUpdateSem; 163 162 … … 186 185 void vbvaReleaseCmd (VBVACMDHDR *pHdr, int32_t cbCmd); 187 186 188 void callFramebufferResize (FramebufferPixelFormat_T pixelFormat, void *pvVRAM, uint32_t cbLine, int w, int h); 187 void handleResizeCompletedEMT (void); 188 volatile uint32_t mu32ResizeStatus; 189 190 enum { 191 ResizeStatus_Void, 192 ResizeStatus_InProgress, 193 ResizeStatus_UpdateDisplayData 194 }; 189 195 }; 190 196

