VirtualBox

Changeset 2106

Show
Ignore:
Timestamp:
04/16/07 17:25:48 (2 years ago)
Author:
vboxsync
Message:

Do not block EMT while resizing the framebuffer.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/include/VBox/err.h

    r1857 r2106  
    10311031 * The format or bit count of the custom mode value is invalid. */ 
    10321032#define VERR_VGA_INVALID_CUSTOM_MODE                (-3500) 
     1033/** The display connector is resizing. */ 
     1034#define VINF_VGA_RESIZE_IN_PROGRESS                 (3501) 
    10331035/** @} */ 
    10341036 
  • trunk/include/VBox/pdm.h

    r2040 r2106  
    655655     * while doing so. 
    656656     * 
     657     * @returns VBox status code. 
    657658     * @param   pInterface          Pointer to this interface. 
    658659     * @thread  The emulation thread. 
    659660     */ 
    660     DECLR3CALLBACKMEMBER(void, pfnUpdateDisplay,(PPDMIDISPLAYPORT pInterface)); 
     661    DECLR3CALLBACKMEMBER(int, pfnUpdateDisplay,(PPDMIDISPLAYPORT pInterface)); 
    661662 
    662663    /** 
     
    666667     * PDMIDISPLAYCONNECTOR interface and calles PDMIDISPLAYCONNECTOR::pfnUpdateRect(). 
    667668     * 
     669     * @returns VBox status code. 
    668670     * @param   pInterface          Pointer to this interface. 
    669671     * @thread  The emulation thread. 
    670672     */ 
    671     DECLR3CALLBACKMEMBER(void, pfnUpdateDisplayAll,(PPDMIDISPLAYPORT pInterface)); 
     673    DECLR3CALLBACKMEMBER(int, pfnUpdateDisplayAll,(PPDMIDISPLAYPORT pInterface)); 
    672674 
    673675    /** 
     
    749751 
    750752    /** 
    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     * 
    755756     * @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. 
    758758     * @thread  The emulation thread. 
    759759     */ 
    760     DECLR3CALLBACKMEMBER(int, pfnSetupVRAM,(PPDMIDISPLAYPORT pInterface, void *pvBuffer, uint32_t cbBuffer)); 
     760    DECLR3CALLBACKMEMBER(void, pfnSetRenderVRAM,(PPDMIDISPLAYPORT pInterface, bool fRender)); 
    761761} PDMIDISPLAYPORT; 
    762762 
     
    774774     * This is called when the resolution changes. This usually happens on 
    775775     * 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. 
    777781     * @param   pInterface          Pointer to this interface. 
    778782     * @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. 
    780784     * @param   cbLine              Size in bytes of a single scan line. 
    781785     * @param   cx                  New display width. 
     
    783787     * @thread  The emulation thread. 
    784788     */ 
    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)); 
    786790 
    787791    /** 
  • trunk/src/VBox/Devices/Graphics/DevVGA.cpp

    r2079 r2106  
    14061406 * - flashing 
    14071407 */ 
     1408#ifndef VBOX 
    14081409static void vga_draw_text(VGAState *s, int full_update) 
     1410#else 
     1411static int vga_draw_text(VGAState *s, int full_update) 
     1412#endif /* !VBOX */ 
    14091413{ 
    14101414    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr; 
     
    14841488    if ((height * width) > CH_ATTR_SIZE) { 
    14851489        /* better than nothing: exit if transient size is too big */ 
     1490#ifndef VBOX 
    14861491        return; 
     1492#else 
     1493        return VINF_SUCCESS; 
     1494#endif /* VBOX */ 
    14871495    } 
    14881496 
     
    14931501#ifndef VBOX 
    14941502        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 */ 
    14991503        s->last_width = width; 
    15001504        s->last_height = height; 
     
    15021506        s->last_cw = cw; 
    15031507        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 */ 
    15041520    } 
    15051521    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr; 
     
    16121628        s1 += line_offset; 
    16131629    } 
     1630#ifdef VBOX 
     1631        return VINF_SUCCESS; 
     1632#endif /* VBOX */ 
    16141633} 
    16151634 
     
    17441763{ 
    17451764    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 #else 
    17521765    /** @todo r=sunlover: If the guest changes VBE_DISPI_INDEX_X_OFFSET, VBE_DISPI_INDEX_Y_OFFSET 
    17531766     *                    registers, then the third parameter of the following call should be 
    17541767     *                    probably 's->CTXSUFF(vram_ptr) + s->vbe_start_addr'. 
    17551768     */ 
    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); 
    17581770 
    17591771    /* last stuff */ 
     
    17641776    s->last_height = cy; 
    17651777 
     1778    if (rc == VINF_VGA_RESIZE_IN_PROGRESS) 
     1779        return rc; 
     1780    AssertRC(rc); 
     1781 
    17661782    /* update palette */ 
    17671783    switch (s->pDrv->cBits) 
     
    17841800 * graphic modes 
    17851801 */ 
     1802#ifndef VBOX 
    17861803static void vga_draw_graphic(VGAState *s, int full_update) 
     1804#else 
     1805static int vga_draw_graphic(VGAState *s, int full_update) 
     1806#endif /* !VBOX */ 
    17871807{ 
    17881808    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask; 
     
    18751895        ||  height         != (int)s->last_height 
    18761896        ||  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; 
    18801902        full_update = 1; 
    18811903    } 
     
    19001922     * programming of the virtual hardware ports. Just return. 
    19011923     */ 
    1902     if (bwidth == 0) return
     1924    if (bwidth == 0) return VINF_SUCCESS
    19031925#endif /* VBOX */  
    19041926    y_start = -1; 
     
    19571979            vga_draw_line(s, d, s->vram_ptr + addr, width); 
    19581980#else /* VBOX */ 
    1959             if (s->pvExtVRAMHC != s->pDrv->pu8Data) /* Only if external VRAM was not setup. */ 
     1981            if (s->fRenderVRAM) 
    19601982                vga_draw_line(s, d, s->CTXSUFF(vram_ptr) + addr, width); 
    19611983#endif /* VBOX */ 
     
    20072029    } 
    20082030    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4); 
     2031#ifdef VBOX 
     2032    return VINF_SUCCESS; 
     2033#endif /* VBOX */ 
    20092034} 
    20102035 
     
    20622087void vga_update_display(void) 
    20632088{ 
    2064 #ifdef DEBUG_sunlover 
    2065     LogFlow(("vga_update_display")); 
    2066 #endif /* DEBUG_sunlover */ 
    2067  
    20682089    VGAState *s = vga_state; 
    20692090#else /* VBOX */ 
    2070 static void vga_update_display(PVGASTATE s) 
    2071 
     2091static int vga_update_display(PVGASTATE s) 
     2092
     2093    int rc = VINF_SUCCESS; 
    20722094#endif /* VBOX */ 
    20732095    int full_update, graphic_mode; 
     
    21122134        switch(graphic_mode) { 
    21132135        case GMODE_TEXT: 
     2136#ifdef VBOX 
     2137            rc = 
     2138#endif /* VBOX */ 
    21142139            vga_draw_text(s, full_update); 
    21152140            break; 
    21162141        case GMODE_GRAPH: 
     2142#ifdef VBOX 
     2143            rc = 
     2144#endif /* VBOX */ 
    21172145            vga_draw_graphic(s, full_update); 
    21182146            break; 
     
    21232151        } 
    21242152    } 
     2153#ifdef VBOX 
     2154    return rc; 
     2155#endif /* VBOX */ 
    21252156} 
    21262157 
     
    35223553 * @thread  The emulation thread. 
    35233554 */ 
    3524 static DECLCALLBACK(void) vgaDummyResize(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy) 
    3525 
     3555static DECLCALLBACK(int) vgaDummyResize(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy) 
     3556
     3557    return VINF_SUCCESS; 
    35263558} 
    35273559 
     
    35723604 * @see     PDMIKEYBOARDPORT::pfnUpdateDisplay() for details. 
    35733605 */ 
    3574 static DECLCALLBACK(void) vgaPortUpdateDisplay(PPDMIDISPLAYPORT pInterface) 
     3606static DECLCALLBACK(int) vgaPortUpdateDisplay(PPDMIDISPLAYPORT pInterface) 
    35753607{ 
    35763608    PVGASTATE pData = IDISPLAYPORT_2_VGASTATE(pInterface); 
     
    35833615    /* This should be called only in non VBVA mode. */ 
    35843616 
    3585     vga_update_display(pData); 
     3617    int rc = vga_update_display(pData); 
     3618    if (rc != VINF_SUCCESS) 
     3619        return rc; 
    35863620 
    35873621    if (pData->fHaveDirtyBits) 
     
    35913625        pData->fHaveDirtyBits = false; 
    35923626    } 
     3627 
     3628    return VINF_SUCCESS; 
    35933629} 
    35943630 
     
    36003636 * @see     PDMIKEYBOARDPORT::pfnUpdateDisplayAll() for details. 
    36013637 */ 
    3602 static DECLCALLBACK(void) vgaPortUpdateDisplayAll(PPDMIDISPLAYPORT pInterface) 
     3638static DECLCALLBACK(int) vgaPortUpdateDisplayAll(PPDMIDISPLAYPORT pInterface) 
    36033639{ 
    36043640    PVGASTATE pData = IDISPLAYPORT_2_VGASTATE(pInterface); 
     
    36123648 
    36133649    pData->graphic_mode = -1; /* force full update */ 
    3614     vga_update_display(pData); 
     3650    return vga_update_display(pData); 
    36153651} 
    36163652 
     
    36603696static DECLCALLBACK(int) vgaPortSnapshot(PPDMIDISPLAYPORT pInterface, void *pvData, size_t cbData, uint32_t *pcx, uint32_t *pcy, size_t *pcbData) 
    36613697{ 
     3698    /* @todo r=sunlover: replace the method with a direct VRAM rendering like in vgaPortUpdateDisplayRect.  */ 
    36623699    PPDMIDISPLAYCONNECTOR   pConnector; 
    36633700    PDMIDISPLAYCONNECTOR    Connector; 
     
    37133750 
    37143751    /* make the snapshot. */ 
    3715     vga_update_display(pData); 
     3752    int rc = vga_update_display(pData); 
     3753    if (rc != VINF_SUCCESS) 
     3754        return rc; 
    37163755 
    37173756    /* restore */ 
     
    38433882 
    38443883    /* Check if there is something to do at all. */ 
    3845     if (s->pvExtVRAMHC == s->pDrv->pu8Data
     3884    if (!s->fRenderVRAM
    38463885    { 
    38473886        /* The framebuffer uses the guest VRAM directly. */ 
    38483887#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")); 
    38503889#endif /* DEBUG_sunlover */ 
    38513890        return; 
     
    39443983     * This is true because coordinates were verified. 
    39453984     */ 
    3946     pu8Src = s->pvExtVRAMHC? (uint8_t *)s->pvExtVRAMHC: s->vram_ptrHC; 
     3985    pu8Src = s->vram_ptrHC; 
    39473986    pu8Src += u32OffsetSrc + y * cbLineSrc + x * cbPixelSrc; 
    39483987 
     
    39654004} 
    39664005 
    3967 static DECLCALLBACK(int) vgaPortSetupVRAM (PPDMIDISPLAYPORT pInterface, void *pvBuffer, uint32_t cbBuffer) 
    3968 
    3969     int rc = VINF_SUCCESS; 
     4006static DECLCALLBACK(void) vgaPortSetRenderVRAM(PPDMIDISPLAYPORT pInterface, bool fRender) 
     4007
    39704008    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; 
    40414013} 
    40424014 
     
    45754547    pData->Port.pfnDisplayBlt       = vgaPortDisplayBlt; 
    45764548    pData->Port.pfnUpdateDisplayRect= vgaPortUpdateDisplayRect; 
    4577     pData->Port.pfnSetupVRAM        = vgaPortSetupVRAM; 
     4549    pData->Port.pfnSetRenderVRAM    = vgaPortSetRenderVRAM; 
    45784550 
    45794551 
  • trunk/src/VBox/Devices/Graphics/DevVGA.h

    r2079 r2106  
    281281    uint32_t                    Padding0;   /* May be removed if more data is added */ 
    282282 
    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; 
    290285 
    291286    /** The PCI device. */ 
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp

    r1931 r2106  
    235235    GEN_CHECK_OFF(VGASTATE, RefreshTimer); 
    236236    GEN_CHECK_OFF(VGASTATE, cMilliesRefreshInterval); 
    237     GEN_CHECK_OFF(VGASTATE, pvExtVRAMHC); 
    238     GEN_CHECK_OFF(VGASTATE, cbExtVRAM); 
     237    GEN_CHECK_OFF(VGASTATE, fRenderVRAM); 
    239238    GEN_CHECK_OFF(VGASTATE, Dev); 
    240239    GEN_CHECK_OFF(VGASTATE, StatGCMemoryRead); 
  • trunk/src/VBox/Frontends/VBoxBFE/DisplayImpl.cpp

    r1550 r2106  
    9393    mcbVbvaPartial = 0; 
    9494 
    95     RTSemEventMultiCreate(&mResizeSem); 
    9695    RTSemEventMultiCreate(&mUpdateSem); 
    9796 
    9897    // reset the event sems 
    99     RTSemEventMultiReset(mResizeSem); 
    10098    RTSemEventMultiReset(mUpdateSem); 
    10199 
     
    105103    mInternalFramebuffer = true; 
    106104    mFramebufferOpened = false; 
     105 
     106    mu32ResizeStatus = ResizeStatus_Void; 
    107107} 
    108108 
     
    110110{ 
    111111    mFramebuffer = 0; 
    112     RTSemEventMultiDestroy(mResizeSem); 
    113112    RTSemEventMultiDestroy(mUpdateSem); 
    114113} 
     
    124123 * @param h New display height 
    125124 */ 
    126 void VMDisplay::handleDisplayResize (int w, int h) 
     125int VMDisplay::handleDisplayResize (int w, int h) 
    127126{ 
    128127    LogFlow(("VMDisplay::handleDisplayResize(): w=%d, h=%d\n", w, h)); 
     
    130129    // if there is no Framebuffer, this call is not interesting 
    131130    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 
    135140    BOOL finished; 
    136141 
    137142    mFramebuffer->Lock(); 
    138  
    139     /* Reset the event here. It could be signalled before it gets to after 'if (!finished)' */ 
    140     RTSemEventMultiReset(mResizeSem); 
    141143 
    142144    mFramebuffer->RequestResize(w, h, &finished); 
     
    150152         */ 
    151153 
    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 */ 
     173void 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); 
    162190} 
    163191 
     
    176204        return E_FAIL; 
    177205 
    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); 
    186209 
    187210    return S_OK; 
     
    423446 * @param  cy         New height in pixels. 
    424447 */ 
    425 DECLCALLBACK(void) VMDisplay::displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy) 
     448DECLCALLBACK(int) VMDisplay::displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy) 
    426449{ 
    427450    PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface); 
    428451 
    429452    // forward call to instance handler 
    430     pDrv->pDisplay->handleDisplayResize(cx, cy); 
     453    return pDrv->pDisplay->handleDisplayResize(cx, cy); 
    431454} 
    432455 
     
    465488 
    466489    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    } 
    467511 
    468512    if (pDisplay->mfPendingVideoAccelEnable) 
  • trunk/src/VBox/Frontends/VBoxBFE/DisplayImpl.h

    r1550 r2106  
    3939 
    4040    // public methods only for internal purposes 
    41     void handleDisplayResize (int w, int h); 
     41    int handleDisplayResize (int w, int h); 
    4242    void handleDisplayUpdate (int x, int y, int cx, int cy); 
    4343 
     
    6767    static DECLCALLBACK(void*) drvQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface); 
    6868    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); 
    7070    static DECLCALLBACK(void)  displayUpdateCallback(PPDMIDISPLAYCONNECTOR pInterface, 
    7171                                                     uint32_t x, uint32_t y, uint32_t cx, uint32_t cy); 
     
    8282 
    8383    ULONG mSupportedAccelOps; 
    84     RTSEMEVENTMULTI mResizeSem; 
    8584    RTSEMEVENTMULTI mUpdateSem; 
    8685 
     
    9796    bool vbvaFetchCmd (struct _VBVACMDHDR **ppHdr, uint32_t *pcbCmd); 
    9897    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    }; 
    99107}; 
    100108 
  • trunk/src/VBox/Main/DisplayImpl.cpp

    r1904 r2106  
    8383    mpVMMDev = NULL; 
    8484    mfVMMDevInited = false; 
    85     RTSemEventMultiCreate(&mResizeSem); 
    8685    RTSemEventMultiCreate(&mUpdateSem); 
    8786 
     
    9291    mLastHeight = 0; 
    9392 
     93    mu32ResizeStatus = ResizeStatus_Void; 
     94 
    9495    return S_OK; 
    9596} 
     
    123124 
    124125    /* reset the event sems */ 
    125     RTSemEventMultiReset(mResizeSem); 
    126126    RTSemEventMultiReset(mUpdateSem); 
    127127 
     
    151151 
    152152    mFramebuffer.setNull(); 
    153     RTSemEventMultiDestroy(mResizeSem); 
    154153    RTSemEventMultiDestroy(mUpdateSem); 
    155154 
     
    187186///////////////////////////////////////////////////////////////////////////// 
    188187 
    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 */ 
     191static int callFramebufferResize (IFramebuffer *pFramebuffer, FramebufferPixelFormat_T pixelFormat, void *pvVRAM, uint32_t cbLine, int w, int h) 
     192
     193    Assert (pFramebuffer); 
    192194 
    193195    /* Call the framebuffer to try and set required pixelFormat. */ 
    194196    BOOL finished = TRUE; 
    195197 
    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); 
    200199 
    201200    if (!finished) 
    202201    { 
    203202        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; 
    214207} 
    215208 
    216209/** 
    217210 *  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. 
    218215 * 
    219216 *  @param w New display width 
     
    222219 *  @thread EMT 
    223220 */ 
    224 void Display::handleDisplayResize (uint32_t bpp, void *pvVRAM, uint32_t cbLine, int w, int h) 
     221int Display::handleDisplayResize (uint32_t bpp, void *pvVRAM, uint32_t cbLine, int w, int h) 
    225222{ 
    226223    LogRel (("Display::handleDisplayResize(): pvVRAM=%p w=%d h=%d bpp=%d cbLine=0x%X\n", 
     
    230227    if (mFramebuffer.isNull()) 
    231228    { 
    232         return
     229        return VINF_SUCCESS
    233230    } 
    234231 
     
    249246    } 
    250247 
     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     */ 
    251257    mFramebuffer->Lock(); 
    252258 
    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. 
    281266         */ 
    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 */ 
     286void 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    } 
    291304 
    292305#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   
    302315#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. */ 
    312318    LogFlowFunc (("Calling VRDP\n")); 
    313  
    314319    mParent->consoleVRDPServer()->SendResize(); 
    315320 
    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)
    319324} 
    320325 
     
    612617 
    613618    /* Update entire display. */ 
    614     mpDrv->pUpPort->pfnUpdateDisplayAll(mpDrv->pUpPort); 
     619    if (mu32ResizeStatus == ResizeStatus_Void) 
     620    { 
     621        mpDrv->pUpPort->pfnUpdateDisplayAll(mpDrv->pUpPort); 
     622    } 
    615623 
    616624    /* Everything OK. VBVA status can be changed. */ 
     
    15341542                "for external framebuffers")); 
    15351543 
    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); 
    15381547 
    15391548    return S_OK; 
     
    17201729 * @see PDMIDISPLAYCONNECTOR::pfnResize 
    17211730 */ 
    1722 DECLCALLBACK(void) Display::displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, 
    1723                                                   uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy) 
     1731DECLCALLBACK(int) Display::displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, 
     1732                                                 uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy) 
    17241733{ 
    17251734    PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface); 
     
    17281737                  bpp, pvVRAM, cbLine, cx, cy)); 
    17291738 
    1730     pDrv->pDisplay->handleDisplayResize(bpp, pvVRAM, cbLine, cx, cy); 
     1739    return pDrv->pDisplay->handleDisplayResize(bpp, pvVRAM, cbLine, cx, cy); 
    17311740} 
    17321741 
     
    17731782 
    17741783    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    } 
    17751804 
    17761805    if (pDisplay->mFramebuffer.isNull()) 
  • trunk/src/VBox/Main/include/DisplayImpl.h

    r470 r2106  
    5959 
    6060    // public methods only for internal purposes 
    61     void handleDisplayResize (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); 
    6262    void handleDisplayUpdate (int x, int y, int cx, int cy); 
    6363    IFramebuffer *getFramebuffer() 
     
    140140    static DECLCALLBACK(int)   drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle); 
    141141    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); 
    143143    static DECLCALLBACK(void)  displayUpdateCallback(PPDMIDISPLAYCONNECTOR pInterface, 
    144144                                                     uint32_t x, uint32_t y, uint32_t cx, uint32_t cy); 
     
    159159    /** bitmask of acceleration operations supported by current framebuffer */ 
    160160    ULONG mSupportedAccelOps; 
    161     RTSEMEVENTMULTI mResizeSem; 
    162161    RTSEMEVENTMULTI mUpdateSem; 
    163162 
     
    186185    void vbvaReleaseCmd (VBVACMDHDR *pHdr, int32_t cbCmd); 
    187186 
    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    }; 
    189195}; 
    190196 

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy