105b261ecSmrg 205b261ecSmrg/* 305b261ecSmrg * Copyright (c) 1998-2001 by The XFree86 Project, Inc. 405b261ecSmrg * 505b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 605b261ecSmrg * copy of this software and associated documentation files (the "Software"), 705b261ecSmrg * to deal in the Software without restriction, including without limitation 805b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 905b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the 1005b261ecSmrg * Software is furnished to do so, subject to the following conditions: 1105b261ecSmrg * 1205b261ecSmrg * The above copyright notice and this permission notice shall be included in 1305b261ecSmrg * all copies or substantial portions of the Software. 1405b261ecSmrg * 1505b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1605b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1705b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1805b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 1905b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2005b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2105b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE. 2205b261ecSmrg * 2305b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s) 2405b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote 2505b261ecSmrg * the sale, use or other dealings in this Software without prior written 2605b261ecSmrg * authorization from the copyright holder(s) and author(s). 2705b261ecSmrg */ 2805b261ecSmrg 2905b261ecSmrg#ifdef HAVE_XORG_CONFIG_H 3005b261ecSmrg#include <xorg-config.h> 3105b261ecSmrg#endif 3205b261ecSmrg 3305b261ecSmrg#include "misc.h" 3405b261ecSmrg#include "xf86.h" 3505b261ecSmrg 3605b261ecSmrg#include <X11/X.h> 3705b261ecSmrg#include "scrnintstr.h" 3805b261ecSmrg#include "regionstr.h" 3905b261ecSmrg#include "xf86fbman.h" 4005b261ecSmrg 4135c4bbdfSmrg/* 4205b261ecSmrg#define DEBUG 4305b261ecSmrg*/ 4405b261ecSmrg 456747b715Smrgstatic DevPrivateKeyRec xf86FBManagerKeyRec; 464642e01fSmrgstatic DevPrivateKey xf86FBManagerKey; 4705b261ecSmrg 4835c4bbdfSmrgBool 4935c4bbdfSmrgxf86RegisterOffscreenManager(ScreenPtr pScreen, FBManagerFuncsPtr funcs) 5035c4bbdfSmrg{ 5105b261ecSmrg 5235c4bbdfSmrg xf86FBManagerKey = &xf86FBManagerKeyRec; 536747b715Smrg 5435c4bbdfSmrg if (!dixRegisterPrivateKey(&xf86FBManagerKeyRec, PRIVATE_SCREEN, 0)) 5535c4bbdfSmrg return FALSE; 566747b715Smrg 5735c4bbdfSmrg dixSetPrivate(&pScreen->devPrivates, xf86FBManagerKey, funcs); 5805b261ecSmrg 5935c4bbdfSmrg return TRUE; 6005b261ecSmrg} 6105b261ecSmrg 626747b715SmrgBool 6305b261ecSmrgxf86FBManagerRunning(ScreenPtr pScreen) 6405b261ecSmrg{ 656747b715Smrg if (xf86FBManagerKey == NULL) 6635c4bbdfSmrg return FALSE; 676747b715Smrg 6835c4bbdfSmrg if (!dixLookupPrivate(&pScreen->devPrivates, xf86FBManagerKey)) 6935c4bbdfSmrg return FALSE; 7005b261ecSmrg 7105b261ecSmrg return TRUE; 7205b261ecSmrg} 7305b261ecSmrg 746747b715SmrgBool 7535c4bbdfSmrgxf86RegisterFreeBoxCallback(ScreenPtr pScreen, 7635c4bbdfSmrg FreeBoxCallbackProcPtr FreeBoxCallback, 7735c4bbdfSmrg void *devPriv) 7835c4bbdfSmrg{ 7935c4bbdfSmrg FBManagerFuncsPtr funcs; 8035c4bbdfSmrg 8135c4bbdfSmrg if (xf86FBManagerKey == NULL) 8235c4bbdfSmrg return FALSE; 8335c4bbdfSmrg if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates, 8435c4bbdfSmrg xf86FBManagerKey))) 8535c4bbdfSmrg return FALSE; 8605b261ecSmrg 8735c4bbdfSmrg return (*funcs->RegisterFreeBoxCallback) (pScreen, FreeBoxCallback, 8835c4bbdfSmrg devPriv); 8935c4bbdfSmrg} 9005b261ecSmrg 916747b715SmrgFBAreaPtr 9235c4bbdfSmrgxf86AllocateOffscreenArea(ScreenPtr pScreen, 9335c4bbdfSmrg int w, int h, 9435c4bbdfSmrg int gran, 9535c4bbdfSmrg MoveAreaCallbackProcPtr moveCB, 9635c4bbdfSmrg RemoveAreaCallbackProcPtr removeCB, void *privData) 9735c4bbdfSmrg{ 9835c4bbdfSmrg FBManagerFuncsPtr funcs; 9905b261ecSmrg 10035c4bbdfSmrg if (xf86FBManagerKey == NULL) 10135c4bbdfSmrg return NULL; 10235c4bbdfSmrg if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates, 10335c4bbdfSmrg xf86FBManagerKey))) 10435c4bbdfSmrg return NULL; 10505b261ecSmrg 10635c4bbdfSmrg return (*funcs->AllocateOffscreenArea) (pScreen, w, h, gran, moveCB, 10735c4bbdfSmrg removeCB, privData); 10805b261ecSmrg} 10905b261ecSmrg 11035c4bbdfSmrgFBLinearPtr 11135c4bbdfSmrgxf86AllocateOffscreenLinear(ScreenPtr pScreen, 11235c4bbdfSmrg int length, 11335c4bbdfSmrg int gran, 11435c4bbdfSmrg MoveLinearCallbackProcPtr moveCB, 11535c4bbdfSmrg RemoveLinearCallbackProcPtr removeCB, 11635c4bbdfSmrg void *privData) 11735c4bbdfSmrg{ 11835c4bbdfSmrg FBManagerFuncsPtr funcs; 11935c4bbdfSmrg 12035c4bbdfSmrg if (xf86FBManagerKey == NULL) 12135c4bbdfSmrg return NULL; 12235c4bbdfSmrg if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates, 12335c4bbdfSmrg xf86FBManagerKey))) 12435c4bbdfSmrg return NULL; 12535c4bbdfSmrg 12635c4bbdfSmrg return (*funcs->AllocateOffscreenLinear) (pScreen, length, gran, moveCB, 12735c4bbdfSmrg removeCB, privData); 12835c4bbdfSmrg} 12905b261ecSmrg 1306747b715Smrgvoid 13105b261ecSmrgxf86FreeOffscreenArea(FBAreaPtr area) 13205b261ecSmrg{ 13335c4bbdfSmrg FBManagerFuncsPtr funcs; 13405b261ecSmrg 13535c4bbdfSmrg if (!area) 13635c4bbdfSmrg return; 13705b261ecSmrg 13835c4bbdfSmrg if (xf86FBManagerKey == NULL) 13935c4bbdfSmrg return; 14035c4bbdfSmrg if (! 14135c4bbdfSmrg (funcs = 14235c4bbdfSmrg (FBManagerFuncsPtr) dixLookupPrivate(&area->pScreen->devPrivates, 14335c4bbdfSmrg xf86FBManagerKey))) 14435c4bbdfSmrg return; 14505b261ecSmrg 14635c4bbdfSmrg (*funcs->FreeOffscreenArea) (area); 14705b261ecSmrg 14835c4bbdfSmrg return; 14905b261ecSmrg} 15005b261ecSmrg 1516747b715Smrgvoid 15205b261ecSmrgxf86FreeOffscreenLinear(FBLinearPtr linear) 15305b261ecSmrg{ 15435c4bbdfSmrg FBManagerFuncsPtr funcs; 15505b261ecSmrg 15635c4bbdfSmrg if (!linear) 15735c4bbdfSmrg return; 15805b261ecSmrg 15935c4bbdfSmrg if (xf86FBManagerKey == NULL) 16035c4bbdfSmrg return; 16135c4bbdfSmrg if (! 16235c4bbdfSmrg (funcs = 16335c4bbdfSmrg (FBManagerFuncsPtr) dixLookupPrivate(&linear->pScreen->devPrivates, 16435c4bbdfSmrg xf86FBManagerKey))) 16535c4bbdfSmrg return; 16605b261ecSmrg 16735c4bbdfSmrg (*funcs->FreeOffscreenLinear) (linear); 16805b261ecSmrg 16935c4bbdfSmrg return; 17005b261ecSmrg} 17105b261ecSmrg 1726747b715SmrgBool 17335c4bbdfSmrgxf86ResizeOffscreenArea(FBAreaPtr resize, int w, int h) 17435c4bbdfSmrg{ 17535c4bbdfSmrg FBManagerFuncsPtr funcs; 17605b261ecSmrg 17735c4bbdfSmrg if (!resize) 17835c4bbdfSmrg return FALSE; 17905b261ecSmrg 18035c4bbdfSmrg if (xf86FBManagerKey == NULL) 18135c4bbdfSmrg return FALSE; 18235c4bbdfSmrg if (! 18335c4bbdfSmrg (funcs = 18435c4bbdfSmrg (FBManagerFuncsPtr) dixLookupPrivate(&resize->pScreen->devPrivates, 18535c4bbdfSmrg xf86FBManagerKey))) 18635c4bbdfSmrg return FALSE; 18735c4bbdfSmrg 18835c4bbdfSmrg return (*funcs->ResizeOffscreenArea) (resize, w, h); 18905b261ecSmrg} 19005b261ecSmrg 1916747b715SmrgBool 19235c4bbdfSmrgxf86ResizeOffscreenLinear(FBLinearPtr resize, int size) 19335c4bbdfSmrg{ 19435c4bbdfSmrg FBManagerFuncsPtr funcs; 19505b261ecSmrg 19635c4bbdfSmrg if (!resize) 19735c4bbdfSmrg return FALSE; 19805b261ecSmrg 19935c4bbdfSmrg if (xf86FBManagerKey == NULL) 20035c4bbdfSmrg return FALSE; 20135c4bbdfSmrg if (! 20235c4bbdfSmrg (funcs = 20335c4bbdfSmrg (FBManagerFuncsPtr) dixLookupPrivate(&resize->pScreen->devPrivates, 20435c4bbdfSmrg xf86FBManagerKey))) 20535c4bbdfSmrg return FALSE; 20635c4bbdfSmrg 20735c4bbdfSmrg return (*funcs->ResizeOffscreenLinear) (resize, size); 20805b261ecSmrg} 20905b261ecSmrg 2106747b715SmrgBool 21135c4bbdfSmrgxf86QueryLargestOffscreenArea(ScreenPtr pScreen, 21235c4bbdfSmrg int *w, int *h, 21335c4bbdfSmrg int gran, int preferences, int severity) 21435c4bbdfSmrg{ 21535c4bbdfSmrg FBManagerFuncsPtr funcs; 21635c4bbdfSmrg 21735c4bbdfSmrg *w = 0; 21835c4bbdfSmrg *h = 0; 21935c4bbdfSmrg 22035c4bbdfSmrg if (xf86FBManagerKey == NULL) 22135c4bbdfSmrg return FALSE; 22235c4bbdfSmrg if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates, 22335c4bbdfSmrg xf86FBManagerKey))) 22435c4bbdfSmrg return FALSE; 22535c4bbdfSmrg 22635c4bbdfSmrg return (*funcs->QueryLargestOffscreenArea) (pScreen, w, h, gran, 22735c4bbdfSmrg preferences, severity); 22805b261ecSmrg} 22905b261ecSmrg 2306747b715SmrgBool 23135c4bbdfSmrgxf86QueryLargestOffscreenLinear(ScreenPtr pScreen, 23235c4bbdfSmrg int *size, int gran, int severity) 23335c4bbdfSmrg{ 23435c4bbdfSmrg FBManagerFuncsPtr funcs; 23535c4bbdfSmrg 23635c4bbdfSmrg *size = 0; 23705b261ecSmrg 23835c4bbdfSmrg if (xf86FBManagerKey == NULL) 23935c4bbdfSmrg return FALSE; 24035c4bbdfSmrg if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates, 24135c4bbdfSmrg xf86FBManagerKey))) 24235c4bbdfSmrg return FALSE; 24335c4bbdfSmrg 24435c4bbdfSmrg return (*funcs->QueryLargestOffscreenLinear) (pScreen, size, gran, 24535c4bbdfSmrg severity); 24635c4bbdfSmrg} 24705b261ecSmrg 2486747b715SmrgBool 24905b261ecSmrgxf86PurgeUnlockedOffscreenAreas(ScreenPtr pScreen) 25005b261ecSmrg{ 25135c4bbdfSmrg FBManagerFuncsPtr funcs; 25205b261ecSmrg 25335c4bbdfSmrg if (xf86FBManagerKey == NULL) 25435c4bbdfSmrg return FALSE; 25535c4bbdfSmrg if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates, 25635c4bbdfSmrg xf86FBManagerKey))) 25735c4bbdfSmrg return FALSE; 25805b261ecSmrg 25935c4bbdfSmrg return (*funcs->PurgeOffscreenAreas) (pScreen); 26005b261ecSmrg} 26105b261ecSmrg 26235c4bbdfSmrg/************************************************************\ 26305b261ecSmrg 26405b261ecSmrg Below is a specific implementation of an offscreen manager. 26505b261ecSmrg 26635c4bbdfSmrg\************************************************************/ 26705b261ecSmrg 2686747b715Smrgstatic DevPrivateKeyRec xf86FBScreenKeyRec; 26935c4bbdfSmrg 2706747b715Smrg#define xf86FBScreenKey (&xf86FBScreenKeyRec) 27105b261ecSmrg 27205b261ecSmrgtypedef struct _FBLink { 27335c4bbdfSmrg FBArea area; 27435c4bbdfSmrg struct _FBLink *next; 27505b261ecSmrg} FBLink, *FBLinkPtr; 27605b261ecSmrg 27705b261ecSmrgtypedef struct _FBLinearLink { 27835c4bbdfSmrg FBLinear linear; 27935c4bbdfSmrg int free; /* need to add free here as FBLinear is publicly accessible */ 28035c4bbdfSmrg FBAreaPtr area; /* only used if allocation came from XY area */ 28135c4bbdfSmrg struct _FBLinearLink *next; 28205b261ecSmrg} FBLinearLink, *FBLinearLinkPtr; 28305b261ecSmrg 28405b261ecSmrgtypedef struct { 28535c4bbdfSmrg ScreenPtr pScreen; 28635c4bbdfSmrg RegionPtr InitialBoxes; 28735c4bbdfSmrg RegionPtr FreeBoxes; 28835c4bbdfSmrg FBLinkPtr UsedAreas; 28935c4bbdfSmrg int NumUsedAreas; 29035c4bbdfSmrg FBLinearLinkPtr LinearAreas; 29135c4bbdfSmrg CloseScreenProcPtr CloseScreen; 29235c4bbdfSmrg int NumCallbacks; 29335c4bbdfSmrg FreeBoxCallbackProcPtr *FreeBoxesUpdateCallback; 29435c4bbdfSmrg DevUnion *devPrivates; 29505b261ecSmrg} FBManager, *FBManagerPtr; 29605b261ecSmrg 29705b261ecSmrgstatic void 29805b261ecSmrgSendCallFreeBoxCallbacks(FBManagerPtr offman) 29905b261ecSmrg{ 30035c4bbdfSmrg int i = offman->NumCallbacks; 30105b261ecSmrg 30235c4bbdfSmrg while (i--) { 30335c4bbdfSmrg (*offman->FreeBoxesUpdateCallback[i]) (offman->pScreen, 30435c4bbdfSmrg offman->FreeBoxes, 30535c4bbdfSmrg offman->devPrivates[i].ptr); 30635c4bbdfSmrg } 30705b261ecSmrg} 30805b261ecSmrg 30905b261ecSmrgstatic Bool 31035c4bbdfSmrglocalRegisterFreeBoxCallback(ScreenPtr pScreen, 31135c4bbdfSmrg FreeBoxCallbackProcPtr FreeBoxCallback, 31235c4bbdfSmrg void *devPriv) 31335c4bbdfSmrg{ 31435c4bbdfSmrg FBManagerPtr offman; 31535c4bbdfSmrg FreeBoxCallbackProcPtr *newCallbacks; 31635c4bbdfSmrg DevUnion *newPrivates; 31735c4bbdfSmrg 31835c4bbdfSmrg offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 31935c4bbdfSmrg xf86FBScreenKey); 32035c4bbdfSmrg newCallbacks = reallocarray(offman->FreeBoxesUpdateCallback, 32135c4bbdfSmrg offman->NumCallbacks + 1, 32235c4bbdfSmrg sizeof(FreeBoxCallbackProcPtr)); 32335c4bbdfSmrg if (!newCallbacks) 32435c4bbdfSmrg return FALSE; 32535c4bbdfSmrg else 32635c4bbdfSmrg offman->FreeBoxesUpdateCallback = newCallbacks; 32735c4bbdfSmrg 32835c4bbdfSmrg newPrivates = reallocarray(offman->devPrivates, 32935c4bbdfSmrg offman->NumCallbacks + 1, 33035c4bbdfSmrg sizeof(DevUnion)); 33135c4bbdfSmrg if (!newPrivates) 33235c4bbdfSmrg return FALSE; 33335c4bbdfSmrg else 33435c4bbdfSmrg offman->devPrivates = newPrivates; 33535c4bbdfSmrg 33635c4bbdfSmrg offman->FreeBoxesUpdateCallback[offman->NumCallbacks] = FreeBoxCallback; 33735c4bbdfSmrg offman->devPrivates[offman->NumCallbacks].ptr = devPriv; 33835c4bbdfSmrg offman->NumCallbacks++; 33935c4bbdfSmrg 34035c4bbdfSmrg SendCallFreeBoxCallbacks(offman); 34105b261ecSmrg 34235c4bbdfSmrg return TRUE; 34305b261ecSmrg} 34405b261ecSmrg 34505b261ecSmrgstatic FBAreaPtr 34635c4bbdfSmrgAllocateArea(FBManagerPtr offman, 34735c4bbdfSmrg int w, int h, 34835c4bbdfSmrg int granularity, 34935c4bbdfSmrg MoveAreaCallbackProcPtr moveCB, 35035c4bbdfSmrg RemoveAreaCallbackProcPtr removeCB, void *privData) 35135c4bbdfSmrg{ 35235c4bbdfSmrg ScreenPtr pScreen = offman->pScreen; 35335c4bbdfSmrg FBLinkPtr link = NULL; 35435c4bbdfSmrg FBAreaPtr area = NULL; 35535c4bbdfSmrg RegionRec NewReg; 35635c4bbdfSmrg int i, x = 0, num; 35735c4bbdfSmrg BoxPtr boxp; 35835c4bbdfSmrg 35935c4bbdfSmrg if (granularity <= 1) 36035c4bbdfSmrg granularity = 0; 36135c4bbdfSmrg 36235c4bbdfSmrg boxp = RegionRects(offman->FreeBoxes); 36335c4bbdfSmrg num = RegionNumRects(offman->FreeBoxes); 36435c4bbdfSmrg 36535c4bbdfSmrg /* look through the free boxes */ 36635c4bbdfSmrg for (i = 0; i < num; i++, boxp++) { 36735c4bbdfSmrg x = boxp->x1; 36835c4bbdfSmrg if (granularity > 1) 36935c4bbdfSmrg x = ((x + granularity - 1) / granularity) * granularity; 37035c4bbdfSmrg 37135c4bbdfSmrg if (((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w)) 37235c4bbdfSmrg continue; 37335c4bbdfSmrg 37435c4bbdfSmrg link = malloc(sizeof(FBLink)); 37535c4bbdfSmrg if (!link) 37635c4bbdfSmrg return NULL; 37705b261ecSmrg 37805b261ecSmrg area = &(link->area); 37905b261ecSmrg link->next = offman->UsedAreas; 38005b261ecSmrg offman->UsedAreas = link; 38105b261ecSmrg offman->NumUsedAreas++; 38235c4bbdfSmrg break; 38335c4bbdfSmrg } 38435c4bbdfSmrg 385ed6184dfSmrg /* try to boot a removable one out if we are not expendable ourselves */ 38635c4bbdfSmrg if (!area && !removeCB) { 38735c4bbdfSmrg link = offman->UsedAreas; 38835c4bbdfSmrg 38935c4bbdfSmrg while (link) { 39035c4bbdfSmrg if (!link->area.RemoveAreaCallback) { 39135c4bbdfSmrg link = link->next; 39235c4bbdfSmrg continue; 39335c4bbdfSmrg } 39435c4bbdfSmrg 39535c4bbdfSmrg boxp = &(link->area.box); 39635c4bbdfSmrg x = boxp->x1; 39735c4bbdfSmrg if (granularity > 1) 39835c4bbdfSmrg x = ((x + granularity - 1) / granularity) * granularity; 39935c4bbdfSmrg 40035c4bbdfSmrg if (((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w)) { 40135c4bbdfSmrg link = link->next; 40235c4bbdfSmrg continue; 40335c4bbdfSmrg } 40435c4bbdfSmrg 40535c4bbdfSmrg /* bye, bye */ 40635c4bbdfSmrg (*link->area.RemoveAreaCallback) (&link->area); 40735c4bbdfSmrg RegionInit(&NewReg, &(link->area.box), 1); 40835c4bbdfSmrg RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &NewReg); 40935c4bbdfSmrg RegionUninit(&NewReg); 41035c4bbdfSmrg 41135c4bbdfSmrg area = &(link->area); 41235c4bbdfSmrg break; 41335c4bbdfSmrg } 41435c4bbdfSmrg } 41535c4bbdfSmrg 41635c4bbdfSmrg if (area) { 41735c4bbdfSmrg area->pScreen = pScreen; 41835c4bbdfSmrg area->granularity = granularity; 41935c4bbdfSmrg area->box.x1 = x; 42035c4bbdfSmrg area->box.x2 = x + w; 42135c4bbdfSmrg area->box.y1 = boxp->y1; 42235c4bbdfSmrg area->box.y2 = boxp->y1 + h; 42335c4bbdfSmrg area->MoveAreaCallback = moveCB; 42435c4bbdfSmrg area->RemoveAreaCallback = removeCB; 42535c4bbdfSmrg area->devPrivate.ptr = privData; 42605b261ecSmrg 4276747b715Smrg RegionInit(&NewReg, &(area->box), 1); 42835c4bbdfSmrg RegionSubtract(offman->FreeBoxes, offman->FreeBoxes, &NewReg); 42935c4bbdfSmrg RegionUninit(&NewReg); 43035c4bbdfSmrg } 43105b261ecSmrg 43235c4bbdfSmrg return area; 43305b261ecSmrg} 43405b261ecSmrg 43505b261ecSmrgstatic FBAreaPtr 43635c4bbdfSmrglocalAllocateOffscreenArea(ScreenPtr pScreen, 43735c4bbdfSmrg int w, int h, 43835c4bbdfSmrg int gran, 43935c4bbdfSmrg MoveAreaCallbackProcPtr moveCB, 44035c4bbdfSmrg RemoveAreaCallbackProcPtr removeCB, void *privData) 44135c4bbdfSmrg{ 44235c4bbdfSmrg FBManagerPtr offman; 44335c4bbdfSmrg FBAreaPtr area = NULL; 44405b261ecSmrg 44535c4bbdfSmrg offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 44635c4bbdfSmrg xf86FBScreenKey); 44735c4bbdfSmrg if ((area = AllocateArea(offman, w, h, gran, moveCB, removeCB, privData))) 44835c4bbdfSmrg SendCallFreeBoxCallbacks(offman); 44935c4bbdfSmrg 45035c4bbdfSmrg return area; 45135c4bbdfSmrg} 45205b261ecSmrg 45305b261ecSmrgstatic void 45405b261ecSmrglocalFreeOffscreenArea(FBAreaPtr area) 45505b261ecSmrg{ 45635c4bbdfSmrg FBManagerPtr offman; 45735c4bbdfSmrg FBLinkPtr pLink, pLinkPrev = NULL; 45835c4bbdfSmrg RegionRec FreedRegion; 45935c4bbdfSmrg ScreenPtr pScreen; 46035c4bbdfSmrg 46135c4bbdfSmrg pScreen = area->pScreen; 46235c4bbdfSmrg offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 46335c4bbdfSmrg xf86FBScreenKey); 46435c4bbdfSmrg pLink = offman->UsedAreas; 46535c4bbdfSmrg if (!pLink) 46635c4bbdfSmrg return; 46735c4bbdfSmrg 46835c4bbdfSmrg while (&(pLink->area) != area) { 46935c4bbdfSmrg pLinkPrev = pLink; 47035c4bbdfSmrg pLink = pLink->next; 47135c4bbdfSmrg if (!pLink) 47235c4bbdfSmrg return; 47335c4bbdfSmrg } 47435c4bbdfSmrg 47535c4bbdfSmrg /* put the area back into the pool */ 47635c4bbdfSmrg RegionInit(&FreedRegion, &(pLink->area.box), 1); 47735c4bbdfSmrg RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &FreedRegion); 47835c4bbdfSmrg RegionUninit(&FreedRegion); 47935c4bbdfSmrg 48035c4bbdfSmrg if (pLinkPrev) 48135c4bbdfSmrg pLinkPrev->next = pLink->next; 48235c4bbdfSmrg else 48335c4bbdfSmrg offman->UsedAreas = pLink->next; 48405b261ecSmrg 48535c4bbdfSmrg free(pLink); 48635c4bbdfSmrg offman->NumUsedAreas--; 48735c4bbdfSmrg 48835c4bbdfSmrg SendCallFreeBoxCallbacks(offman); 48935c4bbdfSmrg} 49005b261ecSmrg 49105b261ecSmrgstatic Bool 49235c4bbdfSmrglocalResizeOffscreenArea(FBAreaPtr resize, int w, int h) 49335c4bbdfSmrg{ 49435c4bbdfSmrg FBManagerPtr offman; 49535c4bbdfSmrg ScreenPtr pScreen; 49635c4bbdfSmrg BoxRec OrigArea; 49735c4bbdfSmrg RegionRec FreedReg; 49835c4bbdfSmrg FBAreaPtr area = NULL; 49935c4bbdfSmrg FBLinkPtr pLink, newLink, pLinkPrev = NULL; 50035c4bbdfSmrg 50135c4bbdfSmrg pScreen = resize->pScreen; 50235c4bbdfSmrg offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 50335c4bbdfSmrg xf86FBScreenKey); 50435c4bbdfSmrg /* find this link */ 50535c4bbdfSmrg if (!(pLink = offman->UsedAreas)) 50635c4bbdfSmrg return FALSE; 50735c4bbdfSmrg 50835c4bbdfSmrg while (&(pLink->area) != resize) { 50935c4bbdfSmrg pLinkPrev = pLink; 51035c4bbdfSmrg pLink = pLink->next; 51135c4bbdfSmrg if (!pLink) 51235c4bbdfSmrg return FALSE; 51335c4bbdfSmrg } 51435c4bbdfSmrg 51535c4bbdfSmrg OrigArea.x1 = resize->box.x1; 51635c4bbdfSmrg OrigArea.x2 = resize->box.x2; 51735c4bbdfSmrg OrigArea.y1 = resize->box.y1; 51835c4bbdfSmrg OrigArea.y2 = resize->box.y2; 51935c4bbdfSmrg 52035c4bbdfSmrg /* if it's smaller, this is easy */ 52135c4bbdfSmrg 52235c4bbdfSmrg if ((w <= (resize->box.x2 - resize->box.x1)) && 52335c4bbdfSmrg (h <= (resize->box.y2 - resize->box.y1))) { 52435c4bbdfSmrg RegionRec NewReg; 52535c4bbdfSmrg 52635c4bbdfSmrg resize->box.x2 = resize->box.x1 + w; 52735c4bbdfSmrg resize->box.y2 = resize->box.y1 + h; 52835c4bbdfSmrg 52935c4bbdfSmrg if ((resize->box.y2 == OrigArea.y2) && (resize->box.x2 == OrigArea.x2)) 53035c4bbdfSmrg return TRUE; 53135c4bbdfSmrg 53235c4bbdfSmrg RegionInit(&FreedReg, &OrigArea, 1); 53335c4bbdfSmrg RegionInit(&NewReg, &(resize->box), 1); 53435c4bbdfSmrg RegionSubtract(&FreedReg, &FreedReg, &NewReg); 53535c4bbdfSmrg RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &FreedReg); 53635c4bbdfSmrg RegionUninit(&FreedReg); 53735c4bbdfSmrg RegionUninit(&NewReg); 53835c4bbdfSmrg 53935c4bbdfSmrg SendCallFreeBoxCallbacks(offman); 54035c4bbdfSmrg 54135c4bbdfSmrg return TRUE; 54235c4bbdfSmrg } 54335c4bbdfSmrg 54435c4bbdfSmrg /* otherwise we remove the old region */ 54535c4bbdfSmrg 54635c4bbdfSmrg RegionInit(&FreedReg, &OrigArea, 1); 54735c4bbdfSmrg RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &FreedReg); 54835c4bbdfSmrg 54935c4bbdfSmrg /* remove the old link */ 55035c4bbdfSmrg if (pLinkPrev) 55135c4bbdfSmrg pLinkPrev->next = pLink->next; 55235c4bbdfSmrg else 55335c4bbdfSmrg offman->UsedAreas = pLink->next; 55435c4bbdfSmrg 55535c4bbdfSmrg /* and try to add a new one */ 55635c4bbdfSmrg 55735c4bbdfSmrg if ((area = AllocateArea(offman, w, h, resize->granularity, 55835c4bbdfSmrg resize->MoveAreaCallback, 55935c4bbdfSmrg resize->RemoveAreaCallback, 56035c4bbdfSmrg resize->devPrivate.ptr))) { 56105b261ecSmrg 56205b261ecSmrg /* copy data over to our link and replace the new with old */ 56335c4bbdfSmrg memcpy(resize, area, sizeof(FBArea)); 56405b261ecSmrg 56505b261ecSmrg pLinkPrev = NULL; 56635c4bbdfSmrg newLink = offman->UsedAreas; 56705b261ecSmrg 56835c4bbdfSmrg while (&(newLink->area) != area) { 56935c4bbdfSmrg pLinkPrev = newLink; 57035c4bbdfSmrg newLink = newLink->next; 57105b261ecSmrg } 57205b261ecSmrg 57335c4bbdfSmrg if (pLinkPrev) 57435c4bbdfSmrg pLinkPrev->next = newLink->next; 57535c4bbdfSmrg else 57635c4bbdfSmrg offman->UsedAreas = newLink->next; 57705b261ecSmrg 57805b261ecSmrg pLink->next = offman->UsedAreas; 57905b261ecSmrg offman->UsedAreas = pLink; 58005b261ecSmrg 58135c4bbdfSmrg free(newLink); 58205b261ecSmrg 58335c4bbdfSmrg /* AllocateArea added one but we really only exchanged one */ 58435c4bbdfSmrg offman->NumUsedAreas--; 58535c4bbdfSmrg } 58635c4bbdfSmrg else { 58735c4bbdfSmrg /* reinstate the old region */ 58835c4bbdfSmrg RegionSubtract(offman->FreeBoxes, offman->FreeBoxes, &FreedReg); 58935c4bbdfSmrg RegionUninit(&FreedReg); 59005b261ecSmrg 59135c4bbdfSmrg pLink->next = offman->UsedAreas; 59235c4bbdfSmrg offman->UsedAreas = pLink; 59335c4bbdfSmrg return FALSE; 59435c4bbdfSmrg } 59505b261ecSmrg 59635c4bbdfSmrg RegionUninit(&FreedReg); 59705b261ecSmrg 59835c4bbdfSmrg SendCallFreeBoxCallbacks(offman); 59905b261ecSmrg 60035c4bbdfSmrg return TRUE; 60105b261ecSmrg} 60205b261ecSmrg 60305b261ecSmrgstatic Bool 60435c4bbdfSmrglocalQueryLargestOffscreenArea(ScreenPtr pScreen, 60535c4bbdfSmrg int *width, int *height, 60635c4bbdfSmrg int granularity, int preferences, int severity) 60735c4bbdfSmrg{ 60805b261ecSmrg FBManagerPtr offman; 60905b261ecSmrg RegionPtr newRegion = NULL; 61005b261ecSmrg BoxPtr pbox; 61105b261ecSmrg int nbox; 61205b261ecSmrg int x, w, h, area, oldArea; 61305b261ecSmrg 61405b261ecSmrg *width = *height = oldArea = 0; 61505b261ecSmrg 61635c4bbdfSmrg if (granularity <= 1) 61735c4bbdfSmrg granularity = 0; 61805b261ecSmrg 61935c4bbdfSmrg if ((preferences < 0) || (preferences > 3)) 62035c4bbdfSmrg return FALSE; 62105b261ecSmrg 62235c4bbdfSmrg offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 62335c4bbdfSmrg xf86FBScreenKey); 62435c4bbdfSmrg if (severity < 0) 62535c4bbdfSmrg severity = 0; 62635c4bbdfSmrg if (severity > 2) 62735c4bbdfSmrg severity = 2; 62805b261ecSmrg 62935c4bbdfSmrg switch (severity) { 63005b261ecSmrg case 2: 63135c4bbdfSmrg if (offman->NumUsedAreas) { 63235c4bbdfSmrg FBLinkPtr pLink; 63335c4bbdfSmrg RegionRec tmpRegion; 63435c4bbdfSmrg 63535c4bbdfSmrg newRegion = RegionCreate(NULL, 1); 63635c4bbdfSmrg RegionCopy(newRegion, offman->InitialBoxes); 63735c4bbdfSmrg pLink = offman->UsedAreas; 63835c4bbdfSmrg 63935c4bbdfSmrg while (pLink) { 64035c4bbdfSmrg if (!pLink->area.RemoveAreaCallback) { 64135c4bbdfSmrg RegionInit(&tmpRegion, &(pLink->area.box), 1); 64235c4bbdfSmrg RegionSubtract(newRegion, newRegion, &tmpRegion); 64335c4bbdfSmrg RegionUninit(&tmpRegion); 64435c4bbdfSmrg } 64535c4bbdfSmrg pLink = pLink->next; 64635c4bbdfSmrg } 64735c4bbdfSmrg 64835c4bbdfSmrg nbox = RegionNumRects(newRegion); 64935c4bbdfSmrg pbox = RegionRects(newRegion); 65035c4bbdfSmrg break; 65135c4bbdfSmrg } 65205b261ecSmrg case 1: 65335c4bbdfSmrg if (offman->NumUsedAreas) { 65435c4bbdfSmrg FBLinkPtr pLink; 65535c4bbdfSmrg RegionRec tmpRegion; 65635c4bbdfSmrg 65735c4bbdfSmrg newRegion = RegionCreate(NULL, 1); 65835c4bbdfSmrg RegionCopy(newRegion, offman->FreeBoxes); 65935c4bbdfSmrg pLink = offman->UsedAreas; 66035c4bbdfSmrg 66135c4bbdfSmrg while (pLink) { 66235c4bbdfSmrg if (pLink->area.RemoveAreaCallback) { 66335c4bbdfSmrg RegionInit(&tmpRegion, &(pLink->area.box), 1); 66435c4bbdfSmrg RegionAppend(newRegion, &tmpRegion); 66535c4bbdfSmrg RegionUninit(&tmpRegion); 66635c4bbdfSmrg } 66735c4bbdfSmrg pLink = pLink->next; 66835c4bbdfSmrg } 66935c4bbdfSmrg 67035c4bbdfSmrg nbox = RegionNumRects(newRegion); 67135c4bbdfSmrg pbox = RegionRects(newRegion); 67235c4bbdfSmrg break; 67335c4bbdfSmrg } 67405b261ecSmrg default: 67535c4bbdfSmrg nbox = RegionNumRects(offman->FreeBoxes); 67635c4bbdfSmrg pbox = RegionRects(offman->FreeBoxes); 67735c4bbdfSmrg break; 67805b261ecSmrg } 67905b261ecSmrg 68035c4bbdfSmrg while (nbox--) { 68135c4bbdfSmrg x = pbox->x1; 68235c4bbdfSmrg if (granularity > 1) 68335c4bbdfSmrg x = ((x + granularity - 1) / granularity) * granularity; 68435c4bbdfSmrg 68535c4bbdfSmrg w = pbox->x2 - x; 68635c4bbdfSmrg h = pbox->y2 - pbox->y1; 68735c4bbdfSmrg area = w * h; 68835c4bbdfSmrg 68935c4bbdfSmrg if (w > 0) { 69035c4bbdfSmrg Bool gotIt = FALSE; 69135c4bbdfSmrg 69235c4bbdfSmrg switch (preferences) { 69335c4bbdfSmrg case FAVOR_AREA_THEN_WIDTH: 69435c4bbdfSmrg if ((area > oldArea) || ((area == oldArea) && (w > *width))) 69535c4bbdfSmrg gotIt = TRUE; 69635c4bbdfSmrg break; 69735c4bbdfSmrg case FAVOR_AREA_THEN_HEIGHT: 69835c4bbdfSmrg if ((area > oldArea) || ((area == oldArea) && (h > *height))) 69935c4bbdfSmrg gotIt = TRUE; 70035c4bbdfSmrg break; 70135c4bbdfSmrg case FAVOR_WIDTH_THEN_AREA: 70235c4bbdfSmrg if ((w > *width) || ((w == *width) && (area > oldArea))) 70335c4bbdfSmrg gotIt = TRUE; 70435c4bbdfSmrg break; 70535c4bbdfSmrg case FAVOR_HEIGHT_THEN_AREA: 70635c4bbdfSmrg if ((h > *height) || ((h == *height) && (area > oldArea))) 70735c4bbdfSmrg gotIt = TRUE; 70835c4bbdfSmrg break; 70935c4bbdfSmrg } 71035c4bbdfSmrg if (gotIt) { 71135c4bbdfSmrg *width = w; 71235c4bbdfSmrg *height = h; 71335c4bbdfSmrg oldArea = area; 71435c4bbdfSmrg } 71505b261ecSmrg } 71635c4bbdfSmrg pbox++; 71705b261ecSmrg } 71805b261ecSmrg 71935c4bbdfSmrg if (newRegion) 72035c4bbdfSmrg RegionDestroy(newRegion); 72105b261ecSmrg 72205b261ecSmrg return TRUE; 72305b261ecSmrg} 72405b261ecSmrg 72505b261ecSmrgstatic Bool 72605b261ecSmrglocalPurgeUnlockedOffscreenAreas(ScreenPtr pScreen) 72705b261ecSmrg{ 72835c4bbdfSmrg FBManagerPtr offman; 72935c4bbdfSmrg FBLinkPtr pLink, tmp, pPrev = NULL; 73035c4bbdfSmrg RegionRec FreedRegion; 73135c4bbdfSmrg Bool anyUsed = FALSE; 73235c4bbdfSmrg 73335c4bbdfSmrg offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 73435c4bbdfSmrg xf86FBScreenKey); 73535c4bbdfSmrg pLink = offman->UsedAreas; 73635c4bbdfSmrg if (!pLink) 73735c4bbdfSmrg return TRUE; 73835c4bbdfSmrg 73935c4bbdfSmrg while (pLink) { 74035c4bbdfSmrg if (pLink->area.RemoveAreaCallback) { 74135c4bbdfSmrg (*pLink->area.RemoveAreaCallback) (&pLink->area); 74235c4bbdfSmrg 74335c4bbdfSmrg RegionInit(&FreedRegion, &(pLink->area.box), 1); 74435c4bbdfSmrg RegionAppend(offman->FreeBoxes, &FreedRegion); 74535c4bbdfSmrg RegionUninit(&FreedRegion); 74635c4bbdfSmrg 74735c4bbdfSmrg if (pPrev) 74835c4bbdfSmrg pPrev->next = pLink->next; 74935c4bbdfSmrg else 75035c4bbdfSmrg offman->UsedAreas = pLink->next; 75135c4bbdfSmrg 75235c4bbdfSmrg tmp = pLink; 75335c4bbdfSmrg pLink = pLink->next; 7546747b715Smrg free(tmp); 75535c4bbdfSmrg offman->NumUsedAreas--; 75635c4bbdfSmrg anyUsed = TRUE; 75735c4bbdfSmrg } 75835c4bbdfSmrg else { 75935c4bbdfSmrg pPrev = pLink; 76035c4bbdfSmrg pLink = pLink->next; 76135c4bbdfSmrg } 76235c4bbdfSmrg } 76335c4bbdfSmrg 76435c4bbdfSmrg if (anyUsed) { 76535c4bbdfSmrg RegionValidate(offman->FreeBoxes, &anyUsed); 76635c4bbdfSmrg SendCallFreeBoxCallbacks(offman); 76735c4bbdfSmrg } 76835c4bbdfSmrg 76935c4bbdfSmrg return TRUE; 77005b261ecSmrg} 77105b261ecSmrg 77235c4bbdfSmrgstatic void 77305b261ecSmrgLinearMoveCBWrapper(FBAreaPtr from, FBAreaPtr to) 77405b261ecSmrg{ 77505b261ecSmrg /* this will never get called */ 77605b261ecSmrg} 77705b261ecSmrg 77835c4bbdfSmrgstatic void 77905b261ecSmrgLinearRemoveCBWrapper(FBAreaPtr area) 78005b261ecSmrg{ 78135c4bbdfSmrg FBManagerPtr offman; 78235c4bbdfSmrg FBLinearLinkPtr pLink, pLinkPrev = NULL; 78335c4bbdfSmrg ScreenPtr pScreen = area->pScreen; 78435c4bbdfSmrg 78535c4bbdfSmrg offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 78635c4bbdfSmrg xf86FBScreenKey); 78735c4bbdfSmrg pLink = offman->LinearAreas; 78835c4bbdfSmrg if (!pLink) 78935c4bbdfSmrg return; 79035c4bbdfSmrg 79135c4bbdfSmrg while (pLink->area != area) { 79205b261ecSmrg pLinkPrev = pLink; 79305b261ecSmrg pLink = pLink->next; 79435c4bbdfSmrg if (!pLink) 79535c4bbdfSmrg return; 79635c4bbdfSmrg } 79705b261ecSmrg 79835c4bbdfSmrg /* give the user the callback it is expecting */ 79935c4bbdfSmrg (*pLink->linear.RemoveLinearCallback) (&(pLink->linear)); 80005b261ecSmrg 80135c4bbdfSmrg if (pLinkPrev) 80205b261ecSmrg pLinkPrev->next = pLink->next; 80335c4bbdfSmrg else 80435c4bbdfSmrg offman->LinearAreas = pLink->next; 80505b261ecSmrg 80635c4bbdfSmrg free(pLink); 80705b261ecSmrg} 80805b261ecSmrg 80905b261ecSmrgstatic void 8106747b715SmrgDumpDebug(FBLinearLinkPtr pLink) 81105b261ecSmrg{ 8126747b715Smrg#ifdef DEBUG 81335c4bbdfSmrg if (!pLink) 81435c4bbdfSmrg ErrorF("MMmm, PLINK IS NULL!\n"); 81505b261ecSmrg 81635c4bbdfSmrg while (pLink) { 81735c4bbdfSmrg ErrorF(" Offset:%08x, Size:%08x, %s,%s\n", 81835c4bbdfSmrg pLink->linear.offset, 81935c4bbdfSmrg pLink->linear.size, 82035c4bbdfSmrg pLink->free ? "Free" : "Used", pLink->area ? "Area" : "Linear"); 82105b261ecSmrg 82235c4bbdfSmrg pLink = pLink->next; 82335c4bbdfSmrg } 82405b261ecSmrg#endif 8256747b715Smrg} 82605b261ecSmrg 82705b261ecSmrgstatic FBLinearPtr 82835c4bbdfSmrgAllocateLinear(FBManagerPtr offman, int size, int granularity, void *privData) 82935c4bbdfSmrg{ 83035c4bbdfSmrg ScreenPtr pScreen = offman->pScreen; 83135c4bbdfSmrg FBLinearLinkPtr linear = NULL; 83235c4bbdfSmrg FBLinearLinkPtr newlink = NULL; 83335c4bbdfSmrg int offset, end; 83435c4bbdfSmrg 83535c4bbdfSmrg if (size <= 0) 83635c4bbdfSmrg return NULL; 83735c4bbdfSmrg 83835c4bbdfSmrg if (!offman->LinearAreas) 83935c4bbdfSmrg return NULL; 84035c4bbdfSmrg 84135c4bbdfSmrg linear = offman->LinearAreas; 84235c4bbdfSmrg while (linear) { 84335c4bbdfSmrg /* Make sure we get a free area that's not an XY fallback case */ 84435c4bbdfSmrg if (!linear->area && linear->free) { 84535c4bbdfSmrg offset = linear->linear.offset; 84635c4bbdfSmrg if (granularity > 1) 84735c4bbdfSmrg offset = 84835c4bbdfSmrg ((offset + granularity - 1) / granularity) * granularity; 84935c4bbdfSmrg end = offset + size; 85035c4bbdfSmrg if (end <= (linear->linear.offset + linear->linear.size)) 85135c4bbdfSmrg break; 85235c4bbdfSmrg } 85335c4bbdfSmrg linear = linear->next; 85435c4bbdfSmrg } 85535c4bbdfSmrg if (!linear) 85635c4bbdfSmrg return NULL; 85735c4bbdfSmrg 85835c4bbdfSmrg /* break left */ 85935c4bbdfSmrg if (offset > linear->linear.offset) { 86035c4bbdfSmrg newlink = malloc(sizeof(FBLinearLink)); 86135c4bbdfSmrg if (!newlink) 86235c4bbdfSmrg return NULL; 86335c4bbdfSmrg newlink->area = NULL; 86435c4bbdfSmrg newlink->linear.offset = offset; 86535c4bbdfSmrg newlink->linear.size = 86635c4bbdfSmrg linear->linear.size - (offset - linear->linear.offset); 86735c4bbdfSmrg newlink->free = 1; 86835c4bbdfSmrg newlink->next = linear->next; 86935c4bbdfSmrg linear->linear.size -= newlink->linear.size; 87035c4bbdfSmrg linear->next = newlink; 87135c4bbdfSmrg linear = newlink; 87235c4bbdfSmrg } 87335c4bbdfSmrg 87435c4bbdfSmrg /* break right */ 87535c4bbdfSmrg if (size < linear->linear.size) { 87635c4bbdfSmrg newlink = malloc(sizeof(FBLinearLink)); 87735c4bbdfSmrg if (!newlink) 87835c4bbdfSmrg return NULL; 87935c4bbdfSmrg newlink->area = NULL; 88035c4bbdfSmrg newlink->linear.offset = offset + size; 88135c4bbdfSmrg newlink->linear.size = linear->linear.size - size; 88235c4bbdfSmrg newlink->free = 1; 88335c4bbdfSmrg newlink->next = linear->next; 88435c4bbdfSmrg linear->linear.size = size; 88535c4bbdfSmrg linear->next = newlink; 88635c4bbdfSmrg } 88735c4bbdfSmrg 88835c4bbdfSmrg /* p = middle block */ 88935c4bbdfSmrg linear->linear.granularity = granularity; 89035c4bbdfSmrg linear->free = 0; 89135c4bbdfSmrg linear->linear.pScreen = pScreen; 89235c4bbdfSmrg linear->linear.MoveLinearCallback = NULL; 89335c4bbdfSmrg linear->linear.RemoveLinearCallback = NULL; 89435c4bbdfSmrg linear->linear.devPrivate.ptr = NULL; 89535c4bbdfSmrg 89635c4bbdfSmrg DumpDebug(offman->LinearAreas); 89735c4bbdfSmrg 89835c4bbdfSmrg return &(linear->linear); 89905b261ecSmrg} 90005b261ecSmrg 90105b261ecSmrgstatic FBLinearPtr 90235c4bbdfSmrglocalAllocateOffscreenLinear(ScreenPtr pScreen, 90335c4bbdfSmrg int length, 90435c4bbdfSmrg int gran, 90535c4bbdfSmrg MoveLinearCallbackProcPtr moveCB, 90635c4bbdfSmrg RemoveLinearCallbackProcPtr removeCB, 90735c4bbdfSmrg void *privData) 90835c4bbdfSmrg{ 90935c4bbdfSmrg FBManagerPtr offman; 91035c4bbdfSmrg FBLinearLinkPtr link; 91135c4bbdfSmrg FBAreaPtr area; 91235c4bbdfSmrg FBLinearPtr linear = NULL; 91335c4bbdfSmrg BoxPtr extents; 91435c4bbdfSmrg int w, h, pitch; 91535c4bbdfSmrg 91635c4bbdfSmrg offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 91735c4bbdfSmrg xf86FBScreenKey); 91835c4bbdfSmrg 91935c4bbdfSmrg /* Try to allocate from linear memory first...... */ 92035c4bbdfSmrg DebugF("ALLOCATING LINEAR\n"); 92135c4bbdfSmrg if ((linear = AllocateLinear(offman, length, gran, privData))) 92235c4bbdfSmrg return linear; 92335c4bbdfSmrg 92435c4bbdfSmrg DebugF("NOPE, ALLOCATING AREA\n"); 92535c4bbdfSmrg 92635c4bbdfSmrg if (!(link = malloc(sizeof(FBLinearLink)))) 92735c4bbdfSmrg return NULL; 92835c4bbdfSmrg 92935c4bbdfSmrg /* No linear available, so try and pinch some from the XY areas */ 93035c4bbdfSmrg extents = RegionExtents(offman->InitialBoxes); 93135c4bbdfSmrg pitch = extents->x2 - extents->x1; 93235c4bbdfSmrg 93335c4bbdfSmrg if (gran > 1) { 93405b261ecSmrg if (gran > pitch) { 93505b261ecSmrg /* we can't match the specified alignment with XY allocations */ 9366747b715Smrg free(link); 93705b261ecSmrg return NULL; 93805b261ecSmrg } 93905b261ecSmrg 94005b261ecSmrg if (pitch % gran) { 94105b261ecSmrg /* pitch and granularity aren't a perfect match, let's allocate 94205b261ecSmrg * a bit more so we can align later on 94305b261ecSmrg */ 94405b261ecSmrg length += gran - 1; 94505b261ecSmrg } 94605b261ecSmrg } 94705b261ecSmrg 94835c4bbdfSmrg if (length < pitch) { /* special case */ 94935c4bbdfSmrg w = length; 95035c4bbdfSmrg h = 1; 95135c4bbdfSmrg } 95235c4bbdfSmrg else { 95335c4bbdfSmrg w = pitch; 95435c4bbdfSmrg h = (length + pitch - 1) / pitch; 95535c4bbdfSmrg } 95635c4bbdfSmrg 95735c4bbdfSmrg if ((area = localAllocateOffscreenArea(pScreen, w, h, gran, 95835c4bbdfSmrg moveCB ? LinearMoveCBWrapper : NULL, 95935c4bbdfSmrg removeCB ? LinearRemoveCBWrapper : 96035c4bbdfSmrg NULL, privData))) { 96135c4bbdfSmrg link->area = area; 96235c4bbdfSmrg link->free = 0; 96335c4bbdfSmrg link->next = offman->LinearAreas; 96435c4bbdfSmrg offman->LinearAreas = link; 96535c4bbdfSmrg linear = &(link->linear); 96635c4bbdfSmrg linear->pScreen = pScreen; 96735c4bbdfSmrg linear->size = h * w; 96835c4bbdfSmrg linear->offset = (pitch * area->box.y1) + area->box.x1; 96935c4bbdfSmrg if (gran > 1) 97005b261ecSmrg linear->offset = ((linear->offset + gran - 1) / gran) * gran; 97135c4bbdfSmrg linear->granularity = gran; 97235c4bbdfSmrg linear->MoveLinearCallback = moveCB; 97335c4bbdfSmrg linear->RemoveLinearCallback = removeCB; 97435c4bbdfSmrg linear->devPrivate.ptr = privData; 97535c4bbdfSmrg } 97635c4bbdfSmrg else 97735c4bbdfSmrg free(link); 97805b261ecSmrg 97935c4bbdfSmrg DumpDebug(offman->LinearAreas); 98005b261ecSmrg 98135c4bbdfSmrg return linear; 98205b261ecSmrg} 98305b261ecSmrg 98435c4bbdfSmrgstatic void 98505b261ecSmrglocalFreeOffscreenLinear(FBLinearPtr linear) 98605b261ecSmrg{ 98735c4bbdfSmrg FBManagerPtr offman; 98835c4bbdfSmrg FBLinearLinkPtr pLink, pLinkPrev = NULL; 98935c4bbdfSmrg ScreenPtr pScreen = linear->pScreen; 99035c4bbdfSmrg 99135c4bbdfSmrg offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 99235c4bbdfSmrg xf86FBScreenKey); 99335c4bbdfSmrg pLink = offman->LinearAreas; 99435c4bbdfSmrg if (!pLink) 99535c4bbdfSmrg return; 99635c4bbdfSmrg 99735c4bbdfSmrg while (&(pLink->linear) != linear) { 99805b261ecSmrg pLinkPrev = pLink; 99905b261ecSmrg pLink = pLink->next; 100035c4bbdfSmrg if (!pLink) 100135c4bbdfSmrg return; 100235c4bbdfSmrg } 100335c4bbdfSmrg 100435c4bbdfSmrg if (pLink->area) { /* really an XY area */ 100535c4bbdfSmrg DebugF("FREEING AREA\n"); 100635c4bbdfSmrg localFreeOffscreenArea(pLink->area); 100735c4bbdfSmrg if (pLinkPrev) 100835c4bbdfSmrg pLinkPrev->next = pLink->next; 100935c4bbdfSmrg else 101035c4bbdfSmrg offman->LinearAreas = pLink->next; 10116747b715Smrg free(pLink); 101235c4bbdfSmrg DumpDebug(offman->LinearAreas); 101335c4bbdfSmrg return; 101435c4bbdfSmrg } 101505b261ecSmrg 101635c4bbdfSmrg pLink->free = 1; 101705b261ecSmrg 101835c4bbdfSmrg if (pLink->next && pLink->next->free) { 101935c4bbdfSmrg FBLinearLinkPtr p = pLink->next; 102035c4bbdfSmrg 102135c4bbdfSmrg pLink->linear.size += p->linear.size; 102235c4bbdfSmrg pLink->next = p->next; 102335c4bbdfSmrg free(p); 102435c4bbdfSmrg } 102535c4bbdfSmrg 102635c4bbdfSmrg if (pLinkPrev) { 102735c4bbdfSmrg if (pLinkPrev->next && pLinkPrev->next->free && !pLinkPrev->area) { 102835c4bbdfSmrg FBLinearLinkPtr p = pLinkPrev->next; 102935c4bbdfSmrg 103035c4bbdfSmrg pLinkPrev->linear.size += p->linear.size; 103135c4bbdfSmrg pLinkPrev->next = p->next; 103235c4bbdfSmrg free(p); 103335c4bbdfSmrg } 103435c4bbdfSmrg } 103535c4bbdfSmrg 103635c4bbdfSmrg DebugF("FREEING LINEAR\n"); 103735c4bbdfSmrg DumpDebug(offman->LinearAreas); 103835c4bbdfSmrg} 103935c4bbdfSmrg 104035c4bbdfSmrgstatic Bool 104105b261ecSmrglocalResizeOffscreenLinear(FBLinearPtr resize, int length) 104205b261ecSmrg{ 104335c4bbdfSmrg FBManagerPtr offman; 104435c4bbdfSmrg FBLinearLinkPtr pLink; 104535c4bbdfSmrg ScreenPtr pScreen = resize->pScreen; 104635c4bbdfSmrg 104735c4bbdfSmrg offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 104835c4bbdfSmrg xf86FBScreenKey); 104935c4bbdfSmrg pLink = offman->LinearAreas; 105035c4bbdfSmrg if (!pLink) 105135c4bbdfSmrg return FALSE; 105235c4bbdfSmrg 105335c4bbdfSmrg while (&(pLink->linear) != resize) { 105405b261ecSmrg pLink = pLink->next; 105535c4bbdfSmrg if (!pLink) 105635c4bbdfSmrg return FALSE; 105735c4bbdfSmrg } 105835c4bbdfSmrg 1059ed6184dfSmrg /* This could actually be a lot smarter and try to move allocations 106035c4bbdfSmrg from XY to linear when available. For now if it was XY, we keep 106135c4bbdfSmrg it XY */ 106235c4bbdfSmrg 106335c4bbdfSmrg if (pLink->area) { /* really an XY area */ 106435c4bbdfSmrg BoxPtr extents; 106535c4bbdfSmrg int pitch, w, h; 106635c4bbdfSmrg 106735c4bbdfSmrg extents = RegionExtents(offman->InitialBoxes); 106835c4bbdfSmrg pitch = extents->x2 - extents->x1; 106935c4bbdfSmrg 107035c4bbdfSmrg if (length < pitch) { /* special case */ 107135c4bbdfSmrg w = length; 107235c4bbdfSmrg h = 1; 107335c4bbdfSmrg } 107435c4bbdfSmrg else { 107535c4bbdfSmrg w = pitch; 107635c4bbdfSmrg h = (length + pitch - 1) / pitch; 107735c4bbdfSmrg } 107805b261ecSmrg 107935c4bbdfSmrg if (localResizeOffscreenArea(pLink->area, w, h)) { 108035c4bbdfSmrg resize->size = h * w; 108135c4bbdfSmrg resize->offset = 108235c4bbdfSmrg (pitch * pLink->area->box.y1) + pLink->area->box.x1; 108335c4bbdfSmrg return TRUE; 108435c4bbdfSmrg } 108535c4bbdfSmrg } 108635c4bbdfSmrg else { 108735c4bbdfSmrg /* TODO!!!! resize the linear area */ 108835c4bbdfSmrg } 108935c4bbdfSmrg 109035c4bbdfSmrg return FALSE; 109135c4bbdfSmrg} 109205b261ecSmrg 109305b261ecSmrgstatic Bool 109435c4bbdfSmrglocalQueryLargestOffscreenLinear(ScreenPtr pScreen, 109535c4bbdfSmrg int *size, int gran, int priority) 109605b261ecSmrg{ 109735c4bbdfSmrg FBManagerPtr offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 109835c4bbdfSmrg xf86FBScreenKey); 109905b261ecSmrg FBLinearLinkPtr pLink; 110005b261ecSmrg FBLinearLinkPtr pLinkRet; 110105b261ecSmrg 110205b261ecSmrg *size = 0; 110335c4bbdfSmrg 110405b261ecSmrg pLink = offman->LinearAreas; 110505b261ecSmrg 110605b261ecSmrg if (pLink && !pLink->area) { 110735c4bbdfSmrg pLinkRet = pLink; 110835c4bbdfSmrg while (pLink) { 110935c4bbdfSmrg if (pLink->free) { 111035c4bbdfSmrg if (pLink->linear.size > pLinkRet->linear.size) 111135c4bbdfSmrg pLinkRet = pLink; 111235c4bbdfSmrg } 111335c4bbdfSmrg pLink = pLink->next; 111435c4bbdfSmrg } 111535c4bbdfSmrg 111635c4bbdfSmrg if (pLinkRet->free) { 111735c4bbdfSmrg *size = pLinkRet->linear.size; 111835c4bbdfSmrg return TRUE; 111905b261ecSmrg } 112005b261ecSmrg } 112135c4bbdfSmrg else { 112235c4bbdfSmrg int w, h; 112305b261ecSmrg 112435c4bbdfSmrg if (localQueryLargestOffscreenArea(pScreen, &w, &h, gran, 112535c4bbdfSmrg FAVOR_WIDTH_THEN_AREA, priority)) { 112635c4bbdfSmrg BoxPtr extents; 112705b261ecSmrg 112835c4bbdfSmrg extents = RegionExtents(offman->InitialBoxes); 112935c4bbdfSmrg if ((extents->x2 - extents->x1) == w) 113035c4bbdfSmrg *size = w * h; 113135c4bbdfSmrg return TRUE; 113235c4bbdfSmrg } 113335c4bbdfSmrg } 113405b261ecSmrg 113535c4bbdfSmrg return FALSE; 113635c4bbdfSmrg} 113705b261ecSmrg 113805b261ecSmrgstatic FBManagerFuncs xf86FBManFuncs = { 113935c4bbdfSmrg localAllocateOffscreenArea, 114035c4bbdfSmrg localFreeOffscreenArea, 114135c4bbdfSmrg localResizeOffscreenArea, 114235c4bbdfSmrg localQueryLargestOffscreenArea, 114335c4bbdfSmrg localRegisterFreeBoxCallback, 114435c4bbdfSmrg localAllocateOffscreenLinear, 114535c4bbdfSmrg localFreeOffscreenLinear, 114635c4bbdfSmrg localResizeOffscreenLinear, 114735c4bbdfSmrg localQueryLargestOffscreenLinear, 114835c4bbdfSmrg localPurgeUnlockedOffscreenAreas 114935c4bbdfSmrg}; 115005b261ecSmrg 115105b261ecSmrgstatic Bool 115235c4bbdfSmrgxf86FBCloseScreen(ScreenPtr pScreen) 115305b261ecSmrg{ 115435c4bbdfSmrg FBLinkPtr pLink, tmp; 115535c4bbdfSmrg FBLinearLinkPtr pLinearLink, tmp2; 115635c4bbdfSmrg FBManagerPtr offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 115735c4bbdfSmrg xf86FBScreenKey); 115835c4bbdfSmrg 115935c4bbdfSmrg pScreen->CloseScreen = offman->CloseScreen; 116035c4bbdfSmrg 116135c4bbdfSmrg pLink = offman->UsedAreas; 116235c4bbdfSmrg while (pLink) { 116335c4bbdfSmrg tmp = pLink; 116435c4bbdfSmrg pLink = pLink->next; 116535c4bbdfSmrg free(tmp); 116635c4bbdfSmrg } 116735c4bbdfSmrg 116835c4bbdfSmrg pLinearLink = offman->LinearAreas; 116935c4bbdfSmrg while (pLinearLink) { 117035c4bbdfSmrg tmp2 = pLinearLink; 117135c4bbdfSmrg pLinearLink = pLinearLink->next; 117235c4bbdfSmrg free(tmp2); 117335c4bbdfSmrg } 117435c4bbdfSmrg 117535c4bbdfSmrg RegionDestroy(offman->InitialBoxes); 117635c4bbdfSmrg RegionDestroy(offman->FreeBoxes); 117735c4bbdfSmrg 117835c4bbdfSmrg free(offman->FreeBoxesUpdateCallback); 117935c4bbdfSmrg free(offman->devPrivates); 118035c4bbdfSmrg free(offman); 118135c4bbdfSmrg dixSetPrivate(&pScreen->devPrivates, xf86FBScreenKey, NULL); 118235c4bbdfSmrg 118335c4bbdfSmrg return (*pScreen->CloseScreen) (pScreen); 118405b261ecSmrg} 118505b261ecSmrg 11866747b715SmrgBool 118735c4bbdfSmrgxf86InitFBManager(ScreenPtr pScreen, BoxPtr FullBox) 118835c4bbdfSmrg{ 118935c4bbdfSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 119035c4bbdfSmrg RegionRec ScreenRegion; 119135c4bbdfSmrg RegionRec FullRegion; 119235c4bbdfSmrg BoxRec ScreenBox; 119335c4bbdfSmrg Bool ret; 119435c4bbdfSmrg 119535c4bbdfSmrg ScreenBox.x1 = 0; 119635c4bbdfSmrg ScreenBox.y1 = 0; 119735c4bbdfSmrg ScreenBox.x2 = pScrn->virtualX; 119835c4bbdfSmrg ScreenBox.y2 = pScrn->virtualY; 119935c4bbdfSmrg 120035c4bbdfSmrg if ((FullBox->x1 > ScreenBox.x1) || (FullBox->y1 > ScreenBox.y1) || 120135c4bbdfSmrg (FullBox->x2 < ScreenBox.x2) || (FullBox->y2 < ScreenBox.y2)) { 120235c4bbdfSmrg return FALSE; 120335c4bbdfSmrg } 120435c4bbdfSmrg 120535c4bbdfSmrg if (FullBox->y2 < FullBox->y1) 120635c4bbdfSmrg return FALSE; 120735c4bbdfSmrg if (FullBox->x2 < FullBox->x1) 120835c4bbdfSmrg return FALSE; 120935c4bbdfSmrg 121035c4bbdfSmrg RegionInit(&ScreenRegion, &ScreenBox, 1); 121135c4bbdfSmrg RegionInit(&FullRegion, FullBox, 1); 121235c4bbdfSmrg 121335c4bbdfSmrg RegionSubtract(&FullRegion, &FullRegion, &ScreenRegion); 121435c4bbdfSmrg 121535c4bbdfSmrg ret = xf86InitFBManagerRegion(pScreen, &FullRegion); 121635c4bbdfSmrg 121735c4bbdfSmrg RegionUninit(&ScreenRegion); 121835c4bbdfSmrg RegionUninit(&FullRegion); 121935c4bbdfSmrg 122035c4bbdfSmrg return ret; 122105b261ecSmrg} 122205b261ecSmrg 12236747b715SmrgBool 122435c4bbdfSmrgxf86InitFBManagerArea(ScreenPtr pScreen, int PixelArea, int Verbosity) 122505b261ecSmrg{ 122635c4bbdfSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 122705b261ecSmrg xRectangle Rect[3]; 122805b261ecSmrg RegionPtr pRegion, pScreenRegion; 122905b261ecSmrg int nRect; 123005b261ecSmrg Bool ret = FALSE; 123105b261ecSmrg 123205b261ecSmrg if (PixelArea < (pScrn->displayWidth * pScrn->virtualY)) 123335c4bbdfSmrg return FALSE; 123405b261ecSmrg 123505b261ecSmrg Rect[0].x = Rect[0].y = 0; 123605b261ecSmrg Rect[0].width = pScrn->displayWidth; 123705b261ecSmrg Rect[0].height = PixelArea / pScrn->displayWidth; 123805b261ecSmrg nRect = 1; 123905b261ecSmrg 124005b261ecSmrg /* Add a possible partial scanline */ 124105b261ecSmrg if ((Rect[1].height = Rect[1].width = PixelArea % pScrn->displayWidth)) { 124235c4bbdfSmrg Rect[1].x = 0; 124335c4bbdfSmrg Rect[1].y = Rect[0].height; 124435c4bbdfSmrg Rect[1].height = 1; 124535c4bbdfSmrg nRect++; 124605b261ecSmrg } 124705b261ecSmrg 124805b261ecSmrg /* Factor out virtual resolution */ 12496747b715Smrg pRegion = RegionFromRects(nRect, Rect, 0); 125005b261ecSmrg if (pRegion) { 125135c4bbdfSmrg if (!RegionNar(pRegion)) { 125235c4bbdfSmrg Rect[2].x = Rect[2].y = 0; 125335c4bbdfSmrg Rect[2].width = pScrn->virtualX; 125435c4bbdfSmrg Rect[2].height = pScrn->virtualY; 125535c4bbdfSmrg 125635c4bbdfSmrg pScreenRegion = RegionFromRects(1, &Rect[2], 0); 125735c4bbdfSmrg if (pScreenRegion) { 125835c4bbdfSmrg if (!RegionNar(pScreenRegion)) { 125935c4bbdfSmrg RegionSubtract(pRegion, pRegion, pScreenRegion); 126035c4bbdfSmrg 126135c4bbdfSmrg ret = xf86InitFBManagerRegion(pScreen, pRegion); 126235c4bbdfSmrg 126335c4bbdfSmrg if (ret && xf86GetVerbosity() >= Verbosity) { 126435c4bbdfSmrg int scrnIndex = pScrn->scrnIndex; 126535c4bbdfSmrg 126635c4bbdfSmrg xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, 126735c4bbdfSmrg "Largest offscreen areas (with overlaps):\n"); 126835c4bbdfSmrg 126935c4bbdfSmrg if (Rect[2].width < Rect[0].width) { 127035c4bbdfSmrg xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, 127135c4bbdfSmrg "\t%d x %d rectangle at %d,0\n", 127235c4bbdfSmrg Rect[0].width - Rect[2].width, 127335c4bbdfSmrg Rect[0].height, Rect[2].width); 127435c4bbdfSmrg } 127535c4bbdfSmrg if (Rect[2].width < Rect[1].width) { 127635c4bbdfSmrg xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, 127735c4bbdfSmrg "\t%d x %d rectangle at %d,0\n", 127835c4bbdfSmrg Rect[1].width - Rect[2].width, 127935c4bbdfSmrg Rect[0].height + Rect[1].height, 128035c4bbdfSmrg Rect[2].width); 128135c4bbdfSmrg } 128235c4bbdfSmrg if (Rect[2].height < Rect[0].height) { 128335c4bbdfSmrg xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, 128435c4bbdfSmrg "\t%d x %d rectangle at 0,%d\n", 128535c4bbdfSmrg Rect[0].width, 128635c4bbdfSmrg Rect[0].height - Rect[2].height, 128735c4bbdfSmrg Rect[2].height); 128835c4bbdfSmrg } 128935c4bbdfSmrg if (Rect[1].height) { 129035c4bbdfSmrg xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, 129135c4bbdfSmrg "\t%d x %d rectangle at 0,%d\n", 129235c4bbdfSmrg Rect[1].width, 129335c4bbdfSmrg Rect[0].height - Rect[2].height + 129435c4bbdfSmrg Rect[1].height, Rect[2].height); 129535c4bbdfSmrg } 129635c4bbdfSmrg } 129735c4bbdfSmrg } 129835c4bbdfSmrg 129935c4bbdfSmrg RegionDestroy(pScreenRegion); 130035c4bbdfSmrg } 130135c4bbdfSmrg } 130235c4bbdfSmrg 130335c4bbdfSmrg RegionDestroy(pRegion); 130405b261ecSmrg } 130505b261ecSmrg 130605b261ecSmrg return ret; 130705b261ecSmrg} 130805b261ecSmrg 13096747b715SmrgBool 131035c4bbdfSmrgxf86InitFBManagerRegion(ScreenPtr pScreen, RegionPtr FullRegion) 131135c4bbdfSmrg{ 131235c4bbdfSmrg FBManagerPtr offman; 131305b261ecSmrg 131435c4bbdfSmrg if (RegionNil(FullRegion)) 131535c4bbdfSmrg return FALSE; 131605b261ecSmrg 131735c4bbdfSmrg if (!dixRegisterPrivateKey(&xf86FBScreenKeyRec, PRIVATE_SCREEN, 0)) 131835c4bbdfSmrg return FALSE; 13196747b715Smrg 132035c4bbdfSmrg if (!xf86RegisterOffscreenManager(pScreen, &xf86FBManFuncs)) 132135c4bbdfSmrg return FALSE; 132205b261ecSmrg 132335c4bbdfSmrg offman = malloc(sizeof(FBManager)); 132435c4bbdfSmrg if (!offman) 132535c4bbdfSmrg return FALSE; 132605b261ecSmrg 132735c4bbdfSmrg dixSetPrivate(&pScreen->devPrivates, xf86FBScreenKey, offman); 132805b261ecSmrg 132935c4bbdfSmrg offman->CloseScreen = pScreen->CloseScreen; 133035c4bbdfSmrg pScreen->CloseScreen = xf86FBCloseScreen; 133105b261ecSmrg 133235c4bbdfSmrg offman->InitialBoxes = RegionCreate(NULL, 1); 133335c4bbdfSmrg offman->FreeBoxes = RegionCreate(NULL, 1); 133405b261ecSmrg 133535c4bbdfSmrg RegionCopy(offman->InitialBoxes, FullRegion); 133635c4bbdfSmrg RegionCopy(offman->FreeBoxes, FullRegion); 133705b261ecSmrg 133835c4bbdfSmrg offman->pScreen = pScreen; 133935c4bbdfSmrg offman->UsedAreas = NULL; 134035c4bbdfSmrg offman->LinearAreas = NULL; 134135c4bbdfSmrg offman->NumUsedAreas = 0; 134235c4bbdfSmrg offman->NumCallbacks = 0; 134335c4bbdfSmrg offman->FreeBoxesUpdateCallback = NULL; 134435c4bbdfSmrg offman->devPrivates = NULL; 134505b261ecSmrg 134635c4bbdfSmrg return TRUE; 134735c4bbdfSmrg} 134805b261ecSmrg 13496747b715SmrgBool 135035c4bbdfSmrgxf86InitFBManagerLinear(ScreenPtr pScreen, int offset, int size) 135135c4bbdfSmrg{ 135235c4bbdfSmrg FBManagerPtr offman; 135335c4bbdfSmrg FBLinearLinkPtr link; 135435c4bbdfSmrg FBLinearPtr linear; 135535c4bbdfSmrg 135635c4bbdfSmrg if (size <= 0) 135735c4bbdfSmrg return FALSE; 135835c4bbdfSmrg 135935c4bbdfSmrg /* we expect people to have called the Area setup first for pixmap cache */ 136035c4bbdfSmrg if (!dixLookupPrivate(&pScreen->devPrivates, xf86FBScreenKey)) 136135c4bbdfSmrg return FALSE; 136235c4bbdfSmrg 136335c4bbdfSmrg offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 136435c4bbdfSmrg xf86FBScreenKey); 136535c4bbdfSmrg offman->LinearAreas = malloc(sizeof(FBLinearLink)); 136635c4bbdfSmrg if (!offman->LinearAreas) 136735c4bbdfSmrg return FALSE; 136835c4bbdfSmrg 136935c4bbdfSmrg link = offman->LinearAreas; 137035c4bbdfSmrg link->area = NULL; 137135c4bbdfSmrg link->next = NULL; 137235c4bbdfSmrg link->free = 1; 137335c4bbdfSmrg linear = &(link->linear); 137435c4bbdfSmrg linear->pScreen = pScreen; 137535c4bbdfSmrg linear->size = size; 137635c4bbdfSmrg linear->offset = offset; 137735c4bbdfSmrg linear->granularity = 0; 137835c4bbdfSmrg linear->MoveLinearCallback = NULL; 137935c4bbdfSmrg linear->RemoveLinearCallback = NULL; 138035c4bbdfSmrg linear->devPrivate.ptr = NULL; 138105b261ecSmrg 138235c4bbdfSmrg return TRUE; 138335c4bbdfSmrg} 138405b261ecSmrg 138535c4bbdfSmrg/* This is an implementation specific function and should 138605b261ecSmrg disappear after the next release. People should use the 138705b261ecSmrg real linear functions instead */ 138805b261ecSmrg 13896747b715SmrgFBAreaPtr 139035c4bbdfSmrgxf86AllocateLinearOffscreenArea(ScreenPtr pScreen, 139135c4bbdfSmrg int length, 139235c4bbdfSmrg int gran, 139335c4bbdfSmrg MoveAreaCallbackProcPtr moveCB, 139435c4bbdfSmrg RemoveAreaCallbackProcPtr removeCB, 139535c4bbdfSmrg void *privData) 139635c4bbdfSmrg{ 139735c4bbdfSmrg FBManagerFuncsPtr funcs; 139835c4bbdfSmrg FBManagerPtr offman; 139935c4bbdfSmrg BoxPtr extents; 140035c4bbdfSmrg int w, h; 140135c4bbdfSmrg 140235c4bbdfSmrg if (xf86FBManagerKey == NULL) 140305b261ecSmrg return NULL; 140435c4bbdfSmrg if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates, 140535c4bbdfSmrg xf86FBManagerKey))) 140605b261ecSmrg return NULL; 140705b261ecSmrg 140835c4bbdfSmrg offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, 140935c4bbdfSmrg xf86FBScreenKey); 141035c4bbdfSmrg extents = RegionExtents(offman->InitialBoxes); 141135c4bbdfSmrg w = extents->x2 - extents->x1; 141205b261ecSmrg 141335c4bbdfSmrg if (gran > 1) { 141435c4bbdfSmrg if (gran > w) 141535c4bbdfSmrg return NULL; 141605b261ecSmrg 141735c4bbdfSmrg if (w % gran) 141835c4bbdfSmrg length += gran - 1; 141935c4bbdfSmrg } 142005b261ecSmrg 142135c4bbdfSmrg if (length <= w) { /* special case */ 142235c4bbdfSmrg h = 1; 142335c4bbdfSmrg w = length; 142435c4bbdfSmrg } 142535c4bbdfSmrg else { 142635c4bbdfSmrg h = (length + w - 1) / w; 142735c4bbdfSmrg } 142805b261ecSmrg 142935c4bbdfSmrg return (*funcs->AllocateOffscreenArea) (pScreen, w, h, gran, moveCB, 143035c4bbdfSmrg removeCB, privData); 143105b261ecSmrg} 1432