VirtualBox

Changeset 36843 in vbox


Ignore:
Timestamp:
Apr 26, 2011 8:33:19 AM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
71402
Message:

3D for VRDP: initial commit (xTracker 5565).

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/HostServices/VBoxCrOpenGLSvc.h

    r34571 r36843  
    4242#define SHCRGL_HOST_FN_CRHGSMI_CTL (11)
    4343#endif
     44#define SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT (20)
    4445/* crOpenGL guest functions */
    4546#define SHCRGL_GUEST_FN_WRITE       (2)
     
    6566#define SHCRGL_CPARMS_WRITE_BUFFER        (4)
    6667#define SHCRGL_CPARMS_WRITE_READ_BUFFERED (3)
    67 
     68#define SHCRGL_CPARMS_SET_OUTPUT_REDIRECT (1)
     69
     70
     71/* @todo Move to H3DOR.h begin */
     72
     73/* Names of supported output redirect formats. */
     74#define H3DOR_FMT_RGBA_TOPDOWN "H3DOR_FMT_RGBA_TOPDOWN"
     75
     76/* Comma separated list of output formats supported by the output redirect target. */
     77#define H3DOR_PROP_FORMATS 0
     78
     79#pragma pack(1)
     80typedef struct {
     81    /* The caller's context of the redirection. */
     82    const void *pvContext;
     83    /* Inform caller that a new window will be redirected. */
     84    DECLR3CALLBACKMEMBER(void, H3DORBegin,           (const void *pvContext, void **ppvInstance,
     85                                                      const char *pszFormat));
     86    /* The window dimension has been changed. */
     87    DECLR3CALLBACKMEMBER(void, H3DORGeometry,        (void *pvInstance,
     88                                                      int32_t x, int32_t y, uint32_t w, uint32_t h));
     89    /* Update the window visible region. */
     90    DECLR3CALLBACKMEMBER(void, H3DORVisibleRegion,   (void *pvInstance,
     91                                                      uint32_t cRects, RTRECT *paRects));
     92    /* A rendered 3D frame is ready. Format of pvData is "pszFormat" parameter of H3DORBegin. */
     93    DECLR3CALLBACKMEMBER(void, H3DORFrame,           (void *pvInstance,
     94                                                      void *pvData, uint32_t cbData));
     95    /* The window is closed. */
     96    DECLR3CALLBACKMEMBER(void, H3DOREnd,             (void *pvInstance));
     97    /* Obtain caller's parameters: the list of supported formats, etc. */
     98    DECLR3CALLBACKMEMBER(int,  H3DORContextProperty, (const void *pvContext, uint32_t index,
     99                                                      void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut));
     100} H3DOUTPUTREDIRECT;
     101#pragma pack()
     102
     103/* @todo Move to H3DOR.h end */
    68104
    69105#ifdef VBOX_WITH_CRHGSMI
  • trunk/src/VBox/GuestHost/OpenGL/include/cr_server.h

    r36052 r36843  
    3535
    3636typedef DECLCALLBACKPTR(void, PFNCRSERVERPRESENTFBO) (void *data, int32_t screenId, int32_t x, int32_t y, uint32_t w, uint32_t h);
     37
     38/* Callbacks for output of the rendered frames.
     39 *
     40 * This allows to pass rendered frames to an external component rather than draw them on screen.
     41 *
     42 * An external component registers the redirection callbacks using crVBoxServerOutputRedirectSet.
     43 *
     44 * The list of formats supported by the caller is obtained using CRORContextProperty.
     45 * The actual format choosed by the service is passed as a CRORBegin parameter.
     46 */
     47typedef struct {
     48    const void *pvContext; /* Supplied by crVBoxServerOutputRedirectSet. */
     49    DECLR3CALLBACKMEMBER(void, CRORBegin,           (const void *pvContext, void **ppvInstance,
     50                                                     const char *pszFormat));
     51    DECLR3CALLBACKMEMBER(void, CRORGeometry,        (void *pvInstance,
     52                                                     int32_t x, int32_t y, uint32_t w, uint32_t h));
     53    DECLR3CALLBACKMEMBER(void, CRORVisibleRegion,   (void *pvInstance,
     54                                                     uint32_t cRects, RTRECT *paRects));
     55    DECLR3CALLBACKMEMBER(void, CRORFrame,           (void *pvInstance,
     56                                                     void *pvData, uint32_t cbData));
     57    DECLR3CALLBACKMEMBER(void, CROREnd,             (void *pvInstance));
     58    DECLR3CALLBACKMEMBER(int,  CRORContextProperty, (const void *pvContext, uint32_t index,
     59                                                      void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut));
     60} CROutputRedirect;
    3761
    3862typedef struct {
     
    7195    GLuint fboWidth, fboHeight;
    7296    GLuint idPBO;
     97
     98    void *pvOutputRedirectInstance;
    7399} CRMuralInfo;
    74100
     
    233259                                                     *using callback above to update vbox framebuffers*/
    234260    GLboolean             bUsePBOForReadback;       /*Use PBO's for data readback*/
     261
     262    GLboolean             bUseOutputRedirect;       /* Whether the output redirect was set. */
     263    CROutputRedirect      outputRedirect;
    235264} CRServer;
    236265
     
    265294extern DECLEXPORT(int32_t) crVBoxServerSetOffscreenRendering(GLboolean value);
    266295
     296extern DECLEXPORT(int32_t) crVBoxServerOutputRedirectSet(const CROutputRedirect *pCallbacks);
     297
    267298#ifdef __cplusplus
    268299}
  • trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp

    r36290 r36843  
    164164        }
    165165
     166        // @todo use critsect only to fetch the list and update the g_SvcPresentFBO's pQueueHead and pQueueTail.
    166167        rc = RTCritSectEnter(&g_SvcPresentFBO.hQueueLock);
    167168        AssertRCReturn(rc, rc);
     
    12421243                    g_pConsole = pConsole;
    12431244
    1244                     /*rc = crVBoxServerSetOffscreenRendering(GL_TRUE);*/
    12451245                    rc = VINF_SUCCESS;
    12461246                }
     
    13491349
    13501350                rc = VINF_SUCCESS;
     1351            }
     1352            break;
     1353        }
     1354        case SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT:
     1355        {
     1356            /*
     1357             * OutputRedirect.
     1358             * Note: the service calls OutputRedirect callbacks directly
     1359             *       and they must not block. If asynchronous processing is needed,
     1360             *       the callback provider must organize this.
     1361             */
     1362            Log(("svcCall: SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT\n"));
     1363
     1364            /* Verify parameter count and types. */
     1365            if (cParms != SHCRGL_CPARMS_SET_OUTPUT_REDIRECT)
     1366            {
     1367                rc = VERR_INVALID_PARAMETER;
     1368            }
     1369            else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
     1370            {
     1371                rc = VERR_INVALID_PARAMETER;
     1372            }
     1373            else
     1374            {
     1375                /* Fetch parameters. */
     1376                H3DOUTPUTREDIRECT *pOutputRedirect = (H3DOUTPUTREDIRECT *)paParms[0].u.pointer.addr;
     1377                uint32_t cbData = paParms[0].u.pointer.size;
     1378
     1379                /* Verify parameters values. */
     1380                if (cbData != sizeof (H3DOUTPUTREDIRECT))
     1381                {
     1382                    rc = VERR_INVALID_PARAMETER;
     1383                }
     1384                else /* Execute the function. */
     1385                {
     1386                    rc = crVBoxServerSetOffscreenRendering(GL_TRUE);
     1387
     1388                    if (RT_SUCCESS(rc))
     1389                    {
     1390                        CROutputRedirect or;
     1391                        or.pvContext = pOutputRedirect->pvContext;
     1392                        or.CRORBegin = pOutputRedirect->H3DORBegin;
     1393                        or.CRORGeometry = pOutputRedirect->H3DORGeometry;
     1394                        or.CRORVisibleRegion = pOutputRedirect->H3DORVisibleRegion;
     1395                        or.CRORFrame = pOutputRedirect->H3DORFrame;
     1396                        or.CROREnd = pOutputRedirect->H3DOREnd;
     1397                        or.CRORContextProperty = pOutputRedirect->H3DORContextProperty;
     1398                        rc = crVBoxServerOutputRedirectSet(&or);
     1399                    }
     1400                }
    13511401            }
    13521402            break;
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h

    r31808 r36843  
    8989GLuint crServerTranslateProgramID(GLuint id);
    9090
     91void crServerSetupOutputRedirect(CRMuralInfo *mural);
    9192void crServerCheckMuralGeometry(CRMuralInfo *mural);
    9293GLboolean crServerSupportRedirMuralFBO(void);
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c

    r36052 r36843  
    5858    cr_server.bForceOffscreenRendering = GL_FALSE;
    5959    cr_server.bUsePBOForReadback = GL_FALSE;
     60    cr_server.bUseOutputRedirect = GL_FALSE;
    6061}
    6162
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c

    r36052 r36843  
    12601260    return VINF_SUCCESS;
    12611261}
     1262
     1263DECLEXPORT(int32_t) crVBoxServerOutputRedirectSet(const CROutputRedirect *pCallbacks)
     1264{
     1265    /* No need for a synchronization as this is single threaded. */
     1266    if (pCallbacks)
     1267    {
     1268        cr_server.outputRedirect = *pCallbacks;
     1269        cr_server.bUseOutputRedirect = true;
     1270    }
     1271    else
     1272    {
     1273        cr_server.bUseOutputRedirect = false;
     1274    }
     1275
     1276    // @todo dynamically intercept already existing output:
     1277    // crHashtableWalk(cr_server.muralTable, crVBoxServerOutputRedirectCB, NULL);
     1278
     1279    return VINF_SUCCESS;
     1280}
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c

    r36052 r36843  
    4646}
    4747
     48/* Called when a new CRMuralInfo is created
     49 * or when OutputRedirect status is changed.
     50 */
     51void crServerSetupOutputRedirect(CRMuralInfo *mural)
     52{
     53    /* Unset the previous redirect. */
     54    if (mural->pvOutputRedirectInstance)
     55    {
     56        cr_server.outputRedirect.CROREnd(mural->pvOutputRedirectInstance);
     57        mural->pvOutputRedirectInstance = NULL;
     58    }
     59
     60    /* Setup a new redirect. */
     61    if (cr_server.bUseOutputRedirect)
     62    {
     63        /* Query supported formats. */
     64        uint32_t cbFormats = 4096;
     65        char *pachFormats = (char *)crAlloc(cbFormats);
     66
     67        if (pachFormats)
     68        {
     69            int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
     70                                                                  0 /* H3DOR_PROP_FORMATS */, // @todo from a header
     71                                                                  pachFormats, cbFormats, &cbFormats);
     72            if (RT_SUCCESS(rc))
     73            {
     74                if (strstr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
     75                {
     76                    cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
     77                                                       &mural->pvOutputRedirectInstance,
     78                                                       "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
     79                }
     80            }
     81
     82            crFree(pachFormats);
     83        }
     84
     85        /* If this is not NULL then there was a supported format. */
     86        if (mural->pvOutputRedirectInstance)
     87        {
     88            cr_server.outputRedirect.CRORGeometry(mural->pvOutputRedirectInstance,
     89                                                  mural->hX, mural->hY,
     90                                                  mural->width, mural->height);
     91            // @todo the code assumes that RTRECT == four of GLInts
     92            cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
     93                                                       mural->cVisibleRects, (RTRECT *)mural->pVisibleRects);
     94        }
     95    }
     96}
     97
    4898void crServerCheckMuralGeometry(CRMuralInfo *mural)
    4999{
     
    136186            cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX, mural->hY);
    137187        }
     188    }
     189
     190    if (mural->pvOutputRedirectInstance)
     191    {
     192        cr_server.outputRedirect.CRORGeometry(mural->pvOutputRedirectInstance,
     193                                              mural->hX, mural->hY,
     194                                              mural->width, mural->height);
    138195    }
    139196}
     
    455512    }
    456513
     514    if (mural->pvOutputRedirectInstance)
     515    {
     516        /* @todo find out why presentfbo is not called but crorframe is called. */
     517        cr_server.outputRedirect.CRORFrame(mural->pvOutputRedirectInstance,
     518                                           pixels,
     519                                           4 * mural->fboWidth * mural->fboHeight);
     520    }
     521
    457522    if (bUsePBO)
    458523    {
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c

    r35998 r36843  
    8888        mural->bReceivedRects = GL_FALSE;
    8989
     90        mural->pvOutputRedirectInstance = NULL;
     91
    9092        /* generate ID for this new window/mural (special-case for file conns) */
    9193        if (cr_server.curClient && cr_server.curClient->conn->type == CR_FILE)
     
    99101        pCreateInfo->visualBits = visBits;
    100102        crHashtableAdd(cr_server.pWindowCreateInfoTable, windowID, pCreateInfo);
     103
     104        crServerSetupOutputRedirect(mural);
    101105    }
    102106
     
    148152    }
    149153
     154    if (mural->pvOutputRedirectInstance)
     155    {
     156        cr_server.outputRedirect.CROREnd(mural->pvOutputRedirectInstance);
     157        mural->pvOutputRedirectInstance = NULL;
     158    }
     159
    150160    if (cr_server.currentWindow == window)
    151161    {
     
    295305
    296306    cr_server.head_spu->dispatch_table.WindowVisibleRegion(mural->spuWindow, cRects, pRects);
     307
     308    if (mural->pvOutputRedirectInstance)
     309    {
     310        /* @todo the code assumes that RTRECT == four GLInts. */
     311        cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
     312                                                   cRects, (RTRECT *)pRects);
     313    }
    297314}
    298315
  • trunk/src/VBox/Main/include/ConsoleVRDPServer.h

    r35722 r36843  
    2424#include <VBox/VBoxAuth.h>
    2525
     26#include <VBox/RemoteDesktop/VRDEImage.h>
     27
    2628#include <VBox/HostServices/VBoxClipboardExt.h>
    2729
     
    151153    static PFNVRDECREATESERVER mpfnVRDECreateServer;
    152154
    153     static VRDEENTRYPOINTS_3 mEntryPoints;
    154     static VRDEENTRYPOINTS_3 *mpEntryPoints;
    155     static VRDECALLBACKS_3 mCallbacks;
     155    static VRDEENTRYPOINTS_4 mEntryPoints;
     156    static VRDEENTRYPOINTS_4 *mpEntryPoints;
     157    static VRDECALLBACKS_4 mCallbacks;
    156158
    157159    static DECLCALLBACK(int)  VRDPCallbackQueryProperty     (void *pvCallback, uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut);
     
    224226
    225227    uint32_t volatile mu32AudioInputClientId;
     228
     229    static DECLCALLBACK(void) H3DORBegin(const void *pvContext, void **ppvInstance,
     230                                         const char *pszFormat);
     231    static DECLCALLBACK(void) H3DORGeometry(void *pvInstance,
     232                                            int32_t x, int32_t y, uint32_t w, uint32_t h);
     233    static DECLCALLBACK(void) H3DORVisibleRegion(void *pvInstance,
     234                                                 uint32_t cRects, RTRECT *paRects);
     235    static DECLCALLBACK(void) H3DORFrame(void *pvInstance,
     236                                         void *pvData, uint32_t cbData);
     237    static DECLCALLBACK(void) H3DOREnd(void *pvInstance);
     238    static DECLCALLBACK(int)  H3DORContextProperty(const void *pvContext, uint32_t index,
     239                                                   void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut);
     240
     241    void remote3DRedirect(void);
     242
     243    /*
     244     * VRDE server optional interfaces.
     245     */
     246
     247    /* Image update interface. */
     248    bool m_fInterfaceImage;
     249    VRDEIMAGECALLBACKS m_interfaceCallbacksImage;
     250    VRDEIMAGEINTERFACE m_interfaceImage;
     251    static DECLCALLBACK(int) VRDEImageCbNotify (void *pvContext,
     252                                                void *pvUser,
     253                                                HVRDEIMAGE hVideo,
     254                                                uint32_t u32Id,
     255                                                void *pvData,
     256                                                uint32_t cbData);
    226257};
    227258
  • trunk/src/VBox/Main/src-client/ConsoleVRDPServer.cpp

    r36063 r36843  
    2525# include "ExtPackManagerImpl.h"
    2626#endif
     27#include "VMMDev.h"
    2728
    2829#include "Global.h"
     
    4041#include <VBox/RemoteDesktop/VRDEOrders.h>
    4142#include <VBox/com/listeners.h>
     43#include <VBox/HostServices/VBoxCrOpenGLSvc.h>
    4244
    4345class VRDPConsoleListener
     
    520522PFNVRDECREATESERVER ConsoleVRDPServer::mpfnVRDECreateServer = NULL;
    521523
    522 VRDEENTRYPOINTS_3 ConsoleVRDPServer::mEntryPoints; /* A copy of the server entry points. */
    523 VRDEENTRYPOINTS_3 *ConsoleVRDPServer::mpEntryPoints = NULL;
    524 
    525 VRDECALLBACKS_3 ConsoleVRDPServer::mCallbacks =
    526 {
    527     { VRDE_INTERFACE_VERSION_3, sizeof(VRDECALLBACKS_3) },
     524VRDEENTRYPOINTS_4 ConsoleVRDPServer::mEntryPoints; /* A copy of the server entry points. */
     525VRDEENTRYPOINTS_4 *ConsoleVRDPServer::mpEntryPoints = NULL;
     526
     527VRDECALLBACKS_4 ConsoleVRDPServer::mCallbacks =
     528{
     529    { VRDE_INTERFACE_VERSION_4, sizeof(VRDECALLBACKS_4) },
    528530    ConsoleVRDPServer::VRDPCallbackQueryProperty,
    529531    ConsoleVRDPServer::VRDPCallbackClientLogon,
     
    13151317
    13161318    mu32AudioInputClientId = 0;
     1319
     1320    /*
     1321     * Optional interfaces.
     1322     */
     1323    m_fInterfaceImage = false;
     1324    memset(&m_interfaceImage, 0, sizeof (m_interfaceImage));
     1325    memset(&m_interfaceCallbacksImage, 0, sizeof (m_interfaceCallbacksImage));
    13171326}
    13181327
     
    13951404        if (RT_SUCCESS(vrc))
    13961405        {
    1397             VRDEENTRYPOINTS_3 *pEntryPoints3;
    1398             vrc = mpfnVRDECreateServer(&mCallbacks.header, this, (VRDEINTERFACEHDR **)&pEntryPoints3, &mhServer);
     1406            VRDEENTRYPOINTS_4 *pEntryPoints4;
     1407            vrc = mpfnVRDECreateServer(&mCallbacks.header, this, (VRDEINTERFACEHDR **)&pEntryPoints4, &mhServer);
    13991408
    14001409            if (RT_SUCCESS(vrc))
    14011410            {
    1402                 mServerInterfaceVersion = 3;
    1403                 mEntryPoints = *pEntryPoints3;
     1411                mServerInterfaceVersion = 4;
     1412                mEntryPoints = *pEntryPoints4;
    14041413                mpEntryPoints = &mEntryPoints;
    14051414            }
    14061415            else if (vrc == VERR_VERSION_MISMATCH)
    14071416            {
    1408                 /* An older version of VRDE is installed, try version 1. */
    1409                 VRDEENTRYPOINTS_1 *pEntryPoints1;
    1410 
    1411                 static VRDECALLBACKS_1 sCallbacks =
    1412                 {
    1413                     { VRDE_INTERFACE_VERSION_1, sizeof(VRDECALLBACKS_1) },
     1417                /* An older version of VRDE is installed, try version 3. */
     1418                VRDEENTRYPOINTS_3 *pEntryPoints3;
     1419
     1420                static VRDECALLBACKS_3 sCallbacks3 =
     1421                {
     1422                    { VRDE_INTERFACE_VERSION_3, sizeof(VRDECALLBACKS_3) },
    14141423                    ConsoleVRDPServer::VRDPCallbackQueryProperty,
    14151424                    ConsoleVRDPServer::VRDPCallbackClientLogon,
     
    14231432                    ConsoleVRDPServer::VRDPCallbackFramebufferUnlock,
    14241433                    ConsoleVRDPServer::VRDPCallbackInput,
    1425                     ConsoleVRDPServer::VRDPCallbackVideoModeHint
     1434                    ConsoleVRDPServer::VRDPCallbackVideoModeHint,
     1435                    ConsoleVRDPServer::VRDECallbackAudioIn
    14261436                };
    14271437
    1428                 vrc = mpfnVRDECreateServer(&sCallbacks.header, this, (VRDEINTERFACEHDR **)&pEntryPoints1, &mhServer);
     1438                vrc = mpfnVRDECreateServer(&sCallbacks3.header, this, (VRDEINTERFACEHDR **)&pEntryPoints3, &mhServer);
    14291439                if (RT_SUCCESS(vrc))
    14301440                {
    1431                     LogRel(("VRDE: loaded an older version of the server.\n"));
    1432 
    14331441                    mServerInterfaceVersion = 3;
    1434                     mEntryPoints.header = pEntryPoints1->header;
    1435                     mEntryPoints.VRDEDestroy = pEntryPoints1->VRDEDestroy;
    1436                     mEntryPoints.VRDEEnableConnections = pEntryPoints1->VRDEEnableConnections;
    1437                     mEntryPoints.VRDEDisconnect = pEntryPoints1->VRDEDisconnect;
    1438                     mEntryPoints.VRDEResize = pEntryPoints1->VRDEResize;
    1439                     mEntryPoints.VRDEUpdate = pEntryPoints1->VRDEUpdate;
    1440                     mEntryPoints.VRDEColorPointer = pEntryPoints1->VRDEColorPointer;
    1441                     mEntryPoints.VRDEHidePointer = pEntryPoints1->VRDEHidePointer;
    1442                     mEntryPoints.VRDEAudioSamples = pEntryPoints1->VRDEAudioSamples;
    1443                     mEntryPoints.VRDEAudioVolume = pEntryPoints1->VRDEAudioVolume;
    1444                     mEntryPoints.VRDEUSBRequest = pEntryPoints1->VRDEUSBRequest;
    1445                     mEntryPoints.VRDEClipboard = pEntryPoints1->VRDEClipboard;
    1446                     mEntryPoints.VRDEQueryInfo = pEntryPoints1->VRDEQueryInfo;
    1447                     mEntryPoints.VRDERedirect = NULL;
    1448                     mEntryPoints.VRDEAudioInOpen = NULL;
    1449                     mEntryPoints.VRDEAudioInClose = NULL;
     1442                    mEntryPoints.header = pEntryPoints3->header;
     1443                    mEntryPoints.VRDEDestroy = pEntryPoints3->VRDEDestroy;
     1444                    mEntryPoints.VRDEEnableConnections = pEntryPoints3->VRDEEnableConnections;
     1445                    mEntryPoints.VRDEDisconnect = pEntryPoints3->VRDEDisconnect;
     1446                    mEntryPoints.VRDEResize = pEntryPoints3->VRDEResize;
     1447                    mEntryPoints.VRDEUpdate = pEntryPoints3->VRDEUpdate;
     1448                    mEntryPoints.VRDEColorPointer = pEntryPoints3->VRDEColorPointer;
     1449                    mEntryPoints.VRDEHidePointer = pEntryPoints3->VRDEHidePointer;
     1450                    mEntryPoints.VRDEAudioSamples = pEntryPoints3->VRDEAudioSamples;
     1451                    mEntryPoints.VRDEAudioVolume = pEntryPoints3->VRDEAudioVolume;
     1452                    mEntryPoints.VRDEUSBRequest = pEntryPoints3->VRDEUSBRequest;
     1453                    mEntryPoints.VRDEClipboard = pEntryPoints3->VRDEClipboard;
     1454                    mEntryPoints.VRDEQueryInfo = pEntryPoints3->VRDEQueryInfo;
     1455                    mEntryPoints.VRDERedirect = pEntryPoints3->VRDERedirect;
     1456                    mEntryPoints.VRDEAudioInOpen = pEntryPoints3->VRDEAudioInOpen;
     1457                    mEntryPoints.VRDEAudioInClose = pEntryPoints3->VRDEAudioInClose;
     1458                    mEntryPoints.VRDEGetInterface = NULL;
    14501459                    mpEntryPoints = &mEntryPoints;
    14511460                }
     1461                else if (vrc == VERR_VERSION_MISMATCH)
     1462                {
     1463                    /* An older version of VRDE is installed, try version 1. */
     1464                    VRDEENTRYPOINTS_1 *pEntryPoints1;
     1465
     1466                    static VRDECALLBACKS_1 sCallbacks1 =
     1467                    {
     1468                        { VRDE_INTERFACE_VERSION_1, sizeof(VRDECALLBACKS_1) },
     1469                        ConsoleVRDPServer::VRDPCallbackQueryProperty,
     1470                        ConsoleVRDPServer::VRDPCallbackClientLogon,
     1471                        ConsoleVRDPServer::VRDPCallbackClientConnect,
     1472                        ConsoleVRDPServer::VRDPCallbackClientDisconnect,
     1473                        ConsoleVRDPServer::VRDPCallbackIntercept,
     1474                        ConsoleVRDPServer::VRDPCallbackUSB,
     1475                        ConsoleVRDPServer::VRDPCallbackClipboard,
     1476                        ConsoleVRDPServer::VRDPCallbackFramebufferQuery,
     1477                        ConsoleVRDPServer::VRDPCallbackFramebufferLock,
     1478                        ConsoleVRDPServer::VRDPCallbackFramebufferUnlock,
     1479                        ConsoleVRDPServer::VRDPCallbackInput,
     1480                        ConsoleVRDPServer::VRDPCallbackVideoModeHint
     1481                    };
     1482
     1483                    vrc = mpfnVRDECreateServer(&sCallbacks1.header, this, (VRDEINTERFACEHDR **)&pEntryPoints1, &mhServer);
     1484                    if (RT_SUCCESS(vrc))
     1485                    {
     1486                        mServerInterfaceVersion = 1;
     1487                        mEntryPoints.header = pEntryPoints1->header;
     1488                        mEntryPoints.VRDEDestroy = pEntryPoints1->VRDEDestroy;
     1489                        mEntryPoints.VRDEEnableConnections = pEntryPoints1->VRDEEnableConnections;
     1490                        mEntryPoints.VRDEDisconnect = pEntryPoints1->VRDEDisconnect;
     1491                        mEntryPoints.VRDEResize = pEntryPoints1->VRDEResize;
     1492                        mEntryPoints.VRDEUpdate = pEntryPoints1->VRDEUpdate;
     1493                        mEntryPoints.VRDEColorPointer = pEntryPoints1->VRDEColorPointer;
     1494                        mEntryPoints.VRDEHidePointer = pEntryPoints1->VRDEHidePointer;
     1495                        mEntryPoints.VRDEAudioSamples = pEntryPoints1->VRDEAudioSamples;
     1496                        mEntryPoints.VRDEAudioVolume = pEntryPoints1->VRDEAudioVolume;
     1497                        mEntryPoints.VRDEUSBRequest = pEntryPoints1->VRDEUSBRequest;
     1498                        mEntryPoints.VRDEClipboard = pEntryPoints1->VRDEClipboard;
     1499                        mEntryPoints.VRDEQueryInfo = pEntryPoints1->VRDEQueryInfo;
     1500                        mEntryPoints.VRDERedirect = NULL;
     1501                        mEntryPoints.VRDEAudioInOpen = NULL;
     1502                        mEntryPoints.VRDEAudioInClose = NULL;
     1503                        mEntryPoints.VRDEGetInterface = NULL;
     1504                        mpEntryPoints = &mEntryPoints;
     1505                    }
     1506                }
    14521507            }
    14531508
    14541509            if (RT_SUCCESS(vrc))
    14551510            {
     1511                LogRel(("VRDE: loaded version %d of the server.\n", mServerInterfaceVersion));
     1512
     1513                if (mServerInterfaceVersion >= 4)
     1514                {
     1515                    /* The server supports optional interfaces. */
     1516                    Assert(mpEntryPoints->VRDEGetInterface != NULL);
     1517
     1518                    /* Image interface. */
     1519                    m_interfaceImage.header.u64Version = 1;
     1520                    m_interfaceImage.header.u64Size = sizeof(m_interfaceImage);
     1521
     1522                    m_interfaceCallbacksImage.header.u64Version = 1;
     1523                    m_interfaceCallbacksImage.header.u64Size = sizeof(m_interfaceCallbacksImage);
     1524                    m_interfaceCallbacksImage.VRDEImageCbNotify = VRDEImageCbNotify;
     1525
     1526                    vrc = mpEntryPoints->VRDEGetInterface(mhServer,
     1527                                                          VRDE_IMAGE_INTERFACE_NAME,
     1528                                                          &m_interfaceImage.header,
     1529                                                          &m_interfaceCallbacksImage.header,
     1530                                                          this);
     1531                    if (RT_SUCCESS(vrc))
     1532                    {
     1533                        m_fInterfaceImage = true;
     1534                    }
     1535
     1536                    /* Since these interfaces are optional, it is always a success here. */
     1537                    vrc = VINF_SUCCESS;
     1538                }
    14561539#ifdef VBOX_WITH_USB
    14571540                remoteUSBThreadStart();
     
    14711554}
    14721555
     1556typedef struct H3DORInstance
     1557{
     1558    ConsoleVRDPServer *pThis;
     1559    HVRDEIMAGE hImageBitmap;
     1560    int32_t x;
     1561    int32_t y;
     1562    uint32_t w;
     1563    uint32_t h;
     1564    bool fCreated;
     1565} H3DORInstance;
     1566
     1567/* static */ DECLCALLBACK(void) ConsoleVRDPServer::H3DORBegin(const void *pvContext, void **ppvInstance,
     1568                                                              const char *pszFormat)
     1569{
     1570    LogFlowFunc(("ctx %p\n", pvContext));
     1571
     1572    H3DORInstance *p = (H3DORInstance *)RTMemAlloc(sizeof (H3DORInstance));
     1573
     1574    if (p)
     1575    {
     1576        p->pThis = (ConsoleVRDPServer *)pvContext;
     1577        p->hImageBitmap = NULL;
     1578        p->x = 0;
     1579        p->y = 0;
     1580        p->w = 0;
     1581        p->h = 0;
     1582        p->fCreated = false;
     1583
     1584        /* Host 3D service passes the actual format of data in this redirect instance.
     1585         * That is what will be in the H3DORFrame's parameters pvData and cbData.
     1586         */
     1587        if (RTStrICmp(pszFormat, H3DOR_FMT_RGBA_TOPDOWN) == 0)
     1588        {
     1589            /* Accept it. */
     1590        }
     1591        else
     1592        {
     1593            RTMemFree(p);
     1594            p = NULL;
     1595        }
     1596    }
     1597
     1598    /* Caller check this for NULL. */
     1599    *ppvInstance = p;
     1600}
     1601
     1602/* static */ DECLCALLBACK(void) ConsoleVRDPServer::H3DORGeometry(void *pvInstance,
     1603                                                                 int32_t x, int32_t y, uint32_t w, uint32_t h)
     1604{
     1605    LogFlowFunc(("ins %p %d,%d %dx%d\n", pvInstance, x, y, w, h));
     1606
     1607    H3DORInstance *p = (H3DORInstance *)pvInstance;
     1608    Assert(p);
     1609    Assert(p->pThis);
     1610
     1611    /* @todo find out what to do if size changes to 0x0 from non zero */
     1612    if (w == 0 || h == 0)
     1613    {
     1614        /* Do nothing. */
     1615        return;
     1616    }
     1617
     1618    RTRECT rect;
     1619    rect.xLeft = x;
     1620    rect.yTop = y;
     1621    rect.xRight = x + w;
     1622    rect.yBottom = y + h;
     1623
     1624    if (p->hImageBitmap)
     1625    {
     1626        /* An image handle has been already created,
     1627         * check if it has the same size as the reported geometry.
     1628         */
     1629        if (   p->x == x
     1630            && p->y == y
     1631            && p->w == w
     1632            && p->h == h)
     1633        {
     1634            LogFlowFunc(("geometry not changed\n"));
     1635            /* Do nothing. Continue using the existing handle. */
     1636        }
     1637        else
     1638        {
     1639            int rc = p->pThis->m_interfaceImage.VRDEImageGeometrySet(p->hImageBitmap, &rect);
     1640            if (RT_SUCCESS(rc))
     1641            {
     1642                p->x = x;
     1643                p->y = y;
     1644                p->w = w;
     1645                p->h = h;
     1646            }
     1647            else
     1648            {
     1649                /* The handle must be recreated. Delete existing handle here. */
     1650                p->pThis->m_interfaceImage.VRDEImageHandleClose(p->hImageBitmap);
     1651                p->hImageBitmap = NULL;
     1652            }
     1653        }
     1654    }
     1655
     1656    if (!p->hImageBitmap)
     1657    {
     1658        /* Create a new bitmap handle. */
     1659        uint32_t u32ScreenId = 0; /* @todo clip to corresponding screens.
     1660                                   * Clipping can be done here or in VRDP server.
     1661                                   * If VRDP does clipping, then uScreenId parameter
     1662                                   * is not necessary and coords must be global.
     1663                                   * (have to check which coords are used in opengl service).
     1664                                   * Since all VRDE API uses a ScreenId,
     1665                                   * the clipping must be done here in ConsoleVRDPServer
     1666                                   */
     1667        uint32_t fu32CompletionFlags = 0;
     1668        int rc = p->pThis->m_interfaceImage.VRDEImageHandleCreate(p->pThis->mhServer,
     1669                                                                  &p->hImageBitmap,
     1670                                                                  p,
     1671                                                                  u32ScreenId,
     1672                                                                  VRDE_IMAGE_F_CREATE_CONTENT_3D
     1673                                                                  | VRDE_IMAGE_F_CREATE_WINDOW,
     1674                                                                  &rect,
     1675                                                                  VRDE_IMAGE_FMT_ID_BITMAP_BGRA8,
     1676                                                                  NULL,
     1677                                                                  0,
     1678                                                                  &fu32CompletionFlags);
     1679        if (RT_SUCCESS(rc))
     1680        {
     1681            p->x = x;
     1682            p->y = y;
     1683            p->w = w;
     1684            p->h = h;
     1685
     1686            if ((fu32CompletionFlags & VRDE_IMAGE_F_COMPLETE_ASYNC) == 0)
     1687            {
     1688                p->fCreated = true;
     1689            }
     1690        }
     1691        else
     1692        {
     1693            p->hImageBitmap = NULL;
     1694            p->w = 0;
     1695            p->h = 0;
     1696        }
     1697    }
     1698}
     1699
     1700/* static */ DECLCALLBACK(void) ConsoleVRDPServer::H3DORVisibleRegion(void *pvInstance,
     1701                                                                      uint32_t cRects, RTRECT *paRects)
     1702{
     1703    LogFlowFunc(("ins %p %d\n", pvInstance, cRects));
     1704
     1705    H3DORInstance *p = (H3DORInstance *)pvInstance;
     1706    Assert(p);
     1707    Assert(p->pThis);
     1708
     1709    if (cRects == 0)
     1710    {
     1711        /* Complete image is visible. */
     1712        RTRECT rect;
     1713        rect.xLeft = p->x;
     1714        rect.yTop = p->y;
     1715        rect.xRight = p->x + p->w;
     1716        rect.yBottom = p->y + p->h;
     1717        p->pThis->m_interfaceImage.VRDEImageRegionSet (p->hImageBitmap,
     1718                                                       1,
     1719                                                       &rect);
     1720    }
     1721    else
     1722    {
     1723        p->pThis->m_interfaceImage.VRDEImageRegionSet (p->hImageBitmap,
     1724                                                       cRects,
     1725                                                       paRects);
     1726    }
     1727}
     1728
     1729/* static */ DECLCALLBACK(void) ConsoleVRDPServer::H3DORFrame(void *pvInstance,
     1730                                                              void *pvData, uint32_t cbData)
     1731{
     1732    LogFlowFunc(("ins %p %p %d\n", pvInstance, pvData, cbData));
     1733
     1734    H3DORInstance *p = (H3DORInstance *)pvInstance;
     1735    Assert(p);
     1736    Assert(p->pThis);
     1737
     1738    /* Currently only a topdown BGR0 bitmap format is supported. */
     1739    VRDEIMAGEBITMAP image;
     1740
     1741    image.cWidth = p->w;
     1742    image.cHeight = p->h;
     1743    image.pvData = pvData;
     1744    image.cbData = cbData;
     1745    image.pvScanLine0 = (uint8_t *)pvData + (p->h - 1) * p->w * 4;
     1746    image.iScanDelta = -4 * p->w;
     1747
     1748    p->pThis->m_interfaceImage.VRDEImageUpdate (p->hImageBitmap,
     1749                                                p->x,
     1750                                                p->y,
     1751                                                p->w,
     1752                                                p->h,
     1753                                                &image,
     1754                                                sizeof(VRDEIMAGEBITMAP));
     1755}
     1756
     1757/* static */ DECLCALLBACK(void) ConsoleVRDPServer::H3DOREnd(void *pvInstance)
     1758{
     1759    LogFlowFunc(("ins %p\n", pvInstance));
     1760
     1761    H3DORInstance *p = (H3DORInstance *)pvInstance;
     1762    Assert(p);
     1763    Assert(p->pThis);
     1764
     1765    p->pThis->m_interfaceImage.VRDEImageHandleClose(p->hImageBitmap);
     1766
     1767    RTMemFree(p);
     1768}
     1769
     1770/* static */ DECLCALLBACK(int) ConsoleVRDPServer::H3DORContextProperty(const void *pvContext, uint32_t index,
     1771                                                                       void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut)
     1772{
     1773    int rc = VINF_SUCCESS;
     1774
     1775    if (index == H3DOR_PROP_FORMATS)
     1776    {
     1777        /* Return a comma separated list of supported formats. */
     1778        static char *pszSupportedFormats = H3DOR_FMT_RGBA_TOPDOWN;
     1779        uint32_t cbOut = (uint32_t)strlen(pszSupportedFormats) + 1;
     1780        if (cbOut <= cbBuffer)
     1781        {
     1782            memcpy(pvBuffer, pszSupportedFormats, cbOut);
     1783        }
     1784        else
     1785        {
     1786            rc = VERR_BUFFER_OVERFLOW;
     1787        }
     1788        *pcbOut = cbOut;
     1789    }
     1790    else
     1791    {
     1792        rc = VERR_NOT_SUPPORTED;
     1793    }
     1794
     1795    return rc;
     1796}
     1797
     1798void ConsoleVRDPServer::remote3DRedirect(void)
     1799{
     1800    if (!m_fInterfaceImage)
     1801    {
     1802        /* No redirect without corresponding interface. */
     1803        return;
     1804    }
     1805
     1806    /* Check if 3D redirection has been enabled. */
     1807    com::Bstr bstr;
     1808    HRESULT hrc = mConsole->getVRDEServer()->GetVRDEProperty(Bstr("H3DRedirect/Enabled").raw(), bstr.asOutParam());
     1809
     1810    if (hrc != S_OK)
     1811    {
     1812        bstr = "";
     1813    }
     1814
     1815    com::Utf8Str value = bstr;
     1816
     1817    bool fEnabled =    RTStrICmp(value.c_str(), "true") == 0
     1818                    || RTStrICmp(value.c_str(), "1") == 0;
     1819
     1820    if (!fEnabled)
     1821    {
     1822        return;
     1823    }
     1824
     1825    /* Tell the host 3D service to redirect output using the ConsoleVRDPServer callbacks. */
     1826    H3DOUTPUTREDIRECT outputRedirect =
     1827    {
     1828        this,
     1829        H3DORBegin,
     1830        H3DORGeometry,
     1831        H3DORVisibleRegion,
     1832        H3DORFrame,
     1833        H3DOREnd,
     1834        H3DORContextProperty
     1835    };
     1836
     1837    VBOXHGCMSVCPARM parm;
     1838
     1839    parm.type = VBOX_HGCM_SVC_PARM_PTR;
     1840    parm.u.pointer.addr = &outputRedirect;
     1841    parm.u.pointer.size = sizeof(outputRedirect);
     1842
     1843    VMMDev *pVMMDev = mConsole->getVMMDev();
     1844
     1845    if (!pVMMDev)
     1846    {
     1847        AssertMsgFailed(("remote3DRedirect no vmmdev\n"));
     1848        return;
     1849    }
     1850
     1851    int rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL",
     1852                                   SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT,
     1853                                   SHCRGL_CPARMS_SET_OUTPUT_REDIRECT,
     1854                                   &parm);
     1855
     1856    if (!RT_SUCCESS(rc))
     1857    {
     1858        AssertMsgFailed(("SHCRGL_HOST_FN_SET_CONSOLE failed with %Rrc\n", rc));
     1859        return;
     1860    }
     1861
     1862    LogRel(("VRDE: Enabled 3D redirect.\n"));
     1863
     1864    return;
     1865}
     1866
     1867/* static */ DECLCALLBACK(int) ConsoleVRDPServer::VRDEImageCbNotify (void *pvContext,
     1868                                                                     void *pvUser,
     1869                                                                     HVRDEIMAGE hVideo,
     1870                                                                     uint32_t u32Id,
     1871                                                                     void *pvData,
     1872                                                                     uint32_t cbData)
     1873{
     1874    LogFlowFunc(("pvContext %p, pvUser %p, hVideo %p, u32Id %u, pvData %p, cbData %d\n",
     1875                 pvContext, pvUser, hVideo, u32Id, pvData, cbData));
     1876
     1877    ConsoleVRDPServer *pServer = static_cast<ConsoleVRDPServer*>(pvContext);
     1878    H3DORInstance *p = (H3DORInstance *)pvUser;
     1879    Assert(p);
     1880    Assert(p->pThis);
     1881    Assert(p->pThis == pServer);
     1882
     1883    // @todo Process u32Id
     1884
     1885    p->fCreated = true;
     1886
     1887    return VINF_SUCCESS;
     1888}
     1889
    14731890void ConsoleVRDPServer::EnableConnections(void)
    14741891{
     
    14761893    {
    14771894        mpEntryPoints->VRDEEnableConnections(mhServer, true);
     1895
     1896        /* Redirect 3D output if it is enabled. */
     1897        remote3DRedirect();
    14781898    }
    14791899}
Note: See TracChangeset for help on using the changeset viewer.

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