1235 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1235 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
| 
 | |
| /*
 | |
|  * Copyright (c) 1998-2001 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).
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_XORG_CONFIG_H
 | |
| #include <xorg-config.h>
 | |
| #endif
 | |
| 
 | |
| #include "misc.h"
 | |
| #include "xf86.h"
 | |
| 
 | |
| #include <X11/X.h>
 | |
| #include "scrnintstr.h"
 | |
| #include "regionstr.h"
 | |
| #include "xf86fbman.h"
 | |
| 
 | |
| /*
 | |
| #define DEBUG
 | |
| */
 | |
| 
 | |
| typedef struct {
 | |
|     FBAreaPtr(*AllocateOffscreenArea) (ScreenPtr pScreen,
 | |
|                                        int w, int h,
 | |
|                                        int granularity,
 | |
|                                        MoveAreaCallbackProcPtr moveCB,
 | |
|                                        RemoveAreaCallbackProcPtr removeCB,
 | |
|                                        void *privData);
 | |
|     void (*FreeOffscreenArea) (FBAreaPtr area);
 | |
|     Bool (*ResizeOffscreenArea) (FBAreaPtr area, int w, int h);
 | |
|     Bool (*QueryLargestOffscreenArea) (ScreenPtr pScreen,
 | |
|                                        int *width, int *height,
 | |
|                                        int granularity,
 | |
|                                        int preferences, int priority);
 | |
| /* linear functions */
 | |
|      FBLinearPtr(*AllocateOffscreenLinear) (ScreenPtr pScreen,
 | |
|                                             int size,
 | |
|                                             int granularity,
 | |
|                                             MoveLinearCallbackProcPtr moveCB,
 | |
|                                             RemoveLinearCallbackProcPtr
 | |
|                                             removeCB, void *privData);
 | |
|     void (*FreeOffscreenLinear) (FBLinearPtr area);
 | |
|     Bool (*ResizeOffscreenLinear) (FBLinearPtr area, int size);
 | |
|     Bool (*QueryLargestOffscreenLinear) (ScreenPtr pScreen,
 | |
|                                          int *size,
 | |
|                                          int granularity, int priority);
 | |
|     Bool (*PurgeOffscreenAreas) (ScreenPtr);
 | |
| } FBManagerFuncs, *FBManagerFuncsPtr;
 | |
| 
 | |
| static DevPrivateKeyRec xf86FBManagerKeyRec;
 | |
| static DevPrivateKey xf86FBManagerKey;
 | |
| 
 | |
| static Bool
 | |
| xf86RegisterOffscreenManager(ScreenPtr pScreen, FBManagerFuncsPtr funcs)
 | |
| {
 | |
| 
 | |
|     xf86FBManagerKey = &xf86FBManagerKeyRec;
 | |
| 
 | |
|     if (!dixRegisterPrivateKey(&xf86FBManagerKeyRec, PRIVATE_SCREEN, 0))
 | |
|         return FALSE;
 | |
| 
 | |
|     dixSetPrivate(&pScreen->devPrivates, xf86FBManagerKey, funcs);
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| FBAreaPtr
 | |
| xf86AllocateOffscreenArea(ScreenPtr pScreen,
 | |
|                           int w, int h,
 | |
|                           int gran,
 | |
|                           MoveAreaCallbackProcPtr moveCB,
 | |
|                           RemoveAreaCallbackProcPtr removeCB, void *privData)
 | |
| {
 | |
|     FBManagerFuncsPtr funcs;
 | |
| 
 | |
|     if (xf86FBManagerKey == NULL)
 | |
|         return NULL;
 | |
|     if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                                        xf86FBManagerKey)))
 | |
|         return NULL;
 | |
| 
 | |
|     return (*funcs->AllocateOffscreenArea) (pScreen, w, h, gran, moveCB,
 | |
|                                             removeCB, privData);
 | |
| }
 | |
| 
 | |
| FBLinearPtr
 | |
| xf86AllocateOffscreenLinear(ScreenPtr pScreen,
 | |
|                             int length,
 | |
|                             int gran,
 | |
|                             MoveLinearCallbackProcPtr moveCB,
 | |
|                             RemoveLinearCallbackProcPtr removeCB,
 | |
|                             void *privData)
 | |
| {
 | |
|     FBManagerFuncsPtr funcs;
 | |
| 
 | |
|     if (xf86FBManagerKey == NULL)
 | |
|         return NULL;
 | |
|     if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                                        xf86FBManagerKey)))
 | |
|         return NULL;
 | |
| 
 | |
|     return (*funcs->AllocateOffscreenLinear) (pScreen, length, gran, moveCB,
 | |
|                                               removeCB, privData);
 | |
| }
 | |
| 
 | |
| void
 | |
| xf86FreeOffscreenArea(FBAreaPtr area)
 | |
| {
 | |
|     FBManagerFuncsPtr funcs;
 | |
| 
 | |
|     if (!area)
 | |
|         return;
 | |
| 
 | |
|     if (xf86FBManagerKey == NULL)
 | |
|         return;
 | |
|     if (!
 | |
|         (funcs =
 | |
|          (FBManagerFuncsPtr) dixLookupPrivate(&area->pScreen->devPrivates,
 | |
|                                               xf86FBManagerKey)))
 | |
|         return;
 | |
| 
 | |
|     (*funcs->FreeOffscreenArea) (area);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void
 | |
| xf86FreeOffscreenLinear(FBLinearPtr linear)
 | |
| {
 | |
|     FBManagerFuncsPtr funcs;
 | |
| 
 | |
|     if (!linear)
 | |
|         return;
 | |
| 
 | |
|     if (xf86FBManagerKey == NULL)
 | |
|         return;
 | |
|     if (!
 | |
|         (funcs =
 | |
|          (FBManagerFuncsPtr) dixLookupPrivate(&linear->pScreen->devPrivates,
 | |
|                                               xf86FBManagerKey)))
 | |
|         return;
 | |
| 
 | |
|     (*funcs->FreeOffscreenLinear) (linear);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| xf86ResizeOffscreenArea(FBAreaPtr resize, int w, int h)
 | |
| {
 | |
|     FBManagerFuncsPtr funcs;
 | |
| 
 | |
|     if (!resize)
 | |
|         return FALSE;
 | |
| 
 | |
|     if (xf86FBManagerKey == NULL)
 | |
|         return FALSE;
 | |
|     if (!
 | |
|         (funcs =
 | |
|          (FBManagerFuncsPtr) dixLookupPrivate(&resize->pScreen->devPrivates,
 | |
|                                               xf86FBManagerKey)))
 | |
|         return FALSE;
 | |
| 
 | |
|     return (*funcs->ResizeOffscreenArea) (resize, w, h);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| xf86ResizeOffscreenLinear(FBLinearPtr resize, int size)
 | |
| {
 | |
|     FBManagerFuncsPtr funcs;
 | |
| 
 | |
|     if (!resize)
 | |
|         return FALSE;
 | |
| 
 | |
|     if (xf86FBManagerKey == NULL)
 | |
|         return FALSE;
 | |
|     if (!
 | |
|         (funcs =
 | |
|          (FBManagerFuncsPtr) dixLookupPrivate(&resize->pScreen->devPrivates,
 | |
|                                               xf86FBManagerKey)))
 | |
|         return FALSE;
 | |
| 
 | |
|     return (*funcs->ResizeOffscreenLinear) (resize, size);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| xf86QueryLargestOffscreenArea(ScreenPtr pScreen,
 | |
|                               int *w, int *h,
 | |
|                               int gran, int preferences, int severity)
 | |
| {
 | |
|     FBManagerFuncsPtr funcs;
 | |
| 
 | |
|     *w = 0;
 | |
|     *h = 0;
 | |
| 
 | |
|     if (xf86FBManagerKey == NULL)
 | |
|         return FALSE;
 | |
|     if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                                        xf86FBManagerKey)))
 | |
|         return FALSE;
 | |
| 
 | |
|     return (*funcs->QueryLargestOffscreenArea) (pScreen, w, h, gran,
 | |
|                                                 preferences, severity);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| xf86QueryLargestOffscreenLinear(ScreenPtr pScreen,
 | |
|                                 int *size, int gran, int severity)
 | |
| {
 | |
|     FBManagerFuncsPtr funcs;
 | |
| 
 | |
|     *size = 0;
 | |
| 
 | |
|     if (xf86FBManagerKey == NULL)
 | |
|         return FALSE;
 | |
|     if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                                        xf86FBManagerKey)))
 | |
|         return FALSE;
 | |
| 
 | |
|     return (*funcs->QueryLargestOffscreenLinear) (pScreen, size, gran,
 | |
|                                                   severity);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| xf86PurgeUnlockedOffscreenAreas(ScreenPtr pScreen)
 | |
| {
 | |
|     FBManagerFuncsPtr funcs;
 | |
| 
 | |
|     if (xf86FBManagerKey == NULL)
 | |
|         return FALSE;
 | |
|     if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                                        xf86FBManagerKey)))
 | |
|         return FALSE;
 | |
| 
 | |
|     return (*funcs->PurgeOffscreenAreas) (pScreen);
 | |
| }
 | |
| 
 | |
| /************************************************************\
 | |
| 
 | |
|    Below is a specific implementation of an offscreen manager.
 | |
| 
 | |
| \************************************************************/
 | |
| 
 | |
| static DevPrivateKeyRec xf86FBScreenKeyRec;
 | |
| 
 | |
| #define xf86FBScreenKey (&xf86FBScreenKeyRec)
 | |
| 
 | |
| typedef struct _FBLink {
 | |
|     FBArea area;
 | |
|     struct _FBLink *next;
 | |
| } FBLink, *FBLinkPtr;
 | |
| 
 | |
| typedef struct _FBLinearLink {
 | |
|     FBLinear linear;
 | |
|     int free;                   /* need to add free here as FBLinear is publicly accessible */
 | |
|     FBAreaPtr area;             /* only used if allocation came from XY area */
 | |
|     struct _FBLinearLink *next;
 | |
| } FBLinearLink, *FBLinearLinkPtr;
 | |
| 
 | |
| typedef struct {
 | |
|     ScreenPtr pScreen;
 | |
|     RegionPtr InitialBoxes;
 | |
|     RegionPtr FreeBoxes;
 | |
|     FBLinkPtr UsedAreas;
 | |
|     int NumUsedAreas;
 | |
|     FBLinearLinkPtr LinearAreas;
 | |
|     CloseScreenProcPtr CloseScreen;
 | |
|     DevUnion *devPrivates;
 | |
| } FBManager, *FBManagerPtr;
 | |
| 
 | |
| static FBAreaPtr
 | |
| AllocateArea(FBManagerPtr offman,
 | |
|              int w, int h,
 | |
|              int granularity,
 | |
|              MoveAreaCallbackProcPtr moveCB,
 | |
|              RemoveAreaCallbackProcPtr removeCB, void *privData)
 | |
| {
 | |
|     ScreenPtr pScreen = offman->pScreen;
 | |
|     FBLinkPtr link = NULL;
 | |
|     FBAreaPtr area = NULL;
 | |
|     RegionRec NewReg;
 | |
|     int i, x = 0, num;
 | |
|     BoxPtr boxp;
 | |
| 
 | |
|     if (granularity <= 1)
 | |
|         granularity = 0;
 | |
| 
 | |
|     boxp = RegionRects(offman->FreeBoxes);
 | |
|     num = RegionNumRects(offman->FreeBoxes);
 | |
| 
 | |
|     /* look through the free boxes */
 | |
|     for (i = 0; i < num; i++, boxp++) {
 | |
|         x = boxp->x1;
 | |
|         if (granularity > 1)
 | |
|             x = ((x + granularity - 1) / granularity) * granularity;
 | |
| 
 | |
|         if (((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w))
 | |
|             continue;
 | |
| 
 | |
|         link = malloc(sizeof(FBLink));
 | |
|         if (!link)
 | |
|             return NULL;
 | |
| 
 | |
|         area = &(link->area);
 | |
|         link->next = offman->UsedAreas;
 | |
|         offman->UsedAreas = link;
 | |
|         offman->NumUsedAreas++;
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     /* try to boot a removable one out if we are not expendable ourselves */
 | |
|     if (!area && !removeCB) {
 | |
|         link = offman->UsedAreas;
 | |
| 
 | |
|         while (link) {
 | |
|             if (!link->area.RemoveAreaCallback) {
 | |
|                 link = link->next;
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             boxp = &(link->area.box);
 | |
|             x = boxp->x1;
 | |
|             if (granularity > 1)
 | |
|                 x = ((x + granularity - 1) / granularity) * granularity;
 | |
| 
 | |
|             if (((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w)) {
 | |
|                 link = link->next;
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             /* bye, bye */
 | |
|             (*link->area.RemoveAreaCallback) (&link->area);
 | |
|             RegionInit(&NewReg, &(link->area.box), 1);
 | |
|             RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &NewReg);
 | |
|             RegionUninit(&NewReg);
 | |
| 
 | |
|             area = &(link->area);
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (area) {
 | |
|         area->pScreen = pScreen;
 | |
|         area->granularity = granularity;
 | |
|         area->box.x1 = x;
 | |
|         area->box.x2 = x + w;
 | |
|         area->box.y1 = boxp->y1;
 | |
|         area->box.y2 = boxp->y1 + h;
 | |
|         area->MoveAreaCallback = moveCB;
 | |
|         area->RemoveAreaCallback = removeCB;
 | |
|         area->devPrivate.ptr = privData;
 | |
| 
 | |
|         RegionInit(&NewReg, &(area->box), 1);
 | |
|         RegionSubtract(offman->FreeBoxes, offman->FreeBoxes, &NewReg);
 | |
|         RegionUninit(&NewReg);
 | |
|     }
 | |
| 
 | |
|     return area;
 | |
| }
 | |
| 
 | |
| static FBAreaPtr
 | |
| localAllocateOffscreenArea(ScreenPtr pScreen,
 | |
|                            int w, int h,
 | |
|                            int gran,
 | |
|                            MoveAreaCallbackProcPtr moveCB,
 | |
|                            RemoveAreaCallbackProcPtr removeCB, void *privData)
 | |
| {
 | |
|     FBManagerPtr offman;
 | |
| 
 | |
|     offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                              xf86FBScreenKey);
 | |
|     return AllocateArea(offman, w, h, gran, moveCB, removeCB, privData);
 | |
| }
 | |
| 
 | |
| static void
 | |
| localFreeOffscreenArea(FBAreaPtr area)
 | |
| {
 | |
|     FBManagerPtr offman;
 | |
|     FBLinkPtr pLink, pLinkPrev = NULL;
 | |
|     RegionRec FreedRegion;
 | |
|     ScreenPtr pScreen;
 | |
| 
 | |
|     pScreen = area->pScreen;
 | |
|     offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                              xf86FBScreenKey);
 | |
|     pLink = offman->UsedAreas;
 | |
|     if (!pLink)
 | |
|         return;
 | |
| 
 | |
|     while (&(pLink->area) != area) {
 | |
|         pLinkPrev = pLink;
 | |
|         pLink = pLink->next;
 | |
|         if (!pLink)
 | |
|             return;
 | |
|     }
 | |
| 
 | |
|     /* put the area back into the pool */
 | |
|     RegionInit(&FreedRegion, &(pLink->area.box), 1);
 | |
|     RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &FreedRegion);
 | |
|     RegionUninit(&FreedRegion);
 | |
| 
 | |
|     if (pLinkPrev)
 | |
|         pLinkPrev->next = pLink->next;
 | |
|     else
 | |
|         offman->UsedAreas = pLink->next;
 | |
| 
 | |
|     free(pLink);
 | |
|     offman->NumUsedAreas--;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| localResizeOffscreenArea(FBAreaPtr resize, int w, int h)
 | |
| {
 | |
|     FBManagerPtr offman;
 | |
|     ScreenPtr pScreen;
 | |
|     BoxRec OrigArea;
 | |
|     RegionRec FreedReg;
 | |
|     FBAreaPtr area = NULL;
 | |
|     FBLinkPtr pLink, newLink, pLinkPrev = NULL;
 | |
| 
 | |
|     pScreen = resize->pScreen;
 | |
|     offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                              xf86FBScreenKey);
 | |
|     /* find this link */
 | |
|     if (!(pLink = offman->UsedAreas))
 | |
|         return FALSE;
 | |
| 
 | |
|     while (&(pLink->area) != resize) {
 | |
|         pLinkPrev = pLink;
 | |
|         pLink = pLink->next;
 | |
|         if (!pLink)
 | |
|             return FALSE;
 | |
|     }
 | |
| 
 | |
|     OrigArea.x1 = resize->box.x1;
 | |
|     OrigArea.x2 = resize->box.x2;
 | |
|     OrigArea.y1 = resize->box.y1;
 | |
|     OrigArea.y2 = resize->box.y2;
 | |
| 
 | |
|     /* if it's smaller, this is easy */
 | |
| 
 | |
|     if ((w <= (resize->box.x2 - resize->box.x1)) &&
 | |
|         (h <= (resize->box.y2 - resize->box.y1))) {
 | |
|         RegionRec NewReg;
 | |
| 
 | |
|         resize->box.x2 = resize->box.x1 + w;
 | |
|         resize->box.y2 = resize->box.y1 + h;
 | |
| 
 | |
|         if ((resize->box.y2 == OrigArea.y2) && (resize->box.x2 == OrigArea.x2))
 | |
|             return TRUE;
 | |
| 
 | |
|         RegionInit(&FreedReg, &OrigArea, 1);
 | |
|         RegionInit(&NewReg, &(resize->box), 1);
 | |
|         RegionSubtract(&FreedReg, &FreedReg, &NewReg);
 | |
|         RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &FreedReg);
 | |
|         RegionUninit(&FreedReg);
 | |
|         RegionUninit(&NewReg);
 | |
| 
 | |
|         return TRUE;
 | |
|     }
 | |
| 
 | |
|     /* otherwise we remove the old region */
 | |
| 
 | |
|     RegionInit(&FreedReg, &OrigArea, 1);
 | |
|     RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &FreedReg);
 | |
| 
 | |
|     /* remove the old link */
 | |
|     if (pLinkPrev)
 | |
|         pLinkPrev->next = pLink->next;
 | |
|     else
 | |
|         offman->UsedAreas = pLink->next;
 | |
| 
 | |
|     /* and try to add a new one */
 | |
| 
 | |
|     if ((area = AllocateArea(offman, w, h, resize->granularity,
 | |
|                              resize->MoveAreaCallback,
 | |
|                              resize->RemoveAreaCallback,
 | |
|                              resize->devPrivate.ptr))) {
 | |
| 
 | |
|         /* copy data over to our link and replace the new with old */
 | |
|         memcpy(resize, area, sizeof(FBArea));
 | |
| 
 | |
|         pLinkPrev = NULL;
 | |
|         newLink = offman->UsedAreas;
 | |
| 
 | |
|         while (&(newLink->area) != area) {
 | |
|             pLinkPrev = newLink;
 | |
|             newLink = newLink->next;
 | |
|         }
 | |
| 
 | |
|         if (pLinkPrev)
 | |
|             pLinkPrev->next = newLink->next;
 | |
|         else
 | |
|             offman->UsedAreas = newLink->next;
 | |
| 
 | |
|         pLink->next = offman->UsedAreas;
 | |
|         offman->UsedAreas = pLink;
 | |
| 
 | |
|         free(newLink);
 | |
| 
 | |
|         /* AllocateArea added one but we really only exchanged one */
 | |
|         offman->NumUsedAreas--;
 | |
|     }
 | |
|     else {
 | |
|         /* reinstate the old region */
 | |
|         RegionSubtract(offman->FreeBoxes, offman->FreeBoxes, &FreedReg);
 | |
|         RegionUninit(&FreedReg);
 | |
| 
 | |
|         pLink->next = offman->UsedAreas;
 | |
|         offman->UsedAreas = pLink;
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     RegionUninit(&FreedReg);
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| localQueryLargestOffscreenArea(ScreenPtr pScreen,
 | |
|                                int *width, int *height,
 | |
|                                int granularity, int preferences, int severity)
 | |
| {
 | |
|     FBManagerPtr offman;
 | |
|     RegionPtr newRegion = NULL;
 | |
|     BoxPtr pbox;
 | |
|     int nbox;
 | |
|     int x, w, h, area, oldArea;
 | |
| 
 | |
|     *width = *height = oldArea = 0;
 | |
| 
 | |
|     if (granularity <= 1)
 | |
|         granularity = 0;
 | |
| 
 | |
|     if ((preferences < 0) || (preferences > 3))
 | |
|         return FALSE;
 | |
| 
 | |
|     offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                              xf86FBScreenKey);
 | |
|     if (severity < 0)
 | |
|         severity = 0;
 | |
|     if (severity > 2)
 | |
|         severity = 2;
 | |
| 
 | |
|     switch (severity) {
 | |
|     case 2:
 | |
|         if (offman->NumUsedAreas) {
 | |
|             FBLinkPtr pLink;
 | |
|             RegionRec tmpRegion;
 | |
| 
 | |
|             newRegion = RegionCreate(NULL, 1);
 | |
|             RegionCopy(newRegion, offman->InitialBoxes);
 | |
|             pLink = offman->UsedAreas;
 | |
| 
 | |
|             while (pLink) {
 | |
|                 if (!pLink->area.RemoveAreaCallback) {
 | |
|                     RegionInit(&tmpRegion, &(pLink->area.box), 1);
 | |
|                     RegionSubtract(newRegion, newRegion, &tmpRegion);
 | |
|                     RegionUninit(&tmpRegion);
 | |
|                 }
 | |
|                 pLink = pLink->next;
 | |
|             }
 | |
| 
 | |
|             nbox = RegionNumRects(newRegion);
 | |
|             pbox = RegionRects(newRegion);
 | |
|             break;
 | |
|         }
 | |
|     case 1:
 | |
|         if (offman->NumUsedAreas) {
 | |
|             FBLinkPtr pLink;
 | |
|             RegionRec tmpRegion;
 | |
| 
 | |
|             newRegion = RegionCreate(NULL, 1);
 | |
|             RegionCopy(newRegion, offman->FreeBoxes);
 | |
|             pLink = offman->UsedAreas;
 | |
| 
 | |
|             while (pLink) {
 | |
|                 if (pLink->area.RemoveAreaCallback) {
 | |
|                     RegionInit(&tmpRegion, &(pLink->area.box), 1);
 | |
|                     RegionAppend(newRegion, &tmpRegion);
 | |
|                     RegionUninit(&tmpRegion);
 | |
|                 }
 | |
|                 pLink = pLink->next;
 | |
|             }
 | |
| 
 | |
|             nbox = RegionNumRects(newRegion);
 | |
|             pbox = RegionRects(newRegion);
 | |
|             break;
 | |
|         }
 | |
|     default:
 | |
|         nbox = RegionNumRects(offman->FreeBoxes);
 | |
|         pbox = RegionRects(offman->FreeBoxes);
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     while (nbox--) {
 | |
|         x = pbox->x1;
 | |
|         if (granularity > 1)
 | |
|             x = ((x + granularity - 1) / granularity) * granularity;
 | |
| 
 | |
|         w = pbox->x2 - x;
 | |
|         h = pbox->y2 - pbox->y1;
 | |
|         area = w * h;
 | |
| 
 | |
|         if (w > 0) {
 | |
|             Bool gotIt = FALSE;
 | |
| 
 | |
|             switch (preferences) {
 | |
|             case FAVOR_AREA_THEN_WIDTH:
 | |
|                 if ((area > oldArea) || ((area == oldArea) && (w > *width)))
 | |
|                     gotIt = TRUE;
 | |
|                 break;
 | |
|             case FAVOR_AREA_THEN_HEIGHT:
 | |
|                 if ((area > oldArea) || ((area == oldArea) && (h > *height)))
 | |
|                     gotIt = TRUE;
 | |
|                 break;
 | |
|             case FAVOR_WIDTH_THEN_AREA:
 | |
|                 if ((w > *width) || ((w == *width) && (area > oldArea)))
 | |
|                     gotIt = TRUE;
 | |
|                 break;
 | |
|             case FAVOR_HEIGHT_THEN_AREA:
 | |
|                 if ((h > *height) || ((h == *height) && (area > oldArea)))
 | |
|                     gotIt = TRUE;
 | |
|                 break;
 | |
|             }
 | |
|             if (gotIt) {
 | |
|                 *width = w;
 | |
|                 *height = h;
 | |
|                 oldArea = area;
 | |
|             }
 | |
|         }
 | |
|         pbox++;
 | |
|     }
 | |
| 
 | |
|     if (newRegion)
 | |
|         RegionDestroy(newRegion);
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| localPurgeUnlockedOffscreenAreas(ScreenPtr pScreen)
 | |
| {
 | |
|     FBManagerPtr offman;
 | |
|     FBLinkPtr pLink, tmp, pPrev = NULL;
 | |
|     RegionRec FreedRegion;
 | |
|     Bool anyUsed = FALSE;
 | |
| 
 | |
|     offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                              xf86FBScreenKey);
 | |
|     pLink = offman->UsedAreas;
 | |
|     if (!pLink)
 | |
|         return TRUE;
 | |
| 
 | |
|     while (pLink) {
 | |
|         if (pLink->area.RemoveAreaCallback) {
 | |
|             (*pLink->area.RemoveAreaCallback) (&pLink->area);
 | |
| 
 | |
|             RegionInit(&FreedRegion, &(pLink->area.box), 1);
 | |
|             RegionAppend(offman->FreeBoxes, &FreedRegion);
 | |
|             RegionUninit(&FreedRegion);
 | |
| 
 | |
|             if (pPrev)
 | |
|                 pPrev->next = pLink->next;
 | |
|             else
 | |
|                 offman->UsedAreas = pLink->next;
 | |
| 
 | |
|             tmp = pLink;
 | |
|             pLink = pLink->next;
 | |
|             free(tmp);
 | |
|             offman->NumUsedAreas--;
 | |
|             anyUsed = TRUE;
 | |
|         }
 | |
|         else {
 | |
|             pPrev = pLink;
 | |
|             pLink = pLink->next;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (anyUsed) {
 | |
|         RegionValidate(offman->FreeBoxes, &anyUsed);
 | |
|     }
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| LinearMoveCBWrapper(FBAreaPtr from, FBAreaPtr to)
 | |
| {
 | |
|     /* this will never get called */
 | |
| }
 | |
| 
 | |
| static void
 | |
| LinearRemoveCBWrapper(FBAreaPtr area)
 | |
| {
 | |
|     FBManagerPtr offman;
 | |
|     FBLinearLinkPtr pLink, pLinkPrev = NULL;
 | |
|     ScreenPtr pScreen = area->pScreen;
 | |
| 
 | |
|     offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                              xf86FBScreenKey);
 | |
|     pLink = offman->LinearAreas;
 | |
|     if (!pLink)
 | |
|         return;
 | |
| 
 | |
|     while (pLink->area != area) {
 | |
|         pLinkPrev = pLink;
 | |
|         pLink = pLink->next;
 | |
|         if (!pLink)
 | |
|             return;
 | |
|     }
 | |
| 
 | |
|     /* give the user the callback it is expecting */
 | |
|     (*pLink->linear.RemoveLinearCallback) (&(pLink->linear));
 | |
| 
 | |
|     if (pLinkPrev)
 | |
|         pLinkPrev->next = pLink->next;
 | |
|     else
 | |
|         offman->LinearAreas = pLink->next;
 | |
| 
 | |
|     free(pLink);
 | |
| }
 | |
| 
 | |
| static void
 | |
| DumpDebug(FBLinearLinkPtr pLink)
 | |
| {
 | |
| #ifdef DEBUG
 | |
|     if (!pLink)
 | |
|         ErrorF("MMmm, PLINK IS NULL!\n");
 | |
| 
 | |
|     while (pLink) {
 | |
|         ErrorF("  Offset:%08x, Size:%08x, %s,%s\n",
 | |
|                pLink->linear.offset,
 | |
|                pLink->linear.size,
 | |
|                pLink->free ? "Free" : "Used", pLink->area ? "Area" : "Linear");
 | |
| 
 | |
|         pLink = pLink->next;
 | |
|     }
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static FBLinearPtr
 | |
| AllocateLinear(FBManagerPtr offman, int size, int granularity, void *privData)
 | |
| {
 | |
|     ScreenPtr pScreen = offman->pScreen;
 | |
|     FBLinearLinkPtr linear = NULL;
 | |
|     FBLinearLinkPtr newlink = NULL;
 | |
|     int offset, end;
 | |
| 
 | |
|     if (size <= 0)
 | |
|         return NULL;
 | |
| 
 | |
|     if (!offman->LinearAreas)
 | |
|         return NULL;
 | |
| 
 | |
|     linear = offman->LinearAreas;
 | |
|     while (linear) {
 | |
|         /* Make sure we get a free area that's not an XY fallback case */
 | |
|         if (!linear->area && linear->free) {
 | |
|             offset = linear->linear.offset;
 | |
|             if (granularity > 1)
 | |
|                 offset =
 | |
|                     ((offset + granularity - 1) / granularity) * granularity;
 | |
|             end = offset + size;
 | |
|             if (end <= (linear->linear.offset + linear->linear.size))
 | |
|                 break;
 | |
|         }
 | |
|         linear = linear->next;
 | |
|     }
 | |
|     if (!linear)
 | |
|         return NULL;
 | |
| 
 | |
|     /* break left */
 | |
|     if (offset > linear->linear.offset) {
 | |
|         newlink = malloc(sizeof(FBLinearLink));
 | |
|         if (!newlink)
 | |
|             return NULL;
 | |
|         newlink->area = NULL;
 | |
|         newlink->linear.offset = offset;
 | |
|         newlink->linear.size =
 | |
|             linear->linear.size - (offset - linear->linear.offset);
 | |
|         newlink->free = 1;
 | |
|         newlink->next = linear->next;
 | |
|         linear->linear.size -= newlink->linear.size;
 | |
|         linear->next = newlink;
 | |
|         linear = newlink;
 | |
|     }
 | |
| 
 | |
|     /* break right */
 | |
|     if (size < linear->linear.size) {
 | |
|         newlink = malloc(sizeof(FBLinearLink));
 | |
|         if (!newlink)
 | |
|             return NULL;
 | |
|         newlink->area = NULL;
 | |
|         newlink->linear.offset = offset + size;
 | |
|         newlink->linear.size = linear->linear.size - size;
 | |
|         newlink->free = 1;
 | |
|         newlink->next = linear->next;
 | |
|         linear->linear.size = size;
 | |
|         linear->next = newlink;
 | |
|     }
 | |
| 
 | |
|     /* p = middle block */
 | |
|     linear->linear.granularity = granularity;
 | |
|     linear->free = 0;
 | |
|     linear->linear.pScreen = pScreen;
 | |
|     linear->linear.MoveLinearCallback = NULL;
 | |
|     linear->linear.RemoveLinearCallback = NULL;
 | |
|     linear->linear.devPrivate.ptr = NULL;
 | |
| 
 | |
|     DumpDebug(offman->LinearAreas);
 | |
| 
 | |
|     return &(linear->linear);
 | |
| }
 | |
| 
 | |
| static FBLinearPtr
 | |
| localAllocateOffscreenLinear(ScreenPtr pScreen,
 | |
|                              int length,
 | |
|                              int gran,
 | |
|                              MoveLinearCallbackProcPtr moveCB,
 | |
|                              RemoveLinearCallbackProcPtr removeCB,
 | |
|                              void *privData)
 | |
| {
 | |
|     FBManagerPtr offman;
 | |
|     FBLinearLinkPtr link;
 | |
|     FBAreaPtr area;
 | |
|     FBLinearPtr linear = NULL;
 | |
|     BoxPtr extents;
 | |
|     int w, h, pitch;
 | |
| 
 | |
|     offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                              xf86FBScreenKey);
 | |
| 
 | |
|     /* Try to allocate from linear memory first...... */
 | |
|     DebugF("ALLOCATING LINEAR\n");
 | |
|     if ((linear = AllocateLinear(offman, length, gran, privData)))
 | |
|         return linear;
 | |
| 
 | |
|     DebugF("NOPE, ALLOCATING AREA\n");
 | |
| 
 | |
|     if (!(link = malloc(sizeof(FBLinearLink))))
 | |
|         return NULL;
 | |
| 
 | |
|     /* No linear available, so try and pinch some from the XY areas */
 | |
|     extents = RegionExtents(offman->InitialBoxes);
 | |
|     pitch = extents->x2 - extents->x1;
 | |
| 
 | |
|     if (gran > 1) {
 | |
|         if (gran > pitch) {
 | |
|             /* we can't match the specified alignment with XY allocations */
 | |
|             free(link);
 | |
|             return NULL;
 | |
|         }
 | |
| 
 | |
|         if (pitch % gran) {
 | |
|             /* pitch and granularity aren't a perfect match, let's allocate
 | |
|              * a bit more so we can align later on
 | |
|              */
 | |
|             length += gran - 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (length < pitch) {       /* special case */
 | |
|         w = length;
 | |
|         h = 1;
 | |
|     }
 | |
|     else {
 | |
|         w = pitch;
 | |
|         h = (length + pitch - 1) / pitch;
 | |
|     }
 | |
| 
 | |
|     if ((area = localAllocateOffscreenArea(pScreen, w, h, gran,
 | |
|                                            moveCB ? LinearMoveCBWrapper : NULL,
 | |
|                                            removeCB ? LinearRemoveCBWrapper :
 | |
|                                            NULL, privData))) {
 | |
|         link->area = area;
 | |
|         link->free = 0;
 | |
|         link->next = offman->LinearAreas;
 | |
|         offman->LinearAreas = link;
 | |
|         linear = &(link->linear);
 | |
|         linear->pScreen = pScreen;
 | |
|         linear->size = h * w;
 | |
|         linear->offset = (pitch * area->box.y1) + area->box.x1;
 | |
|         if (gran > 1)
 | |
|             linear->offset = ((linear->offset + gran - 1) / gran) * gran;
 | |
|         linear->granularity = gran;
 | |
|         linear->MoveLinearCallback = moveCB;
 | |
|         linear->RemoveLinearCallback = removeCB;
 | |
|         linear->devPrivate.ptr = privData;
 | |
|     }
 | |
|     else
 | |
|         free(link);
 | |
| 
 | |
|     DumpDebug(offman->LinearAreas);
 | |
| 
 | |
|     return linear;
 | |
| }
 | |
| 
 | |
| static void
 | |
| localFreeOffscreenLinear(FBLinearPtr linear)
 | |
| {
 | |
|     FBManagerPtr offman;
 | |
|     FBLinearLinkPtr pLink, pLinkPrev = NULL;
 | |
|     ScreenPtr pScreen = linear->pScreen;
 | |
| 
 | |
|     offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                              xf86FBScreenKey);
 | |
|     pLink = offman->LinearAreas;
 | |
|     if (!pLink)
 | |
|         return;
 | |
| 
 | |
|     while (&(pLink->linear) != linear) {
 | |
|         pLinkPrev = pLink;
 | |
|         pLink = pLink->next;
 | |
|         if (!pLink)
 | |
|             return;
 | |
|     }
 | |
| 
 | |
|     if (pLink->area) {          /* really an XY area */
 | |
|         DebugF("FREEING AREA\n");
 | |
|         localFreeOffscreenArea(pLink->area);
 | |
|         if (pLinkPrev)
 | |
|             pLinkPrev->next = pLink->next;
 | |
|         else
 | |
|             offman->LinearAreas = pLink->next;
 | |
|         free(pLink);
 | |
|         DumpDebug(offman->LinearAreas);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     pLink->free = 1;
 | |
| 
 | |
|     if (pLink->next && pLink->next->free) {
 | |
|         FBLinearLinkPtr p = pLink->next;
 | |
| 
 | |
|         pLink->linear.size += p->linear.size;
 | |
|         pLink->next = p->next;
 | |
|         free(p);
 | |
|     }
 | |
| 
 | |
|     if (pLinkPrev) {
 | |
|         if (pLinkPrev->next && pLinkPrev->next->free && !pLinkPrev->area) {
 | |
|             FBLinearLinkPtr p = pLinkPrev->next;
 | |
| 
 | |
|             pLinkPrev->linear.size += p->linear.size;
 | |
|             pLinkPrev->next = p->next;
 | |
|             free(p);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     DebugF("FREEING LINEAR\n");
 | |
|     DumpDebug(offman->LinearAreas);
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| localResizeOffscreenLinear(FBLinearPtr resize, int length)
 | |
| {
 | |
|     FBManagerPtr offman;
 | |
|     FBLinearLinkPtr pLink;
 | |
|     ScreenPtr pScreen = resize->pScreen;
 | |
| 
 | |
|     offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                              xf86FBScreenKey);
 | |
|     pLink = offman->LinearAreas;
 | |
|     if (!pLink)
 | |
|         return FALSE;
 | |
| 
 | |
|     while (&(pLink->linear) != resize) {
 | |
|         pLink = pLink->next;
 | |
|         if (!pLink)
 | |
|             return FALSE;
 | |
|     }
 | |
| 
 | |
|     /* This could actually be a lot smarter and try to move allocations
 | |
|        from XY to linear when available.  For now if it was XY, we keep
 | |
|        it XY */
 | |
| 
 | |
|     if (pLink->area) {          /* really an XY area */
 | |
|         BoxPtr extents;
 | |
|         int pitch, w, h;
 | |
| 
 | |
|         extents = RegionExtents(offman->InitialBoxes);
 | |
|         pitch = extents->x2 - extents->x1;
 | |
| 
 | |
|         if (length < pitch) {   /* special case */
 | |
|             w = length;
 | |
|             h = 1;
 | |
|         }
 | |
|         else {
 | |
|             w = pitch;
 | |
|             h = (length + pitch - 1) / pitch;
 | |
|         }
 | |
| 
 | |
|         if (localResizeOffscreenArea(pLink->area, w, h)) {
 | |
|             resize->size = h * w;
 | |
|             resize->offset =
 | |
|                 (pitch * pLink->area->box.y1) + pLink->area->box.x1;
 | |
|             return TRUE;
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         /* TODO!!!! resize the linear area */
 | |
|     }
 | |
| 
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| localQueryLargestOffscreenLinear(ScreenPtr pScreen,
 | |
|                                  int *size, int gran, int priority)
 | |
| {
 | |
|     FBManagerPtr offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                                           xf86FBScreenKey);
 | |
|     FBLinearLinkPtr pLink;
 | |
|     FBLinearLinkPtr pLinkRet;
 | |
| 
 | |
|     *size = 0;
 | |
| 
 | |
|     pLink = offman->LinearAreas;
 | |
| 
 | |
|     if (pLink && !pLink->area) {
 | |
|         pLinkRet = pLink;
 | |
|         while (pLink) {
 | |
|             if (pLink->free) {
 | |
|                 if (pLink->linear.size > pLinkRet->linear.size)
 | |
|                     pLinkRet = pLink;
 | |
|             }
 | |
|             pLink = pLink->next;
 | |
|         }
 | |
| 
 | |
|         if (pLinkRet->free) {
 | |
|             *size = pLinkRet->linear.size;
 | |
|             return TRUE;
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         int w, h;
 | |
| 
 | |
|         if (localQueryLargestOffscreenArea(pScreen, &w, &h, gran,
 | |
|                                            FAVOR_WIDTH_THEN_AREA, priority)) {
 | |
|             BoxPtr extents;
 | |
| 
 | |
|             extents = RegionExtents(offman->InitialBoxes);
 | |
|             if ((extents->x2 - extents->x1) == w)
 | |
|                 *size = w * h;
 | |
|             return TRUE;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| static FBManagerFuncs xf86FBManFuncs = {
 | |
|     localAllocateOffscreenArea,
 | |
|     localFreeOffscreenArea,
 | |
|     localResizeOffscreenArea,
 | |
|     localQueryLargestOffscreenArea,
 | |
|     localAllocateOffscreenLinear,
 | |
|     localFreeOffscreenLinear,
 | |
|     localResizeOffscreenLinear,
 | |
|     localQueryLargestOffscreenLinear,
 | |
|     localPurgeUnlockedOffscreenAreas
 | |
| };
 | |
| 
 | |
| static Bool
 | |
| xf86FBCloseScreen(ScreenPtr pScreen)
 | |
| {
 | |
|     FBLinkPtr pLink, tmp;
 | |
|     FBLinearLinkPtr pLinearLink, tmp2;
 | |
|     FBManagerPtr offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                                           xf86FBScreenKey);
 | |
| 
 | |
|     pScreen->CloseScreen = offman->CloseScreen;
 | |
| 
 | |
|     pLink = offman->UsedAreas;
 | |
|     while (pLink) {
 | |
|         tmp = pLink;
 | |
|         pLink = pLink->next;
 | |
|         free(tmp);
 | |
|     }
 | |
| 
 | |
|     pLinearLink = offman->LinearAreas;
 | |
|     while (pLinearLink) {
 | |
|         tmp2 = pLinearLink;
 | |
|         pLinearLink = pLinearLink->next;
 | |
|         free(tmp2);
 | |
|     }
 | |
| 
 | |
|     RegionDestroy(offman->InitialBoxes);
 | |
|     RegionDestroy(offman->FreeBoxes);
 | |
| 
 | |
|     free(offman->devPrivates);
 | |
|     free(offman);
 | |
|     dixSetPrivate(&pScreen->devPrivates, xf86FBScreenKey, NULL);
 | |
| 
 | |
|     return (*pScreen->CloseScreen) (pScreen);
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| xf86InitFBManagerRegion(ScreenPtr pScreen, RegionPtr FullRegion);
 | |
| 
 | |
| Bool
 | |
| xf86InitFBManager(ScreenPtr pScreen, BoxPtr FullBox)
 | |
| {
 | |
|     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 | |
|     RegionRec ScreenRegion;
 | |
|     RegionRec FullRegion;
 | |
|     BoxRec ScreenBox;
 | |
|     Bool ret;
 | |
| 
 | |
|     ScreenBox.x1 = 0;
 | |
|     ScreenBox.y1 = 0;
 | |
|     ScreenBox.x2 = pScrn->virtualX;
 | |
|     ScreenBox.y2 = pScrn->virtualY;
 | |
| 
 | |
|     if ((FullBox->x1 > ScreenBox.x1) || (FullBox->y1 > ScreenBox.y1) ||
 | |
|         (FullBox->x2 < ScreenBox.x2) || (FullBox->y2 < ScreenBox.y2)) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     if (FullBox->y2 < FullBox->y1)
 | |
|         return FALSE;
 | |
|     if (FullBox->x2 < FullBox->x1)
 | |
|         return FALSE;
 | |
| 
 | |
|     RegionInit(&ScreenRegion, &ScreenBox, 1);
 | |
|     RegionInit(&FullRegion, FullBox, 1);
 | |
| 
 | |
|     RegionSubtract(&FullRegion, &FullRegion, &ScreenRegion);
 | |
| 
 | |
|     ret = xf86InitFBManagerRegion(pScreen, &FullRegion);
 | |
| 
 | |
|     RegionUninit(&ScreenRegion);
 | |
|     RegionUninit(&FullRegion);
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| xf86InitFBManagerRegion(ScreenPtr pScreen, RegionPtr FullRegion)
 | |
| {
 | |
|     FBManagerPtr offman;
 | |
| 
 | |
|     if (RegionNil(FullRegion))
 | |
|         return FALSE;
 | |
| 
 | |
|     if (!dixRegisterPrivateKey(&xf86FBScreenKeyRec, PRIVATE_SCREEN, 0))
 | |
|         return FALSE;
 | |
| 
 | |
|     if (!xf86RegisterOffscreenManager(pScreen, &xf86FBManFuncs))
 | |
|         return FALSE;
 | |
| 
 | |
|     offman = malloc(sizeof(FBManager));
 | |
|     if (!offman)
 | |
|         return FALSE;
 | |
| 
 | |
|     dixSetPrivate(&pScreen->devPrivates, xf86FBScreenKey, offman);
 | |
| 
 | |
|     offman->CloseScreen = pScreen->CloseScreen;
 | |
|     pScreen->CloseScreen = xf86FBCloseScreen;
 | |
| 
 | |
|     offman->InitialBoxes = RegionCreate(NULL, 1);
 | |
|     offman->FreeBoxes = RegionCreate(NULL, 1);
 | |
| 
 | |
|     RegionCopy(offman->InitialBoxes, FullRegion);
 | |
|     RegionCopy(offman->FreeBoxes, FullRegion);
 | |
| 
 | |
|     offman->pScreen = pScreen;
 | |
|     offman->UsedAreas = NULL;
 | |
|     offman->LinearAreas = NULL;
 | |
|     offman->NumUsedAreas = 0;
 | |
|     offman->devPrivates = NULL;
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| xf86InitFBManagerLinear(ScreenPtr pScreen, int offset, int size)
 | |
| {
 | |
|     FBManagerPtr offman;
 | |
|     FBLinearLinkPtr link;
 | |
|     FBLinearPtr linear;
 | |
| 
 | |
|     if (size <= 0)
 | |
|         return FALSE;
 | |
| 
 | |
|     /* we expect people to have called the Area setup first for pixmap cache */
 | |
|     if (!dixLookupPrivate(&pScreen->devPrivates, xf86FBScreenKey))
 | |
|         return FALSE;
 | |
| 
 | |
|     offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
 | |
|                                              xf86FBScreenKey);
 | |
|     offman->LinearAreas = malloc(sizeof(FBLinearLink));
 | |
|     if (!offman->LinearAreas)
 | |
|         return FALSE;
 | |
| 
 | |
|     link = offman->LinearAreas;
 | |
|     link->area = NULL;
 | |
|     link->next = NULL;
 | |
|     link->free = 1;
 | |
|     linear = &(link->linear);
 | |
|     linear->pScreen = pScreen;
 | |
|     linear->size = size;
 | |
|     linear->offset = offset;
 | |
|     linear->granularity = 0;
 | |
|     linear->MoveLinearCallback = NULL;
 | |
|     linear->RemoveLinearCallback = NULL;
 | |
|     linear->devPrivate.ptr = NULL;
 | |
| 
 | |
|     return TRUE;
 | |
| }
 |