VirtualBox

Ignore:
Timestamp:
Nov 5, 2009 9:51:34 AM (15 years ago)
Author:
vboxsync
Message:

Updated screenshot API (xTracker 4364).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/DisplayImpl.cpp

    r24301 r24373  
    4141# include <VBox/VBoxVideo.h>
    4242#endif
     43
     44#include <VBox/com/array.h>
     45
    4346/**
    4447 * Display driver instance data.
     
    15331536}
    15341537
     1538static int displayTakeScreenshot(PVM pVM, struct DRVMAINDISPLAY *pDrv, BYTE *address, ULONG width, ULONG height)
     1539{
     1540    uint8_t *pu8Data = NULL;
     1541    size_t cbData = 0;
     1542    uint32_t cx = 0;
     1543    uint32_t cy = 0;
     1544
     1545    /* @todo pfnTakeScreenshot is probably callable from any thread, because it uses the VGA device lock. */
     1546    int vrc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)pDrv->pUpPort->pfnTakeScreenshot, 5,
     1547                              pDrv->pUpPort, &pu8Data, &cbData, &cx, &cy);
     1548
     1549    if (RT_SUCCESS(vrc))
     1550    {
     1551        if (cx == width && cy == height)
     1552        {
     1553            /* No scaling required. */
     1554            memcpy(address, pu8Data, cbData);
     1555        }
     1556        else
     1557        {
     1558            /* Scale. */
     1559            LogFlowFunc(("SCALE: %dx%d -> %dx%d\n", cx, cy, width, height));
     1560
     1561            uint8_t *dst = address;
     1562            uint8_t *src = pu8Data;
     1563            int dstX = 0;
     1564            int dstY = 0;
     1565            int srcX = 0;
     1566            int srcY = 0;
     1567            int dstW = width;
     1568            int dstH = height;
     1569            int srcW = cx;
     1570            int srcH = cy;
     1571            gdImageCopyResampled (dst,
     1572                                  src,
     1573                                  dstX, dstY,
     1574                                  srcX, srcY,
     1575                                  dstW, dstH, srcW, srcH);
     1576        }
     1577
     1578        /* This can be called from any thread. */
     1579        pDrv->pUpPort->pfnFreeScreenshot (pDrv->pUpPort, pu8Data);
     1580    }
     1581
     1582    return vrc;
     1583}
     1584
    15351585STDMETHODIMP Display::TakeScreenShot (BYTE *address, ULONG width, ULONG height)
    15361586{
     
    15631613    LogFlowFunc (("Sending SCREENSHOT request\n"));
    15641614
    1565     /*
    1566      * First try use the graphics device features for making a snapshot.
    1567      * This does not support stretching, is an optional feature (returns
    1568      * not supported).
     1615    /* Leave lock because other thread (EMT) is called and it may initiate a resize
     1616     * which also needs lock.
    15691617     *
    1570      * Note: It may cause a display resize. Watch out for deadlocks.
     1618     * This method does not need the lock anymore.
    15711619     */
    1572     int rcVBox = VERR_NOT_SUPPORTED;
    1573     if (    mpDrv->Connector.cx == width
    1574         &&  mpDrv->Connector.cy == height)
    1575     {
    1576         size_t cbData = RT_ALIGN_Z(width, 4) * 4 * height;
    1577         rcVBox = VMR3ReqCallWait(pVM, VMCPUID_ANY,  (PFNRT)mpDrv->pUpPort->pfnSnapshot, 6, mpDrv->pUpPort,
    1578                                  address, cbData, (uintptr_t)NULL, (uintptr_t)NULL, (uintptr_t)NULL);
    1579     }
    1580 
    1581     /*
    1582      * If the function returns not supported, or if stretching is requested,
    1583      * we'll have to do all the work ourselves using the framebuffer data.
    1584      */
    1585     if (rcVBox == VERR_NOT_SUPPORTED || rcVBox == VERR_NOT_IMPLEMENTED)
    1586     {
    1587         /** @todo implement snapshot stretching & generic snapshot fallback. */
    1588         rc = setError (E_NOTIMPL, tr ("This feature is not implemented"));
    1589     }
    1590     else if (RT_FAILURE(rcVBox))
     1620    alock.leave();
     1621
     1622    int vrc = displayTakeScreenshot(pVM, mpDrv, address, width, height);
     1623
     1624    if (vrc == VERR_NOT_IMPLEMENTED)
     1625        rc = setError (E_NOTIMPL,
     1626                       tr ("This feature is not implemented"));
     1627    else if (RT_FAILURE(vrc))
    15911628        rc = setError (VBOX_E_IPRT_ERROR,
    1592             tr ("Could not take a screenshot (%Rrc)"), rcVBox);
     1629                       tr ("Could not take a screenshot (%Rrc)"), vrc);
    15931630
    15941631    LogFlowFunc (("rc=%08X\n", rc));
     
    16001637                                          ComSafeArrayOut(BYTE, aScreenData))
    16011638{
    1602      HRESULT rc = S_OK;
    1603 
    1604      rc = setError (E_NOTIMPL, tr ("This feature is not implemented"));
    1605 
    1606      return rc;
     1639    LogFlowFuncEnter();
     1640    LogFlowFunc (("width=%d, height=%d\n",
     1641                  width, height));
     1642
     1643    CheckComArgSafeArrayNotNull(aScreenData);
     1644    CheckComArgExpr(width, width != 0);
     1645    CheckComArgExpr(height, height != 0);
     1646
     1647    AutoCaller autoCaller(this);
     1648    CheckComRCReturnRC(autoCaller.rc());
     1649
     1650    AutoWriteLock alock(this);
     1651
     1652    CHECK_CONSOLE_DRV (mpDrv);
     1653
     1654    Console::SafeVMPtr pVM (mParent);
     1655    CheckComRCReturnRC(pVM.rc());
     1656
     1657    HRESULT rc = S_OK;
     1658
     1659    LogFlowFunc (("Sending SCREENSHOT request\n"));
     1660
     1661    /* Leave lock because other thread (EMT) is called and it may initiate a resize
     1662     * which also needs lock.
     1663     *
     1664     * This method does not need the lock anymore.
     1665     */
     1666    alock.leave();
     1667
     1668    size_t cbData = width * 4 * height;
     1669    uint8_t *pu8Data = (uint8_t *)RTMemAlloc(cbData);
     1670
     1671    if (!pu8Data)
     1672        return E_OUTOFMEMORY;
     1673
     1674    int vrc = displayTakeScreenshot(pVM, mpDrv, pu8Data, width, height);
     1675
     1676    if (RT_SUCCESS(vrc))
     1677    {
     1678        com::SafeArray<BYTE> screenData (cbData);
     1679        for (unsigned i = 0; i < cbData; i++)
     1680            screenData[i] = pu8Data[i];
     1681        screenData.detachTo(ComSafeArrayOutArg(aScreenData));
     1682    }
     1683    else if (vrc == VERR_NOT_IMPLEMENTED)
     1684        rc = setError (E_NOTIMPL,
     1685                       tr ("This feature is not implemented"));
     1686    else
     1687        rc = setError (VBOX_E_IPRT_ERROR,
     1688                       tr ("Could not take a screenshot (%Rrc)"), vrc);
     1689
     1690    LogFlowFunc (("rc=%08X\n", rc));
     1691    LogFlowFuncLeave();
     1692    return rc;
    16071693}
    16081694
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette