Files
xf86-video-vmware/vmwgfx/vmwgfx_ctrl.c
Thomas Hellstrom 57d4499cc2 vmware/vmwgfx: Disable autolayout if we detect an old resolutionset
While the autolayout feature should really avoid races both with the old
resolutionSet RandR12 code and with new compositor layout code, let's
disable the autolayout feature if someone tries to set the
layout / resolution through the vmwarectrl interface.
That's most likely an old resolutionSet.

Autolayout is turned on on each new screen generation.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Sinclair Yeh <syeh@vmware.com>
2016-02-11 09:15:12 +01:00

529 lines
13 KiB
C

/*
* Copyright 2006-2011 by VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of the copyright holder(s)
* and author(s) shall not be used in advertising or otherwise to promote
* the sale, use or other dealings in this Software without prior written
* authorization from the copyright holder(s) and author(s).
*/
/*
* vmwarectrl.c --
*
* The implementation of the VMWARE_CTRL protocol extension that
* allows X clients to communicate with the driver.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <xorg-server.h>
#include "dixstruct.h"
#include "extnsionst.h"
#include <X11/X.h>
#include <X11/extensions/panoramiXproto.h>
#include "vmwarectrlproto.h"
#include "vmwgfx_driver.h"
#include "vmwgfx_drmi.h"
/*
*----------------------------------------------------------------------------
*
* VMwareCtrlQueryVersion --
*
* Implementation of QueryVersion command handler. Initialises and
* sends a reply.
*
* Results:
* Standard response codes.
*
* Side effects:
* Writes reply to client
*
*----------------------------------------------------------------------------
*/
static int
VMwareCtrlQueryVersion(ClientPtr client)
{
xVMwareCtrlQueryVersionReply rep = { 0, };
register int n;
REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq);
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.majorVersion = VMWARE_CTRL_MAJOR_VERSION;
rep.minorVersion = VMWARE_CTRL_MINOR_VERSION;
if (client->swapped) {
_swaps(&rep.sequenceNumber, n);
_swapl(&rep.length, n);
_swapl(&rep.majorVersion, n);
_swapl(&rep.minorVersion, n);
}
WriteToClient(client, sizeof(xVMwareCtrlQueryVersionReply), (char *)&rep);
return client->noClientException;
}
/*
*----------------------------------------------------------------------------
*
* VMwareCtrlDoSetRes --
*
* Set the custom resolution into the mode list.
*
* This is done by alternately updating one of two dynamic modes. It is
* done this way because the server gets upset if you try to switch
* to a new resolution that has the same index as the current one.
*
* Results:
* TRUE on success, FALSE otherwise.
*
* Side effects:
* One dynamic mode will be updated if successful.
*
*----------------------------------------------------------------------------
*/
static Bool
VMwareCtrlDoSetRes(ScrnInfoPtr pScrn,
CARD32 x,
CARD32 y)
{
modesettingPtr ms = modesettingPTR(pScrn);
struct drm_vmw_rect rect;
int ret;
rect.x = 0;
rect.y = 0;
rect.w = x;
rect.h = y;
ms->autoLayout = FALSE;
ret = vmwgfx_update_gui_layout(ms->fd, 1, &rect);
return (ret == 0);
}
/*
*----------------------------------------------------------------------------
*
* VMwareCtrlSetRes --
*
* Implementation of SetRes command handler. Initialises and sends a
* reply.
*
* Results:
* Standard response codes.
*
* Side effects:
* Writes reply to client
*
*----------------------------------------------------------------------------
*/
static int
VMwareCtrlSetRes(ClientPtr client)
{
REQUEST(xVMwareCtrlSetResReq);
xVMwareCtrlSetResReply rep = { 0, };
ScrnInfoPtr pScrn;
ExtensionEntry *ext;
register int n;
REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq);
if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
return BadMatch;
}
pScrn = ext->extPrivate;
if (pScrn->scrnIndex != stuff->screen) {
return BadMatch;
}
if (!VMwareCtrlDoSetRes(pScrn, stuff->x, stuff->y)) {
return BadValue;
}
rep.type = X_Reply;
rep.length = (sizeof(xVMwareCtrlSetResReply) - sizeof(xGenericReply)) >> 2;
rep.sequenceNumber = client->sequence;
rep.screen = stuff->screen;
rep.x = stuff->x;
rep.y = stuff->y;
if (client->swapped) {
_swaps(&rep.sequenceNumber, n);
_swapl(&rep.length, n);
_swapl(&rep.screen, n);
_swapl(&rep.x, n);
_swapl(&rep.y, n);
}
WriteToClient(client, sizeof(xVMwareCtrlSetResReply), (char *)&rep);
return client->noClientException;
}
/*
*----------------------------------------------------------------------------
*
* VMwareCtrlDoSetTopology --
*
* Set the custom topology and set a dynamic mode to the bounding box
* of the passed topology. If a topology is already pending, then do
* nothing but do not return failure.
*
* Results:
* TRUE on success, FALSE otherwise.
*
* Side effects:
* One dynamic mode and the pending xinerama state will be updated if
* successful.
*
*----------------------------------------------------------------------------
*/
static Bool
VMwareCtrlDoSetTopology(ScrnInfoPtr pScrn,
xXineramaScreenInfo *extents,
unsigned long number)
{
modesettingPtr ms = modesettingPTR(pScrn);
struct drm_vmw_rect *rects;
int i;
int ret;
rects = calloc(number, sizeof(*rects));
if (!rects)
return FALSE;
for (i = 0; i < number; i++) {
rects[i].x = extents[i].x_org;
rects[i].y = extents[i].y_org;
rects[i].w = extents[i].width;
rects[i].h = extents[i].height;
}
ms->autoLayout = FALSE;
ret = vmwgfx_update_gui_layout(ms->fd, number, rects);
free(rects);
return (ret == 0);
}
/*
*----------------------------------------------------------------------------
*
* VMwareCtrlSetTopology --
*
* Implementation of SetTopology command handler. Initialises and sends a
* reply.
*
* Results:
* Standard response codes.
*
* Side effects:
* Writes reply to client
*
*----------------------------------------------------------------------------
*/
static int
VMwareCtrlSetTopology(ClientPtr client)
{
REQUEST(xVMwareCtrlSetTopologyReq);
xVMwareCtrlSetTopologyReply rep = { 0, };
ScrnInfoPtr pScrn;
ExtensionEntry *ext;
register int n;
xXineramaScreenInfo *extents;
REQUEST_AT_LEAST_SIZE(xVMwareCtrlSetTopologyReq);
if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
return BadMatch;
}
pScrn = ext->extPrivate;
if (pScrn->scrnIndex != stuff->screen) {
return BadMatch;
}
extents = (xXineramaScreenInfo *)(stuff + 1);
if (!VMwareCtrlDoSetTopology(pScrn, extents, stuff->number)) {
return BadValue;
}
rep.type = X_Reply;
rep.length = (sizeof(xVMwareCtrlSetTopologyReply) - sizeof(xGenericReply)) >> 2;
rep.sequenceNumber = client->sequence;
rep.screen = stuff->screen;
if (client->swapped) {
_swaps(&rep.sequenceNumber, n);
_swapl(&rep.length, n);
_swapl(&rep.screen, n);
}
WriteToClient(client, sizeof(xVMwareCtrlSetTopologyReply), (char *)&rep);
return client->noClientException;
}
/*
*----------------------------------------------------------------------------
*
* VMwareCtrlDispatch --
*
* Dispatcher for VMWARE_CTRL commands. Calls the correct handler for
* each command type.
*
* Results:
* Standard response codes.
*
* Side effects:
* Side effects of individual command handlers.
*
*----------------------------------------------------------------------------
*/
static int
VMwareCtrlDispatch(ClientPtr client)
{
REQUEST(xReq);
switch(stuff->data) {
case X_VMwareCtrlQueryVersion:
return VMwareCtrlQueryVersion(client);
case X_VMwareCtrlSetRes:
return VMwareCtrlSetRes(client);
case X_VMwareCtrlSetTopology:
return VMwareCtrlSetTopology(client);
}
return BadRequest;
}
/*
*----------------------------------------------------------------------------
*
* SVMwareCtrlQueryVersion --
*
* Wrapper for QueryVersion handler that handles input from other-endian
* clients.
*
* Results:
* Standard response codes.
*
* Side effects:
* Side effects of unswapped implementation.
*
*----------------------------------------------------------------------------
*/
static int
SVMwareCtrlQueryVersion(ClientPtr client)
{
register int n;
REQUEST(xVMwareCtrlQueryVersionReq);
REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq);
_swaps(&stuff->length, n);
return VMwareCtrlQueryVersion(client);
}
/*
*----------------------------------------------------------------------------
*
* SVMwareCtrlSetRes --
*
* Wrapper for SetRes handler that handles input from other-endian
* clients.
*
* Results:
* Standard response codes.
*
* Side effects:
* Side effects of unswapped implementation.
*
*----------------------------------------------------------------------------
*/
static int
SVMwareCtrlSetRes(ClientPtr client)
{
register int n;
REQUEST(xVMwareCtrlSetResReq);
REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq);
_swaps(&stuff->length, n);
_swapl(&stuff->screen, n);
_swapl(&stuff->x, n);
_swapl(&stuff->y, n);
return VMwareCtrlSetRes(client);
}
/*
*----------------------------------------------------------------------------
*
* SVMwareCtrlSetTopology --
*
* Wrapper for SetTopology handler that handles input from other-endian
* clients.
*
* Results:
* Standard response codes.
*
* Side effects:
* Side effects of unswapped implementation.
*
*----------------------------------------------------------------------------
*/
static int
SVMwareCtrlSetTopology(ClientPtr client)
{
register int n;
REQUEST(xVMwareCtrlSetTopologyReq);
REQUEST_SIZE_MATCH(xVMwareCtrlSetTopologyReq);
_swaps(&stuff->length, n);
_swapl(&stuff->screen, n);
_swapl(&stuff->number, n);
/* Each extent is a struct of shorts. */
SwapRestS(stuff);
return VMwareCtrlSetTopology(client);
}
/*
*----------------------------------------------------------------------------
*
* SVMwareCtrlDispatch --
*
* Wrapper for dispatcher that handles input from other-endian clients.
*
* Results:
* Standard response codes.
*
* Side effects:
* Side effects of individual command handlers.
*
*----------------------------------------------------------------------------
*/
static int
SVMwareCtrlDispatch(ClientPtr client)
{
REQUEST(xReq);
switch(stuff->data) {
case X_VMwareCtrlQueryVersion:
return SVMwareCtrlQueryVersion(client);
case X_VMwareCtrlSetRes:
return SVMwareCtrlSetRes(client);
case X_VMwareCtrlSetTopology:
return SVMwareCtrlSetTopology(client);
}
return BadRequest;
}
/*
*----------------------------------------------------------------------------
*
* VMwareCtrlResetProc --
*
* Cleanup handler called when the extension is removed.
*
* Results:
* None
*
* Side effects:
* None
*
*----------------------------------------------------------------------------
*/
static void
VMwareCtrlResetProc(ExtensionEntry* extEntry)
{
/* Currently, no cleanup is necessary. */
}
/*
*----------------------------------------------------------------------------
*
* VMwareCtrl_ExitInit --
*
* Initialiser for the VMWARE_CTRL protocol extension.
*
* Results:
* None.
*
* Side effects:
* Protocol extension will be registered if successful.
*
*----------------------------------------------------------------------------
*/
void
vmw_ctrl_ext_init(ScrnInfoPtr pScrn)
{
ExtensionEntry *myext;
if (!(myext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
if (!(myext = AddExtension(VMWARE_CTRL_PROTOCOL_NAME, 0, 0,
VMwareCtrlDispatch,
SVMwareCtrlDispatch,
VMwareCtrlResetProc,
StandardMinorOpcode))) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to add VMWARE_CTRL extension\n");
return;
}
/*
* For now, only support one screen as that's all the virtual
* hardware supports.
*/
myext->extPrivate = pScrn;
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Initialized VMWARE_CTRL extension version %d.%d\n",
VMWARE_CTRL_MAJOR_VERSION, VMWARE_CTRL_MINOR_VERSION);
}
}