summaryrefslogtreecommitdiff
path: root/hw/xfree86/common/xf86fbman.c
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-25 19:29:01 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-25 19:29:01 +0000
commitadc7f9a4ebdfe11d4cd6de9388b63dfe36450b39 (patch)
tree23eb7becc5360b2cbe16aa8d45529880067f3989 /hw/xfree86/common/xf86fbman.c
parent90f1536dd315cd265bfc7ef35058761a65a01734 (diff)
XFree86 4.3.99.16 Bring the tree up to date for the Cygwin folksxf86-4_3_99_16
Diffstat (limited to 'hw/xfree86/common/xf86fbman.c')
-rw-r--r--hw/xfree86/common/xf86fbman.c315
1 files changed, 261 insertions, 54 deletions
diff --git a/hw/xfree86/common/xf86fbman.c b/hw/xfree86/common/xf86fbman.c
index 7f4cffaae..b7c4afa1c 100644
--- a/hw/xfree86/common/xf86fbman.c
+++ b/hw/xfree86/common/xf86fbman.c
@@ -1,4 +1,31 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86fbman.c,v 1.24 2001/12/05 19:23:52 mvojkovi Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86fbman.c,v 1.28 2003/11/03 05:11:03 tsi Exp $ */
+
+/*
+ * 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).
+ */
#include "misc.h"
#include "xf86.h"
@@ -8,6 +35,10 @@
#include "regionstr.h"
#include "xf86fbman.h"
+/*
+#define DEBUG
+*/
+
static int xf86FBMangerIndex = -1;
static unsigned long xf86ManagerGeneration = 0;
@@ -118,19 +149,19 @@ xf86FreeOffscreenArea(FBAreaPtr area)
void
-xf86FreeOffscreenLinear(FBLinearPtr area)
+xf86FreeOffscreenLinear(FBLinearPtr linear)
{
FBManagerFuncsPtr funcs;
- if(!area) return;
+ if(!linear) return;
if(xf86FBMangerIndex < 0)
return;
if(!(funcs =
- (FBManagerFuncsPtr)area->pScreen->devPrivates[xf86FBMangerIndex].ptr))
+ (FBManagerFuncsPtr)linear->pScreen->devPrivates[xf86FBMangerIndex].ptr))
return;
- (*funcs->FreeOffscreenLinear)(area);
+ (*funcs->FreeOffscreenLinear)(linear);
return;
}
@@ -244,18 +275,19 @@ typedef struct _FBLink {
} FBLink, *FBLinkPtr;
typedef struct _FBLinearLink {
- FBLinear linear;
- FBAreaPtr area;
+ 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;
+ ScreenPtr pScreen;
+ RegionPtr InitialBoxes;
+ RegionPtr FreeBoxes;
+ FBLinkPtr UsedAreas;
+ int NumUsedAreas;
FBLinearLinkPtr LinearAreas;
CloseScreenProcPtr CloseScreen;
int NumCallbacks;
@@ -772,6 +804,97 @@ LinearRemoveCBWrapper(FBAreaPtr area)
xfree(pLink);
}
+#ifdef DEBUG
+static void
+Dump(FBLinearLinkPtr pLink)
+{
+ 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,
+ pointer 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 + 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 = xalloc(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 = xalloc(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;
+
+#ifdef DEBUG
+ Dump(offman->LinearAreas);
+#endif
+
+ return &(linear->linear);
+}
static FBLinearPtr
localAllocateOffscreenLinear(
@@ -791,28 +914,21 @@ localAllocateOffscreenLinear(
offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
- if(!(link = xalloc(sizeof(FBLinearLink))))
- return NULL;
+ /* Try to allocate from linear memory first...... */
+#ifdef DEBUG
+ ErrorF("ALLOCATING LINEAR\n");
+#endif
+ if ((linear = AllocateLinear(offman, length, gran, privData)))
+ return linear;
-#if 0
- if(we have linear heap space) {
- if(able to allocate some) {
- link->area = NULL;
- link->next = offman->LinearAreas;
- offman->LinearAreas = link;
- linear = link->linear;
- linear->pScreen = pScreen;
- linear->size = length;
- linear->offset = ????;
- linear->granularity = gran;
- linear->MoveLinearAreaCallback = moveCB;
- linear->RemoveLinearAreaCallback = removeCB;
- linear->devPrivate.ptr = privData;
- return linear;
- } /* else fallthrough */
- }
+#ifdef DEBUG
+ ErrorF("NOPE, ALLOCATING AREA\n");
#endif
+ if(!(link = xalloc(sizeof(FBLinearLink))))
+ return NULL;
+
+ /* No linear available, so try and pinch some from the XY areas */
extents = REGION_EXTENTS(pScreen, offman->InitialBoxes);
pitch = extents->x2 - extents->x1;
@@ -836,6 +952,7 @@ localAllocateOffscreenLinear(
privData)))
{
link->area = area;
+ link->free = 0;
link->next = offman->LinearAreas;
offman->LinearAreas = link;
linear = &(link->linear);
@@ -849,6 +966,10 @@ localAllocateOffscreenLinear(
} else
xfree(link);
+#ifdef DEBUG
+ Dump(offman->LinearAreas);
+#endif
+
return linear;
}
@@ -861,7 +982,7 @@ localFreeOffscreenLinear(FBLinearPtr linear)
ScreenPtr pScreen = linear->pScreen;
offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
-
+
pLink = offman->LinearAreas;
if(!pLink) return;
@@ -872,16 +993,42 @@ localFreeOffscreenLinear(FBLinearPtr linear)
}
if(pLink->area) { /* really an XY area */
- localFreeOffscreenArea(pLink->area);
- } else {
- /* free the linear area */
+#ifdef DEBUG
+ ErrorF("FREEING AREA\n");
+#endif
+ localFreeOffscreenArea(pLink->area);
+ if(pLinkPrev)
+ pLinkPrev->next = pLink->next;
+ else offman->LinearAreas = pLink->next;
+ xfree(pLink);
+#ifdef DEBUG
+ Dump(offman->LinearAreas);
+#endif
+ return;
}
- if(pLinkPrev)
- pLinkPrev->next = pLink->next;
- else offman->LinearAreas = pLink->next;
+ pLink->free = 1;
- xfree(pLink);
+ 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);
+ }
+ }
+
+#ifdef DEBUG
+ ErrorF("FREEING LINEAR\n");
+ Dump(offman->LinearAreas);
+#endif
}
@@ -889,7 +1036,7 @@ static Bool
localResizeOffscreenLinear(FBLinearPtr resize, int length)
{
FBManagerPtr offman;
- FBLinearLinkPtr pLink, pLinkPrev = NULL;
+ FBLinearLinkPtr pLink;
ScreenPtr pScreen = resize->pScreen;
offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
@@ -898,7 +1045,6 @@ localResizeOffscreenLinear(FBLinearPtr resize, int length)
if(!pLink) return FALSE;
while(&(pLink->linear) != resize) {
- pLinkPrev = pLink;
pLink = pLink->next;
if(!pLink) return FALSE;
}
@@ -928,7 +1074,7 @@ localResizeOffscreenLinear(FBLinearPtr resize, int length)
return TRUE;
}
} else {
- /* resize the linear area */
+ /* TODO!!!! resize the linear area */
}
return FALSE;
@@ -943,22 +1089,45 @@ localQueryLargestOffscreenLinear(
int priority
)
{
- int w, h;
+ FBManagerPtr offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+ FBLinearLinkPtr pLink;
+ FBLinearLinkPtr pLinkRet;
*size = 0;
+
+ if (!offman->LinearAreas) return FALSE;
- /* for now, we only look at XY space */
- if(localQueryLargestOffscreenArea(pScreen, &w, &h, gran,
- FAVOR_WIDTH_THEN_AREA, priority))
- {
- FBManagerPtr offman;
- BoxPtr extents;
+ pLink = offman->LinearAreas;
+ pLinkRet = pLink;
- offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
- extents = REGION_EXTENTS(pScreen, offman->InitialBoxes);
- if((extents->x2 - extents->x1) == w)
- *size = w * h;
- return TRUE;
+ if (!pLink->area) {
+ 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))
+ {
+ FBManagerPtr offman;
+ BoxPtr extents;
+
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+ extents = REGION_EXTENTS(pScreen, offman->InitialBoxes);
+ if((extents->x2 - extents->x1) == w)
+ *size = w * h;
+ return TRUE;
+ }
}
return FALSE;
@@ -1189,6 +1358,44 @@ xf86InitFBManagerRegion(
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 (!pScreen->devPrivates[xf86FBScreenIndex].ptr)
+ return FALSE;
+
+ offman = pScreen->devPrivates[xf86FBScreenIndex].ptr;
+
+ offman->LinearAreas = xalloc(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;
+}
/* This is an implementation specific function and should