/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86DGA.c,v 1.47 2003/08/24 17:36:51 dawes Exp $ */ /* * 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 */ #include "xf86.h" #include "xf86str.h" #include "xf86Priv.h" #include "dgaproc.h" #include "xf86dgastr.h" #include "colormapst.h" #include "pixmapstr.h" #include "inputstr.h" #include "globals.h" #include "servermd.h" #include "micmap.h" #ifdef XKB #include "XKBsrv.h" #endif #include "xf86Xinput.h" static unsigned long DGAGeneration = 0; static int DGAScreenIndex = -1; static Bool DGACloseScreen(int i, ScreenPtr pScreen); static void DGADestroyColormap(ColormapPtr pmap); static void DGAInstallColormap(ColormapPtr pmap); static void DGAUninstallColormap(ColormapPtr pmap); static void DGACopyModeInfo( DGAModePtr mode, XDGAModePtr xmode ); #if defined(XFree86LOADER) || !defined(XFreeXDGA) int *XDGAEventBase = NULL; #else int *XDGAEventBase = &DGAEventBase; #endif #define DGA_GET_SCREEN_PRIV(pScreen) \ ((DGAScreenPtr)((pScreen)->devPrivates[DGAScreenIndex].ptr)) typedef struct _FakedVisualList{ Bool free; VisualPtr pVisual; struct _FakedVisualList *next; } 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; } DGAScreenRec, *DGAScreenPtr; Bool DGAInit( ScreenPtr pScreen, DGAFunctionPtr funcs, DGAModePtr modes, int num ){ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; DGAScreenPtr pScreenPriv; int i; if(!funcs || !funcs->SetMode || !funcs->OpenFramebuffer) return FALSE; if(!modes || num <= 0) return FALSE; if(DGAGeneration != serverGeneration) { if((DGAScreenIndex = AllocateScreenPrivateIndex()) < 0) return FALSE; DGAGeneration = serverGeneration; } if(!(pScreenPriv = (DGAScreenPtr)xalloc(sizeof(DGAScreenRec)))) return FALSE; pScreenPriv->pScrn = pScrn; pScreenPriv->numModes = num; pScreenPriv->modes = modes; pScreenPriv->current = NULL; 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; #ifdef PANORAMIX if(!noPanoramiXExtension) for(i = 0; i < num; i++) modes[i].flags &= ~DGA_PIXMAP_AVAILABLE; #endif pScreen->devPrivates[DGAScreenIndex].ptr = (pointer)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; /* * This is now set in InitOutput(). * pScrn->SetDGAMode = xf86SetDGAMode; */ return TRUE; } static void FreeMarkedVisuals(ScreenPtr pScreen) { DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); FakedVisualList *prev, *curr, *tmp; if(!pScreenPriv->fakedVisuals) return; prev = NULL; curr = pScreenPriv->fakedVisuals; while(curr) { if(curr->free) { tmp = curr; curr = curr->next; if(prev) prev->next = curr; else pScreenPriv->fakedVisuals = curr; xfree(tmp->pVisual); xfree(tmp); } else { prev = curr; curr = curr->next; } } } static Bool DGACloseScreen(int i, ScreenPtr pScreen) { DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); FreeMarkedVisuals(pScreen); pScreen->CloseScreen = pScreenPriv->CloseScreen; pScreen->DestroyColormap = pScreenPriv->DestroyColormap; pScreen->InstallColormap = pScreenPriv->InstallColormap; pScreen->UninstallColormap = pScreenPriv->UninstallColormap; /* DGAShutdown() should have ensured that no DGA screen were active by here */ xfree(pScreenPriv); return((*pScreen->CloseScreen)(i, pScreen)); } static void 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) { pScreen->DestroyColormap = pScreenPriv->DestroyColormap; (*pScreen->DestroyColormap)(pmap); pScreen->DestroyColormap = DGADestroyColormap; } } static void 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; } } pScreen->InstallColormap = pScreenPriv->InstallColormap; (*pScreen->InstallColormap)(pmap); pScreen->InstallColormap = DGAInstallColormap; } static void 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; } } pScreen->UninstallColormap = pScreenPriv->UninstallColormap; (*pScreen->UninstallColormap)(pmap); 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 (DGAScreenIndex < 0) 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); } xfree(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); } pScreenPriv->grabMouse = FALSE; pScreenPriv->grabKeyboard = FALSE; return Success; } if(!pScrn->vtSema && !pScreenPriv->current) /* Really switched away */ return BadAlloc; if((num > 0) && (num <= pScreenPriv->numModes)) pMode = &(pScreenPriv->modes[num - 1]); else return BadValue; if(!(device = (DGADevicePtr)xalloc(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)) { xfree(device); return BadAlloc; } pScrn->currentMode = pMode->mode; 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); } xfree(pScreenPriv->current); pScreenPriv->current = NULL; } if(pMode->flags & DGA_PIXMAP_AVAILABLE) { if((pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pMode->depth))) { (*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; return Success; } /*********** exported ones ***************/ void 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; } } Bool DGAChangePixmapMode(int index, int *x, int *y, int mode) { DGAScreenPtr pScreenPriv; DGADevicePtr pDev; DGAModePtr pMode; PixmapPtr pPix; if(DGAScreenIndex < 0) 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; } Bool DGAAvailable(int index) { if(DGAScreenIndex < 0) return FALSE; if (!xf86NoSharedResources(((ScrnInfoPtr)screenInfo.screens[index]-> devPrivates[xf86ScreenIndex].ptr)->scrnIndex,MEM)) return FALSE; if(DGA_GET_SCREEN_PRIV(screenInfo.screens[index])) return TRUE; return FALSE; } Bool DGAActive(int index) { DGAScreenPtr pScreenPriv; if(DGAScreenIndex < 0) return FALSE; pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); if(pScreenPriv && pScreenPriv->current) return TRUE; return FALSE; } /* Called by the event code in case the server is abruptly terminated */ void DGAShutdown() { ScrnInfoPtr pScrn; int i; if(DGAScreenIndex < 0) return; for(i = 0; i < screenInfo.numScreens; i++) { pScrn = xf86Screens[i]; (void)(*pScrn->SetDGAMode)(pScrn->scrnIndex, 0, NULL); } } /* Called by the extension to initialize a mode */ int DGASetMode( int index, int num, XDGAModePtr mode, PixmapPtr *pPix ){ ScrnInfoPtr pScrn = xf86Screens[index]; DGADeviceRec device; int ret; /* We rely on the extension to check that DGA is available */ ret = (*pScrn->SetDGAMode)(index, num, &device); if((ret == Success) && num) { DGACopyModeInfo(device.mode, mode); *pPix = device.pPix; } 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; } int DGAGetViewportStatus(int index) { DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); /* We rely on the extension to check that DGA is active */ if (!pScreenPriv->funcs->GetViewport) return 0; return (*pScreenPriv->funcs->GetViewport)(pScreenPriv->pScrn); } int DGASetViewport( int index, int x, int y, int mode ){ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); if (pScreenPriv->funcs->SetViewport) (*pScreenPriv->funcs->SetViewport)(pScreenPriv->pScrn, x, y, mode); return Success; } static int BitsClear(CARD32 data) { int bits = 0; CARD32 mask; for(mask = 1; mask; mask <<= 1) { if(!(data & mask)) bits++; else break; } return bits; } int 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 = xalloc(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 = xalloc(sizeof(FakedVisualList)))) { xfree(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); } /* Called by the extension to install a colormap on DGA active screens */ void 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 */ if(!pScreenPriv->dgaColormap) pScreenPriv->savedColormap = miInstalledMaps[pScreen->myNum]; pScreenPriv->dgaColormap = cmap; (*pScreen->InstallColormap)(cmap); } int DGASync(int index) { DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); /* We rely on the extension to check that DGA is active */ if (pScreenPriv->funcs->Sync) (*pScreenPriv->funcs->Sync)(pScreenPriv->pScrn); return Success; } 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; } 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; } 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]); /* 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; } int DGAGetModes(int index) { DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); /* We rely on the extension to check that DGA is available */ return pScreenPriv->numModes; } int DGAGetModeInfo( int index, XDGAModePtr mode, int num ){ DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); /* We rely on the extension to check that DGA is available */ if((num <= 0) || (num > pScreenPriv->numModes)) return BadValue; DGACopyModeInfo(&(pScreenPriv->modes[num - 1]), mode); return Success; } 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; } Bool DGAVTSwitch(void) { ScreenPtr pScreen; int i; for(i = 0; i < screenInfo.numScreens; i++) { pScreen = screenInfo.screens[i]; /* Alternatively, this could send events to DGA clients */ if(DGAScreenIndex >= 0) { DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); if(pScreenPriv && pScreenPriv->current) return FALSE; } } return TRUE; } /* We have the power to steal or modify events that are about to get queued */ Bool DGAStealKeyEvent(int index, xEvent *e) { DGAScreenPtr pScreenPriv; dgaEvent de; if(DGAScreenIndex < 0) /* no DGA */ return FALSE; pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); if(!pScreenPriv || !pScreenPriv->grabKeyboard) /* no direct mode */ return FALSE; de.u.u.type = e->u.u.type + *XDGAEventBase; de.u.u.detail = e->u.u.detail; de.u.event.time = e->u.keyButtonPointer.time; xf86eqEnqueue ((xEvent *) &de); return TRUE; } static int DGAMouseX, DGAMouseY; Bool DGAStealMouseEvent(int index, xEvent *e, int dx, int dy) { DGAScreenPtr pScreenPriv; dgaEvent de; if(DGAScreenIndex < 0) /* no DGA */ return FALSE; pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); if(!pScreenPriv || !pScreenPriv->grabMouse) /* no direct mode */ return FALSE; DGAMouseX += dx; if (DGAMouseX < 0) DGAMouseX = 0; else if (DGAMouseX > screenInfo.screens[index]->width) DGAMouseX = screenInfo.screens[index]->width; DGAMouseY += dy; if (DGAMouseY < 0) DGAMouseY = 0; else if (DGAMouseY > screenInfo.screens[index]->height) DGAMouseY = screenInfo.screens[index]->height; de.u.u.type = e->u.u.type + *XDGAEventBase; de.u.u.detail = e->u.u.detail; de.u.event.time = e->u.keyButtonPointer.time; de.u.event.dx = dx; de.u.event.dy = dy; de.u.event.pad1 = DGAMouseX; de.u.event.pad2 = DGAMouseY; xf86eqEnqueue ((xEvent *) &de); return TRUE; } Bool DGAIsDgaEvent (xEvent *e) { int coreEquiv; if (DGAScreenIndex < 0 || XDGAEventBase == 0) return FALSE; coreEquiv = e->u.u.type - *XDGAEventBase; if (KeyPress <= coreEquiv && coreEquiv <= MotionNotify) return TRUE; return FALSE; } #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) */ }; static void DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd) { int key, bit; register BYTE *kptr; register int i; register CARD8 modifiers; register CARD16 mask; int coreEquiv; xEvent core; KeyClassPtr keyc = keybd->key; DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); coreEquiv = de->u.u.type - *XDGAEventBase; /* * Fill in remaining event state */ de->u.event.dx = 0; de->u.event.dy = 0; de->u.event.screen = pScreen->myNum; de->u.event.state = keyc->state | (inputInfo.pointer)->button->state; /* * Keep the core state in sync by duplicating what * CoreProcessKeyboardEvent does */ key = de->u.u.detail; kptr = &keyc->down[key >> 3]; bit = 1 << (key & 7); modifiers = keyc->modifierMap[key]; switch (coreEquiv) { case KeyPress: inputInfo.pointer->valuator->motionHintWindow = NullWindow; *kptr |= bit; keyc->prev_state = keyc->state; if (noXkbExtension) { for (i = 0, mask = 1; modifiers; i++, mask <<= 1) { if (mask & modifiers) { /* This key affects modifier "i" */ keyc->modifierKeyCount[i]++; keyc->state |= mask; modifiers &= ~mask; } } } break; case KeyRelease: inputInfo.pointer->valuator->motionHintWindow = NullWindow; *kptr &= ~bit; keyc->prev_state = keyc->state; if (noXkbExtension) { for (i = 0, mask = 1; modifiers; i++, mask <<= 1) { if (mask & modifiers) { /* This key affects modifier "i" */ if (--keyc->modifierKeyCount[i] <= 0) { keyc->state &= ~mask; keyc->modifierKeyCount[i] = 0; } modifiers &= ~mask; } } } break; } /* * Deliver the DGA event */ if (pScreenPriv->client) { /* If the DGA client has selected input, then deliver based on the usual filter */ TryClientEvents (pScreenPriv->client, (xEvent *) de, 1, filters[coreEquiv], pScreenPriv->input, 0); } else { /* If the keyboard is actively grabbed, deliver a grabbed core event */ if (keybd->grab && !keybd->fromPassiveGrab) { core.u.u.type = coreEquiv; core.u.u.detail = de->u.u.detail; core.u.keyButtonPointer.time = de->u.event.time; core.u.keyButtonPointer.eventX = de->u.event.dx; core.u.keyButtonPointer.eventY = de->u.event.dy; core.u.keyButtonPointer.rootX = de->u.event.dx; core.u.keyButtonPointer.rootY = de->u.event.dy; core.u.keyButtonPointer.state = de->u.event.state; DeliverGrabbedEvent (&core, keybd, FALSE, 1); } } } static void DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse) { ButtonClassPtr butc = mouse->button; int coreEquiv; DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); xEvent core; coreEquiv = de->u.u.type - *XDGAEventBase; /* * Fill in remaining event state */ de->u.event.screen = pScreen->myNum; de->u.event.state = butc->state | inputInfo.keyboard->key->state; /* * Keep the core state in sync by duplicating what * CoreProcessPointerEvent does */ if (coreEquiv != MotionNotify) { register int key; register BYTE *kptr; int bit; key = de->u.u.detail; kptr = &butc->down[key >> 3]; bit = 1 << (key & 7); switch (coreEquiv) { case ButtonPress: mouse->valuator->motionHintWindow = NullWindow; if (!(*kptr & bit)) butc->buttonsDown++; butc->motionMask = ButtonMotionMask; *kptr |= bit; if (key <= 5) butc->state |= (Button1Mask >> 1) << key; break; case ButtonRelease: mouse->valuator->motionHintWindow = NullWindow; if (*kptr & bit) --butc->buttonsDown; if (!butc->buttonsDown) butc->motionMask = 0; *kptr &= ~bit; if (key == 0) return; if (key <= 5) butc->state &= ~((Button1Mask >> 1) << key); break; } } /* * Deliver the DGA event */ if (pScreenPriv->client) { /* If the DGA client has selected input, then deliver based on the usual filter */ TryClientEvents (pScreenPriv->client, (xEvent *) de, 1, filters[coreEquiv], pScreenPriv->input, 0); } else { /* If the pointer is actively grabbed, deliver a grabbed core event */ if (mouse->grab && !mouse->fromPassiveGrab) { core.u.u.type = coreEquiv; core.u.u.detail = de->u.u.detail; core.u.keyButtonPointer.time = de->u.event.time; core.u.keyButtonPointer.eventX = de->u.event.dx; core.u.keyButtonPointer.eventY = de->u.event.dy; core.u.keyButtonPointer.rootX = de->u.event.dx; core.u.keyButtonPointer.rootY = de->u.event.dy; core.u.keyButtonPointer.state = de->u.event.state; DeliverGrabbedEvent (&core, mouse, FALSE, 1); } } } Bool DGADeliverEvent (ScreenPtr pScreen, xEvent *e) { dgaEvent *de = (dgaEvent *) e; DGAScreenPtr pScreenPriv; int coreEquiv; /* no DGA */ if (DGAScreenIndex < 0 || XDGAEventBase == 0) return FALSE; pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); /* DGA not initialized on this screen */ if (!pScreenPriv) return FALSE; coreEquiv = de->u.u.type - *XDGAEventBase; /* Not a DGA event */ if (coreEquiv < KeyPress || coreEquiv > MotionNotify) return FALSE; switch (coreEquiv) { case KeyPress: case KeyRelease: DGAProcessKeyboardEvent (pScreen, de, inputInfo.keyboard); break; default: DGAProcessPointerEvent (pScreen, de, inputInfo.pointer); break; } return TRUE; } 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); } void DGACloseFramebuffer(int index) { DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); /* We rely on the extension to check that DGA is available */ if(pScreenPriv->funcs->CloseFramebuffer) (*pScreenPriv->funcs->CloseFramebuffer)(pScreenPriv->pScrn); } /* For DGA 1.0 backwards compatibility only */ int 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 = ((pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)) + 3) & ~3L; 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; }