small refactor to region handling
[aros:aros.git] / AROS / workbench / devs / monitors / Compositor / compositorclass.c
1 /*
2     Copyright © 2010-2013, The AROS Development Team. All rights reserved.
3     $Id$
4 */
5
6 #define DEBUG 0
7 #if (DEBUG)
8 #define DTOGGLE(x) x
9 #define DMODE(x) x
10 #define DMOVE(x) x
11 #define DRECALC(x) x
12 #define DREDRAWBM(x) x
13 #define DREDRAWSCR(x) x
14 #define DSTACK(x) x
15 #define DUPDATE(x) x
16 #else
17 #define DTOGGLE(x)
18 #define DMODE(x)
19 #define DMOVE(x)
20 #define DRECALC(x)
21 #define DREDRAWBM(x)
22 #define DREDRAWSCR(x)
23 #define DSTACK(x)
24 #define DUPDATE(x)
25 #endif
26
27 #include <aros/debug.h>
28
29 #include <clib/alib_protos.h>
30 #include <proto/exec.h>
31 #include <proto/dos.h>
32 #include <proto/graphics.h>
33 #include <proto/intuition.h>
34 #include <proto/oop.h>
35 #include <proto/utility.h>
36
37 #include <graphics/view.h>
38 #include <hidd/graphics.h>
39
40 #include "compositor_intern.h"
41
42 #define COMPOSITOR_PREFS "SYS/compositor.prefs"
43 #define COMPOSITOR_PEFSTEMPLATE  "ABOVE/S,BELOW/S,LEFT/S,RIGHT/S,ALPHA/S"
44
45 #define CAPABILITY_FLAGS (COMPF_ABOVE|COMPF_BELOW|COMPF_LEFT|COMPF_RIGHT|COMPF_ALPHA)
46
47 enum
48 {
49     ARG_ABOVE = 0,
50     ARG_BELOW,
51     ARG_LEFT,
52     ARG_RIGHT,
53     ARG_ALPHA,
54     NOOFARGS
55 };
56
57
58 #ifdef GfxBase
59 #undef GfxBase
60 #endif
61 #define GfxBase compdata->GraphicsBase
62 #ifdef IntuitionBase
63 #undef IntuitionBase
64 #endif
65 #define IntuitionBase compdata->IntuitionBase
66
67 #define _RECT(x) x.MinX, x.MinY, x.MaxX, x.MaxY
68
69 #define MAX(a,b) a > b ? a : b
70 #define MIN(a,b) a < b ? a : b
71
72 BOOL isRectInRegion(struct Region *region, struct Rectangle *rect)
73 {
74     struct RegionRectangle *rrect = region->RegionRectangle;
75
76     while (rrect)
77     {
78         if (AndRectRect(&rrect->bounds, rect, NULL))
79             return TRUE;
80
81         rrect = rrect->Next;
82     }
83     return FALSE;
84 }
85
86 static struct StackBitMapNode * HIDDCompositorFindBitMapStackNode(struct HIDDCompositorData * compdata, OOP_Object * bm)
87 {
88     struct StackBitMapNode * n = NULL;
89     
90     ForeachNode(&compdata->bitmapstack, n)
91     {
92         if (n->bm == bm)
93             return n;
94     }
95
96     return NULL;
97 }
98
99 struct Screen *HIDDCompositorFindBitMapScreen(struct HIDDCompositorData *compdata, OOP_Object *bm)
100 {
101     struct Screen *curScreen = NULL;
102
103     for (curScreen = IntuitionBase->FirstScreen; curScreen != NULL; curScreen = curScreen->NextScreen)
104     {
105         if (bm == HIDD_BM_OBJ(curScreen->RastPort.BitMap))
106         return curScreen;
107     }
108     
109     return (struct Screen *)NULL;
110 }
111
112 static VOID HIDDCompositorValidateBitMapPositionChange(OOP_Object * bm, SIPTR *newxoffset, SIPTR *newyoffset, LONG displayedwidth, LONG displayedheight)
113 {
114     IPTR width, height;
115     LONG neglimit, poslimit;
116
117     OOP_GetAttr(bm, aHidd_BitMap_Width, &width);
118     OOP_GetAttr(bm, aHidd_BitMap_Height, &height);
119
120     /* Check x position */
121     if (width > displayedwidth)
122     {
123         neglimit = displayedwidth - width;
124         poslimit = 0;
125     }
126     else
127     {
128         neglimit = 0;
129         poslimit = displayedwidth - width;
130     }
131
132     if (*(newxoffset) > poslimit)
133         *(newxoffset) = poslimit;
134     if (*(newxoffset) < neglimit)
135         *(newxoffset) = neglimit;
136
137     /* Check y position */
138     if (height > displayedheight)
139         neglimit = displayedheight - height; /* Limit for scroll */
140     else
141         neglimit = 0;
142     poslimit = displayedheight - 15; /* Limit for drag */
143
144     if (*(newyoffset) > poslimit)
145         *(newyoffset) = poslimit;
146     if (*(newyoffset) < neglimit)
147         *(newyoffset) = neglimit;
148 }
149
150 static VOID HIDDCompositorRecalculateVisibleRegions(struct HIDDCompositorData *compdata)
151 {
152     struct StackBitMapNode      *n = NULL, *tmpn;
153     struct Region               *dispvisregion = NULL;
154     ULONG                       oldflags = compdata->flags;
155
156     DRECALC(bug("[Compositor:%s] Display rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(compdata->displayrect)));
157
158     /*
159      * This function assumes bitmapstack is in correct Z order: 
160      * from topmost to bottom most
161      */
162     if ((dispvisregion = NewRegion()) != NULL)
163     {
164         OrRectRegion(dispvisregion, &compdata->displayrect);
165
166         compdata->flags &= ~COMPSTATEF_HASALPHA;
167         if (compdata->alpharegion)
168         {
169             DisposeRegion(compdata->alpharegion);
170             compdata->alpharegion = NULL;
171         }
172         DRECALC(bug("[Compositor:%s] DisplayRegion @ 0x%p\n", __PRETTY_FUNCTION__, dispvisregion));
173
174         ForeachNodeSafe(&compdata->bitmapstack, n, tmpn)
175         {
176             /* Get bitmap bounding box in screen coordinates */
177             struct Rectangle tmprect;
178
179             n->sbmflags &= ~STACKNODEF_VISIBLE;
180
181             if (n->screenregion)
182                 ClearRegion(n->screenregion);
183             else
184                 n->screenregion = NewRegion();
185
186             if (n->screenregion)
187             {
188                 struct RegionRectangle *srrect;
189
190                 tmprect.MinX = n->leftedge;
191                 tmprect.MaxX = n->leftedge + OOP_GET(n->bm, aHidd_BitMap_Width) - 1;
192                 tmprect.MinY = n->topedge;
193                 tmprect.MaxY = n->topedge  + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
194
195                 DRECALC(bug("[Compositor:%s] Screen Rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
196
197                 OrRectRegion(n->screenregion, &tmprect); // Start with the Screen's dimensions ..
198                 AndRegionRegion(dispvisregion, n->screenregion); // And adjust for the "Display"
199
200                 if ((srrect = n->screenregion->RegionRectangle) != NULL)
201                 {
202                     while (srrect)
203                     {
204                         tmprect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
205                         tmprect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
206                         tmprect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
207                         tmprect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
208
209                         if (!(n->sbmflags & COMPF_ALPHA))
210                             ClearRectRegion(dispvisregion, &tmprect);
211                         else
212                         {
213                             compdata->flags |= COMPSTATEF_HASALPHA;
214                             if (!(compdata->alpharegion))
215                                 compdata->alpharegion = NewRegion();
216                             
217                             OrRectRegion(compdata->alpharegion, &tmprect);
218                         }
219                         srrect = srrect->Next;
220                     }
221
222                     if (!(compdata->capabilities & COMPF_ABOVE) && !(n->sbmflags & COMPF_ABOVE))
223                     {
224                         tmprect.MinX = compdata->displayrect.MinX;
225                         tmprect.MaxX = compdata->displayrect.MaxX;
226                         tmprect.MinY = compdata->displayrect.MinY;
227                         tmprect.MaxY = n->topedge - 1;
228                         ClearRectRegion(dispvisregion, &tmprect);
229                     }
230                     if (!(compdata->capabilities & COMPF_BELOW) && !(n->sbmflags & COMPF_BELOW))
231                     {
232                         tmprect.MinX = compdata->displayrect.MinX;
233                         tmprect.MaxX = compdata->displayrect.MaxX;
234                         tmprect.MinY = n->topedge  + OOP_GET(n->bm, aHidd_BitMap_Height);
235                         tmprect.MaxY = compdata->displayrect.MaxY;
236                         ClearRectRegion(dispvisregion, &tmprect);
237                     }
238                     if (!(compdata->capabilities & COMPF_LEFT) && !(n->sbmflags & COMPF_LEFT))
239                     {
240                         tmprect.MinX = compdata->displayrect.MinX;
241                         tmprect.MaxX = n->leftedge - 1;
242                         tmprect.MinY = n->topedge;
243                         tmprect.MaxY = n->topedge  + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
244                         ClearRectRegion(dispvisregion, &tmprect);
245                     }
246                     if (!(compdata->capabilities & COMPF_RIGHT) && !(n->sbmflags & COMPF_RIGHT))
247                     {
248                         tmprect.MinX = n->leftedge + OOP_GET(n->bm, aHidd_BitMap_Width);
249                         tmprect.MaxX = compdata->displayrect.MaxX;
250                         tmprect.MinY = n->topedge;
251                         tmprect.MaxY = n->topedge  + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
252                         ClearRectRegion(dispvisregion, &tmprect);
253                     }
254                     n->sbmflags |= STACKNODEF_VISIBLE;
255                 }
256
257                 DRECALC(bug("[Compositor:%s] HiddBitmap 0x%p, topedge %d, visible %d\n", __PRETTY_FUNCTION__, 
258                             n->bm, n->topedge, (n->sbmflags & STACKNODEF_VISIBLE)));
259             }
260             else
261             {
262                 DRECALC(bug("[Compositor:%s] Failed to create Screen Region\n", __PRETTY_FUNCTION__));
263             }
264         }
265         DisposeRegion(dispvisregion);
266         if (compdata->flags != oldflags)
267         {
268             ULONG newflags = (~oldflags) & compdata->flags;
269             DRECALC(bug("[Compositor:%s] Newly set flags %08x\n", __PRETTY_FUNCTION__, newflags));
270             if ((!(newflags & COMPSTATEF_HASALPHA)) && (oldflags & COMPSTATEF_HASALPHA))
271             {
272                 DRECALC(bug("[Compositor:%s] Alpha removed\n", __PRETTY_FUNCTION__));
273                 if (compdata->alpharegion)
274                     DisposeRegion(compdata->alpharegion);
275
276                 if (compdata->intermedbitmap)
277                     HIDD_Gfx_DisposeBitMap(compdata->gfx, compdata->intermedbitmap);
278
279                 compdata->alpharegion = NULL;
280                 compdata->intermedbitmap = NULL;
281             }
282         }
283     }
284     else
285     {
286         DRECALC(bug("[Compositor:%s] Failed to create Display Region\n", __PRETTY_FUNCTION__));
287     }
288 }
289
290 static HIDDT_ModeID FindBestHiddMode(struct HIDDCompositorData *compdata, ULONG width, ULONG height, ULONG depth, ULONG *res_depth)
291 {
292     HIDDT_ModeID mode = vHidd_ModeID_Invalid;
293     OOP_Object *sync, *pf;
294     IPTR w, h, d;
295     ULONG dw, dh, delta;
296     ULONG found_delta  = -1;
297     ULONG found_width  = 0;
298     ULONG found_height = 0;
299     ULONG found_depth  = 0;
300     HIDDT_ModeID found_mode = vHidd_ModeID_Invalid;
301
302     DMODE(bug("[%s] Finding best match for mode %ux%ux%u\n", __PRETTY_FUNCTION__, width, height, depth));
303
304     while ((mode = HIDD_Gfx_NextModeID(compdata->gfx, mode, &sync, &pf)) != vHidd_ModeID_Invalid)
305     {
306         BOOL match;
307
308         DMODE(bug("[%s] Checking mode 0x%08X... ", __PRETTY_FUNCTION__, mode));
309         if (OOP_GET(pf, aHidd_PixFmt_ColorModel) != vHidd_ColorModel_TrueColor)
310         {
311             DMODE(bug("Skipped (not truecolor)\n"));
312             continue;
313         }
314
315         OOP_GetAttr(sync, aHidd_Sync_HDisp, &w);
316         OOP_GetAttr(sync, aHidd_Sync_VDisp, &h);
317         OOP_GetAttr(pf, aHidd_PixFmt_Depth, &d);
318
319         dw = w > width  ? w - width  : w < width  ? width  - w : 1;
320         dh = h > height ? h - height : h < height ? height - h : 1;
321         delta = dw * dh;
322
323         match = FALSE;
324         if (delta < found_delta)
325         {
326             /* If mode resolution is closer to the needed one, we've got a better match */
327             found_delta  = delta;
328             found_width  = w;
329             found_height = h;
330
331             match = TRUE;
332         }
333         else if (delta == found_delta)
334         {
335             /* If resolution is the same as that of current candidate mode, we can look at depth. */
336             if (found_depth > depth)
337             {
338                 /*
339                  * Candidate mode if deeper than requested. We can supersede it with another mode
340                  * of smaller depth, but which still matches our request.
341                  */
342                 if ((d < found_depth) && (d >= depth))
343                     match = TRUE;
344             }
345             else if (found_depth < depth)
346             {
347                 /*
348                  * We want better depth than current candidate.
349                  * In this case anything deeper will do.
350                  */
351                 if (d > found_depth)
352                     match = TRUE;
353             }
354         }
355
356         if (match)
357         {
358             /*
359              * Mode with the same delta, but larger depth, may supersede
360              * previous mode, if we prefer deeper ones.
361              */
362             DMODE(bug("Selected (%ldx%ldx%ld, delta = %u)", w, h, d, delta));
363             found_depth = d;
364             found_mode  = mode;
365         }
366         DMODE(bug("\n"));
367     }
368
369     /* Store mode information */ 
370     compdata->displayrect.MinX = 0;
371     compdata->displayrect.MinY = 0;
372     compdata->displayrect.MaxX = found_width  - 1;
373     compdata->displayrect.MaxY = found_height - 1;
374     *res_depth = found_depth;
375
376     return found_mode;
377 }
378
379 static void UpdateDisplayMode(struct HIDDCompositorData *compdata)
380 {
381     struct StackBitMapNode *n;
382     IPTR                modeid, width = 0, height = 0, depth;
383     OOP_Object          *sync, *pf;
384     UBYTE               comp_depth = 16;
385     ULONG               found_depth;
386
387     DSTACK(bug("[Compositor] %s()\n", __PRETTY_FUNCTION__));
388
389     /*
390      * Examine all bitmaps in the stack to figure out the needed depth.
391      * We need a maximum depth of all depths in order to keep correct colors.
392      * But not less than 16 bits, because we can't compose on a LUT screen.
393      *
394      * If a LUT bitmap is present in the stack (depth < 9), we request truecolor
395      * screen for better color presentation.
396      *
397      * We examine bitmaps in reverse order, in this case 'sync' will hold
398      * information about the top bitmap when we exit the loop.
399      * Size of our composited mode needs to be as close as possible to that one.
400      */
401     for (n = (struct StackBitMapNode *)compdata->bitmapstack.mlh_TailPred;
402          n->n.mln_Pred; n = (struct StackBitMapNode *)n->n.mln_Pred)
403     {
404         if ((!(n->sbmflags & COMPF_ALPHA)) && (n->sbmflags & STACKNODEF_DISPLAYABLE))
405         {
406             OOP_GetAttr(n->bm, aHidd_BitMap_ModeID, &modeid);
407             HIDD_Gfx_GetMode(compdata->gfx, modeid, &sync, &pf);
408
409             if (OOP_GET(pf, aHidd_PixFmt_ColorModel) == vHidd_ColorModel_TrueColor)
410             {
411                 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
412                 if (depth > comp_depth)
413                     comp_depth = depth;
414             }
415             else
416             {
417                 /*
418                  * If we have a LUT bitmap on stack, we request 24-bit screen
419                  * for better color transfer.
420                  */
421                 comp_depth = 24;
422             }
423         }
424         else
425         {
426             IPTR curwidth, curheight;
427             OOP_GetAttr(n->bm, aHidd_BitMap_Width, &curwidth);
428             OOP_GetAttr(n->bm, aHidd_BitMap_Height, &curheight);
429             if (curwidth > width)
430                 width = curwidth;
431             if (curheight > height)
432                 height = curheight;
433         }
434     }
435
436     if (sync)
437     {
438         /* Get the needed size */
439         OOP_GetAttr(sync, aHidd_Sync_HDisp, &width);
440         OOP_GetAttr(sync, aHidd_Sync_VDisp, &height);
441     }
442
443     DSTACK(bug("[%s] Prefered mode %ldx%ldx%d\n", __PRETTY_FUNCTION__, width, height, comp_depth));
444
445     modeid = FindBestHiddMode(compdata, width, height, comp_depth, &found_depth);
446     DSTACK(bug("[%s] Composition Display ModeID 0x%08X [current 0x%08X]\n", __PRETTY_FUNCTION__, modeid, compdata->displaymode));
447
448     if (modeid != compdata->displaymode)
449     {
450         /* The mode is different. Need to prepare information needed for compositing */
451         struct TagItem gctags[] =
452         {
453             { aHidd_GC_Foreground, 0x99999999 }, 
454             { TAG_DONE           , 0          }
455         };
456
457         /* Signal mode change */ 
458         compdata->displaymode = modeid;
459         compdata->displaydepth = comp_depth;
460         compdata->modeschanged = TRUE;
461
462         /* Get gray foregound */
463         if (found_depth < 24)
464             gctags[0].ti_Data = 0x9492;
465
466         OOP_SetAttrs(compdata->gc, gctags);
467     }
468 }
469
470 static inline void HIDDCompositorRedrawBitmap(struct HIDDCompositorData *compdata, OOP_Object *renderTarget, struct StackBitMapNode *n, struct Rectangle *rect)
471 {
472     /* The given rectangle is already in screen coordinate system here */
473     ULONG blitwidth  = rect->MaxX - rect->MinX + 1;
474     ULONG blitheight = rect->MaxY - rect->MinY + 1;
475
476     DREDRAWBM(bug("[Compositor:%s] Redraw HiddBitMap 0x%p, Rect[%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, n->bm,
477                   rect->MinX, rect->MinY, rect->MaxX, rect->MaxY));
478
479     if (!(n->sbmflags & COMPF_ALPHA))
480     {
481         DREDRAWBM(bug("[Compositor:%s] Blitting %dx%d [from %d, %d]\n", __PRETTY_FUNCTION__, blitwidth, blitheight, 
482               rect->MinX - n->leftedge, rect->MinY - n->topedge));
483
484         HIDD_Gfx_CopyBox(compdata->gfx, n->bm,
485                         /* Transform to source bitmap coord system */
486                         rect->MinX - n->leftedge, rect->MinY - n->topedge,
487                         renderTarget,
488                         rect->MinX, rect->MinY, blitwidth, blitheight,
489                         compdata->gc);
490     }
491     else
492     {
493         UBYTE *baseaddress;
494         ULONG width, height, banksize, memsize;
495         IPTR modulo;
496
497         DREDRAWBM(bug("[Compositor:%s] AlphaBlending %dx%d @ %d,%d to %d,%d\n", __PRETTY_FUNCTION__,
498               blitwidth, blitheight,
499               rect->MinX - n->leftedge, rect->MinY - n->topedge, rect->MinX, rect->MinY));
500
501         if (HIDD_BM_ObtainDirectAccess(n->bm, &baseaddress, &width, &height, &banksize, &memsize))
502         {
503             DREDRAWBM(bug("[Compositor:%s] Alpha baseaddress @ 0x%p\n", __PRETTY_FUNCTION__, baseaddress));
504             OOP_GetAttr(n->bm, aHidd_BitMap_BytesPerRow, &modulo);
505             HIDD_BM_PutAlphaImage(renderTarget, compdata->gfx , baseaddress + ((rect->MinY - n->topedge) * modulo) + ((rect->MinX - n->leftedge) << 2), modulo,
506                                                 rect->MinX, rect->MinY, blitwidth, blitheight);
507             HIDD_BM_ReleaseDirectAccess(n->bm);
508         }
509     }
510 }
511
512 static inline void HIDDCompositorFillRect(struct HIDDCompositorData *compdata, OOP_Object *renderTarget, ULONG MinX, ULONG MinY, ULONG MaxX, ULONG MaxY)
513 {
514     DREDRAWSCR(bug("[Compositor:%s] Filling [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
515                    MinX, MinY, MaxX, MaxY));
516
517     HIDD_BM_FillRect(renderTarget, compdata->gc,
518                      MinX, MinY, MaxX, MaxY);
519 }
520
521
522 static VOID HIDDCompositorRedrawAlphaRegions(struct HIDDCompositorData *compdata, struct Rectangle *drawrect)
523 {
524     OOP_Object          *renderTarget = compdata->displaybitmap;
525     struct Rectangle    alpharect;
526     struct StackBitMapNode *n;
527     struct BitMap       *backbm;
528
529     if (compdata->intermedbitmap)
530         renderTarget = compdata->intermedbitmap;
531
532     DREDRAWSCR(if (drawrect){ bug("[Compositor:%s] Rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT((*drawrect))); })
533
534     OOP_GetAttr(renderTarget, aHidd_BitMap_BMStruct, (IPTR *)&backbm);
535
536     // Alpha Regions are drawn in reverse order incase they overlap..
537     for (n = (struct StackBitMapNode *)compdata->bitmapstack.mlh_TailPred;
538         n->n.mln_Pred; n = (struct StackBitMapNode *)n->n.mln_Pred)
539     {
540         if ((n->sbmflags & STACKNODEF_VISIBLE) &&
541             (n->sbmflags & COMPF_ALPHA) &&
542             (n->screenregion))
543         {
544             struct RegionRectangle *srrect;
545
546             DREDRAWSCR(bug("[Compositor:%s] Alpha Screen Region @ 0x%p HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__,
547                                n->screenregion, n->bm));
548
549             if ((srrect = n->screenregion->RegionRectangle) != NULL)
550             {
551                 DREDRAWSCR(bug("[Compositor:%s] Compositing Visible Alpha Regions..\n", __PRETTY_FUNCTION__));
552                 while (srrect)
553                 {
554                     alpharect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
555                     alpharect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
556                     alpharect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
557                     alpharect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
558
559                     if (!(drawrect) || AndRectRect(drawrect, &alpharect, &alpharect))
560                     {
561                         DREDRAWSCR(bug("[Compositor:%s] Alpha-Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(alpharect)));
562
563                         if ((n->prealphacomphook) && (backbm != NULL))
564                         {
565                             struct HIDD_BackFillHookMsg preprocessmsg;
566                             preprocessmsg.bounds = &alpharect;
567                             preprocessmsg.offsetx = 0;
568                             preprocessmsg.offsety = 0;
569                             CallHookPkt(n->prealphacomphook, backbm, &preprocessmsg);
570                         }
571
572                         HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &alpharect);
573                         if (renderTarget == compdata->displaybitmap)
574                             HIDD_BM_UpdateRect(compdata->displaybitmap,
575                                alpharect.MinX, alpharect.MinY,
576                                alpharect.MaxX - alpharect.MinX + 1,
577                                alpharect.MaxY - alpharect.MinY + 1);
578                     }
579                     srrect = srrect->Next;
580                 }
581             }
582         }
583     }
584 }
585
586 static VOID HIDDCompositorRedrawVisibleRegions(struct HIDDCompositorData *compdata, struct Rectangle *drawrect)
587 {
588     OOP_Object          *renderTarget = compdata->displaybitmap;
589     struct Region       *dispvisregion = NULL;
590     struct Rectangle    tmprect;
591     struct BitMap       *clearbm;
592     struct StackBitMapNode *n;
593
594     DREDRAWSCR(bug("[Compositor:%s] Redrawing Display (GfxBase @ 0x%p)\n", __PRETTY_FUNCTION__, GfxBase));
595
596     if (!(drawrect))
597     {
598         /* Recalculate visible regions */
599         HIDDCompositorRecalculateVisibleRegions(compdata);
600     }
601
602     if ((compdata->flags & COMPSTATEF_HASALPHA) && (compdata->intermedbitmap))
603         renderTarget = compdata->intermedbitmap;
604
605     if ((dispvisregion = NewRegion()) != NULL)
606     {
607         if (drawrect)
608             OrRectRegion(dispvisregion, drawrect);
609         else
610             OrRectRegion(dispvisregion, &compdata->displayrect);
611
612         DRECALC(bug("[Compositor:%s] Display rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(compdata->displayrect)));
613
614         ForeachNode(&compdata->bitmapstack, n)
615         {
616             if ((n->sbmflags & STACKNODEF_VISIBLE) &&
617                 (!(n->sbmflags & COMPF_ALPHA)) &&
618                 (n->screenregion))
619             {
620                 struct RegionRectangle * srrect;
621                 DREDRAWSCR(bug("[Compositor:%s] Screen Region @ 0x%p HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__,
622                                n->screenregion, n->bm));
623
624                 // Render the visable regions ..
625                 if ((srrect = n->screenregion->RegionRectangle) != NULL)
626                 {
627                     DREDRAWSCR(bug("[Compositor:%s] Redrawing Visible Screen Regions..\n", __PRETTY_FUNCTION__));
628                     while (srrect)
629                     {
630                         tmprect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
631                         tmprect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
632                         tmprect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
633                         tmprect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
634
635                         if (!(drawrect) || AndRectRect(drawrect, &tmprect, &tmprect))
636                         {
637                             DREDRAWSCR(bug("[Compositor:%s] Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
638
639                             HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &tmprect);
640                             if (renderTarget == compdata->displaybitmap)
641                                 HIDD_BM_UpdateRect(compdata->displaybitmap,
642                                    tmprect.MinX, tmprect.MinY,
643                                    tmprect.MaxX - tmprect.MinX + 1,
644                                    tmprect.MaxY - tmprect.MinY + 1);
645                         }
646                         srrect = srrect->Next;
647                     }
648                     ClearRegionRegion(n->screenregion, dispvisregion);
649                 }
650             }
651         }
652         OOP_GetAttr(renderTarget, aHidd_BitMap_BMStruct, (IPTR *)&clearbm);
653
654         struct RegionRectangle * dispclrrect = dispvisregion->RegionRectangle;
655         while (dispclrrect)
656         {
657             struct HIDD_BackFillHookMsg clearmsg;
658
659             tmprect.MinX = dispclrrect->bounds.MinX + dispvisregion->bounds.MinX;
660             tmprect.MinY = dispclrrect->bounds.MinY + dispvisregion->bounds.MinY;
661             tmprect.MaxX = dispclrrect->bounds.MaxX + dispvisregion->bounds.MinX;
662             tmprect.MaxY = dispclrrect->bounds.MaxY + dispvisregion->bounds.MinY;
663
664             if (!(drawrect) || AndRectRect(drawrect, &tmprect, &tmprect))
665             {
666                 DREDRAWSCR(bug("[Compositor:%s] Render Display Void Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
667
668                 if (clearbm)
669                 {
670                     clearmsg.bounds = &tmprect;
671                     clearmsg.offsetx = 0;
672                     clearmsg.offsety = 0;
673                     CallHookPkt(compdata->backfillhook, clearbm, &clearmsg);
674                 }
675
676                 if (renderTarget == compdata->displaybitmap)
677                     HIDD_BM_UpdateRect(compdata->displaybitmap,
678                        tmprect.MinX, tmprect.MinY,
679                        tmprect.MaxX - tmprect.MinX + 1,
680                        tmprect.MaxY - tmprect.MinY + 1);
681             }
682             dispclrrect = dispclrrect->Next;
683         }
684         if (compdata->flags & COMPSTATEF_HASALPHA)
685         {
686             HIDDCompositorRedrawAlphaRegions(compdata, drawrect);
687         }
688         DisposeRegion(dispvisregion);
689     }
690     if (renderTarget != compdata->displaybitmap)
691     {
692         DREDRAWSCR(bug("[Compositor:%s] Copying Alpha Intermediary BitMap\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
693         if (!(drawrect))
694         {
695             HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
696                     compdata->displayrect.MinX, compdata->displayrect.MinY,
697                     compdata->displaybitmap,
698                     compdata->displayrect.MinX, compdata->displayrect.MinY,
699                     compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
700                     compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
701                     compdata->gc);
702             HIDD_BM_UpdateRect(compdata->displaybitmap,
703                     compdata->displayrect.MinX, compdata->displayrect.MinY,
704                     compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
705                     compdata->displayrect.MaxY - compdata->displayrect.MinY + 1);
706         }
707         else
708         {
709             HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
710                     drawrect->MinX, drawrect->MinY,
711                     compdata->displaybitmap,
712                     drawrect->MinX, drawrect->MinY,
713                     drawrect->MaxX - drawrect->MinX + 1,
714                     drawrect->MaxY - drawrect->MinY + 1,
715                     compdata->gc);
716             HIDD_BM_UpdateRect(compdata->displaybitmap,
717                     drawrect->MinX, drawrect->MinY,
718                     drawrect->MaxX - drawrect->MinX + 1,
719                     drawrect->MaxY - drawrect->MinY + 1);
720         }
721     }
722 }
723
724 /*  
725
726 There are several cases that needs to be handled in this code. They are documented
727 below. Please read it before making changes.
728 etb     = existing topbitmap
729 ntb     = new top bitmap
730 sb      = screen bitmap
731 cb      = composited bitmap
732 fs      = covers full screen
733 nfs     = not covers full screen
734 mA      = mode "A"
735 mB      = mode "B"
736 disp()  = dispose
737 new()   = new
738
739 The resulting mode is always that of screen bitmap as set in "effect" column.
740 The composited bitmap always matches the resulting screen mode or is NULL.
741
742 | exiting screen situation          | change         | effect                               |
743 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - SAME MODE                               |
744 | etb->fs, mA, sb==etb, cb==NULL    | ntb->fs, mA    | sb==ntb, cb==NULL                    |
745 | etb->fs, mA, sb==etb, cb!=NULL    | ntb->fs, mA    | sb==ntb, cb!=NULL                    |
746 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE           |
747 | etb->fs, mA, sb==etb, cb==NULL    | ntb->nfs, mA   | new(cb), sb==cb, cb!=NULL            |
748 | etb->fs, mA, sb==etb, cb!=NULL    | ntb->nfs, mA   | sb==cb, cb!=NULL                     |
749 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - SAME MODE           |
750 | etb->nfs, mA, sb==cb, cb==NULL    | NOT POSSIBLE                                          |
751 | etb->nfs, mA, sb==cb, cb!=NULL    | ntb->fs, mA    | sb==ntb, cb!=NULL                    |
752 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE       |
753 | etb->nfs, mA, sb==cb, cb==NULL    | NOT POSSIBLE                                          |
754 | etb->nfs, mA, sb==cb, cb!=NULL    | ntb->nfs, mA   | sb==cb, cb!=NULL                     |
755
756
757 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - DIFFERENT MODES                         |
758 | etb->fs, mA, sb==etb, cb==NULL    | ntb->fs, mB    | sb==ntb, cb==NULL                    |
759 | etb->fs, mA, sb==etb, cb!=NULL    | ntb->fs, mB    | disp(cb), sb==ntb, cb==NULL          |
760 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES     |
761 | etb->fs, mA, sb==etb, cb==NULL    | ntb->nfs, mB   | new(cb), sb==cb, cb!=NULL            |
762 | etb->fs, mA, sb==etb, cb!=NULL    | ntb->nfs, mB   | disp(cb), new(cb), sb==cb, cb!=NULL  |
763 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - DIFFERENT MODES     |
764 | etb->nfs, mA, sb==cb, cb==NULL    | NOT POSSIBLE                                          |
765 | etb->nfs, mA, sb==cb, cb!=NULL    | ntb->fs, mB    | disp(cb), sb==ntb, cb==NULL          |
766 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
767 | etb->nfs, mA, sb==cb, cb==NULL    | NOT POSSIBLE                                          |
768 | etb->nfs, mA, sb==cb, cb!=NULL    | ntb->nfs, mB   | disp(cb), new(cb), sb==cb, cb!=NULL  |
769
770
771 | USE CASE: DRAGGING SCREEN DOWN                                                            |
772 | etb->fs, mA, sb==etb, cb==NULL    | ntb->nfs, mA   | new(cb), sb==cb                      |
773 | etb->fs, mA, sb==etb, cb!=NULL    | ntb->nfs, mA   | sb==cb                               |
774 | USE CASE: DRAGGING SCREEN UP                                                              |
775 | etb->nfs, mA, sb==cb, cb!=NULL    | ntb->fs, mA    | sb==etb                              |
776 | etb->nfs, mA, sb==cb, cb==NULL    | NOT POSSIBLE                                          |
777
778 Resulting rules (order matters):
779
780 (a) if ((cb!=NULL) && (etb->mode!=ntb->mode)) {dispose(cb), cb=NULL}
781 (b) if ((ntb->nfs) && (cb==NULL)) new(cb)
782 (c) if (ntb->nfs) sb=cb
783 (d) if (ntb->fs) sb=ntb
784
785 Additional rule:
786 (e) if (oldsb!=sb) modeswitch(sb)
787
788 02.09.2011: we don't remember sb any more because we don't handle it in any way. Instead
789             we either have or don't have displaybitmap. If we have it, composition
790             is on (sb = cb). If we don't have it, composition is off (sb = ntb).
791 */
792 static BOOL HIDDCompositorToggleCompositing(struct HIDDCompositorData *compdata, BOOL newtop)
793 {
794     /* 
795      * If the topbitmap covers the complete screen, show it instead of 
796      * displaybitmap. Remember that screen bitmap -> composited bitmap
797      * mirroring has a negative impact on performance.
798      */
799     OOP_Object *oldcompositedbitmap = compdata->displaybitmap;
800     struct StackBitMapNode *topnode = (struct StackBitMapNode *)compdata->bitmapstack.mlh_Head;
801     OOP_Object *newsdispbitmap = NULL;
802     struct BitMap *tmpBM;
803     struct TagItem bmtags[2];
804
805     BOOL ok = TRUE, composit = FALSE;
806
807     /* (a) If mode change is needed, enforce opening a new screen */
808     if (compdata->modeschanged)
809     {
810         DTOGGLE(bug("[Compositor:%s] Display Mode changed\n", __PRETTY_FUNCTION__));
811         compdata->displaybitmap = NULL;
812     }
813
814     bmtags[0].ti_Tag = BMATags_DisplayID;           bmtags[0].ti_Data = (compdata->displayid | compdata->displaymode);
815     bmtags[1].ti_Tag = TAG_DONE;                    bmtags[1].ti_Data = TAG_DONE;
816
817     if ((topnode->topedge > 0) || ((compdata->displayrect.MaxY - compdata->displayrect.MinY + 1) > OOP_GET(topnode->bm, aHidd_BitMap_Height)))
818         composit = TRUE;
819     else if ((topnode->leftedge > 0) || ((compdata->displayrect.MaxX - compdata->displayrect.MinX + 1) > OOP_GET(topnode->bm, aHidd_BitMap_Width)))
820         composit = TRUE;
821     else if (topnode->sbmflags & COMPF_ALPHA)
822         composit = TRUE;
823
824     if (composit)
825     {
826         /* (b) */
827         if (compdata->displaybitmap == NULL)
828         {
829             /*
830              * displaybitmap == NULL means we were in passthrough mode before,
831              * or have just changed display mode - set up screen for composition.
832              */
833             DTOGGLE(bug("[Compositor:%s] Initialising Display-Compositor..\n", __PRETTY_FUNCTION__));
834
835             if (compdata->fb)
836             {
837                 /*
838                  * If our display driver uses a framebuffer, we can reuse it.
839                  * Copy its original contents back into the bitmap which it replaced,
840                  * then change framebuffer's video mode.
841                  * Framebuffer is the only bitmap which can change its ModeID on the fly.
842                  */
843                 DTOGGLE(bug("[Compositor:%s] Using Display Famebuffer HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__, compdata->fb));
844
845                  /* Do this comparison in order not to show the framebuffer twice */
846                 if (oldcompositedbitmap != compdata->fb)
847                 {
848                     /*
849                      * 1. It's legal to show the framebuffer itself. This causes copying
850                      *    back old bitmap contents and detaching from it.
851                      * 2. The result of this will always match compdata->fb.
852                      * 3. Internally this is a simple blit operation, it can't fail.
853                      */
854                     DTOGGLE(bug("[Compositor:%s] Copying old Famebuffer BitMap\n", __PRETTY_FUNCTION__));
855                     compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, compdata->fb, fHidd_Gfx_Show_CopyBack);
856                 }
857
858                 /* Switch display mode on the framebuffer. */
859                 OOP_SetAttrsTags(compdata->fb, aHidd_BitMap_ModeID, compdata->displaymode, TAG_DONE);
860                 /* We are now compositing on the framebuffer */
861                 compdata->displaybitmap = compdata->fb;
862             }
863             else
864             {
865                 /*
866                  * There's no framebuffer.
867                  * Create a new bitmap that will be used for compositing.
868                  */
869                 
870                 tmpBM = AllocBitMap(compdata->displayrect.MaxX - compdata->displayrect.MinX  + 1,
871                                              compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
872                                              compdata->displaydepth,
873                                              BMF_DISPLAYABLE|BMF_CHECKVALUE, (struct BitMap *)bmtags);
874                 if (tmpBM)
875                 {
876                     compdata->displaybitmap = HIDD_BM_OBJ(tmpBM);
877                     DTOGGLE(bug("[Compositor:%s] Created Compositor Display BitMap @ 0x%p [HiddBitMap @ 0x%p]\n", __PRETTY_FUNCTION__, tmpBM, compdata->displaybitmap));
878
879                     /* Mode changed, this bitmap will be shown later */
880                     newsdispbitmap = compdata->displaybitmap;
881
882                     /* NewBitMap can fail, handle this */
883                     if (!newsdispbitmap)
884                         ok = FALSE;
885                 }
886             }
887         }
888         else /* if (compdata->displaybitmap == NULL) */
889         {
890             /*
891              * We are already in compositing mode and will stay in it.
892              * Do not destroy our working bitmap.
893              */
894             oldcompositedbitmap = NULL;
895         }
896
897         if ((compdata->flags & COMPSTATEF_HASALPHA) && !(compdata->intermedbitmap))
898         {
899             tmpBM = AllocBitMap(compdata->displayrect.MaxX - compdata->displayrect.MinX  + 1,
900                                          compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
901                                          compdata->displaydepth,
902                                          BMF_CHECKVALUE, (struct BitMap *)bmtags);
903             if (tmpBM)
904             {
905                 compdata->intermedbitmap = HIDD_BM_OBJ(tmpBM);
906                 DTOGGLE(bug("[Compositor:%s] Allocated Alpha Intermediary BitMap @ 0x%p [HiddBitMap @ 0x%p]\n", __PRETTY_FUNCTION__, tmpBM, compdata->intermedbitmap));
907             }
908         }
909         /*
910          * (c) Here composition is turned on (displaybitmap != NULL).
911          * Redraw bitmap stack - compensate possible changes
912          */
913         if (ok)
914             HIDDCompositorRedrawVisibleRegions(compdata, NULL);
915     }
916     else if (oldcompositedbitmap || newtop)
917     {
918         /*
919          * (d) Set passthrough mode and display the frontmost bitmap.
920          * This is also triggered by 'newtop' parameter, which tells us
921          * that frontmost bitmap has been changed, and we need to display a new one.
922          * Old displaybitmap has been remembered in the beginning. If it's not
923          * NULL, it will be destroyed in the end.
924          */
925         newsdispbitmap = compdata->topbitmap;
926         compdata->displaybitmap = NULL;
927     }
928
929     DTOGGLE(bug("[Compositor:%s] oldcompbm 0x%p, topbm 0x%p, dispbm 0x%p, newscreenbm 0x%p\n", __PRETTY_FUNCTION__,
930             oldcompositedbitmap, compdata->topbitmap, compdata->displaybitmap, newsdispbitmap));
931
932     /*
933      * (e) If the screenbitmap changed, show the new screenbitmap.
934      * We do it after refreshing, for better visual appearance.
935      */
936     if (newsdispbitmap)
937     {
938         IPTR w, h;
939
940         compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, newsdispbitmap, fHidd_Gfx_Show_CopyBack);
941         DTOGGLE(bug("[Compositor:%s] Displayed HiddBitMap 0x%p, Show returned 0x%p\n", __PRETTY_FUNCTION__, newsdispbitmap, compdata->screenbitmap));
942
943         /* After Show we need Update for mirroring drivers */
944         if (compdata->screenbitmap)
945         {
946             OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Width, &w);
947             OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Height, &h);
948             HIDD_BM_UpdateRect(compdata->screenbitmap, 0, 0, w, h);
949         }
950     }
951
952     /*
953      * (a) - disposing of oldcompositingbitmap needs to happen after mode switch 
954      * since it could have been the current screenbitmap
955      */
956     if (oldcompositedbitmap && (oldcompositedbitmap != compdata->fb))
957     {
958         struct BitMap *freebm;
959
960         DTOGGLE(bug("[Compositor:%s] Disposing old working bitmap 0x%p\n", __PRETTY_FUNCTION__, oldcompositedbitmap));
961
962         OOP_GetAttr(oldcompositedbitmap, aHidd_BitMap_BMStruct, (IPTR *)&freebm);
963         if (freebm != NULL)
964         {
965             FreeBitMap(freebm);
966         }
967         else
968             HIDD_Gfx_DisposeBitMap(compdata->gfx, oldcompositedbitmap);
969
970     }
971
972     /* Handled */
973     compdata->modeschanged = FALSE;
974
975     return ok;
976 }
977
978 static VOID HIDDCompositorPurgeBitMapStack(struct HIDDCompositorData * compdata)
979 {
980     struct StackBitMapNode * curr, * next;
981
982     ForeachNodeSafe(&compdata->bitmapstack, curr, next)
983     {
984         if (curr->screenregion)
985             DisposeRegion(curr->screenregion);
986
987         FreeMem(curr, sizeof(struct StackBitMapNode));
988     }
989
990     NEWLIST(&compdata->bitmapstack);
991 }
992
993 static void HIDDCompositorShowSingle(struct HIDDCompositorData *compdata, OOP_Object *bm)
994 {
995     /* Show the single top bitmap */
996     compdata->topbitmap = bm;
997     compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, bm, fHidd_Gfx_Show_CopyBack);
998
999     /* Dispose working bitmap (if any) */
1000     if (compdata->displaybitmap)
1001     {
1002         /* Be careful with the framebuffer */
1003         if (compdata->displaybitmap != compdata->fb)
1004             HIDD_Gfx_DisposeBitMap(compdata->gfx, compdata->displaybitmap);
1005
1006         /* This will deactivate us */
1007         compdata->displaybitmap = NULL;
1008     }
1009 }
1010
1011 /* Emergency error recovery function */
1012 static void HIDDCompositorReset(struct HIDDCompositorData *compdata)
1013 {
1014     /* Purge bitmap stack */
1015     HIDDCompositorPurgeBitMapStack(compdata);
1016
1017     /*
1018      * Reset our internal state so that next BitMapStackChanged
1019      * causes complete reinitialization.
1020      */
1021     compdata->displaymode = vHidd_ModeID_Invalid;
1022     compdata->screenbitmap = NULL;
1023
1024     compdata->flags &= ~COMPSTATEF_HASALPHA;
1025 }
1026
1027 VOID CompositorParseConfig(struct HIDDCompositorData *compdata)
1028 {
1029     struct RDArgs *rdargs;
1030     IPTR CompArgs[NOOFARGS] = { 0 };
1031     TEXT CompConfig[1024];
1032
1033     /* use default amiga-like capabailities */
1034     compdata->capabilities = COMPF_ABOVE;
1035
1036     rdargs = AllocDosObjectTags(DOS_RDARGS, TAG_END);
1037     if (rdargs != NULL)
1038     {
1039         if (GetVar(COMPOSITOR_PREFS, CompConfig, 1024, GVF_GLOBAL_ONLY) != -1)
1040         {
1041             rdargs->RDA_Source.CS_Buffer = CompConfig;
1042             rdargs->RDA_Source.CS_Length = strlen(rdargs->RDA_Source.CS_Buffer);
1043             rdargs->RDA_DAList = (IPTR)NULL;
1044             rdargs->RDA_Buffer = NULL;
1045             rdargs->RDA_BufSiz = 0;
1046             rdargs->RDA_ExtHelp = NULL;
1047             rdargs->RDA_Flags = 0;
1048
1049             if (ReadArgs(COMPOSITOR_PEFSTEMPLATE, CompArgs, rdargs) != NULL)
1050             {
1051                 if (CompArgs[ARG_ABOVE])
1052                     compdata->capabilities |= COMPF_ABOVE;
1053                 else
1054                     compdata->capabilities &= ~COMPF_ABOVE;
1055                 
1056                 if (CompArgs[ARG_BELOW])
1057                     compdata->capabilities |= COMPF_BELOW;
1058                 else
1059                     compdata->capabilities &= ~COMPF_BELOW;
1060                 
1061                 if (CompArgs[ARG_LEFT])
1062                     compdata->capabilities |= COMPF_LEFT;
1063                 else
1064                     compdata->capabilities &= ~COMPF_LEFT;
1065                 
1066                 if (CompArgs[ARG_RIGHT])
1067                     compdata->capabilities |= COMPF_RIGHT;
1068                 else
1069                     compdata->capabilities &= ~COMPF_RIGHT;
1070
1071                 if (CompArgs[ARG_ALPHA])
1072                     compdata->capabilities |= COMPF_ALPHA;
1073                 else
1074                     compdata->capabilities &= ~COMPF_ALPHA;
1075
1076                 FreeArgs(rdargs);
1077             }
1078         }
1079         FreeDosObject(DOS_RDARGS, rdargs);
1080     }
1081 }
1082
1083 AROS_UFH3(void, CompositorDefaultBackFillFunc,
1084     AROS_UFHA(struct Hook *             , h,      A0),
1085     AROS_UFHA(struct BitMap *              , bm,     A2),
1086     AROS_UFHA(struct HIDD_BackFillHookMsg *  , msg,    A1))
1087 {
1088     AROS_USERFUNC_INIT
1089
1090     struct HIDDCompositorData *compdata = h->h_Data;
1091
1092     D(bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata));
1093
1094     HIDDCompositorFillRect(compdata, HIDD_BM_OBJ(bm), msg->bounds->MinX, msg->bounds->MinY, msg->bounds->MaxX, msg->bounds->MaxY);
1095
1096     AROS_USERFUNC_EXIT
1097 }
1098
1099 /* PUBLIC METHODS */
1100 OOP_Object *METHOD(Compositor, Root, New)
1101 {
1102     o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
1103
1104     if (o)
1105     {
1106         OOP_MethodID disposemid;
1107         struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1108
1109         D(bug("[%s] Compositor @ 0x%p, data @ 0x%p\n", __PRETTY_FUNCTION__, o, compdata));
1110
1111         CompositorParseConfig(compdata);
1112
1113         compdata->capabilities = (ULONG)GetTagData(aHidd_Compositor_State, compdata->capabilities, msg->attrList);
1114
1115         D(bug("[%s] Compositor Capabilities: %08lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
1116
1117         compdata->displaymode = vHidd_ModeID_Invalid;
1118
1119         NEWLIST(&compdata->bitmapstack);
1120
1121         compdata->defaultbackfill.h_Entry = (HOOKFUNC)AROS_ASMSYMNAME(CompositorDefaultBackFillFunc);
1122         compdata->defaultbackfill.h_Data = compdata;
1123         compdata->backfillhook = &compdata->defaultbackfill;
1124
1125         InitSemaphore(&compdata->semaphore);
1126
1127         compdata->displayid = (ULONG)GetTagData(aHidd_Compositor_DisplayID, 0, msg->attrList);
1128         compdata->gfx = (OOP_Object *)GetTagData(aHidd_Compositor_GfxHidd, 0, msg->attrList);
1129         compdata->fb  = (OOP_Object *)GetTagData(aHidd_Compositor_FrameBuffer, 0, msg->attrList);
1130
1131         D(bug("[%s] DisplayID %08lx for Gfx Driver @ 0x%p\n", __PRETTY_FUNCTION__, compdata->displayid, compdata->gfx));
1132
1133         GfxBase = (APTR)OpenLibrary("graphics.library", 41);
1134         IntuitionBase = (APTR)OpenLibrary("intuition.library", 50);
1135
1136         /* GfxHidd is mandatory */
1137         if ((compdata->GraphicsBase) && (compdata->gfx != NULL))
1138         {
1139             /* Create GC object that will be used for drawing operations */
1140             compdata->gc = HIDD_Gfx_NewGC(compdata->gfx, NULL);
1141
1142             D(bug("[%s] Compositor GC @ %p\n", __PRETTY_FUNCTION__, compdata->gc));
1143
1144             if ((compdata->gfx) && (compdata->gc))
1145                 return o;
1146         }
1147
1148         /* Creation failed */
1149         disposemid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
1150         OOP_CoerceMethod(cl, o, &disposemid);
1151     }
1152
1153     return NULL;
1154 }
1155
1156 void METHOD(Compositor, Root, Dispose)
1157 {
1158
1159     D(
1160         struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1161         bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata);
1162       )
1163
1164     OOP_DoSuperMethod(cl, o, &msg->mID);
1165 }
1166
1167 VOID METHOD(Compositor, Root, Get)
1168 {
1169     ULONG idx;
1170
1171     struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1172
1173     if (IS_COMPOSITOR_ATTR(msg->attrID, idx))
1174     {
1175         switch (idx)
1176         {
1177             case aoHidd_Compositor_Capabilities:
1178             {
1179                 *msg->storage = (IPTR)CAPABILITY_FLAGS;
1180                 D(bug("[%s] Compositor Capabilities: %lx\n", __PRETTY_FUNCTION__, *msg->storage));
1181                 return;
1182             }
1183             case aoHidd_Compositor_State:
1184             {
1185                 *msg->storage = (IPTR)(compdata->capabilities & CAPABILITY_FLAGS);
1186                 D(bug("[%s] Compositor State: %lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
1187                 return;
1188             }
1189             case aoHidd_Compositor_BackFillHook:
1190             {
1191                 D(bug("[%s] BackFillHook: 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook));
1192                 *msg->storage = (IPTR)compdata->backfillhook;
1193                 return;
1194             }
1195         }
1196     }
1197     OOP_DoSuperMethod(cl, o, &msg->mID);
1198 }
1199
1200 VOID METHOD(Compositor, Root, Set)
1201 {
1202     ULONG idx;
1203
1204     struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1205     struct TagItem *tag, *tstate = msg->attrList;
1206
1207     while ((tag = NextTagItem(&tstate)))
1208     {
1209         if (IS_COMPOSITOR_ATTR(tag->ti_Tag, idx))
1210         {
1211             switch (idx)
1212             {
1213                 case aoHidd_Compositor_State:
1214                 {
1215                     D(bug("[%s] Compositor Capabilities State: %lx -> ", __PRETTY_FUNCTION__, compdata->capabilities));
1216                     compdata->capabilities = (ULONG)(tag->ti_Data & CAPABILITY_FLAGS);
1217                     D(bug("%lx\n", compdata->capabilities));
1218                     break;
1219                 }
1220                 case aoHidd_Compositor_BackFillHook:
1221                 {
1222                     if (tag->ti_Data)
1223                     {
1224                         D(bug("[%s] BackFillHook: 0x%p -> 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook, tag->ti_Data));
1225                         compdata->backfillhook = (struct Hook *)tag->ti_Data;
1226                     }
1227                     else
1228                     {
1229                         D(bug("[%s] Default BackFillHook\n", __PRETTY_FUNCTION__));
1230                         compdata->backfillhook = &compdata->defaultbackfill;
1231                     }
1232                     break;
1233                 }
1234             }
1235         }
1236     }
1237
1238     OOP_DoSuperMethod(cl, o, &msg->mID);
1239 }
1240
1241 OOP_Object *METHOD(Compositor, Hidd_Compositor, BitMapStackChanged)
1242 {
1243     struct HIDD_ViewPortData *vpdata;
1244     struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1245     struct StackBitMapNode *n;
1246     struct Screen *bmScreen;
1247     OOP_Object *bmpxfmt;
1248     int bmstdfmt;
1249     BOOL newtop = FALSE;
1250     BOOL ok = TRUE;
1251
1252     DSTACK(bug("[Compositor] %s: Top bitmap: 0x%lx\n", __PRETTY_FUNCTION__, msg->data->Bitmap));
1253
1254     LOCK_COMPOSITOR_WRITE
1255
1256     /* Free all items which are already on the list */
1257     HIDDCompositorPurgeBitMapStack(compdata);
1258
1259     if (!msg->data)
1260     {
1261         UNLOCK_COMPOSITOR
1262
1263         DSTACK(bug("[Compositor] %s: No ViewPort specified\n", __PRETTY_FUNCTION__));
1264
1265         /* Blank screen */
1266         HIDDCompositorShowSingle(compdata, NULL);
1267
1268         /* We know we are inactive after this */
1269         *msg->active = FALSE;
1270         /* This can return NULL, it's okay */
1271         return compdata->screenbitmap;
1272     }
1273
1274     /* Copy bitmaps pointers to our stack */
1275     for (vpdata = msg->data; vpdata; vpdata = vpdata->Next)
1276     {
1277         n = AllocMem(sizeof(struct StackBitMapNode), MEMF_ANY | MEMF_CLEAR);
1278         if (!n)
1279         {
1280             /*
1281              * Error happened.
1282              * We need to reset own state and return NULL. graphics.library
1283              * falls back to no composition in this case.
1284              */
1285             DSTACK(bug("[Compositor] %s: Error allocating StackBitMapNode!!!\n", __PRETTY_FUNCTION__));
1286
1287             ok = FALSE;
1288             break;
1289         }
1290
1291         DSTACK(bug("[Compositor] %s: ViewPort 0x%p, offset (%d, %d)\n", __PRETTY_FUNCTION__, vpdata->vpe->ViewPort, vpdata->vpe->ViewPort->DxOffset, vpdata->vpe->ViewPort->DyOffset));
1292
1293         n->bm                   = vpdata->Bitmap;
1294         n->sbmflags             = STACKNODEF_DISPLAYABLE;
1295         n->leftedge             = vpdata->vpe->ViewPort->DxOffset;
1296         n->topedge              = vpdata->vpe->ViewPort->DyOffset;
1297
1298         n->screenregion = NewRegion();
1299
1300         if ((bmScreen = HIDDCompositorFindBitMapScreen(compdata, n->bm)) != NULL)
1301         {
1302             DSTACK(bug("[Compositor] %s: Screen @ 0x%p\n", __PRETTY_FUNCTION__, bmScreen));
1303             GetAttr(SA_CompositingFlags, (Object *)bmScreen, &n->sbmflags);
1304             DSTACK(bug("[Compositor] %s: CompositingFlags %08x\n", __PRETTY_FUNCTION__, n->sbmflags));
1305             n->sbmflags |= STACKNODEF_DISPLAYABLE;
1306             if (n->sbmflags & COMPF_ALPHA)
1307             {
1308                 GetAttr(SA_AlphaPreCompositHook, (Object *)bmScreen, (IPTR *)&n->prealphacomphook);
1309                 DSTACK(bug("[Compositor] %s: Pre-AlphaComposit Hook @ 0x%p\n", __PRETTY_FUNCTION__, n->prealphacomphook));
1310             }
1311         }
1312
1313         if (n->sbmflags & COMPF_ALPHA)
1314         {
1315             bmpxfmt = (OOP_Object *)OOP_GET(n->bm, aHidd_BitMap_PixFmt);
1316             bmstdfmt = (int)OOP_GET(bmpxfmt, aHidd_PixFmt_StdPixFmt);
1317             DSTACK(bug("[Compositor] %s: Screen BitMap PixFmt %lx @ 0x%p\n", __PRETTY_FUNCTION__, bmstdfmt, bmpxfmt));
1318
1319             switch (bmstdfmt)
1320             {
1321                 case vHidd_StdPixFmt_ARGB32:
1322                 case vHidd_StdPixFmt_BGRA32:
1323                 case vHidd_StdPixFmt_RGBA32:
1324                 case vHidd_StdPixFmt_ABGR32:
1325                 {
1326                     DSTACK(bug("[Compositor] %s: Screen BitMap has Alpha\n", __PRETTY_FUNCTION__));
1327
1328                     compdata->flags |= COMPSTATEF_HASALPHA;
1329                     break;
1330                 }
1331                 default:
1332                 {
1333                     n->sbmflags &= ~COMPF_ALPHA;
1334                     break;
1335                 }
1336             }
1337         }
1338
1339         if (!(n->sbmflags & COMPF_ALPHA))
1340         {
1341             if ((((BOOL)OOP_GET(n->bm, aHidd_BitMap_Displayable)) != TRUE))
1342                 n->sbmflags &= ~STACKNODEF_DISPLAYABLE;
1343         }
1344         AddTail((struct List *)&compdata->bitmapstack, (struct Node *)n);
1345     }
1346
1347     /* Switch mode if needed */
1348     UpdateDisplayMode(compdata);
1349
1350     if (msg->data->Bitmap != compdata->topbitmap)
1351     {
1352         /* Set the new pointer to top bitmap */
1353         compdata->topbitmap = msg->data->Bitmap;
1354         newtop = TRUE;
1355     }
1356
1357     if (ok)
1358     {
1359         /*
1360          * Validate bitmap offsets - they might not match the compositing rules taking
1361          * new displayedwidth/displayedheight values
1362          */
1363         ForeachNode(&compdata->bitmapstack, n)
1364         {
1365             HIDDCompositorValidateBitMapPositionChange(n->bm, &n->leftedge, &n->topedge, 
1366                                                         compdata->displayrect.MaxX + 1, compdata->displayrect.MaxY + 1);
1367             DSTACK(bug("[Compositor] %s: Bitmap 0x%p, display size %d x %d, validated position (%ld, %ld)\n", __PRETTY_FUNCTION__,
1368                        n->bm, compdata->displayrect.MaxX + 1, compdata->displayrect.MaxY + 1,
1369                        n->leftedge, n->topedge));
1370         }
1371
1372         /* Toogle compositing based on screen positions */
1373         ok = HIDDCompositorToggleCompositing(compdata, newtop);
1374     }
1375
1376     /* Handle error */
1377     if (!ok)
1378     {
1379         HIDDCompositorReset(compdata);
1380         HIDDCompositorShowSingle(compdata, msg->data->Bitmap);
1381     }
1382
1383     UNLOCK_COMPOSITOR
1384
1385     DSTACK(bug("[%s] Done, composited bitmap 0x%p\n", __PRETTY_FUNCTION__, compdata->displaybitmap));
1386
1387     /* Tell if the composition is active */
1388     *msg->active = compdata->displaybitmap ? TRUE : FALSE;
1389     /* Return actually displayed bitmap */
1390     return compdata->screenbitmap;
1391 }
1392
1393 VOID METHOD(Compositor, Hidd_Compositor, BitMapRectChanged)
1394 {
1395     struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1396     OOP_Object                *renderTarget;
1397
1398     if (compdata->displaybitmap)
1399     {
1400         /* Composition is active, handle redraw if the bitmap is on screen */
1401         struct StackBitMapNode *n;
1402
1403         DUPDATE(bug("[%s] Bitmap 0x%p\n", __PRETTY_FUNCTION__, msg->bm));
1404
1405         LOCK_COMPOSITOR_READ
1406
1407         if (compdata->intermedbitmap)
1408             renderTarget = compdata->intermedbitmap;
1409         else
1410             renderTarget = compdata->displaybitmap;
1411
1412         n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1413         if (n && (n->sbmflags & STACKNODEF_VISIBLE))
1414         {
1415             struct Rectangle srcrect, dstandvisrect;
1416
1417             srcrect.MinX = n->leftedge + msg->x;
1418             srcrect.MinY = n->topedge + msg->y;
1419             srcrect.MaxX = srcrect.MinX + msg->width - 1; 
1420             srcrect.MaxY = srcrect.MinY + msg->height - 1;
1421             DUPDATE(bug("[%s] Bitmap rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, msg->x, msg->y, msg->x + msg->width - 1, msg->y + msg->height - 1));
1422
1423             DUPDATE(bug("[%s] Screen-relative rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(srcrect)));
1424
1425             struct RegionRectangle * srrect = n->screenregion->RegionRectangle;
1426             while (srrect)
1427             {
1428                 BOOL updateAlphaBmps = FALSE;
1429
1430                 dstandvisrect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
1431                 dstandvisrect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
1432                 dstandvisrect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
1433                 dstandvisrect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
1434
1435                 if (AndRectRect(&srcrect, &dstandvisrect, &dstandvisrect))
1436                 {
1437                     /* Intersection is valid. Blit. */
1438                     DUPDATE(bug("[%s] Clipped rect (%d, %d) - (%d, %d)\n", __PRETTY_FUNCTION__, _RECT(dstandvisrect)));
1439
1440                     if (!(n->sbmflags & COMPF_ALPHA))
1441                     {
1442                         if ((compdata->alpharegion) && (isRectInRegion(compdata->alpharegion, &dstandvisrect)))
1443                         {
1444                             DUPDATE(bug("[%s] ** Bitmap in Alpha Region!\n", __PRETTY_FUNCTION__));
1445                             updateAlphaBmps = TRUE;
1446                         }
1447                         HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &dstandvisrect);
1448                     }
1449                     else
1450                     {
1451                         updateAlphaBmps = FALSE;
1452                         HIDDCompositorRedrawVisibleRegions(compdata, &dstandvisrect);
1453                     }
1454
1455                     if (updateAlphaBmps)
1456                         HIDDCompositorRedrawAlphaRegions(compdata, &dstandvisrect);
1457
1458                     if (renderTarget != compdata->displaybitmap)
1459                     {
1460                         HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
1461                                 dstandvisrect.MinX, dstandvisrect.MinY,
1462                                 compdata->displaybitmap,
1463                                 dstandvisrect.MinX, dstandvisrect.MinY,
1464                                 dstandvisrect.MaxX - dstandvisrect.MinX + 1,
1465                                 dstandvisrect.MaxY - dstandvisrect.MinY + 1,
1466                                 compdata->gc);
1467                     }
1468
1469                     HIDD_BM_UpdateRect(compdata->displaybitmap,
1470                                        dstandvisrect.MinX, dstandvisrect.MinY,
1471                                        dstandvisrect.MaxX - dstandvisrect.MinX + 1,
1472                                        dstandvisrect.MaxY - dstandvisrect.MinY + 1);
1473                 }
1474                 srrect = srrect->Next;
1475             }
1476         }
1477
1478         UNLOCK_COMPOSITOR
1479         
1480         DUPDATE(bug("[%s] Done\n", __PRETTY_FUNCTION__));
1481     }
1482     else
1483     {
1484         /* In order to speed things up, we handle passthrough ourselves here. */
1485         HIDD_BM_UpdateRect(msg->bm, msg->x, msg->y, msg->width, msg->height);
1486     }
1487 }
1488
1489 IPTR METHOD(Compositor, Hidd_Compositor, BitMapPositionChange)
1490 {
1491     struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1492     struct StackBitMapNode *n;
1493     IPTR disp_width, disp_height;
1494
1495     LOCK_COMPOSITOR_READ
1496
1497     n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1498     if (n)
1499     {
1500         /* The bitmap is on display. Validate against screen size */
1501         disp_width  = compdata->displayrect.MaxX + 1;
1502         disp_height = compdata->displayrect.MaxY + 1;
1503     }
1504     else
1505     {
1506         /* The bitmap is not displayed yet. Validate against its own ModeID size. */
1507         HIDDT_ModeID modeid = vHidd_ModeID_Invalid;
1508         OOP_Object *bmfriend, *sync, *pf;
1509
1510         OOP_GetAttr(msg->bm, aHidd_BitMap_ModeID, &modeid);
1511
1512         if ((modeid == vHidd_ModeID_Invalid) && (OOP_GET(msg->bm, aHidd_BitMap_Compositable)))
1513         {
1514             OOP_GetAttr(msg->bm, aHidd_BitMap_Friend, (IPTR *)&bmfriend);
1515             if (bmfriend)
1516                 OOP_GetAttr(bmfriend, aHidd_BitMap_ModeID, &modeid);
1517         }
1518
1519         if (modeid == vHidd_ModeID_Invalid)
1520         {
1521             /*
1522                 * Nondisplayable bitmaps don't scroll.
1523                 * In fact they simply can't get in here because MakeVPort() performs the validation.
1524                 * But who knows what bug can slip into someone's software...
1525                 */
1526             UNLOCK_COMPOSITOR
1527             return FALSE;
1528         }
1529
1530         HIDD_Gfx_GetMode(compdata->gfx, modeid, &sync, &pf);
1531         OOP_GetAttr(sync, aHidd_Sync_HDisp, &disp_width);
1532         OOP_GetAttr(sync, aHidd_Sync_VDisp, &disp_height);
1533     }
1534
1535     DMOVE(bug("[%s] Validating bitmap 0x%p, position (%ld, %ld), limits %ld x %ld\n", __PRETTY_FUNCTION__,
1536           msg->bm, *msg->newxoffset, *msg->newyoffset, disp_width, disp_height));
1537
1538     HIDDCompositorValidateBitMapPositionChange(msg->bm, msg->newxoffset, msg->newyoffset,
1539                                                 disp_width, disp_height);
1540
1541     DMOVE(bug("[%s] Validated position (%ld, %ld)\n", __PRETTY_FUNCTION__, *msg->newxoffset, *msg->newyoffset));
1542
1543     if (n && ((*msg->newxoffset != n->leftedge) || (*msg->newyoffset != n->topedge)))
1544     {
1545         DMOVE(bug("[%s] Old position (%ld, %ld)\n", __PRETTY_FUNCTION__, n->leftedge, n->topedge));
1546
1547         /* Reflect the change if it happened */
1548         n->leftedge = *msg->newxoffset;
1549         n->topedge  = *msg->newyoffset;
1550
1551         if (compdata->topbitmap == msg->bm)
1552         {
1553             /*
1554              * If this is the frontmost bitmap, we may want to toggle compositing,
1555              * if it starts/stops covering the whole screen at one point.
1556              * We don't need to call HIDDCompositorRedrawVisibleRegions() here because
1557              * HIDDCompositorToggleCompositing() does this itself, for improved
1558              * visual appearance.
1559              */
1560             HIDDCompositorToggleCompositing(compdata, FALSE);    
1561         }
1562         else
1563             HIDDCompositorRedrawVisibleRegions(compdata, NULL);
1564     }
1565
1566     UNLOCK_COMPOSITOR
1567
1568     /* Return active state */
1569     return compdata->displaybitmap ? TRUE : FALSE;
1570 }
1571
1572 IPTR METHOD(Compositor, Hidd_Compositor, BitMapValidate)
1573 {
1574     if (IS_HIDD_BM(msg->bm))
1575         return TRUE;
1576     
1577     return FALSE;
1578 }
1579
1580 IPTR METHOD(Compositor, Hidd_Compositor, BitMapEnable)
1581 {
1582     if (IS_HIDD_BM(msg->bm))
1583     {
1584         if (!(OOP_GET(HIDD_BM_OBJ(msg->bm), aHidd_BitMap_Displayable)))
1585         {
1586             struct TagItem composittags[] = {
1587                 {aHidd_BitMap_Compositable, TRUE},
1588                 {TAG_DONE            , 0    }
1589             };
1590
1591             D(bug("[GfxCompositor]: Marking BitMap 0x%lx as Compositable\n", msg->bm));
1592             OOP_SetAttrs(HIDD_BM_OBJ(msg->bm), composittags);
1593         }
1594         return TRUE;
1595     }
1596
1597     return FALSE;
1598 }
1599
1600 #define NUM_Compositor_Root_METHODS 4
1601
1602 static const struct OOP_MethodDescr Compositor_Root_descr[] =
1603 {
1604     {(OOP_MethodFunc)Compositor__Root__New, moRoot_New},
1605     {(OOP_MethodFunc)Compositor__Root__Dispose, moRoot_Dispose},
1606     {(OOP_MethodFunc)Compositor__Root__Get, moRoot_Get},
1607     {(OOP_MethodFunc)Compositor__Root__Set, moRoot_Set},
1608     {NULL, 0}
1609 };
1610
1611 #define NUM_Compositor_Hidd_Compositor_METHODS 5
1612
1613 static const struct OOP_MethodDescr Compositor_Hidd_Compositor_descr[] =
1614 {
1615     {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapStackChanged, moHidd_Compositor_BitMapStackChanged},
1616     {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapRectChanged, moHidd_Compositor_BitMapRectChanged},
1617     {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapPositionChange, moHidd_Compositor_BitMapPositionChange},
1618     {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapValidate, moHidd_Compositor_BitMapValidate},
1619     {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapEnable, moHidd_Compositor_BitMapEnable},
1620     {NULL, 0}
1621 };
1622
1623 const struct OOP_InterfaceDescr Compositor_ifdescr[] =
1624 {
1625     {Compositor_Root_descr, IID_Root, NUM_Compositor_Root_METHODS},
1626     {Compositor_Hidd_Compositor_descr, IID_Hidd_Compositor, NUM_Compositor_Hidd_Compositor_METHODS},
1627     {NULL, NULL}
1628 };