Call OwnBlitter() only if both blitter queues are empty.
[AROS.git] / rom / hyperlayers / createlayertaglist.c
blobb47abc46557b5b7ef999e94ff6c8f52399654f71
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/libcall.h>
7 #include <graphics/clip.h>
8 #include <graphics/layers.h>
9 #include <intuition/extensions.h>
10 #include <utility/tagitem.h>
11 #include <proto/exec.h>
12 #include <proto/utility.h>
13 #include <proto/graphics.h>
14 #include <proto/layers.h>
16 #include "basicfuncs.h"
17 #include "layers_intern.h"
20 * LA_InFrontOf and LA_Behind are intentionally left
21 * because they allow to implement AmigaOS4-compatible functionality.
23 struct Layer *CreateLayerTagList(struct Layer_Info *li, struct BitMap *bm, LONG x0, LONG y0,
24 LONG x1, LONG y1, LONG flags, int priority, struct TagItem *tagList,
25 struct LayersBase *LayersBase)
27 struct BitMap * superbitmap = NULL;
28 struct Hook * hook = NULL, *shapehook = NULL;
29 APTR win = 0;
30 int visible = TRUE;
31 struct Layer * behind = NULL, * infrontof = NULL, * parent = NULL;
32 struct Layer * l;
33 struct RastPort * rp;
34 struct Region * layershape = NULL, *shape;
35 const struct TagItem *tstate = tagList;
36 struct TagItem *tag;
38 while((tag = NextTagItem(&tstate)))
40 switch (tag->ti_Tag)
42 case LA_BackfillHook:
43 hook = (struct Hook *)tag->ti_Data;
44 break;
46 case LA_SuperBitMap:
47 superbitmap = (struct BitMap *)tag->ti_Data;
48 break;
50 case LA_ChildOf:
51 parent = (struct Layer *)tag->ti_Data;
52 break;
54 case LA_InFrontOf:
55 infrontof = (struct Layer *)tag->ti_Data;
56 break;
58 case LA_Behind:
59 behind = (struct Layer *)tag->ti_Data;
60 break;
62 case LA_Hidden:
63 visible = !tag->ti_Data;
64 break;
66 case LA_ShapeRegion:
67 layershape = (struct Region *)tag->ti_Data;
68 break;
70 case LA_ShapeHook:
71 shapehook = (struct Hook *)tag->ti_Data;
72 break;
74 case LA_WindowPtr:
75 win = (APTR)tag->ti_Data;
76 break;
80 } /* while((tag = NextTagItem(&tstate))) */
82 if ((flags & LAYERSUPER) && (NULL == superbitmap))
83 return NULL;
85 if (!parent)
87 parent = li->check_lp;
88 if (!parent)
90 /* Root layer not yet installed */
92 if (priority != ROOTPRIORITY) /* avoid endless recursion */
94 struct TagItem tags[] =
96 {LA_Hidden, TRUE },
97 {TAG_DONE }
100 if (!(CreateLayerTagList(li,
104 GetBitMapAttr(bm, BMA_WIDTH) - 1,
105 GetBitMapAttr(bm, BMA_HEIGHT) - 1,
107 ROOTPRIORITY,
108 tags,
109 LayersBase)))
111 li->check_lp = NULL;
112 return NULL;
115 parent = li->check_lp;
121 * User gives coordinates reltive to parent.
122 * Adjust the shape to the absolute coordinates
123 * If this is the root layer, I don't have to
124 * do anything. I recognize the root layer if there
125 * is no parent.
128 if (infrontof && infrontof->priority > priority)
129 return NULL;
131 if (behind && behind->priority < priority)
132 return NULL;
134 /* First create the shape region relative to nothing, that is 0,0 origin */
136 shape = NewRectRegion(0, 0, x1 - x0, y1 - y0);
137 if (!shape)
138 return NULL;
140 if (shapehook)
142 struct ShapeHookMsg msg;
143 struct Rectangle NewBounds, OldBounds;
145 msg.NewShape = layershape;
146 msg.OldShape = layershape;
147 msg.NewBounds = &NewBounds;
148 msg.OldBounds = &OldBounds;
150 NewBounds.MinX = x0;
151 NewBounds.MinY = y0;
152 NewBounds.MaxX = x1;
153 NewBounds.MaxY = y1;
154 OldBounds.MinX = 0;
155 OldBounds.MinY = 0;
156 OldBounds.MaxX = 0;
157 OldBounds.MaxY = 0;
159 if (CallHookPkt(shapehook, NULL, &msg))
160 layershape = msg.NewShape;
163 if (layershape) if (!AndRegionRegion(layershape, shape))
165 DisposeRegion(shape);
166 return NULL;
169 if (parent)
171 /* Convert from parent layer relative coords to screen relative coords */
173 x0 += parent->bounds.MinX;
174 y0 += parent->bounds.MinY;
175 x1 += parent->bounds.MinX;
176 y1 += parent->bounds.MinY;
179 /* Make shape region relative to screen */
180 _TranslateRect(&shape->bounds, x0, y0);
182 l = AllocMem(sizeof(struct IntLayer), MEMF_CLEAR|MEMF_PUBLIC);
183 rp = CreateRastPort();
186 if (l && rp)
188 IL(l)->shapehook = shapehook;
189 l->Window = win;
190 l->shaperegion = layershape;
191 l->rp = rp;
193 rp->Layer = l;
194 rp->BitMap = bm;
196 l->Flags = (WORD) flags;
197 l->LayerInfo = li;
199 l->SuperBitMap = superbitmap;
200 l->BackFill = hook;
201 l->priority = priority;
203 InitSemaphore(&l->Lock);
205 l->shape = shape;
206 l->bounds.MinX = x0;
207 l->bounds.MaxX = x1;
208 l->bounds.MinY = y0;
209 l->bounds.MaxY = y1;
210 l->Width = x1 - x0 + 1;
211 l->Height = y1 - y0 + 1;
213 LockLayer(0, l);
215 if (NULL == (l->DamageList = NewRegion()))
216 goto failexit;
217 if (NULL == (l->VisibleRegion = NewRegion()))
218 goto failexit;
219 if (NULL == (l->visibleshape = NewRegion()))
220 goto failexit;
222 l->visible = visible;
224 if (NULL == li->check_lp)
225 li->check_lp = l;
227 l->parent = parent;
229 if (parent)
230 l->nesting = parent->nesting+1;
231 else
232 l->nesting = 0;
234 LockLayers(li);
238 * If neither a layer in front or behind is
239 * given the search for the place according to
240 * the priority and insert it there. I
241 * determine behind or infrontof here!
243 if (NULL != li->top_layer)
245 if (!infrontof && !behind)
247 int end = FALSE;
248 struct Layer * lastgood;
249 infrontof = parent;
253 lastgood = infrontof;
254 infrontof = infrontof->front;
255 if (NULL == infrontof)
257 infrontof = lastgood;
258 break;
260 if (infrontof->parent != l->parent)
262 infrontof = lastgood;
263 break;
265 while (infrontof->nesting >= l->nesting)
267 lastgood = infrontof;
268 infrontof = infrontof->front;
269 if (NULL == infrontof ||
270 infrontof->priority > l->priority)
272 infrontof = lastgood;
273 end = TRUE;
274 break;
280 while (FALSE == end);
285 if (infrontof || (NULL == behind))
287 if (NULL == infrontof)
288 infrontof = li->top_layer;
290 if (li->top_layer == infrontof)
292 li->top_layer = l;
293 l->front = NULL;
294 l->back = infrontof;
295 if (NULL != infrontof)
296 infrontof->front = l;
298 else
300 l->front = infrontof->front;
301 l->back = infrontof;
302 infrontof->front->back = l;
303 infrontof->front = l;
306 else if (behind)
308 l->front = behind;
309 l->back = behind->back;
310 if (l->back)
311 l->back->front = l;
312 behind->back = l;
317 SetRegion(l->shape, l->visibleshape);
318 if (l->parent)
319 AndRegionRegion(l->parent->shape, l->visibleshape);
322 if (IS_VISIBLE(l))
325 * layer is to be visible
327 struct Layer * _l = l->back;
328 struct Layer * lparent = l->parent;
331 * Does this layer have a layer in front of it?
332 * If yes, then take that layer's VisibleRegion and
333 * cut out that layer's shape. This is then the
334 * VisibleRegion of my layer.
336 if (l->front)
338 SetRegion(l->front->VisibleRegion, l->VisibleRegion);
339 ClearRegionRegion(l->front->visibleshape, l->VisibleRegion);
341 else
342 SetRegion(li->check_lp->shape, l->VisibleRegion);
346 * First tell all layers behind this layer to
347 * back up their parts that the new layer will
348 * be hiding.
350 while (1)
352 if (IS_VISIBLE(_l) && DO_OVERLAP(&l->shape->bounds, &_l->shape->bounds))
353 _BackupPartsOfLayer(_l, l->visibleshape, 0, FALSE, LayersBase);
354 else
355 ClearRegionRegion(l->visibleshape, _l->VisibleRegion);
357 if (_l == lparent)
359 if (IS_VISIBLE(_l) || (NULL == lparent->parent))
360 break;
361 else
362 lparent = lparent->parent;
364 _l = _l->back;
369 * Show the layer according to its visible area
370 * This function creates the cliprects in the area
371 * of the layer.
372 * This also works for invisible layers since their Visible
373 * Region is non existent.
375 if (!IS_ROOTLAYER(l))
376 _ShowLayer(l, LayersBase);
378 else
379 goto failexit;
381 UnlockLayers(li);
383 return l;
385 failexit:
386 if (l)
388 if (l->VisibleRegion)
389 DisposeRegion(l->VisibleRegion);
390 if (l->DamageList)
391 DisposeRegion(l->DamageList);
392 if (l->visibleshape)
393 DisposeRegion(l->visibleshape);
394 FreeMem(l, sizeof(struct IntLayer));
397 if (rp)
398 FreeRastPort(rp);
400 return NULL;
401 } /* CreateBehindHookLayer */