3 * Copyright (c) 1998-2001 by The XFree86 Project, Inc.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
23 * Except as contained in this notice, the name of the copyright holder(s)
24 * and author(s) shall not be used in advertising or otherwise to promote
25 * the sale, use or other dealings in this Software without prior written
26 * authorization from the copyright holder(s) and author(s).
29 #ifdef HAVE_XORG_CONFIG_H
30 #include <xorg-config.h>
37 #include "scrnintstr.h"
38 #include "regionstr.h"
39 #include "xf86fbman.h"
45 static DevPrivateKeyRec xf86FBManagerKeyRec
;
46 static DevPrivateKey xf86FBManagerKey
;
49 xf86RegisterOffscreenManager(ScreenPtr pScreen
, FBManagerFuncsPtr funcs
)
52 xf86FBManagerKey
= &xf86FBManagerKeyRec
;
54 if (!dixRegisterPrivateKey(&xf86FBManagerKeyRec
, PRIVATE_SCREEN
, 0))
57 dixSetPrivate(&pScreen
->devPrivates
, xf86FBManagerKey
, funcs
);
63 xf86FBManagerRunning(ScreenPtr pScreen
)
65 if (xf86FBManagerKey
== NULL
)
68 if (!dixLookupPrivate(&pScreen
->devPrivates
, xf86FBManagerKey
))
75 xf86RegisterFreeBoxCallback(ScreenPtr pScreen
,
76 FreeBoxCallbackProcPtr FreeBoxCallback
,
79 FBManagerFuncsPtr funcs
;
81 if (xf86FBManagerKey
== NULL
)
83 if (!(funcs
= (FBManagerFuncsPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
87 return (*funcs
->RegisterFreeBoxCallback
) (pScreen
, FreeBoxCallback
,
92 xf86AllocateOffscreenArea(ScreenPtr pScreen
,
95 MoveAreaCallbackProcPtr moveCB
,
96 RemoveAreaCallbackProcPtr removeCB
, pointer privData
)
98 FBManagerFuncsPtr funcs
;
100 if (xf86FBManagerKey
== NULL
)
102 if (!(funcs
= (FBManagerFuncsPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
106 return (*funcs
->AllocateOffscreenArea
) (pScreen
, w
, h
, gran
, moveCB
,
111 xf86AllocateOffscreenLinear(ScreenPtr pScreen
,
114 MoveLinearCallbackProcPtr moveCB
,
115 RemoveLinearCallbackProcPtr removeCB
,
118 FBManagerFuncsPtr funcs
;
120 if (xf86FBManagerKey
== NULL
)
122 if (!(funcs
= (FBManagerFuncsPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
126 return (*funcs
->AllocateOffscreenLinear
) (pScreen
, length
, gran
, moveCB
,
131 xf86FreeOffscreenArea(FBAreaPtr area
)
133 FBManagerFuncsPtr funcs
;
138 if (xf86FBManagerKey
== NULL
)
142 (FBManagerFuncsPtr
) dixLookupPrivate(&area
->pScreen
->devPrivates
,
146 (*funcs
->FreeOffscreenArea
) (area
);
152 xf86FreeOffscreenLinear(FBLinearPtr linear
)
154 FBManagerFuncsPtr funcs
;
159 if (xf86FBManagerKey
== NULL
)
163 (FBManagerFuncsPtr
) dixLookupPrivate(&linear
->pScreen
->devPrivates
,
167 (*funcs
->FreeOffscreenLinear
) (linear
);
173 xf86ResizeOffscreenArea(FBAreaPtr resize
, int w
, int h
)
175 FBManagerFuncsPtr funcs
;
180 if (xf86FBManagerKey
== NULL
)
184 (FBManagerFuncsPtr
) dixLookupPrivate(&resize
->pScreen
->devPrivates
,
188 return (*funcs
->ResizeOffscreenArea
) (resize
, w
, h
);
192 xf86ResizeOffscreenLinear(FBLinearPtr resize
, int size
)
194 FBManagerFuncsPtr funcs
;
199 if (xf86FBManagerKey
== NULL
)
203 (FBManagerFuncsPtr
) dixLookupPrivate(&resize
->pScreen
->devPrivates
,
207 return (*funcs
->ResizeOffscreenLinear
) (resize
, size
);
211 xf86QueryLargestOffscreenArea(ScreenPtr pScreen
,
213 int gran
, int preferences
, int severity
)
215 FBManagerFuncsPtr funcs
;
220 if (xf86FBManagerKey
== NULL
)
222 if (!(funcs
= (FBManagerFuncsPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
226 return (*funcs
->QueryLargestOffscreenArea
) (pScreen
, w
, h
, gran
,
227 preferences
, severity
);
231 xf86QueryLargestOffscreenLinear(ScreenPtr pScreen
,
232 int *size
, int gran
, int severity
)
234 FBManagerFuncsPtr funcs
;
238 if (xf86FBManagerKey
== NULL
)
240 if (!(funcs
= (FBManagerFuncsPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
244 return (*funcs
->QueryLargestOffscreenLinear
) (pScreen
, size
, gran
,
249 xf86PurgeUnlockedOffscreenAreas(ScreenPtr pScreen
)
251 FBManagerFuncsPtr funcs
;
253 if (xf86FBManagerKey
== NULL
)
255 if (!(funcs
= (FBManagerFuncsPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
259 return (*funcs
->PurgeOffscreenAreas
) (pScreen
);
262 /************************************************************\
264 Below is a specific implementation of an offscreen manager.
266 \************************************************************/
268 static DevPrivateKeyRec xf86FBScreenKeyRec
;
270 #define xf86FBScreenKey (&xf86FBScreenKeyRec)
272 typedef struct _FBLink
{
274 struct _FBLink
*next
;
275 } FBLink
, *FBLinkPtr
;
277 typedef struct _FBLinearLink
{
279 int free
; /* need to add free here as FBLinear is publicly accessible */
280 FBAreaPtr area
; /* only used if allocation came from XY area */
281 struct _FBLinearLink
*next
;
282 } FBLinearLink
, *FBLinearLinkPtr
;
286 RegionPtr InitialBoxes
;
290 FBLinearLinkPtr LinearAreas
;
291 CloseScreenProcPtr CloseScreen
;
293 FreeBoxCallbackProcPtr
*FreeBoxesUpdateCallback
;
294 DevUnion
*devPrivates
;
295 } FBManager
, *FBManagerPtr
;
298 SendCallFreeBoxCallbacks(FBManagerPtr offman
)
300 int i
= offman
->NumCallbacks
;
303 (*offman
->FreeBoxesUpdateCallback
[i
]) (offman
->pScreen
,
305 offman
->devPrivates
[i
].ptr
);
310 localRegisterFreeBoxCallback(ScreenPtr pScreen
,
311 FreeBoxCallbackProcPtr FreeBoxCallback
,
315 FreeBoxCallbackProcPtr
*newCallbacks
;
316 DevUnion
*newPrivates
;
318 offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
320 newCallbacks
= realloc(offman
->FreeBoxesUpdateCallback
,
321 sizeof(FreeBoxCallbackProcPtr
) *
322 (offman
->NumCallbacks
+ 1));
326 offman
->FreeBoxesUpdateCallback
= newCallbacks
;
328 newPrivates
= realloc(offman
->devPrivates
,
329 sizeof(DevUnion
) * (offman
->NumCallbacks
+ 1));
333 offman
->devPrivates
= newPrivates
;
335 offman
->FreeBoxesUpdateCallback
[offman
->NumCallbacks
] = FreeBoxCallback
;
336 offman
->devPrivates
[offman
->NumCallbacks
].ptr
= devPriv
;
337 offman
->NumCallbacks
++;
339 SendCallFreeBoxCallbacks(offman
);
345 AllocateArea(FBManagerPtr offman
,
348 MoveAreaCallbackProcPtr moveCB
,
349 RemoveAreaCallbackProcPtr removeCB
, pointer privData
)
351 ScreenPtr pScreen
= offman
->pScreen
;
352 FBLinkPtr link
= NULL
;
353 FBAreaPtr area
= NULL
;
358 if (granularity
<= 1)
361 boxp
= RegionRects(offman
->FreeBoxes
);
362 num
= RegionNumRects(offman
->FreeBoxes
);
364 /* look through the free boxes */
365 for (i
= 0; i
< num
; i
++, boxp
++) {
368 x
= ((x
+ granularity
- 1) / granularity
) * granularity
;
370 if (((boxp
->y2
- boxp
->y1
) < h
) || ((boxp
->x2
- x
) < w
))
373 link
= malloc(sizeof(FBLink
));
377 area
= &(link
->area
);
378 link
->next
= offman
->UsedAreas
;
379 offman
->UsedAreas
= link
;
380 offman
->NumUsedAreas
++;
384 /* try to boot a removeable one out if we are not expendable ourselves */
385 if (!area
&& !removeCB
) {
386 link
= offman
->UsedAreas
;
389 if (!link
->area
.RemoveAreaCallback
) {
394 boxp
= &(link
->area
.box
);
397 x
= ((x
+ granularity
- 1) / granularity
) * granularity
;
399 if (((boxp
->y2
- boxp
->y1
) < h
) || ((boxp
->x2
- x
) < w
)) {
405 (*link
->area
.RemoveAreaCallback
) (&link
->area
);
406 RegionInit(&NewReg
, &(link
->area
.box
), 1);
407 RegionUnion(offman
->FreeBoxes
, offman
->FreeBoxes
, &NewReg
);
408 RegionUninit(&NewReg
);
410 area
= &(link
->area
);
416 area
->pScreen
= pScreen
;
417 area
->granularity
= granularity
;
419 area
->box
.x2
= x
+ w
;
420 area
->box
.y1
= boxp
->y1
;
421 area
->box
.y2
= boxp
->y1
+ h
;
422 area
->MoveAreaCallback
= moveCB
;
423 area
->RemoveAreaCallback
= removeCB
;
424 area
->devPrivate
.ptr
= privData
;
426 RegionInit(&NewReg
, &(area
->box
), 1);
427 RegionSubtract(offman
->FreeBoxes
, offman
->FreeBoxes
, &NewReg
);
428 RegionUninit(&NewReg
);
435 localAllocateOffscreenArea(ScreenPtr pScreen
,
438 MoveAreaCallbackProcPtr moveCB
,
439 RemoveAreaCallbackProcPtr removeCB
, pointer privData
)
442 FBAreaPtr area
= NULL
;
444 offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
446 if ((area
= AllocateArea(offman
, w
, h
, gran
, moveCB
, removeCB
, privData
)))
447 SendCallFreeBoxCallbacks(offman
);
453 localFreeOffscreenArea(FBAreaPtr area
)
456 FBLinkPtr pLink
, pLinkPrev
= NULL
;
457 RegionRec FreedRegion
;
460 pScreen
= area
->pScreen
;
461 offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
463 pLink
= offman
->UsedAreas
;
467 while (&(pLink
->area
) != area
) {
474 /* put the area back into the pool */
475 RegionInit(&FreedRegion
, &(pLink
->area
.box
), 1);
476 RegionUnion(offman
->FreeBoxes
, offman
->FreeBoxes
, &FreedRegion
);
477 RegionUninit(&FreedRegion
);
480 pLinkPrev
->next
= pLink
->next
;
482 offman
->UsedAreas
= pLink
->next
;
485 offman
->NumUsedAreas
--;
487 SendCallFreeBoxCallbacks(offman
);
491 localResizeOffscreenArea(FBAreaPtr resize
, int w
, int h
)
497 FBAreaPtr area
= NULL
;
498 FBLinkPtr pLink
, newLink
, pLinkPrev
= NULL
;
500 pScreen
= resize
->pScreen
;
501 offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
504 if (!(pLink
= offman
->UsedAreas
))
507 while (&(pLink
->area
) != resize
) {
514 OrigArea
.x1
= resize
->box
.x1
;
515 OrigArea
.x2
= resize
->box
.x2
;
516 OrigArea
.y1
= resize
->box
.y1
;
517 OrigArea
.y2
= resize
->box
.y2
;
519 /* if it's smaller, this is easy */
521 if ((w
<= (resize
->box
.x2
- resize
->box
.x1
)) &&
522 (h
<= (resize
->box
.y2
- resize
->box
.y1
))) {
525 resize
->box
.x2
= resize
->box
.x1
+ w
;
526 resize
->box
.y2
= resize
->box
.y1
+ h
;
528 if ((resize
->box
.y2
== OrigArea
.y2
) && (resize
->box
.x2
== OrigArea
.x2
))
531 RegionInit(&FreedReg
, &OrigArea
, 1);
532 RegionInit(&NewReg
, &(resize
->box
), 1);
533 RegionSubtract(&FreedReg
, &FreedReg
, &NewReg
);
534 RegionUnion(offman
->FreeBoxes
, offman
->FreeBoxes
, &FreedReg
);
535 RegionUninit(&FreedReg
);
536 RegionUninit(&NewReg
);
538 SendCallFreeBoxCallbacks(offman
);
543 /* otherwise we remove the old region */
545 RegionInit(&FreedReg
, &OrigArea
, 1);
546 RegionUnion(offman
->FreeBoxes
, offman
->FreeBoxes
, &FreedReg
);
548 /* remove the old link */
550 pLinkPrev
->next
= pLink
->next
;
552 offman
->UsedAreas
= pLink
->next
;
554 /* and try to add a new one */
556 if ((area
= AllocateArea(offman
, w
, h
, resize
->granularity
,
557 resize
->MoveAreaCallback
,
558 resize
->RemoveAreaCallback
,
559 resize
->devPrivate
.ptr
))) {
561 /* copy data over to our link and replace the new with old */
562 memcpy(resize
, area
, sizeof(FBArea
));
565 newLink
= offman
->UsedAreas
;
567 while (&(newLink
->area
) != area
) {
569 newLink
= newLink
->next
;
573 pLinkPrev
->next
= newLink
->next
;
575 offman
->UsedAreas
= newLink
->next
;
577 pLink
->next
= offman
->UsedAreas
;
578 offman
->UsedAreas
= pLink
;
582 /* AllocateArea added one but we really only exchanged one */
583 offman
->NumUsedAreas
--;
586 /* reinstate the old region */
587 RegionSubtract(offman
->FreeBoxes
, offman
->FreeBoxes
, &FreedReg
);
588 RegionUninit(&FreedReg
);
590 pLink
->next
= offman
->UsedAreas
;
591 offman
->UsedAreas
= pLink
;
595 RegionUninit(&FreedReg
);
597 SendCallFreeBoxCallbacks(offman
);
603 localQueryLargestOffscreenArea(ScreenPtr pScreen
,
604 int *width
, int *height
,
605 int granularity
, int preferences
, int severity
)
608 RegionPtr newRegion
= NULL
;
611 int x
, w
, h
, area
, oldArea
;
613 *width
= *height
= oldArea
= 0;
615 if (granularity
<= 1)
618 if ((preferences
< 0) || (preferences
> 3))
621 offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
630 if (offman
->NumUsedAreas
) {
634 newRegion
= RegionCreate(NULL
, 1);
635 RegionCopy(newRegion
, offman
->InitialBoxes
);
636 pLink
= offman
->UsedAreas
;
639 if (!pLink
->area
.RemoveAreaCallback
) {
640 RegionInit(&tmpRegion
, &(pLink
->area
.box
), 1);
641 RegionSubtract(newRegion
, newRegion
, &tmpRegion
);
642 RegionUninit(&tmpRegion
);
647 nbox
= RegionNumRects(newRegion
);
648 pbox
= RegionRects(newRegion
);
652 if (offman
->NumUsedAreas
) {
656 newRegion
= RegionCreate(NULL
, 1);
657 RegionCopy(newRegion
, offman
->FreeBoxes
);
658 pLink
= offman
->UsedAreas
;
661 if (pLink
->area
.RemoveAreaCallback
) {
662 RegionInit(&tmpRegion
, &(pLink
->area
.box
), 1);
663 RegionAppend(newRegion
, &tmpRegion
);
664 RegionUninit(&tmpRegion
);
669 nbox
= RegionNumRects(newRegion
);
670 pbox
= RegionRects(newRegion
);
674 nbox
= RegionNumRects(offman
->FreeBoxes
);
675 pbox
= RegionRects(offman
->FreeBoxes
);
682 x
= ((x
+ granularity
- 1) / granularity
) * granularity
;
685 h
= pbox
->y2
- pbox
->y1
;
691 switch (preferences
) {
692 case FAVOR_AREA_THEN_WIDTH
:
693 if ((area
> oldArea
) || ((area
== oldArea
) && (w
> *width
)))
696 case FAVOR_AREA_THEN_HEIGHT
:
697 if ((area
> oldArea
) || ((area
== oldArea
) && (h
> *height
)))
700 case FAVOR_WIDTH_THEN_AREA
:
701 if ((w
> *width
) || ((w
== *width
) && (area
> oldArea
)))
704 case FAVOR_HEIGHT_THEN_AREA
:
705 if ((h
> *height
) || ((h
== *height
) && (area
> oldArea
)))
719 RegionDestroy(newRegion
);
725 localPurgeUnlockedOffscreenAreas(ScreenPtr pScreen
)
728 FBLinkPtr pLink
, tmp
, pPrev
= NULL
;
729 RegionRec FreedRegion
;
730 Bool anyUsed
= FALSE
;
732 offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
734 pLink
= offman
->UsedAreas
;
739 if (pLink
->area
.RemoveAreaCallback
) {
740 (*pLink
->area
.RemoveAreaCallback
) (&pLink
->area
);
742 RegionInit(&FreedRegion
, &(pLink
->area
.box
), 1);
743 RegionAppend(offman
->FreeBoxes
, &FreedRegion
);
744 RegionUninit(&FreedRegion
);
747 pPrev
->next
= pLink
->next
;
749 offman
->UsedAreas
= pLink
->next
;
754 offman
->NumUsedAreas
--;
764 RegionValidate(offman
->FreeBoxes
, &anyUsed
);
765 SendCallFreeBoxCallbacks(offman
);
772 LinearMoveCBWrapper(FBAreaPtr from
, FBAreaPtr to
)
774 /* this will never get called */
778 LinearRemoveCBWrapper(FBAreaPtr area
)
781 FBLinearLinkPtr pLink
, pLinkPrev
= NULL
;
782 ScreenPtr pScreen
= area
->pScreen
;
784 offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
786 pLink
= offman
->LinearAreas
;
790 while (pLink
->area
!= area
) {
797 /* give the user the callback it is expecting */
798 (*pLink
->linear
.RemoveLinearCallback
) (&(pLink
->linear
));
801 pLinkPrev
->next
= pLink
->next
;
803 offman
->LinearAreas
= pLink
->next
;
809 DumpDebug(FBLinearLinkPtr pLink
)
813 ErrorF("MMmm, PLINK IS NULL!\n");
816 ErrorF(" Offset:%08x, Size:%08x, %s,%s\n",
817 pLink
->linear
.offset
,
819 pLink
->free
? "Free" : "Used", pLink
->area
? "Area" : "Linear");
827 AllocateLinear(FBManagerPtr offman
, int size
, int granularity
, pointer privData
)
829 ScreenPtr pScreen
= offman
->pScreen
;
830 FBLinearLinkPtr linear
= NULL
;
831 FBLinearLinkPtr newlink
= NULL
;
837 if (!offman
->LinearAreas
)
840 linear
= offman
->LinearAreas
;
842 /* Make sure we get a free area that's not an XY fallback case */
843 if (!linear
->area
&& linear
->free
) {
844 offset
= linear
->linear
.offset
;
847 ((offset
+ granularity
- 1) / granularity
) * granularity
;
849 if (end
<= (linear
->linear
.offset
+ linear
->linear
.size
))
852 linear
= linear
->next
;
858 if (offset
> linear
->linear
.offset
) {
859 newlink
= malloc(sizeof(FBLinearLink
));
862 newlink
->area
= NULL
;
863 newlink
->linear
.offset
= offset
;
864 newlink
->linear
.size
=
865 linear
->linear
.size
- (offset
- linear
->linear
.offset
);
867 newlink
->next
= linear
->next
;
868 linear
->linear
.size
-= newlink
->linear
.size
;
869 linear
->next
= newlink
;
874 if (size
< linear
->linear
.size
) {
875 newlink
= malloc(sizeof(FBLinearLink
));
878 newlink
->area
= NULL
;
879 newlink
->linear
.offset
= offset
+ size
;
880 newlink
->linear
.size
= linear
->linear
.size
- size
;
882 newlink
->next
= linear
->next
;
883 linear
->linear
.size
= size
;
884 linear
->next
= newlink
;
887 /* p = middle block */
888 linear
->linear
.granularity
= granularity
;
890 linear
->linear
.pScreen
= pScreen
;
891 linear
->linear
.MoveLinearCallback
= NULL
;
892 linear
->linear
.RemoveLinearCallback
= NULL
;
893 linear
->linear
.devPrivate
.ptr
= NULL
;
895 DumpDebug(offman
->LinearAreas
);
897 return &(linear
->linear
);
901 localAllocateOffscreenLinear(ScreenPtr pScreen
,
904 MoveLinearCallbackProcPtr moveCB
,
905 RemoveLinearCallbackProcPtr removeCB
,
909 FBLinearLinkPtr link
;
911 FBLinearPtr linear
= NULL
;
915 offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
918 /* Try to allocate from linear memory first...... */
919 DebugF("ALLOCATING LINEAR\n");
920 if ((linear
= AllocateLinear(offman
, length
, gran
, privData
)))
923 DebugF("NOPE, ALLOCATING AREA\n");
925 if (!(link
= malloc(sizeof(FBLinearLink
))))
928 /* No linear available, so try and pinch some from the XY areas */
929 extents
= RegionExtents(offman
->InitialBoxes
);
930 pitch
= extents
->x2
- extents
->x1
;
934 /* we can't match the specified alignment with XY allocations */
940 /* pitch and granularity aren't a perfect match, let's allocate
941 * a bit more so we can align later on
947 if (length
< pitch
) { /* special case */
953 h
= (length
+ pitch
- 1) / pitch
;
956 if ((area
= localAllocateOffscreenArea(pScreen
, w
, h
, gran
,
957 moveCB
? LinearMoveCBWrapper
: NULL
,
958 removeCB
? LinearRemoveCBWrapper
:
962 link
->next
= offman
->LinearAreas
;
963 offman
->LinearAreas
= link
;
964 linear
= &(link
->linear
);
965 linear
->pScreen
= pScreen
;
966 linear
->size
= h
* w
;
967 linear
->offset
= (pitch
* area
->box
.y1
) + area
->box
.x1
;
969 linear
->offset
= ((linear
->offset
+ gran
- 1) / gran
) * gran
;
970 linear
->granularity
= gran
;
971 linear
->MoveLinearCallback
= moveCB
;
972 linear
->RemoveLinearCallback
= removeCB
;
973 linear
->devPrivate
.ptr
= privData
;
978 DumpDebug(offman
->LinearAreas
);
984 localFreeOffscreenLinear(FBLinearPtr linear
)
987 FBLinearLinkPtr pLink
, pLinkPrev
= NULL
;
988 ScreenPtr pScreen
= linear
->pScreen
;
990 offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
992 pLink
= offman
->LinearAreas
;
996 while (&(pLink
->linear
) != linear
) {
1003 if (pLink
->area
) { /* really an XY area */
1004 DebugF("FREEING AREA\n");
1005 localFreeOffscreenArea(pLink
->area
);
1007 pLinkPrev
->next
= pLink
->next
;
1009 offman
->LinearAreas
= pLink
->next
;
1011 DumpDebug(offman
->LinearAreas
);
1017 if (pLink
->next
&& pLink
->next
->free
) {
1018 FBLinearLinkPtr p
= pLink
->next
;
1020 pLink
->linear
.size
+= p
->linear
.size
;
1021 pLink
->next
= p
->next
;
1026 if (pLinkPrev
->next
&& pLinkPrev
->next
->free
&& !pLinkPrev
->area
) {
1027 FBLinearLinkPtr p
= pLinkPrev
->next
;
1029 pLinkPrev
->linear
.size
+= p
->linear
.size
;
1030 pLinkPrev
->next
= p
->next
;
1035 DebugF("FREEING LINEAR\n");
1036 DumpDebug(offman
->LinearAreas
);
1040 localResizeOffscreenLinear(FBLinearPtr resize
, int length
)
1042 FBManagerPtr offman
;
1043 FBLinearLinkPtr pLink
;
1044 ScreenPtr pScreen
= resize
->pScreen
;
1046 offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
1048 pLink
= offman
->LinearAreas
;
1052 while (&(pLink
->linear
) != resize
) {
1053 pLink
= pLink
->next
;
1058 /* This could actually be alot smarter and try to move allocations
1059 from XY to linear when available. For now if it was XY, we keep
1062 if (pLink
->area
) { /* really an XY area */
1066 extents
= RegionExtents(offman
->InitialBoxes
);
1067 pitch
= extents
->x2
- extents
->x1
;
1069 if (length
< pitch
) { /* special case */
1075 h
= (length
+ pitch
- 1) / pitch
;
1078 if (localResizeOffscreenArea(pLink
->area
, w
, h
)) {
1079 resize
->size
= h
* w
;
1081 (pitch
* pLink
->area
->box
.y1
) + pLink
->area
->box
.x1
;
1086 /* TODO!!!! resize the linear area */
1093 localQueryLargestOffscreenLinear(ScreenPtr pScreen
,
1094 int *size
, int gran
, int priority
)
1096 FBManagerPtr offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
1098 FBLinearLinkPtr pLink
;
1099 FBLinearLinkPtr pLinkRet
;
1103 pLink
= offman
->LinearAreas
;
1105 if (pLink
&& !pLink
->area
) {
1109 if (pLink
->linear
.size
> pLinkRet
->linear
.size
)
1112 pLink
= pLink
->next
;
1115 if (pLinkRet
->free
) {
1116 *size
= pLinkRet
->linear
.size
;
1123 if (localQueryLargestOffscreenArea(pScreen
, &w
, &h
, gran
,
1124 FAVOR_WIDTH_THEN_AREA
, priority
)) {
1125 FBManagerPtr offman
;
1128 offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
1130 extents
= RegionExtents(offman
->InitialBoxes
);
1131 if ((extents
->x2
- extents
->x1
) == w
)
1140 static FBManagerFuncs xf86FBManFuncs
= {
1141 localAllocateOffscreenArea
,
1142 localFreeOffscreenArea
,
1143 localResizeOffscreenArea
,
1144 localQueryLargestOffscreenArea
,
1145 localRegisterFreeBoxCallback
,
1146 localAllocateOffscreenLinear
,
1147 localFreeOffscreenLinear
,
1148 localResizeOffscreenLinear
,
1149 localQueryLargestOffscreenLinear
,
1150 localPurgeUnlockedOffscreenAreas
1154 xf86FBCloseScreen(ScreenPtr pScreen
)
1156 FBLinkPtr pLink
, tmp
;
1157 FBLinearLinkPtr pLinearLink
, tmp2
;
1158 FBManagerPtr offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
1161 pScreen
->CloseScreen
= offman
->CloseScreen
;
1163 pLink
= offman
->UsedAreas
;
1166 pLink
= pLink
->next
;
1170 pLinearLink
= offman
->LinearAreas
;
1171 while (pLinearLink
) {
1173 pLinearLink
= pLinearLink
->next
;
1177 RegionDestroy(offman
->InitialBoxes
);
1178 RegionDestroy(offman
->FreeBoxes
);
1180 free(offman
->FreeBoxesUpdateCallback
);
1181 free(offman
->devPrivates
);
1183 dixSetPrivate(&pScreen
->devPrivates
, xf86FBScreenKey
, NULL
);
1185 return (*pScreen
->CloseScreen
) (pScreen
);
1189 xf86InitFBManager(ScreenPtr pScreen
, BoxPtr FullBox
)
1191 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1192 RegionRec ScreenRegion
;
1193 RegionRec FullRegion
;
1199 ScreenBox
.x2
= pScrn
->virtualX
;
1200 ScreenBox
.y2
= pScrn
->virtualY
;
1202 if ((FullBox
->x1
> ScreenBox
.x1
) || (FullBox
->y1
> ScreenBox
.y1
) ||
1203 (FullBox
->x2
< ScreenBox
.x2
) || (FullBox
->y2
< ScreenBox
.y2
)) {
1207 if (FullBox
->y2
< FullBox
->y1
)
1209 if (FullBox
->x2
< FullBox
->x1
)
1212 RegionInit(&ScreenRegion
, &ScreenBox
, 1);
1213 RegionInit(&FullRegion
, FullBox
, 1);
1215 RegionSubtract(&FullRegion
, &FullRegion
, &ScreenRegion
);
1217 ret
= xf86InitFBManagerRegion(pScreen
, &FullRegion
);
1219 RegionUninit(&ScreenRegion
);
1220 RegionUninit(&FullRegion
);
1226 xf86InitFBManagerArea(ScreenPtr pScreen
, int PixelArea
, int Verbosity
)
1228 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1230 RegionPtr pRegion
, pScreenRegion
;
1234 if (PixelArea
< (pScrn
->displayWidth
* pScrn
->virtualY
))
1237 Rect
[0].x
= Rect
[0].y
= 0;
1238 Rect
[0].width
= pScrn
->displayWidth
;
1239 Rect
[0].height
= PixelArea
/ pScrn
->displayWidth
;
1242 /* Add a possible partial scanline */
1243 if ((Rect
[1].height
= Rect
[1].width
= PixelArea
% pScrn
->displayWidth
)) {
1245 Rect
[1].y
= Rect
[0].height
;
1250 /* Factor out virtual resolution */
1251 pRegion
= RegionFromRects(nRect
, Rect
, 0);
1253 if (!RegionNar(pRegion
)) {
1254 Rect
[2].x
= Rect
[2].y
= 0;
1255 Rect
[2].width
= pScrn
->virtualX
;
1256 Rect
[2].height
= pScrn
->virtualY
;
1258 pScreenRegion
= RegionFromRects(1, &Rect
[2], 0);
1259 if (pScreenRegion
) {
1260 if (!RegionNar(pScreenRegion
)) {
1261 RegionSubtract(pRegion
, pRegion
, pScreenRegion
);
1263 ret
= xf86InitFBManagerRegion(pScreen
, pRegion
);
1265 if (ret
&& xf86GetVerbosity() >= Verbosity
) {
1266 int scrnIndex
= pScrn
->scrnIndex
;
1268 xf86DrvMsgVerb(scrnIndex
, X_INFO
, Verbosity
,
1269 "Largest offscreen areas (with overlaps):\n");
1271 if (Rect
[2].width
< Rect
[0].width
) {
1272 xf86DrvMsgVerb(scrnIndex
, X_INFO
, Verbosity
,
1273 "\t%d x %d rectangle at %d,0\n",
1274 Rect
[0].width
- Rect
[2].width
,
1275 Rect
[0].height
, Rect
[2].width
);
1277 if (Rect
[2].width
< Rect
[1].width
) {
1278 xf86DrvMsgVerb(scrnIndex
, X_INFO
, Verbosity
,
1279 "\t%d x %d rectangle at %d,0\n",
1280 Rect
[1].width
- Rect
[2].width
,
1281 Rect
[0].height
+ Rect
[1].height
,
1284 if (Rect
[2].height
< Rect
[0].height
) {
1285 xf86DrvMsgVerb(scrnIndex
, X_INFO
, Verbosity
,
1286 "\t%d x %d rectangle at 0,%d\n",
1288 Rect
[0].height
- Rect
[2].height
,
1291 if (Rect
[1].height
) {
1292 xf86DrvMsgVerb(scrnIndex
, X_INFO
, Verbosity
,
1293 "\t%d x %d rectangle at 0,%d\n",
1295 Rect
[0].height
- Rect
[2].height
+
1296 Rect
[1].height
, Rect
[2].height
);
1301 RegionDestroy(pScreenRegion
);
1305 RegionDestroy(pRegion
);
1312 xf86InitFBManagerRegion(ScreenPtr pScreen
, RegionPtr FullRegion
)
1314 FBManagerPtr offman
;
1316 if (RegionNil(FullRegion
))
1319 if (!dixRegisterPrivateKey(&xf86FBScreenKeyRec
, PRIVATE_SCREEN
, 0))
1322 if (!xf86RegisterOffscreenManager(pScreen
, &xf86FBManFuncs
))
1325 offman
= malloc(sizeof(FBManager
));
1329 dixSetPrivate(&pScreen
->devPrivates
, xf86FBScreenKey
, offman
);
1331 offman
->CloseScreen
= pScreen
->CloseScreen
;
1332 pScreen
->CloseScreen
= xf86FBCloseScreen
;
1334 offman
->InitialBoxes
= RegionCreate(NULL
, 1);
1335 offman
->FreeBoxes
= RegionCreate(NULL
, 1);
1337 RegionCopy(offman
->InitialBoxes
, FullRegion
);
1338 RegionCopy(offman
->FreeBoxes
, FullRegion
);
1340 offman
->pScreen
= pScreen
;
1341 offman
->UsedAreas
= NULL
;
1342 offman
->LinearAreas
= NULL
;
1343 offman
->NumUsedAreas
= 0;
1344 offman
->NumCallbacks
= 0;
1345 offman
->FreeBoxesUpdateCallback
= NULL
;
1346 offman
->devPrivates
= NULL
;
1352 xf86InitFBManagerLinear(ScreenPtr pScreen
, int offset
, int size
)
1354 FBManagerPtr offman
;
1355 FBLinearLinkPtr link
;
1361 /* we expect people to have called the Area setup first for pixmap cache */
1362 if (!dixLookupPrivate(&pScreen
->devPrivates
, xf86FBScreenKey
))
1365 offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
1367 offman
->LinearAreas
= malloc(sizeof(FBLinearLink
));
1368 if (!offman
->LinearAreas
)
1371 link
= offman
->LinearAreas
;
1375 linear
= &(link
->linear
);
1376 linear
->pScreen
= pScreen
;
1377 linear
->size
= size
;
1378 linear
->offset
= offset
;
1379 linear
->granularity
= 0;
1380 linear
->MoveLinearCallback
= NULL
;
1381 linear
->RemoveLinearCallback
= NULL
;
1382 linear
->devPrivate
.ptr
= NULL
;
1387 /* This is an implementation specific function and should
1388 disappear after the next release. People should use the
1389 real linear functions instead */
1392 xf86AllocateLinearOffscreenArea(ScreenPtr pScreen
,
1395 MoveAreaCallbackProcPtr moveCB
,
1396 RemoveAreaCallbackProcPtr removeCB
,
1399 FBManagerFuncsPtr funcs
;
1400 FBManagerPtr offman
;
1404 if (xf86FBManagerKey
== NULL
)
1406 if (!(funcs
= (FBManagerFuncsPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
1410 offman
= (FBManagerPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
1412 extents
= RegionExtents(offman
->InitialBoxes
);
1413 w
= extents
->x2
- extents
->x1
;
1423 if (length
<= w
) { /* special case */
1428 h
= (length
+ w
- 1) / w
;
1431 return (*funcs
->AllocateOffscreenArea
) (pScreen
, w
, h
, gran
, moveCB
,
1432 removeCB
, privData
);