- HD_SCSICMD: assume there is no sense-data buffer if no AUTOSENSE
[AROS.git] / rom / hyperlayers / basicfuncs.c
blob5f9cae6ad7091005ec0417d04f978dc2b6066e09
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Basic support functions for layers.library.
6 Lang: English.
7 */
9 #include <aros/config.h>
10 #include <aros/asmcall.h>
11 #include <exec/memory.h>
12 #include <graphics/rastport.h>
13 #include <graphics/clip.h>
14 #include <graphics/regions.h>
15 #include <graphics/layers.h>
16 #include <graphics/gfx.h>
17 #include <utility/hooks.h>
18 #include <setjmp.h>
20 #include <proto/exec.h>
21 #include <proto/alib.h>
22 #include <proto/graphics.h>
23 #include <proto/layers.h>
24 #include <proto/arossupport.h>
26 #include "layers_intern.h"
27 #include "basicfuncs.h"
29 #define CLIPRECTS_OUTSIDE_OF_SHAPE 1
31 #define SCROLLSIGN +
34 * Sections:
36 * + Blitter
37 * + Hook
38 * + Layer
39 * + LayerInfo
40 * + Rectangle
41 * + Resource Handling
42 * + Miscellaneous
46 /***************************************************************************/
47 /* BLITTER */
48 /***************************************************************************/
50 #define CR2NR_NOBITMAP 0
51 #define CR2NR_BITMAP 1
53 #if !(AROS_FLAVOUR & AROS_FLAVOUR_NATIVE)
55 * These functions cause the infamous "fixed or forbidden register was spilled"
56 * bug/feature in m68k gcc, so these were written straight in asm. They can be
57 * found in config/m68k-native/layers, for the m68k AROSfA target. Other targets,
58 * that use stack passing, can use these versions.
61 void BltRPtoCR(struct RastPort * rp,
62 struct ClipRect * cr,
63 ULONG Mode,
64 struct LayersBase * LayersBase)
66 BltBitMap(rp->BitMap,
67 cr->bounds.MinX,
68 cr->bounds.MinY,
69 cr->BitMap,
70 ALIGN_OFFSET(cr->bounds.MinX), 0,
71 cr->bounds.MaxX - cr->bounds.MinX + 1,
72 cr->bounds.MaxY - cr->bounds.MinY + 1,
73 Mode,
74 ~0,
75 NULL);
79 void BltCRtoRP(struct RastPort * rp,
80 struct ClipRect * cr,
81 ULONG Mode,
82 struct LayersBase * LayersBase)
84 BltBitMap(cr->BitMap,
85 ALIGN_OFFSET(cr->bounds.MinX),
87 rp->BitMap,
88 cr->bounds.MinX,
89 cr->bounds.MinY,
90 cr->bounds.MaxX - cr->bounds.MinX + 1,
91 cr->bounds.MaxY - cr->bounds.MinY + 1,
92 Mode,
93 ~0,
94 NULL);
98 #endif /* if !native */
100 /***************************************************************************/
101 /* HOOK */
102 /***************************************************************************/
104 struct layerhookmsg
106 struct Layer *l;
107 /* struct Rectangle rect; (replaced by the next line!) */
108 WORD MinX, MinY, MaxX, MaxY;
109 LONG OffsetX, OffsetY;
112 void _CallLayerHook(struct Hook * h,
113 struct RastPort * rp,
114 struct Layer * L,
115 struct Rectangle * R,
116 WORD offsetX,
117 WORD offsetY,
118 struct LayersBase * LayersBase)
120 struct BitMap * bm = rp->BitMap;
122 if (L)
124 if (IL(L)->intflags & INTFLAG_AVOID_BACKFILL) return;
127 if (h == LAYERS_BACKFILL)
129 /* Use default backfill, which means that I will clear the area */
130 BltBitMap(bm,
134 R->MinX,
135 R->MinY,
136 R->MaxX - R->MinX + 1,
137 R->MaxY - R->MinY + 1,
138 0x000,
139 0xff,
140 NULL);
141 /* that's it */
142 return;
145 if (h != LAYERS_NOBACKFILL)
147 struct layerhookmsg msg;
148 msg.l = L;
149 msg.MinX = R->MinX;
150 msg.MinY = R->MinY;
151 msg.MaxX = R->MaxX;
152 msg.MaxY = R->MaxY;
153 msg.OffsetX = offsetX;
154 msg.OffsetY = offsetY;
156 AROS_UFC3NR(void, h->h_Entry,
157 AROS_UFCA(struct Hook *, h ,A0),
158 AROS_UFCA(struct RastPort *, rp ,A2),
159 AROS_UFCA(struct layerhookmsg *, &msg,A1)
166 /***************************************************************************/
167 /* LAYER */
168 /***************************************************************************/
171 * Free a layer and all its associated structures
173 void _FreeLayer(struct Layer * l, struct LayersBase *LayersBase)
175 struct ClipRect * cr = l->ClipRect, * _cr;
177 while (cr)
179 if (cr->BitMap)
180 FreeBitMap(cr->BitMap);
181 _cr = cr->Next;
183 FreePooled(LayersBase->lb_ClipRectPool, cr, sizeof(struct ClipRect));
185 cr = _cr;
189 * also free all backed up cliprects.
191 cr = l->SuperSaveClipRects;
193 while (cr)
195 _cr = cr->Next;
196 FreePooled(LayersBase->lb_ClipRectPool, cr, sizeof(struct ClipRect));
198 cr = _cr;
201 DisposeRegion(l->DamageList);
202 DisposeRegion(l->VisibleRegion);
203 DisposeRegion(l->shape);
204 DisposeRegion(l->visibleshape);
206 FreeMem(l, sizeof(struct IntLayer));
211 /***************************************************************************/
212 /* LAYERINFO */
213 /***************************************************************************/
215 /*-------------------------------------------------------------------------*/
217 * Allocate LayerInfo_extra and initialize its resource list. Layers uses
218 * this resource list to keep track of various memory allocations it makes
219 * for the layers. See ResourceNode and ResData in layers_intern.h for the
220 * node structure. See AddLayersResource for more information on the basic
221 * operation.
223 BOOL _AllocExtLayerInfo(struct Layer_Info * li, struct LayersBase *LayersBase)
225 if(++li->fatten_count != 0)
226 return TRUE;
228 if(!(li->LayerInfo_extra = AllocMem(sizeof(struct LayerInfo_extra),MEMF_PUBLIC|MEMF_CLEAR)))
229 return FALSE;
231 NewList((struct List *)&((struct LayerInfo_extra *)li->LayerInfo_extra)->lie_ResourceList);
233 return TRUE;
237 * Free LayerInfo_extra.
239 void _FreeExtLayerInfo(struct Layer_Info * li, struct LayersBase *LayersBase)
241 if(--li->fatten_count >= 0)
242 return;
244 /* Kill Root Layer */
246 if (li->check_lp)
247 DeleteLayer(0UL, li->check_lp);
248 li->check_lp = NULL;
250 if(li->LayerInfo_extra == NULL)
251 return;
253 FreeMem(li->LayerInfo_extra, sizeof(struct LayerInfo_extra));
255 li->LayerInfo_extra = NULL;
259 * Dynamically allocate LayerInfo_extra if it isn't already there.
261 BOOL SafeAllocExtLI(struct Layer_Info * li,
262 struct LayersBase * LayersBase)
264 LockLayerInfo(li);
266 /* Check to see if we can ignore the rest of this call. :-) */
267 if(li->Flags & NEWLAYERINFO_CALLED)
268 return TRUE;
270 if(_AllocExtLayerInfo(li, LayersBase))
271 return TRUE;
273 UnlockLayerInfo(li);
275 return FALSE;
279 * Free LayerInfo_extra if it was dynamically allocated, and unlock the LI.
281 void SafeFreeExtLI(struct Layer_Info * li,
282 struct LayersBase * LayersBase)
284 if(!(li->Flags & NEWLAYERINFO_CALLED))
285 _FreeExtLayerInfo(li, LayersBase);
287 UnlockLayerInfo(li);
290 /***************************************************************************/
291 /* RECTANGLE */
292 /***************************************************************************/
295 #define MAX(a,b) ((a) > (b) ? (a) : (b))
296 #define MIN(a,b) ((a) < (b) ? (a) : (b))
298 void _TranslateRect(struct Rectangle *rect, WORD dx, WORD dy)
300 rect->MinX += dx;
301 rect->MinY += dy;
302 rect->MaxX += dx;
303 rect->MaxY += dy;
307 /***************************************************************************/
308 /* RESOURCE HANDLING */
309 /***************************************************************************/
312 * Allocate memory for a ClipRect.
315 struct ClipRect * _AllocClipRect(struct Layer * L, struct LayersBase *LayersBase)
317 struct ClipRect * CR;
319 CR = L->SuperSaveClipRects;
321 if (NULL != CR)
323 /* I want to access the list of free ClipRects alone */
324 L->SuperSaveClipRects = CR->Next;
325 L->SuperSaveClipRectCounter--;
327 CR->Flags = 0;
328 CR->Next = NULL;
329 CR->lobs = NULL;
330 CR->BitMap = NULL;
331 return CR;
334 return AllocPooled(LayersBase->lb_ClipRectPool, sizeof(struct ClipRect));
338 * Return memory of a ClipRect for later use.
341 void _FreeClipRect(struct ClipRect * CR,
342 struct Layer * L,
343 struct LayersBase * LayersBase)
345 if (L->SuperSaveClipRectCounter < MAXSUPERSAVECLIPRECTS)
347 /* Add the ClipRect to the front of the list */
348 CR -> Next = L -> SuperSaveClipRects;
349 L -> SuperSaveClipRects = CR;
350 L -> SuperSaveClipRectCounter++;
352 else
354 FreePooled(LayersBase->lb_ClipRectPool, CR, sizeof(struct ClipRect));
359 * Free a whole list of cliprects including the allocated bitmaps (if any)
362 void _FreeClipRectListBM(struct Layer * L,
363 struct ClipRect * CR,
364 struct LayersBase *LayersBase)
366 struct ClipRect * _CR = CR;
367 BOOL isSmart;
368 if ((L->Flags & (LAYERSUPER|LAYERSMART)) == LAYERSMART)
369 isSmart = TRUE;
370 else
371 isSmart = FALSE;
374 * This function is not watching for the upper limit of
375 * pre allocated cliprects.
377 L->SuperSaveClipRectCounter++;
379 while (TRUE)
381 if (NULL != _CR->BitMap && TRUE == isSmart)
383 FreeBitMap(_CR->BitMap);
384 _CR->BitMap = NULL;
386 if (NULL != _CR->Next)
388 L->SuperSaveClipRectCounter++;
389 _CR = _CR->Next;
391 else
392 break;
394 /* _CR is the last ClipRect in the list. I concatenate the
395 currently preallocated list of ClipRects with that list. */
396 _CR->Next = L->SuperSaveClipRects;
398 /* CR is the head of the ClipRect list now */
399 L->SuperSaveClipRects = CR;
403 /***************************************************************************/
404 /* MISCELLANEOUS */
405 /***************************************************************************/
407 struct ClipRect * _CreateClipRectsFromRegion(struct Region *r,
408 struct Layer * l,
409 int invisible,
410 struct Region * inverter,
411 struct LayersBase *LayersBase)
413 int looped = FALSE;
414 struct ClipRect * firstcr = NULL, * cr;
415 struct BitMap * display_bm = l->rp->BitMap;
418 * From region r create cliprects
420 while (1)
422 struct RegionRectangle * rr = r->RegionRectangle;
423 while (rr)
425 cr = _AllocClipRect(l, LayersBase);
426 cr->bounds.MinX = rr->bounds.MinX + r->bounds.MinX;
427 cr->bounds.MinY = rr->bounds.MinY + r->bounds.MinY;
428 cr->bounds.MaxX = rr->bounds.MaxX + r->bounds.MinX;
429 cr->bounds.MaxY = rr->bounds.MaxY + r->bounds.MinY;
430 cr->lobs = (struct Layer *)(IPTR)invisible;
431 cr->Next = firstcr;
433 if (TRUE == invisible && IS_SMARTREFRESH(l))
435 cr->BitMap = AllocBitMap(
436 cr->bounds.MaxX - cr->bounds.MinX + 1 + 16,
437 cr->bounds.MaxY - cr->bounds.MinY + 1,
438 display_bm->Depth,
439 BMF_CLEAR,
440 display_bm);
443 #if 0
444 kprintf("\t\t%s: Created cliprect %d/%d-%d/%d invisible: %d\n",
445 __FUNCTION__,
446 cr->bounds.MinX,
447 cr->bounds.MinY,
448 cr->bounds.MaxX,
449 cr->bounds.MaxY,
450 invisible);
451 #endif
453 firstcr = cr;
455 rr = rr->Next;
458 if (FALSE == looped)
461 * Flip the shape to the opposite part and
462 * limit it to its own shape.
464 if (inverter)
465 XorRegionRegion(inverter, r);
466 else
467 XorRectRegion(r,&l->bounds);
469 #if !CLIPRECTS_OUTSIDE_OF_SHAPE
470 AndRegionRegion(l->shape,r);
471 #else
472 AndRectRegion(r,&l->bounds);
473 #endif
474 if (TRUE == invisible)
475 invisible = FALSE;
476 else
477 invisible = TRUE;
478 looped = TRUE;
480 else
481 break;
482 } /* while (1) */
484 return firstcr;
488 int _CopyClipRectsToClipRects(struct Layer * l,
489 struct ClipRect * oldcr,
490 struct ClipRect * newcr,
491 int srcdx,
492 int destdx,
493 int backupmode,
494 int freelist,
495 int addtodamagelist,
496 struct LayersBase *LayersBase)
498 struct BitMap * display_bm = l->rp->BitMap;
500 while (NULL != oldcr)
502 struct ClipRect * _cr = newcr;
503 int area = RECTAREA(&oldcr->bounds);
504 while ((NULL != _cr) && (0 != area) )
506 struct Rectangle intersect;
509 * Do the two rectangles overlap?
511 if (AndRectRect(&_cr->bounds, &oldcr->bounds, &intersect))
513 LONG xSize = intersect.MaxX - intersect.MinX + 1;
514 LONG ySize = intersect.MaxY - intersect.MinY + 1;
517 * Is this new one supposed to be invisible?
519 if (NULL != _cr->lobs)
521 struct BitMap * srcbm;
523 * The new one is supposed to be invisible.
524 * So for SIMPLEREFRESH layers I don't have to
525 * do anything if
526 * a) not in backupmode or
527 * b) old cr was invisible
529 if (IS_SIMPLEREFRESH(l) && FALSE == backupmode && NULL == _cr->BitMap)
531 if (FALSE == addtodamagelist)
533 struct Rectangle rect = intersect;
535 _TranslateRect(&rect, -l->bounds.MinX, -l->bounds.MinY);
537 /* FIXME:
538 * stegerg: Not sure if this is a good idea. What for example if
539 * updating is done in several passes? And CopyClipRectsToClipRects is
540 * used by all kinds of functions including BeginUpdate/EndUpdate/InstallClipRegion/etc.
542 ClearRectRegion(l->DamageList, &rect);
543 #if 0
544 kprintf("");
545 kprintf("%s: Removing %d/%d-%d/%d from damagelist!\t",
546 __FUNCTION__,
547 rect.MinX,
548 rect.MinY,
549 rect.MaxX,
550 rect.MaxY
552 kprintf("%s: Layer: %d/%d-%d/%d!\n",
553 __FUNCTION__,
554 l->bounds.MinX,
555 l->bounds.MinY,
556 l->bounds.MaxX,
557 l->bounds.MaxY
559 kprintf("%s: oldcr: %d/%d-%d/%d!\t",
560 __FUNCTION__,
561 oldcr->bounds.MinX,
562 oldcr->bounds.MinY,
563 oldcr->bounds.MaxX,
564 oldcr->bounds.MaxY
566 kprintf("%s: _cr: %d/%d-%d/%d!\n\n",
567 __FUNCTION__,
568 _cr->bounds.MinX,
569 _cr->bounds.MinY,
570 _cr->bounds.MaxX,
571 _cr->bounds.MaxY
573 #endif
576 else if (IS_SIMPLEREFRESH(l) && TRUE == backupmode && NULL != oldcr->lobs)
578 if (TRUE == addtodamagelist)
580 struct Rectangle rect = intersect;
581 _TranslateRect(&rect, -l->bounds.MinX, -l->bounds.MinY);
583 // FIXME (if possible)
584 // !!! Also areas where a child disappears beyond the
585 // boundaries of its parent are added here!
586 OrRectRegion(l->DamageList, &rect);
587 #if 0
588 kprintf("_cr->BitMap: %p ,_cr->lobs: %d\n",_cr->BitMap,_cr->lobs);
589 #endif
590 #if 0
591 kprintf("%s: Adding %d/%d-%d/%d to damagelist of l=%p!\t",
592 __FUNCTION__,
593 rect.MinX,
594 rect.MinY,
595 rect.MaxX,
596 rect.MaxY,
599 #endif
600 #if 0
601 kprintf("%s: Layer: %d/%d-%d/%d!\n",
602 __FUNCTION__,
603 l->bounds.MinX,
604 l->bounds.MinY,
605 l->bounds.MaxX,
606 l->bounds.MaxY
608 kprintf("%s: oldcr: %d/%d-%d/%d!\t",
609 __FUNCTION__,
610 oldcr->bounds.MinX,
611 oldcr->bounds.MinY,
612 oldcr->bounds.MaxX,
613 oldcr->bounds.MaxY
615 kprintf("%s: _cr: %d/%d-%d/%d!\n\n",
616 __FUNCTION__,
617 _cr->bounds.MinX,
618 _cr->bounds.MinY,
619 _cr->bounds.MaxX,
620 _cr->bounds.MaxY
622 #endif
623 } else {
624 //kprintf("Not adding to damage list for l=%p!\n",l);
627 else
629 LONG xSrc, xDest;
630 LONG ySrc, yDest;
631 struct BitMap * destbm;
633 if (IS_SUPERREFRESH(l))
634 destbm = l->SuperBitMap;
635 else
636 destbm = _cr->BitMap;
639 * Does the source rect have a bitmap (off screen)
640 * or is it on the screen.
642 if (oldcr->lobs && !IS_SUPERREFRESH(l))
645 * Copy from hidden bitmap to hidden bitmap
647 xSrc = (oldcr->bounds.MinX - _cr->bounds.MinX);
648 if (xSrc < 0)
651 * oldcr is further to the left
653 xSrc = -xSrc;
654 xDest = 0;
656 else
659 * oldcr is further to the right
661 xDest = xSrc;
662 xSrc = 0;
665 xSrc += ALIGN_OFFSET(oldcr->bounds.MinX + srcdx);
666 xDest += ALIGN_OFFSET(_cr->bounds.MinX + destdx);
668 ySrc = (oldcr->bounds.MinY - _cr->bounds.MinY);
669 if (ySrc < 0)
671 ySrc = -ySrc;
672 yDest = 0;
674 else
676 yDest = ySrc;
677 ySrc = 0;
679 //kprintf("Using old cr's BitMap!\n");
680 srcbm = oldcr->BitMap;
682 else
685 * Copy from screen.
687 if (oldcr->bounds.MinX > _cr->bounds.MinX)
689 xSrc = oldcr->bounds.MinX;
690 if (IS_SUPERREFRESH(l))
691 xDest = (oldcr->bounds.MinX - _cr->bounds.MinX) SCROLLSIGN l->Scroll_X;
692 else
693 xDest = (oldcr->bounds.MinX - _cr->bounds.MinX) + ALIGN_OFFSET((_cr->bounds.MinX + destdx));
695 else
697 xSrc = _cr->bounds.MinX;
698 if (IS_SUPERREFRESH(l))
699 xDest = SCROLLSIGN l->Scroll_X;
700 else
701 xDest = ALIGN_OFFSET((_cr->bounds.MinX + destdx));
704 if (oldcr->bounds.MinY > _cr->bounds.MinY)
706 ySrc = oldcr->bounds.MinY;
707 yDest = oldcr->bounds.MinY - _cr->bounds.MinY;
708 if (IS_SUPERREFRESH(l))
709 yDest = yDest SCROLLSIGN l->Scroll_Y;
711 else
713 ySrc = _cr->bounds.MinY;
714 yDest = 0;
715 if (IS_SUPERREFRESH(l))
716 yDest = yDest SCROLLSIGN l->Scroll_Y;
719 srcbm = l->rp->BitMap;
720 //kprintf("Using bitmap of screen!\n");
723 if (IS_SIMPLEREFRESH(l) &&
724 NULL == _cr->BitMap &&
725 TRUE == backupmode)
728 * Get a bitmap (if not there) and make a backup
730 _cr->BitMap = AllocBitMap(
731 _cr->bounds.MaxX - _cr->bounds.MinX + 1 + 16 ,
732 _cr->bounds.MaxY - _cr->bounds.MinY + 1,
733 display_bm->Depth,
734 BMF_CLEAR,
735 display_bm);
736 destbm = _cr->BitMap;
739 BltBitMap(srcbm,
740 xSrc,
741 ySrc,
742 destbm,
743 xDest,
744 yDest,
745 xSize,
746 ySize,
747 0x0c0,
748 0xff,
749 NULL);
750 #if 0
751 kprintf("%s: backing up: from %d/%d to %d/%d width:%d, height: %d\n",
752 __FUNCTION__,
753 xSrc,
754 ySrc,
755 xDest,
756 yDest,
757 xSize,
758 ySize);
759 #endif
761 area -= (xSize * ySize);
765 else //if (FALSE == backupmode)
768 * The new one is visible. if the old one was not visible
769 * then I have to show it.
770 * If it is a simple refresh layer and it has it
771 * backed up (only when moving!) then I must show
772 * this. If it has nothing backed up then I must
773 * add a part to the damage list.
775 if (IS_SIMPLEREFRESH(l) &&
776 (NULL != oldcr->lobs) &&
777 (NULL == oldcr->BitMap))
779 if (NULL != oldcr->lobs && NULL == oldcr->BitMap)
781 struct Rectangle rect = intersect;
783 _CallLayerHook(l->BackFill,
784 l->rp,
786 &rect,
787 rect.MinX,
788 rect.MinY,
789 LayersBase);
790 _TranslateRect(&rect, -l->bounds.MinX, -l->bounds.MinY);
791 OrRectRegion(l->DamageList, &rect);
792 #if 0
793 kprintf("Adding: %d\n",addtodamagelist);
794 kprintf("%s: Adding %d/%d-%d/%d to damagelist!\t",
795 __FUNCTION__,
796 rect.MinX,
797 rect.MinY,
798 rect.MaxX,
799 rect.MaxY
801 kprintf("%s: Layer: %d/%d-%d/%d!\n",
802 __FUNCTION__,
803 l->bounds.MinX,
804 l->bounds.MinY,
805 l->bounds.MaxX,
806 l->bounds.MaxY
808 kprintf("%s: oldcr: %d/%d-%d/%d!\t",
809 __FUNCTION__,
810 oldcr->bounds.MinX,
811 oldcr->bounds.MinY,
812 oldcr->bounds.MaxX,
813 oldcr->bounds.MaxY
815 kprintf("%s: _cr: %d/%d-%d/%d!\n",
816 __FUNCTION__,
817 _cr->bounds.MinX,
818 _cr->bounds.MinY,
819 _cr->bounds.MaxX,
820 _cr->bounds.MaxY
822 #endif
825 else
827 //kprintf("%s: Showing a part of a backed up bitmap!\n",__FUNCTION__);
828 if (NULL != oldcr->lobs)
831 * Copy out of hidden bitmap
833 LONG xSrc, xDest;
834 LONG ySrc, yDest;
835 struct BitMap * srcbm;
837 if (IS_SUPERREFRESH(l))
838 srcbm = l->SuperBitMap;
839 else
840 srcbm = oldcr->BitMap;
843 * I have to make the old one visible
844 * two cases left: SMART REFRESH and SUPERBITMAP
847 if (!IS_SUPERREFRESH(l))
850 * Copy from hidden BitMap to screen!
851 * If a simple refresh layer is moved it might
852 * also have a BitMap!!!
854 xSrc = (oldcr->bounds.MinX - _cr->bounds.MinX);
855 if (xSrc < 0)
858 * old cr is further to the left
860 xSrc = -xSrc + ALIGN_OFFSET(oldcr->bounds.MinX + srcdx);
861 xDest = _cr->bounds.MinX;
863 else
866 * oldcr is further to the right
868 xDest = oldcr->bounds.MinX;
869 xSrc = ALIGN_OFFSET(oldcr->bounds.MinX + srcdx);
872 ySrc = (oldcr->bounds.MinY - _cr->bounds.MinY);
873 if (ySrc < 0)
875 ySrc = -ySrc;
876 yDest = _cr->bounds.MinY;
878 else
880 yDest = oldcr->bounds.MinY;
881 ySrc = 0;
884 else
887 * superbitmap layer
889 xSrc = (oldcr->bounds.MinX > _cr->bounds.MinX) ?
890 oldcr->bounds.MinX - _cr->bounds.MinX SCROLLSIGN l->Scroll_X :
891 _cr->bounds.MinX - oldcr->bounds.MinX SCROLLSIGN l->Scroll_X;
892 xDest = _cr->bounds.MinX;
894 ySrc = (oldcr->bounds.MinY > _cr->bounds.MinY) ?
895 oldcr->bounds.MinY - _cr->bounds.MinY SCROLLSIGN l->Scroll_Y :
896 _cr->bounds.MinY - oldcr->bounds.MinY SCROLLSIGN l->Scroll_Y;
897 yDest = _cr->bounds.MinY;
901 #if 0
902 kprintf("\t\t%s: Show cliprect: %d/%d-%d/%d; blitting to %d/%d _cr->lobs: %d\n",
903 __FUNCTION__,
904 oldcr->bounds.MinX,
905 oldcr->bounds.MinY,
906 oldcr->bounds.MaxX,
907 oldcr->bounds.MaxY,
908 xDest,
909 yDest,
910 _cr->lobs);
911 #endif
913 /* FIXME: Must have oldcr->BitMap also for SuperBitMap layers! */
915 BltBitMap(srcbm,
916 xSrc,
917 ySrc,
918 l->rp->BitMap,
919 xDest,
920 yDest,
921 xSize,
922 ySize,
923 0x0c0,
924 0xff,
925 NULL);
927 } /* if was hidden cliprect */
928 } /* if is simple else ... */
929 } /* if new cliprect is visible or invisible */
930 } /* if rectangles overlap */
931 else
934 if (IS_SMARTREFRESH(l) && TRUE == backupmode && NULL == _cr->BitMap && NULL != _cr->lobs)
936 _cr->BitMap = AllocBitMap(_cr->bounds.MaxX - _cr->bounds.MinX + 1 + 16 ,
937 _cr->bounds.MaxY - _cr->bounds.MinY + 1,
938 display_bm->Depth,
939 BMF_CLEAR,
940 display_bm);
943 _cr = _cr->Next;
944 } /* all new cliprects */
946 if (TRUE == freelist)
948 _cr = oldcr->Next;
949 if (oldcr->BitMap)
950 FreeBitMap(oldcr->BitMap);
951 _FreeClipRect(oldcr, l, LayersBase);
952 oldcr = _cr;
954 else
955 oldcr = oldcr->Next;
956 } /* for all old cliprects */
958 CHECKDAMAGELIST(l);
961 * If this is a simple refresh layer and I am not in
962 * backup mode and I am not adding to the damagelist
963 * the I must call the backfillhook for the
964 * area of the damage list of a simple refresh layer
967 if (IS_SIMPLEREFRESH(l) &&
968 (l->Flags & LAYERREFRESH) &&
969 FALSE == backupmode &&
970 FALSE == addtodamagelist)
972 struct Region * dr = l->DamageList;
973 struct RegionRectangle * rr;
975 _TranslateRect(&dr->bounds, l->bounds.MinX, l->bounds.MinY);
976 AndRectRegion(dr, &l->bounds);
977 AndRegionRegion(l->VisibleRegion, dr);
978 AndRegionRegion(l->visibleshape, dr);
980 _TranslateRect(&dr->bounds, -l->bounds.MinX, -l->bounds.MinY);
982 rr = dr->RegionRectangle;
983 while (rr)
985 _TranslateRect(&rr->bounds,
986 dr->bounds.MinX + l->bounds.MinX,
987 dr->bounds.MinY + l->bounds.MinY);
989 _CallLayerHook(l->BackFill,
990 l->rp,
992 &rr->bounds,
993 rr->bounds.MinX,
994 rr->bounds.MinY,
995 LayersBase);
997 _TranslateRect(&rr->bounds,
998 -dr->bounds.MinX-l->bounds.MinX,
999 -dr->bounds.MinY-l->bounds.MinY);
1000 rr = rr->Next;
1005 return TRUE;
1009 * Backup any parts of the layer that overlap with the backup_region
1010 * and that are not already backed up. Create the cliprects and
1011 * bitmaps if necessary.
1012 * Assumption: Only visible parts become invisible,
1013 * invisible parts will not become visible.
1015 * This function MUST not manipulate hide_region!!!!
1017 int _BackupPartsOfLayer(struct Layer * l,
1018 struct Region * hide_region,
1019 int dx,
1020 int backupsimplerefresh,
1021 struct LayersBase * LayersBase)
1023 struct ClipRect * newcr;
1024 struct Region *r, * clipregion;
1027 * Uninstall clipping region. This causes all pixels to
1028 * be copied into the cliprects that cover the complete
1029 * area of the layer.
1032 clipregion = _InternalInstallClipRegion(l, NULL, 0, 0, LayersBase);
1034 ClearRegionRegion(hide_region,l->VisibleRegion);
1035 r = AndRegionRegionND(l->visibleshape, l->VisibleRegion);
1037 if (r)
1039 newcr = _CreateClipRectsFromRegion(r,l,FALSE,NULL,LayersBase);
1040 DisposeRegion(r);
1042 if (newcr)
1044 _CopyClipRectsToClipRects(l,
1045 l->ClipRect /* source */,
1046 newcr /* destination */,
1049 backupsimplerefresh,
1050 TRUE,
1051 TRUE,
1052 LayersBase);
1054 l->ClipRect = newcr;
1059 * Reinstall the clipping region. This causes the
1060 * whole visible area of the layer to be copied
1061 * into the clipping regions cliprects. The
1062 * regular list of cliprects is still maintained.
1064 if (clipregion)
1065 _InternalInstallClipRegion(l, clipregion, dx, dx, LayersBase);
1067 return TRUE;
1071 * Show any parts of the layer that overlap with the backup_region
1072 * and that are not already show.
1074 * This function MUST not manipulate show_region!!!!
1077 int _ShowPartsOfLayer(struct Layer * l,
1078 struct Region * show_region,
1079 struct LayersBase * LayersBase)
1081 struct ClipRect * newcr;
1082 struct Region *r;
1083 struct Region * clipregion;
1085 //kprintf("%s called for %p\n",__FUNCTION__,l);
1088 * If there is a clipping region then the whole
1089 * window is currently backed up in l->ClipRect
1090 * That covers the complete area. I must first
1091 * make these visible, move them back to
1092 * l->_cliprects and recreate the clipping cliprects
1093 * according to the clipregion
1096 if (show_region == l->VisibleRegion)
1097 kprintf("ERROR - same regions!! %s\n",__FUNCTION__);
1099 clipregion = InstallClipRegion(l, NULL);
1101 OrRegionRegion(show_region,l->VisibleRegion);
1102 r = AndRegionRegionND(l->visibleshape, l->VisibleRegion);
1103 if (r != NULL)
1105 newcr = _CreateClipRectsFromRegion(r,l,FALSE,NULL,LayersBase);
1106 DisposeRegion(r);
1108 _CopyClipRectsToClipRects(l,
1109 l->ClipRect /* source */,
1110 newcr /* destination */,
1113 FALSE,
1114 TRUE,
1115 FALSE,
1116 LayersBase);
1119 l->ClipRect = newcr;
1121 if (clipregion)
1122 InstallClipRegion(l, clipregion);
1124 return TRUE;
1127 int _ShowLayer(struct Layer * l, struct LayersBase *LayersBase)
1129 struct Region *r;
1130 struct RegionRectangle * rr;
1131 struct ClipRect * prevcr = NULL;
1132 struct BitMap * bm = l->rp->BitMap;
1133 int invisible = FALSE;
1135 r = AndRegionRegionND(l->shape, l->VisibleRegion);
1136 AndRegionRegion(l->parent->shape, r);
1138 while (1)
1140 rr = r->RegionRectangle;
1142 while (NULL != rr)
1144 struct ClipRect * cr;
1146 cr = (struct ClipRect *)AllocPooled(LayersBase->lb_ClipRectPool, sizeof(struct ClipRect));
1148 //kprintf("\t\tinvisible: %d !!!!!!!!!!!!\n",invisible);
1150 MinX(cr) = MinX(rr) + MinX(r);
1151 MinY(cr) = MinY(rr) + MinY(r);
1152 MaxX(cr) = MaxX(rr) + MinX(r);
1153 MaxY(cr) = MaxY(rr) + MinY(r);
1154 cr->lobs = (struct Layer *)(IPTR)invisible;
1155 #if 0
1156 kprintf("\t\t%s: Created cliprect %d/%d-%d/%d invisible: %d\n",
1157 __FUNCTION__,
1158 cr->bounds.MinX,
1159 cr->bounds.MinY,
1160 cr->bounds.MaxX,
1161 cr->bounds.MaxY,
1162 invisible);
1163 #endif
1164 if (prevcr)
1165 prevcr->Next = cr;
1166 else
1167 l->ClipRect = cr;
1169 prevcr = cr;
1171 if (FALSE == invisible)
1173 #if 0
1174 kprintf("\t\tClearing background! %d/%d-%d/%d bitmap: %p\n",
1175 cr->bounds.MinX,
1176 cr->bounds.MinY,
1177 cr->bounds.MaxX,
1178 cr->bounds.MaxY,
1179 l->rp->BitMap
1181 #endif
1182 if (IS_SUPERREFRESH(l))
1184 BltBitMap(l->SuperBitMap,
1185 cr->bounds.MinX - l->bounds.MinX,
1186 cr->bounds.MinY - l->bounds.MinY,
1187 l->rp->BitMap,
1188 cr->bounds.MinX,
1189 cr->bounds.MinY,
1190 cr->bounds.MaxX - cr->bounds.MinX + 1,
1191 cr->bounds.MaxY - cr->bounds.MinY + 1,
1192 0x0c0,
1193 0xff,
1194 NULL);
1196 else
1198 _CallLayerHook(l->BackFill,
1199 l->rp,
1201 &cr->bounds,
1202 cr->bounds.MinX,
1203 cr->bounds.MinY,
1204 LayersBase);
1207 else
1210 * This part is to be invisible!
1212 if (IS_SMARTREFRESH(l))
1214 cr->BitMap = AllocBitMap(
1215 cr->bounds.MaxX - cr->bounds.MinX + 1 + 16,
1216 cr->bounds.MaxY - cr->bounds.MinY + 1,
1217 bm->Depth,
1218 BMF_CLEAR,
1219 bm);
1221 /* FIXME:
1222 * stegerg: the backfill hook should be called for this bitmap!
1223 * But _CallLayerHook always uses rp->BitMap
1228 rr=rr->Next;
1231 if (FALSE == invisible)
1233 XorRectRegion(r, &l->bounds);
1234 #if !CLIPRECTS_OUTSIDE_OF_SHAPE
1235 AndRegionRegion(l->shape, r);
1236 #endif
1237 invisible = TRUE;
1239 else
1240 break;
1243 DisposeRegion(r);
1245 return TRUE;
1249 * It is assumed that the region r is not needed anymore.
1251 void _BackFillRegion(struct Layer * l,
1252 struct Region * r,
1253 int addtodamagelist,
1254 struct LayersBase * LayersBase)
1256 struct RegionRectangle * RR;
1258 RR = r->RegionRectangle;
1259 if (NULL == RR) return;
1261 if (IS_SIMPLEREFRESH(l))
1263 /* Only for simple refresh layers, becuase smart refresh layers
1264 may have damage outside of visibleshape, like when being dragged
1265 off screen */
1267 AndRegionRegion(l->visibleshape, r);
1269 else
1271 /* Maybe not needed, but to be sure ... */
1273 AndRectRegion(r, &l->bounds);
1277 if (TRUE == addtodamagelist)
1279 l->Flags |= LAYERREFRESH;
1281 #if 1
1282 /* Region coords are screen relative, but damagelist coords are layer relative! */
1284 _TranslateRect(&r->bounds, -l->bounds.MinX, -l->bounds.MinY);
1285 OrRegionRegion(r, l->DamageList);
1286 _TranslateRect(&r->bounds, l->bounds.MinX, l->bounds.MinY);
1288 #else
1289 while (NULL != RR)
1291 struct Rectangle rect = RR->bounds;
1293 //kprintf("%s: adding to damagelist!\n",__FUNCTION__);
1295 /* Region coords are screen relative, but damagelist coords are layer relative! */
1297 _TranslateRect(&rect,
1298 r->bounds.MinX - l->bounds.MinX,
1299 r->bounds.MinY - l->bounds.MinY);
1300 #if 0
1301 kprintf("%s: Adding %d/%d-%d/%d to damagelist!\n",
1302 __FUNCTION__,
1303 rect.MinX,
1304 rect.MinY,
1305 rect.MaxX,
1306 rect.MaxY
1308 #endif
1309 OrRectRegion(l->DamageList, &rect);
1311 _TranslateRect(&rect,
1312 -r->bounds.MinX + l->bounds.MinX,
1313 -r->bounds.MinY + l->bounds.MinY);
1315 RR = RR->Next;
1317 } /* while (NULL != RR) */
1318 #endif
1320 } /* if (TRUE == addtodamagelist) */
1322 AndRegionRegion(l->VisibleRegion, r);
1323 if (l->shaperegion)
1325 /* shaperegion is layer relative, while r is screen relative */
1327 _TranslateRect(&r->bounds, -l->bounds.MinX, -l->bounds.MinY);
1328 AndRegionRegion(l->shaperegion, r);
1329 _TranslateRect(&r->bounds, l->bounds.MinX, l->bounds.MinY);
1332 RR = r->RegionRectangle;
1333 /* check if a region is empty */
1334 while (NULL != RR)
1336 _TranslateRect(&RR->bounds, r->bounds.MinX, r->bounds.MinY);
1338 #if 0
1339 kprintf("\t\t: %s Clearing rect : %d/%d-%d/%d layer: %p, hook: %p, bitmap: %p\n",
1340 __FUNCTION__,
1341 RR->bounds.MinX,
1342 RR->bounds.MinY,
1343 RR->bounds.MaxX,
1344 RR->bounds.MaxY,
1346 l->BackFill,
1347 l->rp->BitMap);
1348 #endif
1349 _CallLayerHook(l->BackFill,
1350 l->rp,
1352 &RR->bounds,
1353 RR->bounds.MinX,
1354 RR->bounds.MinY,
1355 LayersBase);
1356 RR = RR->Next;
1361 struct Region *_InternalInstallClipRegion(struct Layer *l, struct Region *region,
1362 WORD srcdx, WORD destdx,
1363 struct LayersBase *LayersBase)
1365 struct Region * OldRegion;
1366 BOOL updating = FALSE;
1367 OldRegion = l->ClipRegion;
1369 if ((OldRegion != NULL) || (region != NULL))
1371 if (l->Flags & LAYERUPDATING)
1373 /* InstallClipRegion does not work if the layer is in update state (BeginUpdate) */
1375 updating = TRUE;
1376 EndUpdate(l, FALSE);
1378 OldRegion = l->ClipRegion;
1381 /* is there a clipregion currently installed? */
1382 if (NULL != OldRegion)
1385 * Copy the contents of the region cliprects to the regular
1386 * cliprects if layer is a SMARTLAYER. Also free the list of
1387 * region cliprects.
1389 if (NULL != l->ClipRect)
1391 if (IS_SMARTREFRESH(l))
1392 _CopyClipRectsToClipRects(l,
1393 l->ClipRect,
1394 l->_cliprects,
1395 srcdx,
1396 destdx,
1397 FALSE,
1398 TRUE,
1399 FALSE,
1400 LayersBase);
1401 else
1402 _FreeClipRectListBM(l, l->ClipRect, LayersBase);
1405 /* restore the regular ClipRects */
1406 l->ClipRect = l->_cliprects;
1410 /* at this point the regular cliprects are in l->ClipRect in any case !*/
1412 /* if there's no new region to install then there's not much to do */
1413 l->ClipRegion = region;
1415 if (NULL == region)
1416 l->_cliprects = NULL;
1417 else
1419 struct Region *r;
1421 /* convert the region to a list of ClipRects */
1422 /* backup the old cliprects */
1423 l->_cliprects = l->ClipRect;
1425 _TranslateRect(&region->bounds, l->bounds.MinX, l->bounds.MinY);
1427 r = AndRegionRegionND(l->VisibleRegion, region);
1428 AndRegionRegion(l->shape, r);
1430 l->ClipRect = _CreateClipRectsFromRegion(r,
1432 FALSE,
1433 region,
1434 LayersBase);
1435 DisposeRegion(r);
1437 _CopyClipRectsToClipRects(l,
1438 l->_cliprects,
1439 l->ClipRect,
1440 srcdx,
1441 destdx,
1442 FALSE,
1443 FALSE,
1444 TRUE,
1445 LayersBase); /* stegerg: should be FALSE. but that does not work??? */
1447 _TranslateRect(&region->bounds, -l->bounds.MinX, -l->bounds.MinY);
1449 /* right now I am assuming that everything went alright */
1452 if (updating)
1453 BeginUpdate(l);
1455 } /* if ((OldRegion != NULL) || (region != NULL)) */
1457 return OldRegion;