VirtualBox

Ignore:
Timestamp:
Dec 14, 2017 11:14:08 AM (7 years ago)
Author:
vboxsync
Message:

Additions/x11/VBoxClient: split vmsvga service into separate X11 and drm ones.
bugref:8533: Additions/x11: fully support VMSVGA

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/x11/VBoxClient/display-svga.cpp

    r69500 r70126  
    11/* $Id$ */
    22/** @file
    3  * X11 guest client - VMSVGA emulation resize event pass-through to guest
     3 * X11 guest client - VMSVGA emulation resize event pass-through to drm guest
    44 * driver.
    55 */
     
    4747
    4848/** Maximum number of supported screens.  DRM and X11 both limit this to 32. */
     49/** @todo if this ever changes, dynamically allocate resizeable arrays in the
     50 *  context structure. */
    4951#define VMW_MAX_HEADS 32
    5052
     
    162164}
    163165
    164 /* VMWare X.Org driver control parts definitions. */
    165 
    166 #include <X11/Xlibint.h>
    167 
    168 struct X11CONTEXT
    169 {
    170     Display *pDisplay;
    171     int hRandRMajor;
    172     int hVMWMajor;
    173 };
    174 
    175 static void x11Connect(struct X11CONTEXT *pContext)
    176 {
    177     int dummy;
    178 
    179     if (pContext->pDisplay != NULL)
    180         VBClFatalError(("%s called with bad argument\n", __func__));
    181     pContext->pDisplay = XOpenDisplay(NULL);
    182     if (pContext->pDisplay == NULL)
    183         return;
    184     if (   !XQueryExtension(pContext->pDisplay, "RANDR",
    185                             &pContext->hRandRMajor, &dummy, &dummy)
    186         || !XQueryExtension(pContext->pDisplay, "VMWARE_CTRL",
    187                             &pContext->hVMWMajor, &dummy, &dummy))
    188     {
    189         XCloseDisplay(pContext->pDisplay);
    190         pContext->pDisplay = NULL;
    191     }
    192 }
    193 
    194 #define X11_VMW_TOPOLOGY_REQ 2
    195 struct X11VMWRECT /* xXineramaScreenInfo in Xlib headers. */
    196 {
    197     int16_t x;
    198     int16_t y;
    199     uint16_t w;
    200     uint16_t h;
    201 };
    202 AssertCompileSize(struct X11VMWRECT, 8);
    203 
    204 struct X11REQHEADER
    205 {
    206     uint8_t hMajor;
    207     uint8_t idType;
    208     uint16_t cd;
    209 };
    210 
    211 struct X11VMWTOPOLOGYREQ
    212 {
    213     struct X11REQHEADER header;
    214     uint32_t idX11Screen;
    215     uint32_t cScreens;
    216     uint32_t u32Pad;
    217     struct X11VMWRECT aRects[1];
    218 };
    219 AssertCompileSize(struct X11VMWTOPOLOGYREQ, 24);
    220 
    221 #define X11_VMW_TOPOLOGY_REPLY_SIZE 32
    222 
    223 #define X11_VMW_RESOLUTION_REQUEST 1
    224 struct X11VMWRESOLUTIONREQ
    225 {
    226     struct X11REQHEADER header;
    227     uint32_t idX11Screen;
    228     uint32_t x;
    229     uint32_t y;
    230 };
    231 AssertCompileSize(struct X11VMWRESOLUTIONREQ, 16);
    232 
    233 #define X11_VMW_RESOLUTION_REPLY_SIZE 32
    234 
    235 #define X11_RANDR_GET_SCREEN_REQUEST 5
    236 struct X11RANDRGETSCREENREQ
    237 {
    238     struct X11REQHEADER header;
    239     uint32_t hWindow;
    240 };
    241 AssertCompileSize(struct X11RANDRGETSCREENREQ, 8);
    242 
    243 #define X11_RANDR_GET_SCREEN_REPLY_SIZE 32
    244 
    245 /* This was a macro in old Xlib versions and a function in newer ones; the
    246  * display members touched by the macro were declared as ABI for compatibility
    247  * reasons.  To simplify building with different generations, we duplicate the
    248  * code. */
    249 static void x11GetRequest(struct X11CONTEXT *pContext, uint8_t hMajor,
    250                           uint8_t idType, size_t cb, struct X11REQHEADER **ppReq)
    251 {
    252     if (pContext->pDisplay->bufptr + cb > pContext->pDisplay->bufmax)
    253         _XFlush(pContext->pDisplay);
    254     if (pContext->pDisplay->bufptr + cb > pContext->pDisplay->bufmax)
    255         VBClFatalError(("%s display buffer overflow.\n", __func__));
    256     if (cb % 4 != 0)
    257         VBClFatalError(("%s bad parameter.\n", __func__));
    258     pContext->pDisplay->last_req = pContext->pDisplay->bufptr;
    259     *ppReq = (struct X11REQHEADER *)pContext->pDisplay->bufptr;
    260     (*ppReq)->hMajor = hMajor;
    261     (*ppReq)->idType = idType;
    262     (*ppReq)->cd = cb / 4;
    263     pContext->pDisplay->bufptr += cb;
    264     pContext->pDisplay->request++;
    265 }
    266 
    267 static void x11SendHints(struct X11CONTEXT *pContext, struct DRMVMWRECT *pRects,
    268                          unsigned cRects)
    269 {
    270     unsigned i;
    271     struct X11VMWTOPOLOGYREQ     *pReqTopology;
    272     uint8_t                       repTopology[X11_VMW_TOPOLOGY_REPLY_SIZE];
    273     struct X11VMWRESOLUTIONREQ   *pReqResolution;
    274     uint8_t                       repResolution[X11_VMW_RESOLUTION_REPLY_SIZE];
    275 
    276     if (!VALID_PTR(pContext->pDisplay))
    277         VBClFatalError(("%s bad display argument.\n", __func__));
    278     if (cRects == 0)
    279         return;
    280     /* Try a topology (multiple screen) request. */
    281     x11GetRequest(pContext, pContext->hVMWMajor, X11_VMW_TOPOLOGY_REQ,
    282                     sizeof(struct X11VMWTOPOLOGYREQ)
    283                   + sizeof(struct X11VMWRECT) * (cRects - 1),
    284                   (struct X11REQHEADER **)&pReqTopology);
    285     pReqTopology->idX11Screen = DefaultScreen(pContext->pDisplay);
    286     pReqTopology->cScreens = cRects;
    287     for (i = 0; i < cRects; ++i)
    288     {
    289         pReqTopology->aRects[i].x = pRects[i].x;
    290         pReqTopology->aRects[i].y = pRects[i].y;
    291         pReqTopology->aRects[i].w = pRects[i].w;
    292         pReqTopology->aRects[i].h = pRects[i].h;
    293     }
    294     _XSend(pContext->pDisplay, NULL, 0);
    295     if (_XReply(pContext->pDisplay, (xReply *)&repTopology, 0, xTrue))
    296         return;
    297     /* That failed, so try the old single screen set resolution.  We prefer
    298      * simpler code to negligeably improved efficiency, so we just always try
    299      * both requests instead of doing version checks or caching. */
    300     x11GetRequest(pContext, pContext->hVMWMajor, X11_VMW_RESOLUTION_REQUEST,
    301                   sizeof(struct X11VMWTOPOLOGYREQ),
    302                   (struct X11REQHEADER **)&pReqResolution);
    303     pReqResolution->idX11Screen = DefaultScreen(pContext->pDisplay);
    304     pReqResolution->x = pRects[0].x;
    305     pReqResolution->y = pRects[0].y;
    306     if (_XReply(pContext->pDisplay, (xReply *)&repResolution, 0, xTrue))
    307         return;
    308     /* What now? */
    309     VBClFatalError(("%s failed to set resolution\n", __func__));
    310 }
    311 
    312 /** Call RRGetScreenInfo to wake up the server to the new modes. */
    313 static void x11GetScreenInfo(struct X11CONTEXT *pContext)
    314 {
    315     struct X11RANDRGETSCREENREQ *pReqGetScreen;
    316     uint8_t                      repGetScreen[X11_RANDR_GET_SCREEN_REPLY_SIZE];
    317 
    318     if (!VALID_PTR(pContext->pDisplay))
    319         VBClFatalError(("%s bad display argument.\n", __func__));
    320     x11GetRequest(pContext, pContext->hRandRMajor, X11_RANDR_GET_SCREEN_REQUEST,
    321                     sizeof(struct X11RANDRGETSCREENREQ),
    322                   (struct X11REQHEADER **)&pReqGetScreen);
    323     pReqGetScreen->hWindow = DefaultRootWindow(pContext->pDisplay);
    324     _XSend(pContext->pDisplay, NULL, 0);
    325     if (!_XReply(pContext->pDisplay, (xReply *)&repGetScreen, 0, xTrue))
    326         VBClFatalError(("%s failed to set resolution\n", __func__));
    327 }
    328 
    329166static const char *getPidFilePath()
    330167{
     
    337174    (void)fDaemonised;
    338175    struct DRMCONTEXT drmContext = { NIL_RTFILE };
    339     struct X11CONTEXT x11Context = { NULL };
    340176    unsigned i;
    341177    int rc;
     
    350186    drmConnect(&drmContext);
    351187    if (drmContext.hDevice == NIL_RTFILE)
    352     {
    353         x11Connect(&x11Context);
    354         if (x11Context.pDisplay == NULL)
    355             return VINF_SUCCESS;
    356     }
     188        return VINF_SUCCESS;
    357189    /* Initialise the guest library. */
    358190    rc = VbglR3InitUser();
     
    407239            }
    408240        }
    409         if (drmContext.hDevice != NIL_RTFILE)
    410             drmSendHints(&drmContext, aRects, cHeads);
    411         else
    412         {
    413             x11SendHints(&x11Context, aRects, cHeads);
    414             x11GetScreenInfo(&x11Context);
    415         }
     241        drmSendHints(&drmContext, aRects, cHeads);
    416242    }
    417243}
    418244
    419 struct VBCLSERVICE interface =
     245static struct VBCLSERVICE interface =
    420246{
    421247    getPidFilePath,
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