xenocara/xserver/hw/xfree86/common/xf86DGA.c

1174 lines
32 KiB
C
Raw Normal View History

2006-11-26 11:13:41 -07:00
/*
* Copyright (c) 1998-2002 by The XFree86 Project, 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).
*
* Written by Mark Vojkovich
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include "xf86.h"
#include "xf86str.h"
#include "xf86Priv.h"
#include "dgaproc.h"
#include <X11/extensions/xf86dgaproto.h>
2006-11-26 11:13:41 -07:00
#include "colormapst.h"
#include "pixmapstr.h"
#include "inputstr.h"
#include "globals.h"
#include "servermd.h"
#include "micmap.h"
#include "xkbsrv.h"
2006-11-26 11:13:41 -07:00
#include "xf86Xinput.h"
#include "exglobals.h"
#include "exevents.h"
#include "eventstr.h"
#include "eventconvert.h"
2006-11-26 11:13:41 -07:00
2007-11-24 10:55:21 -07:00
#include "mi.h"
static DevPrivateKeyRec DGAScreenKeyRec;
#define DGAScreenKeyRegistered dixPrivateKeyRegistered(&DGAScreenKeyRec)
2011-11-05 07:32:40 -06:00
static Bool mieq_installed;
2006-11-26 11:13:41 -07:00
static Bool DGACloseScreen(int i, ScreenPtr pScreen);
static void DGADestroyColormap(ColormapPtr pmap);
static void DGAInstallColormap(ColormapPtr pmap);
static void DGAUninstallColormap(ColormapPtr pmap);
static void DGAHandleEvent(int screen_num, InternalEvent *event,
DeviceIntPtr device);
2006-11-26 11:13:41 -07:00
static void
DGACopyModeInfo(DGAModePtr mode, XDGAModePtr xmode);
2006-11-26 11:13:41 -07:00
int *XDGAEventBase = NULL;
2006-11-26 11:13:41 -07:00
#define DGA_GET_SCREEN_PRIV(pScreen) ((DGAScreenPtr) \
dixLookupPrivate(&(pScreen)->devPrivates, &DGAScreenKeyRec))
2006-11-26 11:13:41 -07:00
typedef struct _FakedVisualList {
Bool free;
VisualPtr pVisual;
struct _FakedVisualList *next;
2006-11-26 11:13:41 -07:00
} FakedVisualList;
typedef struct {
ScrnInfoPtr pScrn;
int numModes;
DGAModePtr modes;
CloseScreenProcPtr CloseScreen;
DestroyColormapProcPtr DestroyColormap;
InstallColormapProcPtr InstallColormap;
UninstallColormapProcPtr UninstallColormap;
DGADevicePtr current;
DGAFunctionPtr funcs;
int input;
ClientPtr client;
int pixmapMode;
FakedVisualList *fakedVisuals;
ColormapPtr dgaColormap;
ColormapPtr savedColormap;
Bool grabMouse;
Bool grabKeyboard;
2006-11-26 11:13:41 -07:00
} DGAScreenRec, *DGAScreenPtr;
Bool
DGAInit(ScreenPtr pScreen, DGAFunctionPtr funcs, DGAModePtr modes, int num)
{
2006-11-26 11:13:41 -07:00
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
DGAScreenPtr pScreenPriv;
int i;
if (!funcs || !funcs->SetMode || !funcs->OpenFramebuffer)
return FALSE;
2006-11-26 11:13:41 -07:00
if (!modes || num <= 0)
return FALSE;
2006-11-26 11:13:41 -07:00
if (!dixRegisterPrivateKey(&DGAScreenKeyRec, PRIVATE_SCREEN, 0))
return FALSE;
2006-11-26 11:13:41 -07:00
2009-10-31 08:09:43 -06:00
pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
if (!pScreenPriv) {
if (!(pScreenPriv = (DGAScreenPtr) malloc(sizeof(DGAScreenRec))))
return FALSE;
dixSetPrivate(&pScreen->devPrivates, &DGAScreenKeyRec, pScreenPriv);
pScreenPriv->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = DGACloseScreen;
pScreenPriv->DestroyColormap = pScreen->DestroyColormap;
pScreen->DestroyColormap = DGADestroyColormap;
pScreenPriv->InstallColormap = pScreen->InstallColormap;
pScreen->InstallColormap = DGAInstallColormap;
pScreenPriv->UninstallColormap = pScreen->UninstallColormap;
pScreen->UninstallColormap = DGAUninstallColormap;
2009-10-31 08:09:43 -06:00
}
2006-11-26 11:13:41 -07:00
pScreenPriv->pScrn = pScrn;
pScreenPriv->numModes = num;
pScreenPriv->modes = modes;
pScreenPriv->current = NULL;
2006-11-26 11:13:41 -07:00
pScreenPriv->funcs = funcs;
pScreenPriv->input = 0;
pScreenPriv->client = NULL;
pScreenPriv->fakedVisuals = NULL;
pScreenPriv->dgaColormap = NULL;
pScreenPriv->savedColormap = NULL;
pScreenPriv->grabMouse = FALSE;
pScreenPriv->grabKeyboard = FALSE;
for (i = 0; i < num; i++)
modes[i].num = i + 1;
2006-11-26 11:13:41 -07:00
#ifdef PANORAMIX
if (!noPanoramiXExtension)
for (i = 0; i < num; i++)
modes[i].flags &= ~DGA_PIXMAP_AVAILABLE;
2006-11-26 11:13:41 -07:00
#endif
return TRUE;
}
/* DGAReInitModes allows the driver to re-initialize
* the DGA mode list.
*/
Bool
DGAReInitModes(ScreenPtr pScreen, DGAModePtr modes, int num)
{
2006-11-26 11:13:41 -07:00
DGAScreenPtr pScreenPriv;
int i;
/* No DGA? Ignore call (but don't make it look like it failed) */
if (!DGAScreenKeyRegistered)
return TRUE;
2006-11-26 11:13:41 -07:00
pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
/* Same as above */
if (!pScreenPriv)
return TRUE;
2006-11-26 11:13:41 -07:00
/* Can't do this while DGA is active */
if (pScreenPriv->current)
return FALSE;
2006-11-26 11:13:41 -07:00
/* Quick sanity check */
if (!num)
modes = NULL;
else if (!modes)
num = 0;
2006-11-26 11:13:41 -07:00
pScreenPriv->numModes = num;
pScreenPriv->modes = modes;
/* This practically disables DGA. So be it. */
if (!num)
return TRUE;
2006-11-26 11:13:41 -07:00
for (i = 0; i < num; i++)
modes[i].num = i + 1;
2006-11-26 11:13:41 -07:00
#ifdef PANORAMIX
if (!noPanoramiXExtension)
for (i = 0; i < num; i++)
modes[i].flags &= ~DGA_PIXMAP_AVAILABLE;
2006-11-26 11:13:41 -07:00
#endif
return TRUE;
2006-11-26 11:13:41 -07:00
}
static void
FreeMarkedVisuals(ScreenPtr pScreen)
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
FakedVisualList *prev, *curr, *tmp;
if (!pScreenPriv->fakedVisuals)
return;
2006-11-26 11:13:41 -07:00
prev = NULL;
curr = pScreenPriv->fakedVisuals;
while (curr) {
if (curr->free) {
tmp = curr;
curr = curr->next;
if (prev)
prev->next = curr;
else
pScreenPriv->fakedVisuals = curr;
free(tmp->pVisual);
free(tmp);
}
else {
prev = curr;
curr = curr->next;
}
2006-11-26 11:13:41 -07:00
}
}
static Bool
2006-11-26 11:13:41 -07:00
DGACloseScreen(int i, ScreenPtr pScreen)
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
2006-11-26 11:13:41 -07:00
if (mieq_installed) {
mieqSetHandler(ET_DGAEvent, NULL);
mieq_installed = FALSE;
}
2007-11-24 10:55:21 -07:00
FreeMarkedVisuals(pScreen);
2006-11-26 11:13:41 -07:00
pScreen->CloseScreen = pScreenPriv->CloseScreen;
pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
pScreen->InstallColormap = pScreenPriv->InstallColormap;
pScreen->UninstallColormap = pScreenPriv->UninstallColormap;
2006-11-26 11:13:41 -07:00
/* DGAShutdown() should have ensured that no DGA
screen were active by here */
2006-11-26 11:13:41 -07:00
free(pScreenPriv);
2006-11-26 11:13:41 -07:00
return ((*pScreen->CloseScreen) (i, pScreen));
2006-11-26 11:13:41 -07:00
}
static void
2006-11-26 11:13:41 -07:00
DGADestroyColormap(ColormapPtr pmap)
{
ScreenPtr pScreen = pmap->pScreen;
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
VisualPtr pVisual = pmap->pVisual;
if (pScreenPriv->fakedVisuals) {
FakedVisualList *curr = pScreenPriv->fakedVisuals;
while (curr) {
if (curr->pVisual == pVisual) {
/* We can't get rid of them yet since FreeColormap
still needs the pVisual during the cleanup */
curr->free = TRUE;
break;
}
curr = curr->next;
}
}
if (pScreenPriv->DestroyColormap) {
2006-11-26 11:13:41 -07:00
pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
(*pScreen->DestroyColormap) (pmap);
2006-11-26 11:13:41 -07:00
pScreen->DestroyColormap = DGADestroyColormap;
}
2006-11-26 11:13:41 -07:00
}
static void
2006-11-26 11:13:41 -07:00
DGAInstallColormap(ColormapPtr pmap)
{
ScreenPtr pScreen = pmap->pScreen;
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
if (pScreenPriv->current && pScreenPriv->dgaColormap) {
if (pmap != pScreenPriv->dgaColormap) {
pScreenPriv->savedColormap = pmap;
pmap = pScreenPriv->dgaColormap;
}
2006-11-26 11:13:41 -07:00
}
pScreen->InstallColormap = pScreenPriv->InstallColormap;
(*pScreen->InstallColormap) (pmap);
2006-11-26 11:13:41 -07:00
pScreen->InstallColormap = DGAInstallColormap;
}
static void
2006-11-26 11:13:41 -07:00
DGAUninstallColormap(ColormapPtr pmap)
{
ScreenPtr pScreen = pmap->pScreen;
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
if (pScreenPriv->current && pScreenPriv->dgaColormap) {
if (pmap == pScreenPriv->dgaColormap) {
pScreenPriv->dgaColormap = NULL;
}
2006-11-26 11:13:41 -07:00
}
pScreen->UninstallColormap = pScreenPriv->UninstallColormap;
(*pScreen->UninstallColormap) (pmap);
2006-11-26 11:13:41 -07:00
pScreen->UninstallColormap = DGAUninstallColormap;
}
int
xf86SetDGAMode(int index, int num, DGADevicePtr devRet)
{
ScreenPtr pScreen = screenInfo.screens[index];
DGAScreenPtr pScreenPriv;
ScrnInfoPtr pScrn;
DGADevicePtr device;
PixmapPtr pPix = NULL;
DGAModePtr pMode = NULL;
/* First check if DGAInit was successful on this screen */
if (!DGAScreenKeyRegistered)
return BadValue;
pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
if (!pScreenPriv)
return BadValue;
pScrn = pScreenPriv->pScrn;
if (!num) {
if (pScreenPriv->current) {
PixmapPtr oldPix = pScreenPriv->current->pPix;
if (oldPix) {
if (oldPix->drawable.id)
FreeResource(oldPix->drawable.id, RT_NONE);
else
(*pScreen->DestroyPixmap) (oldPix);
}
free(pScreenPriv->current);
pScreenPriv->current = NULL;
pScrn->vtSema = TRUE;
(*pScreenPriv->funcs->SetMode) (pScrn, NULL);
if (pScreenPriv->savedColormap) {
(*pScreen->InstallColormap) (pScreenPriv->savedColormap);
pScreenPriv->savedColormap = NULL;
}
pScreenPriv->dgaColormap = NULL;
(*pScrn->EnableDisableFBAccess) (index, TRUE);
FreeMarkedVisuals(pScreen);
}
2006-11-26 11:13:41 -07:00
pScreenPriv->grabMouse = FALSE;
pScreenPriv->grabKeyboard = FALSE;
return Success;
}
2006-11-26 11:13:41 -07:00
if (!pScrn->vtSema && !pScreenPriv->current) /* Really switched away */
return BadAlloc;
2006-11-26 11:13:41 -07:00
if ((num > 0) && (num <= pScreenPriv->numModes))
pMode = &(pScreenPriv->modes[num - 1]);
else
return BadValue;
2011-11-05 07:32:40 -06:00
if (!(device = (DGADevicePtr) malloc(sizeof(DGADeviceRec))))
return BadAlloc;
if (!pScreenPriv->current) {
Bool oldVTSema = pScrn->vtSema;
pScrn->vtSema = FALSE; /* kludge until we rewrite VT switching */
(*pScrn->EnableDisableFBAccess) (index, FALSE);
pScrn->vtSema = oldVTSema;
}
if (!(*pScreenPriv->funcs->SetMode) (pScrn, pMode)) {
free(device);
return BadAlloc;
}
pScrn->currentMode = pMode->mode;
2006-11-26 11:13:41 -07:00
if (!pScreenPriv->current && !pScreenPriv->input) {
/* if it's multihead we need to warp the cursor off of
our screen so it doesn't get trapped */
}
pScrn->vtSema = FALSE;
if (pScreenPriv->current) {
PixmapPtr oldPix = pScreenPriv->current->pPix;
if (oldPix) {
if (oldPix->drawable.id)
FreeResource(oldPix->drawable.id, RT_NONE);
else
(*pScreen->DestroyPixmap) (oldPix);
}
free(pScreenPriv->current);
pScreenPriv->current = NULL;
}
2006-11-26 11:13:41 -07:00
if (pMode->flags & DGA_PIXMAP_AVAILABLE) {
if ((pPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, pMode->depth, 0))) {
(*pScreen->ModifyPixmapHeader) (pPix,
pMode->pixmapWidth,
pMode->pixmapHeight, pMode->depth,
pMode->bitsPerPixel,
pMode->bytesPerScanline,
(pointer) (pMode->address));
}
}
devRet->mode = device->mode = pMode;
devRet->pPix = device->pPix = pPix;
pScreenPriv->current = device;
pScreenPriv->pixmapMode = FALSE;
pScreenPriv->grabMouse = TRUE;
pScreenPriv->grabKeyboard = TRUE;
if (!mieq_installed) {
mieqSetHandler(ET_DGAEvent, DGAHandleEvent);
mieq_installed = TRUE;
}
return Success;
}
2006-11-26 11:13:41 -07:00
/*********** exported ones ***************/
void
2006-11-26 11:13:41 -07:00
DGASetInputMode(int index, Bool keyboard, Bool mouse)
{
ScreenPtr pScreen = screenInfo.screens[index];
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
if (pScreenPriv) {
pScreenPriv->grabMouse = mouse;
pScreenPriv->grabKeyboard = keyboard;
if (!mieq_installed) {
mieqSetHandler(ET_DGAEvent, DGAHandleEvent);
mieq_installed = TRUE;
}
}
2006-11-26 11:13:41 -07:00
}
Bool
2006-11-26 11:13:41 -07:00
DGAChangePixmapMode(int index, int *x, int *y, int mode)
{
DGAScreenPtr pScreenPriv;
DGADevicePtr pDev;
DGAModePtr pMode;
PixmapPtr pPix;
if (!DGAScreenKeyRegistered)
return FALSE;
pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
if (!pScreenPriv || !pScreenPriv->current || !pScreenPriv->current->pPix)
return FALSE;
pDev = pScreenPriv->current;
pPix = pDev->pPix;
pMode = pDev->mode;
if (mode) {
int shift = 2;
if (*x > (pMode->pixmapWidth - pMode->viewportWidth))
*x = pMode->pixmapWidth - pMode->viewportWidth;
if (*y > (pMode->pixmapHeight - pMode->viewportHeight))
*y = pMode->pixmapHeight - pMode->viewportHeight;
switch (xf86Screens[index]->bitsPerPixel) {
case 16:
shift = 1;
break;
case 32:
shift = 0;
break;
default:
break;
}
if (BITMAP_SCANLINE_PAD == 64)
shift++;
*x = (*x >> shift) << shift;
pPix->drawable.x = *x;
pPix->drawable.y = *y;
pPix->drawable.width = pMode->viewportWidth;
pPix->drawable.height = pMode->viewportHeight;
}
else {
pPix->drawable.x = 0;
pPix->drawable.y = 0;
pPix->drawable.width = pMode->pixmapWidth;
pPix->drawable.height = pMode->pixmapHeight;
}
pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER;
pScreenPriv->pixmapMode = mode;
return TRUE;
2006-11-26 11:13:41 -07:00
}
Bool
DGAAvailable(int index)
2006-11-26 11:13:41 -07:00
{
if (!DGAScreenKeyRegistered)
return FALSE;
2006-11-26 11:13:41 -07:00
if (DGA_GET_SCREEN_PRIV(screenInfo.screens[index]))
return TRUE;
return FALSE;
2006-11-26 11:13:41 -07:00
}
Bool
DGAActive(int index)
2006-11-26 11:13:41 -07:00
{
DGAScreenPtr pScreenPriv;
2006-11-26 11:13:41 -07:00
if (!DGAScreenKeyRegistered)
return FALSE;
2006-11-26 11:13:41 -07:00
pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
2006-11-26 11:13:41 -07:00
if (pScreenPriv && pScreenPriv->current)
return TRUE;
2006-11-26 11:13:41 -07:00
return FALSE;
2006-11-26 11:13:41 -07:00
}
/* Called by the event code in case the server is abruptly terminated */
void
DGAShutdown(void)
2006-11-26 11:13:41 -07:00
{
ScrnInfoPtr pScrn;
int i;
if (!DGAScreenKeyRegistered)
return;
2006-11-26 11:13:41 -07:00
for (i = 0; i < screenInfo.numScreens; i++) {
pScrn = xf86Screens[i];
2006-11-26 11:13:41 -07:00
(void) (*pScrn->SetDGAMode) (pScrn->scrnIndex, 0, NULL);
2006-11-26 11:13:41 -07:00
}
}
/* Called by the extension to initialize a mode */
int
DGASetMode(int index, int num, XDGAModePtr mode, PixmapPtr *pPix)
{
2006-11-26 11:13:41 -07:00
ScrnInfoPtr pScrn = xf86Screens[index];
DGADeviceRec device;
int ret;
/* We rely on the extension to check that DGA is available */
2006-11-26 11:13:41 -07:00
ret = (*pScrn->SetDGAMode) (index, num, &device);
if ((ret == Success) && num) {
DGACopyModeInfo(device.mode, mode);
*pPix = device.pPix;
2006-11-26 11:13:41 -07:00
}
return ret;
}
/* Called from the extension to let the DDX know which events are requested */
void
DGASelectInput(int index, ClientPtr client, long mask)
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
/* We rely on the extension to check that DGA is available */
pScreenPriv->client = client;
pScreenPriv->input = mask;
2006-11-26 11:13:41 -07:00
}
int
DGAGetViewportStatus(int index)
2006-11-26 11:13:41 -07:00
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
2006-11-26 11:13:41 -07:00
/* We rely on the extension to check that DGA is active */
2006-11-26 11:13:41 -07:00
if (!pScreenPriv->funcs->GetViewport)
return 0;
2006-11-26 11:13:41 -07:00
return (*pScreenPriv->funcs->GetViewport) (pScreenPriv->pScrn);
2006-11-26 11:13:41 -07:00
}
int
DGASetViewport(int index, int x, int y, int mode)
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
2006-11-26 11:13:41 -07:00
if (pScreenPriv->funcs->SetViewport)
(*pScreenPriv->funcs->SetViewport) (pScreenPriv->pScrn, x, y, mode);
return Success;
}
2006-11-26 11:13:41 -07:00
static int
BitsClear(CARD32 data)
{
int bits = 0;
CARD32 mask;
for (mask = 1; mask; mask <<= 1) {
if (!(data & mask))
bits++;
else
break;
}
2006-11-26 11:13:41 -07:00
return bits;
2006-11-26 11:13:41 -07:00
}
int
2006-11-26 11:13:41 -07:00
DGACreateColormap(int index, ClientPtr client, int id, int mode, int alloc)
{
ScreenPtr pScreen = screenInfo.screens[index];
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
FakedVisualList *fvlp;
VisualPtr pVisual;
DGAModePtr pMode;
ColormapPtr pmap;
if (!mode || (mode > pScreenPriv->numModes))
return BadValue;
if ((alloc != AllocNone) && (alloc != AllocAll))
return BadValue;
pMode = &(pScreenPriv->modes[mode - 1]);
if (!(pVisual = malloc(sizeof(VisualRec))))
return BadAlloc;
pVisual->vid = FakeClientID(0);
pVisual->class = pMode->visualClass;
pVisual->nplanes = pMode->depth;
pVisual->ColormapEntries = 1 << pMode->depth;
pVisual->bitsPerRGBValue = (pMode->depth + 2) / 3;
switch (pVisual->class) {
case PseudoColor:
case GrayScale:
case StaticGray:
pVisual->bitsPerRGBValue = 8; /* not quite */
pVisual->redMask = 0;
pVisual->greenMask = 0;
pVisual->blueMask = 0;
pVisual->offsetRed = 0;
pVisual->offsetGreen = 0;
pVisual->offsetBlue = 0;
break;
case DirectColor:
case TrueColor:
pVisual->ColormapEntries = 1 << pVisual->bitsPerRGBValue;
/* fall through */
case StaticColor:
pVisual->redMask = pMode->red_mask;
pVisual->greenMask = pMode->green_mask;
pVisual->blueMask = pMode->blue_mask;
pVisual->offsetRed = BitsClear(pVisual->redMask);
pVisual->offsetGreen = BitsClear(pVisual->greenMask);
pVisual->offsetBlue = BitsClear(pVisual->blueMask);
}
if (!(fvlp = malloc(sizeof(FakedVisualList)))) {
free(pVisual);
return BadAlloc;
}
fvlp->free = FALSE;
fvlp->pVisual = pVisual;
fvlp->next = pScreenPriv->fakedVisuals;
pScreenPriv->fakedVisuals = fvlp;
LEGAL_NEW_RESOURCE(id, client);
return CreateColormap(id, pScreen, pVisual, &pmap, alloc, client->index);
2006-11-26 11:13:41 -07:00
}
/* Called by the extension to install a colormap on DGA active screens */
void
2006-11-26 11:13:41 -07:00
DGAInstallCmap(ColormapPtr cmap)
{
ScreenPtr pScreen = cmap->pScreen;
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
/* We rely on the extension to check that DGA is active */
2006-11-26 11:13:41 -07:00
if (!pScreenPriv->dgaColormap)
pScreenPriv->savedColormap = GetInstalledmiColormap(pScreen);
2006-11-26 11:13:41 -07:00
pScreenPriv->dgaColormap = cmap;
2006-11-26 11:13:41 -07:00
(*pScreen->InstallColormap) (cmap);
2006-11-26 11:13:41 -07:00
}
int
2006-11-26 11:13:41 -07:00
DGASync(int index)
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
2006-11-26 11:13:41 -07:00
/* We rely on the extension to check that DGA is active */
2006-11-26 11:13:41 -07:00
if (pScreenPriv->funcs->Sync)
(*pScreenPriv->funcs->Sync) (pScreenPriv->pScrn);
return Success;
2006-11-26 11:13:41 -07:00
}
int
DGAFillRect(int index, int x, int y, int w, int h, unsigned long color)
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
/* We rely on the extension to check that DGA is active */
if (pScreenPriv->funcs->FillRect &&
(pScreenPriv->current->mode->flags & DGA_FILL_RECT)) {
(*pScreenPriv->funcs->FillRect) (pScreenPriv->pScrn, x, y, w, h, color);
return Success;
}
return BadMatch;
2006-11-26 11:13:41 -07:00
}
int
DGABlitRect(int index, int srcx, int srcy, int w, int h, int dstx, int dsty)
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
/* We rely on the extension to check that DGA is active */
if (pScreenPriv->funcs->BlitRect &&
(pScreenPriv->current->mode->flags & DGA_BLIT_RECT)) {
(*pScreenPriv->funcs->BlitRect) (pScreenPriv->pScrn,
srcx, srcy, w, h, dstx, dsty);
return Success;
}
return BadMatch;
2006-11-26 11:13:41 -07:00
}
int
DGABlitTransRect(int index,
int srcx, int srcy,
int w, int h, int dstx, int dsty, unsigned long color)
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
2006-11-26 11:13:41 -07:00
/* We rely on the extension to check that DGA is active */
if (pScreenPriv->funcs->BlitTransRect &&
(pScreenPriv->current->mode->flags & DGA_BLIT_RECT_TRANS)) {
(*pScreenPriv->funcs->BlitTransRect) (pScreenPriv->pScrn,
srcx, srcy, w, h, dstx, dsty,
color);
return Success;
}
return BadMatch;
}
2006-11-26 11:13:41 -07:00
int
2006-11-26 11:13:41 -07:00
DGAGetModes(int index)
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
2006-11-26 11:13:41 -07:00
/* We rely on the extension to check that DGA is available */
2006-11-26 11:13:41 -07:00
return pScreenPriv->numModes;
}
2006-11-26 11:13:41 -07:00
int
DGAGetModeInfo(int index, XDGAModePtr mode, int num)
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
2006-11-26 11:13:41 -07:00
/* We rely on the extension to check that DGA is available */
2006-11-26 11:13:41 -07:00
if ((num <= 0) || (num > pScreenPriv->numModes))
return BadValue;
2006-11-26 11:13:41 -07:00
DGACopyModeInfo(&(pScreenPriv->modes[num - 1]), mode);
2006-11-26 11:13:41 -07:00
return Success;
}
2006-11-26 11:13:41 -07:00
static void
DGACopyModeInfo(DGAModePtr mode, XDGAModePtr xmode)
{
DisplayModePtr dmode = mode->mode;
xmode->num = mode->num;
xmode->name = dmode->name;
xmode->VSync_num = (int) (dmode->VRefresh * 1000.0);
xmode->VSync_den = 1000;
xmode->flags = mode->flags;
xmode->imageWidth = mode->imageWidth;
xmode->imageHeight = mode->imageHeight;
xmode->pixmapWidth = mode->pixmapWidth;
xmode->pixmapHeight = mode->pixmapHeight;
xmode->bytesPerScanline = mode->bytesPerScanline;
xmode->byteOrder = mode->byteOrder;
xmode->depth = mode->depth;
xmode->bitsPerPixel = mode->bitsPerPixel;
xmode->red_mask = mode->red_mask;
xmode->green_mask = mode->green_mask;
xmode->blue_mask = mode->blue_mask;
xmode->visualClass = mode->visualClass;
xmode->viewportWidth = mode->viewportWidth;
xmode->viewportHeight = mode->viewportHeight;
xmode->xViewportStep = mode->xViewportStep;
xmode->yViewportStep = mode->yViewportStep;
xmode->maxViewportX = mode->maxViewportX;
xmode->maxViewportY = mode->maxViewportY;
xmode->viewportFlags = mode->viewportFlags;
xmode->reserved1 = mode->reserved1;
xmode->reserved2 = mode->reserved2;
xmode->offset = mode->offset;
if (dmode->Flags & V_INTERLACE)
xmode->flags |= DGA_INTERLACED;
if (dmode->Flags & V_DBLSCAN)
xmode->flags |= DGA_DOUBLESCAN;
2006-11-26 11:13:41 -07:00
}
Bool
2006-11-26 11:13:41 -07:00
DGAVTSwitch(void)
{
ScreenPtr pScreen;
int i;
for (i = 0; i < screenInfo.numScreens; i++) {
pScreen = screenInfo.screens[i];
2006-11-26 11:13:41 -07:00
/* Alternatively, this could send events to DGA clients */
2006-11-26 11:13:41 -07:00
if (DGAScreenKeyRegistered) {
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
2006-11-26 11:13:41 -07:00
if (pScreenPriv && pScreenPriv->current)
return FALSE;
}
2006-11-26 11:13:41 -07:00
}
return TRUE;
2006-11-26 11:13:41 -07:00
}
Bool
DGAStealKeyEvent(DeviceIntPtr dev, int index, int key_code, int is_down)
2006-11-26 11:13:41 -07:00
{
DGAScreenPtr pScreenPriv;
DGAEvent event;
if (!DGAScreenKeyRegistered) /* no DGA */
2007-11-24 10:55:21 -07:00
return FALSE;
2006-11-26 11:13:41 -07:00
if (key_code < 8 || key_code > 255)
return FALSE;
pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
2006-11-26 11:13:41 -07:00
if (!pScreenPriv || !pScreenPriv->grabKeyboard) /* no direct mode */
return FALSE;
2007-11-24 10:55:21 -07:00
memset(&event, 0, sizeof(event));
event.header = ET_Internal;
event.type = ET_DGAEvent;
event.length = sizeof(event);
event.time = GetTimeInMillis();
event.subtype = (is_down ? ET_KeyPress : ET_KeyRelease);
event.detail = key_code;
event.dx = 0;
event.dy = 0;
mieqEnqueue(dev, (InternalEvent *) &event);
2006-11-26 11:13:41 -07:00
return TRUE;
}
2006-11-26 11:13:41 -07:00
Bool
DGAStealMotionEvent(DeviceIntPtr dev, int index, int dx, int dy)
2006-11-26 11:13:41 -07:00
{
DGAScreenPtr pScreenPriv;
DGAEvent event;
2006-11-26 11:13:41 -07:00
if (!DGAScreenKeyRegistered) /* no DGA */
2007-11-24 10:55:21 -07:00
return FALSE;
2006-11-26 11:13:41 -07:00
pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
if (!pScreenPriv || !pScreenPriv->grabMouse) /* no direct mode */
2007-11-24 10:55:21 -07:00
return FALSE;
memset(&event, 0, sizeof(event));
event.header = ET_Internal;
event.type = ET_DGAEvent;
event.length = sizeof(event);
event.time = GetTimeInMillis();
event.subtype = ET_Motion;
event.detail = 0;
event.dx = dx;
event.dy = dy;
mieqEnqueue(dev, (InternalEvent *) &event);
2006-11-26 11:13:41 -07:00
return TRUE;
}
2007-11-24 10:55:21 -07:00
Bool
DGAStealButtonEvent(DeviceIntPtr dev, int index, int button, int is_down)
2007-11-24 10:55:21 -07:00
{
DGAScreenPtr pScreenPriv;
DGAEvent event;
2007-11-24 10:55:21 -07:00
if (!DGAScreenKeyRegistered) /* no DGA */
2007-11-24 10:55:21 -07:00
return FALSE;
2007-11-24 10:55:21 -07:00
pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
if (!pScreenPriv || !pScreenPriv->grabMouse)
return FALSE;
memset(&event, 0, sizeof(event));
event.header = ET_Internal;
event.type = ET_DGAEvent;
event.length = sizeof(event);
event.time = GetTimeInMillis();
event.subtype = (is_down ? ET_ButtonPress : ET_ButtonRelease);
event.detail = button;
event.dx = 0;
event.dy = 0;
mieqEnqueue(dev, (InternalEvent *) &event);
2007-11-24 10:55:21 -07:00
return TRUE;
}
/* We have the power to steal or modify events that are about to get queued */
#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */
static Mask filters[] = {
NoSuchEvent, /* 0 */
NoSuchEvent, /* 1 */
KeyPressMask, /* KeyPress */
KeyReleaseMask, /* KeyRelease */
ButtonPressMask, /* ButtonPress */
ButtonReleaseMask, /* ButtonRelease */
PointerMotionMask, /* MotionNotify (initial state) */
2006-11-26 11:13:41 -07:00
};
static void
DGAProcessKeyboardEvent(ScreenPtr pScreen, DGAEvent * event, DeviceIntPtr keybd)
2006-11-26 11:13:41 -07:00
{
KeyClassPtr keyc = keybd->key;
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
DeviceIntPtr pointer = GetMaster(keybd, POINTER_OR_FLOAT);
DeviceEvent ev;
memset(&ev, 0, sizeof(ev));
2011-11-05 07:32:40 -06:00
ev.header = ET_Internal;
ev.length = sizeof(ev);
ev.detail.key = event->detail;
ev.type = event->subtype;
ev.root_x = 0;
ev.root_y = 0;
ev.corestate = XkbStateFieldFromRec(&keyc->xkbInfo->state);
ev.corestate |= pointer->button->state;
UpdateDeviceState(keybd, &ev);
2006-11-26 11:13:41 -07:00
/*
* Deliver the DGA event
*/
if (pScreenPriv->client) {
dgaEvent de;
de.u.u.type = *XDGAEventBase + GetCoreType(ev.type);
de.u.u.detail = event->detail;
de.u.event.time = event->time;
2011-11-05 07:32:40 -06:00
de.u.event.dx = event->dx;
de.u.event.dy = event->dy;
de.u.event.screen = pScreen->myNum;
de.u.event.state = ev.corestate;
/* If the DGA client has selected input, then deliver based on the usual filter */
TryClientEvents(pScreenPriv->client, keybd, (xEvent *) &de, 1,
filters[ev.type], pScreenPriv->input, 0);
2006-11-26 11:13:41 -07:00
}
else {
/* If the keyboard is actively grabbed, deliver a grabbed core event */
if (keybd->deviceGrab.grab && !keybd->deviceGrab.fromPassiveGrab) {
ev.detail.key = event->detail;
ev.time = event->time;
ev.root_x = event->dx;
ev.root_y = event->dy;
ev.corestate = event->state;
ev.deviceid = keybd->id;
DeliverGrabbedEvent((InternalEvent *) &ev, keybd, FALSE);
}
2006-11-26 11:13:41 -07:00
}
}
static void
DGAProcessPointerEvent(ScreenPtr pScreen, DGAEvent * event, DeviceIntPtr mouse)
2006-11-26 11:13:41 -07:00
{
ButtonClassPtr butc = mouse->button;
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
DeviceEvent ev;
DeviceIntPtr master = GetMaster(mouse, MASTER_KEYBOARD);
2006-11-26 11:13:41 -07:00
memset(&ev, 0, sizeof(ev));
ev.header = ET_Internal;
ev.length = sizeof(ev);
ev.type = event->subtype;
ev.corestate = butc ? butc->state : 0;
if (master && master->key)
ev.corestate |= XkbStateFieldFromRec(&master->key->xkbInfo->state);
UpdateDeviceState(mouse, &ev);
2006-11-26 11:13:41 -07:00
/*
* Deliver the DGA event
*/
if (pScreenPriv->client) {
dgaEvent de;
int coreEquiv;
coreEquiv = GetCoreType(ev.type);
de.u.u.type = *XDGAEventBase + coreEquiv;
de.u.u.detail = event->detail;
de.u.event.time = event->time;
2011-11-05 07:32:40 -06:00
de.u.event.dx = event->dx;
de.u.event.dy = event->dy;
de.u.event.screen = pScreen->myNum;
de.u.event.state = ev.corestate;
/* If the DGA client has selected input, then deliver based on the usual filter */
TryClientEvents(pScreenPriv->client, mouse, (xEvent *) &de, 1,
filters[coreEquiv], pScreenPriv->input, 0);
2006-11-26 11:13:41 -07:00
}
else {
/* If the pointer is actively grabbed, deliver a grabbed core event */
if (mouse->deviceGrab.grab && !mouse->deviceGrab.fromPassiveGrab) {
ev.detail.button = event->detail;
ev.time = event->time;
ev.root_x = event->dx;
ev.root_y = event->dy;
ev.corestate = event->state;
/* DGA is core only, so valuators.data doesn't actually matter.
* Mask must be set for EventToCore to create motion events. */
SetBit(ev.valuators.mask, 0);
SetBit(ev.valuators.mask, 1);
DeliverGrabbedEvent((InternalEvent *) &ev, mouse, FALSE);
}
2006-11-26 11:13:41 -07:00
}
}
Bool
DGAOpenFramebuffer(int index,
char **name,
unsigned char **mem, int *size, int *offset, int *flags)
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
/* We rely on the extension to check that DGA is available */
return (*pScreenPriv->funcs->OpenFramebuffer) (pScreenPriv->pScrn,
name, mem, size, offset,
flags);
2006-11-26 11:13:41 -07:00
}
void
2006-11-26 11:13:41 -07:00
DGACloseFramebuffer(int index)
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
2006-11-26 11:13:41 -07:00
/* We rely on the extension to check that DGA is available */
if (pScreenPriv->funcs->CloseFramebuffer)
(*pScreenPriv->funcs->CloseFramebuffer) (pScreenPriv->pScrn);
2006-11-26 11:13:41 -07:00
}
/* For DGA 1.0 backwards compatibility only */
int
2006-11-26 11:13:41 -07:00
DGAGetOldDGAMode(int index)
{
DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
ScrnInfoPtr pScrn = pScreenPriv->pScrn;
DGAModePtr mode;
int i, w, h, p;
/* We rely on the extension to check that DGA is available */
w = pScrn->currentMode->HDisplay;
h = pScrn->currentMode->VDisplay;
p = pad_to_int32(pScrn->displayWidth * bits_to_bytes(pScrn->bitsPerPixel));
for (i = 0; i < pScreenPriv->numModes; i++) {
mode = &(pScreenPriv->modes[i]);
if ((mode->viewportWidth == w) && (mode->viewportHeight == h) &&
(mode->bytesPerScanline == p) &&
(mode->bitsPerPixel == pScrn->bitsPerPixel) &&
(mode->depth == pScrn->depth)) {
return mode->num;
}
}
return 0;
2006-11-26 11:13:41 -07:00
}
2007-11-24 10:55:21 -07:00
static void
DGAHandleEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2007-11-24 10:55:21 -07:00
{
DGAEvent *event = &ev->dga_event;
ScreenPtr pScreen = screenInfo.screens[screen_num];
DGAScreenPtr pScreenPriv;
2007-11-24 10:55:21 -07:00
/* no DGA */
if (!DGAScreenKeyRegistered || XDGAEventBase == 0)
return;
2007-11-24 10:55:21 -07:00
pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
2007-11-24 10:55:21 -07:00
/* DGA not initialized on this screen */
if (!pScreenPriv)
return;
2011-11-05 07:32:40 -06:00
if (!IsMaster(device))
return;
2011-11-05 07:32:40 -06:00
switch (event->subtype) {
2007-11-24 10:55:21 -07:00
case KeyPress:
case KeyRelease:
DGAProcessKeyboardEvent(pScreen, event, device);
break;
case MotionNotify:
case ButtonPress:
case ButtonRelease:
DGAProcessPointerEvent(pScreen, event, device);
break;
2007-11-24 10:55:21 -07:00
default:
break;
2007-11-24 10:55:21 -07:00
}
}