small refactor to region handling
[AROS.git] / workbench / devs / monitors / Compositor / compositorclass.c
blobb1ea581314b1f3f5d43a41cbab84e33e0e857db5
1 /*
2 Copyright © 2010-2013, The AROS Development Team. All rights reserved.
3 $Id$
4 */
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
27 #include <aros/debug.h>
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>
37 #include <graphics/view.h>
38 #include <hidd/graphics.h>
40 #include "compositor_intern.h"
42 #define COMPOSITOR_PREFS "SYS/compositor.prefs"
43 #define COMPOSITOR_PEFSTEMPLATE "ABOVE/S,BELOW/S,LEFT/S,RIGHT/S,ALPHA/S"
45 #define CAPABILITY_FLAGS (COMPF_ABOVE|COMPF_BELOW|COMPF_LEFT|COMPF_RIGHT|COMPF_ALPHA)
47 enum
49 ARG_ABOVE = 0,
50 ARG_BELOW,
51 ARG_LEFT,
52 ARG_RIGHT,
53 ARG_ALPHA,
54 NOOFARGS
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
67 #define _RECT(x) x.MinX, x.MinY, x.MaxX, x.MaxY
69 #define MAX(a,b) a > b ? a : b
70 #define MIN(a,b) a < b ? a : b
72 BOOL isRectInRegion(struct Region *region, struct Rectangle *rect)
74 struct RegionRectangle *rrect = region->RegionRectangle;
76 while (rrect)
78 if (AndRectRect(&rrect->bounds, rect, NULL))
79 return TRUE;
81 rrect = rrect->Next;
83 return FALSE;
86 static struct StackBitMapNode * HIDDCompositorFindBitMapStackNode(struct HIDDCompositorData * compdata, OOP_Object * bm)
88 struct StackBitMapNode * n = NULL;
90 ForeachNode(&compdata->bitmapstack, n)
92 if (n->bm == bm)
93 return n;
96 return NULL;
99 struct Screen *HIDDCompositorFindBitMapScreen(struct HIDDCompositorData *compdata, OOP_Object *bm)
101 struct Screen *curScreen = NULL;
103 for (curScreen = IntuitionBase->FirstScreen; curScreen != NULL; curScreen = curScreen->NextScreen)
105 if (bm == HIDD_BM_OBJ(curScreen->RastPort.BitMap))
106 return curScreen;
109 return (struct Screen *)NULL;
112 static VOID HIDDCompositorValidateBitMapPositionChange(OOP_Object * bm, SIPTR *newxoffset, SIPTR *newyoffset, LONG displayedwidth, LONG displayedheight)
114 IPTR width, height;
115 LONG neglimit, poslimit;
117 OOP_GetAttr(bm, aHidd_BitMap_Width, &width);
118 OOP_GetAttr(bm, aHidd_BitMap_Height, &height);
120 /* Check x position */
121 if (width > displayedwidth)
123 neglimit = displayedwidth - width;
124 poslimit = 0;
126 else
128 neglimit = 0;
129 poslimit = displayedwidth - width;
132 if (*(newxoffset) > poslimit)
133 *(newxoffset) = poslimit;
134 if (*(newxoffset) < neglimit)
135 *(newxoffset) = neglimit;
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 */
144 if (*(newyoffset) > poslimit)
145 *(newyoffset) = poslimit;
146 if (*(newyoffset) < neglimit)
147 *(newyoffset) = neglimit;
150 static VOID HIDDCompositorRecalculateVisibleRegions(struct HIDDCompositorData *compdata)
152 struct StackBitMapNode *n = NULL, *tmpn;
153 struct Region *dispvisregion = NULL;
154 ULONG oldflags = compdata->flags;
156 DRECALC(bug("[Compositor:%s] Display rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(compdata->displayrect)));
159 * This function assumes bitmapstack is in correct Z order:
160 * from topmost to bottom most
162 if ((dispvisregion = NewRegion()) != NULL)
164 OrRectRegion(dispvisregion, &compdata->displayrect);
166 compdata->flags &= ~COMPSTATEF_HASALPHA;
167 if (compdata->alpharegion)
169 DisposeRegion(compdata->alpharegion);
170 compdata->alpharegion = NULL;
172 DRECALC(bug("[Compositor:%s] DisplayRegion @ 0x%p\n", __PRETTY_FUNCTION__, dispvisregion));
174 ForeachNodeSafe(&compdata->bitmapstack, n, tmpn)
176 /* Get bitmap bounding box in screen coordinates */
177 struct Rectangle tmprect;
179 n->sbmflags &= ~STACKNODEF_VISIBLE;
181 if (n->screenregion)
182 ClearRegion(n->screenregion);
183 else
184 n->screenregion = NewRegion();
186 if (n->screenregion)
188 struct RegionRectangle *srrect;
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;
195 DRECALC(bug("[Compositor:%s] Screen Rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
197 OrRectRegion(n->screenregion, &tmprect); // Start with the Screen's dimensions ..
198 AndRegionRegion(dispvisregion, n->screenregion); // And adjust for the "Display"
200 if ((srrect = n->screenregion->RegionRectangle) != NULL)
202 while (srrect)
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;
209 if (!(n->sbmflags & COMPF_ALPHA))
210 ClearRectRegion(dispvisregion, &tmprect);
211 else
213 compdata->flags |= COMPSTATEF_HASALPHA;
214 if (!(compdata->alpharegion))
215 compdata->alpharegion = NewRegion();
217 OrRectRegion(compdata->alpharegion, &tmprect);
219 srrect = srrect->Next;
222 if (!(compdata->capabilities & COMPF_ABOVE) && !(n->sbmflags & COMPF_ABOVE))
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);
230 if (!(compdata->capabilities & COMPF_BELOW) && !(n->sbmflags & COMPF_BELOW))
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);
238 if (!(compdata->capabilities & COMPF_LEFT) && !(n->sbmflags & COMPF_LEFT))
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);
246 if (!(compdata->capabilities & COMPF_RIGHT) && !(n->sbmflags & COMPF_RIGHT))
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);
254 n->sbmflags |= STACKNODEF_VISIBLE;
257 DRECALC(bug("[Compositor:%s] HiddBitmap 0x%p, topedge %d, visible %d\n", __PRETTY_FUNCTION__,
258 n->bm, n->topedge, (n->sbmflags & STACKNODEF_VISIBLE)));
260 else
262 DRECALC(bug("[Compositor:%s] Failed to create Screen Region\n", __PRETTY_FUNCTION__));
265 DisposeRegion(dispvisregion);
266 if (compdata->flags != oldflags)
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))
272 DRECALC(bug("[Compositor:%s] Alpha removed\n", __PRETTY_FUNCTION__));
273 if (compdata->alpharegion)
274 DisposeRegion(compdata->alpharegion);
276 if (compdata->intermedbitmap)
277 HIDD_Gfx_DisposeBitMap(compdata->gfx, compdata->intermedbitmap);
279 compdata->alpharegion = NULL;
280 compdata->intermedbitmap = NULL;
284 else
286 DRECALC(bug("[Compositor:%s] Failed to create Display Region\n", __PRETTY_FUNCTION__));
290 static HIDDT_ModeID FindBestHiddMode(struct HIDDCompositorData *compdata, ULONG width, ULONG height, ULONG depth, ULONG *res_depth)
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;
302 DMODE(bug("[%s] Finding best match for mode %ux%ux%u\n", __PRETTY_FUNCTION__, width, height, depth));
304 while ((mode = HIDD_Gfx_NextModeID(compdata->gfx, mode, &sync, &pf)) != vHidd_ModeID_Invalid)
306 BOOL match;
308 DMODE(bug("[%s] Checking mode 0x%08X... ", __PRETTY_FUNCTION__, mode));
309 if (OOP_GET(pf, aHidd_PixFmt_ColorModel) != vHidd_ColorModel_TrueColor)
311 DMODE(bug("Skipped (not truecolor)\n"));
312 continue;
315 OOP_GetAttr(sync, aHidd_Sync_HDisp, &w);
316 OOP_GetAttr(sync, aHidd_Sync_VDisp, &h);
317 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &d);
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;
323 match = FALSE;
324 if (delta < found_delta)
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;
331 match = TRUE;
333 else if (delta == found_delta)
335 /* If resolution is the same as that of current candidate mode, we can look at depth. */
336 if (found_depth > depth)
339 * Candidate mode if deeper than requested. We can supersede it with another mode
340 * of smaller depth, but which still matches our request.
342 if ((d < found_depth) && (d >= depth))
343 match = TRUE;
345 else if (found_depth < depth)
348 * We want better depth than current candidate.
349 * In this case anything deeper will do.
351 if (d > found_depth)
352 match = TRUE;
356 if (match)
359 * Mode with the same delta, but larger depth, may supersede
360 * previous mode, if we prefer deeper ones.
362 DMODE(bug("Selected (%ldx%ldx%ld, delta = %u)", w, h, d, delta));
363 found_depth = d;
364 found_mode = mode;
366 DMODE(bug("\n"));
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;
376 return found_mode;
379 static void UpdateDisplayMode(struct HIDDCompositorData *compdata)
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;
387 DSTACK(bug("[Compositor] %s()\n", __PRETTY_FUNCTION__));
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.
394 * If a LUT bitmap is present in the stack (depth < 9), we request truecolor
395 * screen for better color presentation.
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.
401 for (n = (struct StackBitMapNode *)compdata->bitmapstack.mlh_TailPred;
402 n->n.mln_Pred; n = (struct StackBitMapNode *)n->n.mln_Pred)
404 if ((!(n->sbmflags & COMPF_ALPHA)) && (n->sbmflags & STACKNODEF_DISPLAYABLE))
406 OOP_GetAttr(n->bm, aHidd_BitMap_ModeID, &modeid);
407 HIDD_Gfx_GetMode(compdata->gfx, modeid, &sync, &pf);
409 if (OOP_GET(pf, aHidd_PixFmt_ColorModel) == vHidd_ColorModel_TrueColor)
411 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
412 if (depth > comp_depth)
413 comp_depth = depth;
415 else
418 * If we have a LUT bitmap on stack, we request 24-bit screen
419 * for better color transfer.
421 comp_depth = 24;
424 else
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;
436 if (sync)
438 /* Get the needed size */
439 OOP_GetAttr(sync, aHidd_Sync_HDisp, &width);
440 OOP_GetAttr(sync, aHidd_Sync_VDisp, &height);
443 DSTACK(bug("[%s] Prefered mode %ldx%ldx%d\n", __PRETTY_FUNCTION__, width, height, comp_depth));
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));
448 if (modeid != compdata->displaymode)
450 /* The mode is different. Need to prepare information needed for compositing */
451 struct TagItem gctags[] =
453 { aHidd_GC_Foreground, 0x99999999 },
454 { TAG_DONE , 0 }
457 /* Signal mode change */
458 compdata->displaymode = modeid;
459 compdata->displaydepth = comp_depth;
460 compdata->modeschanged = TRUE;
462 /* Get gray foregound */
463 if (found_depth < 24)
464 gctags[0].ti_Data = 0x9492;
466 OOP_SetAttrs(compdata->gc, gctags);
470 static inline void HIDDCompositorRedrawBitmap(struct HIDDCompositorData *compdata, OOP_Object *renderTarget, struct StackBitMapNode *n, struct Rectangle *rect)
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;
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));
479 if (!(n->sbmflags & COMPF_ALPHA))
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));
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);
491 else
493 UBYTE *baseaddress;
494 ULONG width, height, banksize, memsize;
495 IPTR modulo;
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));
501 if (HIDD_BM_ObtainDirectAccess(n->bm, &baseaddress, &width, &height, &banksize, &memsize))
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);
512 static inline void HIDDCompositorFillRect(struct HIDDCompositorData *compdata, OOP_Object *renderTarget, ULONG MinX, ULONG MinY, ULONG MaxX, ULONG MaxY)
514 DREDRAWSCR(bug("[Compositor:%s] Filling [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
515 MinX, MinY, MaxX, MaxY));
517 HIDD_BM_FillRect(renderTarget, compdata->gc,
518 MinX, MinY, MaxX, MaxY);
522 static VOID HIDDCompositorRedrawAlphaRegions(struct HIDDCompositorData *compdata, struct Rectangle *drawrect)
524 OOP_Object *renderTarget = compdata->displaybitmap;
525 struct Rectangle alpharect;
526 struct StackBitMapNode *n;
527 struct BitMap *backbm;
529 if (compdata->intermedbitmap)
530 renderTarget = compdata->intermedbitmap;
532 DREDRAWSCR(if (drawrect){ bug("[Compositor:%s] Rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT((*drawrect))); })
534 OOP_GetAttr(renderTarget, aHidd_BitMap_BMStruct, (IPTR *)&backbm);
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)
540 if ((n->sbmflags & STACKNODEF_VISIBLE) &&
541 (n->sbmflags & COMPF_ALPHA) &&
542 (n->screenregion))
544 struct RegionRectangle *srrect;
546 DREDRAWSCR(bug("[Compositor:%s] Alpha Screen Region @ 0x%p HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__,
547 n->screenregion, n->bm));
549 if ((srrect = n->screenregion->RegionRectangle) != NULL)
551 DREDRAWSCR(bug("[Compositor:%s] Compositing Visible Alpha Regions..\n", __PRETTY_FUNCTION__));
552 while (srrect)
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;
559 if (!(drawrect) || AndRectRect(drawrect, &alpharect, &alpharect))
561 DREDRAWSCR(bug("[Compositor:%s] Alpha-Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(alpharect)));
563 if ((n->prealphacomphook) && (backbm != NULL))
565 struct HIDD_BackFillHookMsg preprocessmsg;
566 preprocessmsg.bounds = &alpharect;
567 preprocessmsg.offsetx = 0;
568 preprocessmsg.offsety = 0;
569 CallHookPkt(n->prealphacomphook, backbm, &preprocessmsg);
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);
579 srrect = srrect->Next;
586 static VOID HIDDCompositorRedrawVisibleRegions(struct HIDDCompositorData *compdata, struct Rectangle *drawrect)
588 OOP_Object *renderTarget = compdata->displaybitmap;
589 struct Region *dispvisregion = NULL;
590 struct Rectangle tmprect;
591 struct BitMap *clearbm;
592 struct StackBitMapNode *n;
594 DREDRAWSCR(bug("[Compositor:%s] Redrawing Display (GfxBase @ 0x%p)\n", __PRETTY_FUNCTION__, GfxBase));
596 if (!(drawrect))
598 /* Recalculate visible regions */
599 HIDDCompositorRecalculateVisibleRegions(compdata);
602 if ((compdata->flags & COMPSTATEF_HASALPHA) && (compdata->intermedbitmap))
603 renderTarget = compdata->intermedbitmap;
605 if ((dispvisregion = NewRegion()) != NULL)
607 if (drawrect)
608 OrRectRegion(dispvisregion, drawrect);
609 else
610 OrRectRegion(dispvisregion, &compdata->displayrect);
612 DRECALC(bug("[Compositor:%s] Display rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(compdata->displayrect)));
614 ForeachNode(&compdata->bitmapstack, n)
616 if ((n->sbmflags & STACKNODEF_VISIBLE) &&
617 (!(n->sbmflags & COMPF_ALPHA)) &&
618 (n->screenregion))
620 struct RegionRectangle * srrect;
621 DREDRAWSCR(bug("[Compositor:%s] Screen Region @ 0x%p HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__,
622 n->screenregion, n->bm));
624 // Render the visable regions ..
625 if ((srrect = n->screenregion->RegionRectangle) != NULL)
627 DREDRAWSCR(bug("[Compositor:%s] Redrawing Visible Screen Regions..\n", __PRETTY_FUNCTION__));
628 while (srrect)
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;
635 if (!(drawrect) || AndRectRect(drawrect, &tmprect, &tmprect))
637 DREDRAWSCR(bug("[Compositor:%s] Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
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);
646 srrect = srrect->Next;
648 ClearRegionRegion(n->screenregion, dispvisregion);
652 OOP_GetAttr(renderTarget, aHidd_BitMap_BMStruct, (IPTR *)&clearbm);
654 struct RegionRectangle * dispclrrect = dispvisregion->RegionRectangle;
655 while (dispclrrect)
657 struct HIDD_BackFillHookMsg clearmsg;
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;
664 if (!(drawrect) || AndRectRect(drawrect, &tmprect, &tmprect))
666 DREDRAWSCR(bug("[Compositor:%s] Render Display Void Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
668 if (clearbm)
670 clearmsg.bounds = &tmprect;
671 clearmsg.offsetx = 0;
672 clearmsg.offsety = 0;
673 CallHookPkt(compdata->backfillhook, clearbm, &clearmsg);
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);
682 dispclrrect = dispclrrect->Next;
684 if (compdata->flags & COMPSTATEF_HASALPHA)
686 HIDDCompositorRedrawAlphaRegions(compdata, drawrect);
688 DisposeRegion(dispvisregion);
690 if (renderTarget != compdata->displaybitmap)
692 DREDRAWSCR(bug("[Compositor:%s] Copying Alpha Intermediary BitMap\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
693 if (!(drawrect))
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);
707 else
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);
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
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.
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 |
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 |
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 |
778 Resulting rules (order matters):
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
785 Additional rule:
786 (e) if (oldsb!=sb) modeswitch(sb)
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).
792 static BOOL HIDDCompositorToggleCompositing(struct HIDDCompositorData *compdata, BOOL newtop)
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.
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];
805 BOOL ok = TRUE, composit = FALSE;
807 /* (a) If mode change is needed, enforce opening a new screen */
808 if (compdata->modeschanged)
810 DTOGGLE(bug("[Compositor:%s] Display Mode changed\n", __PRETTY_FUNCTION__));
811 compdata->displaybitmap = NULL;
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;
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;
824 if (composit)
826 /* (b) */
827 if (compdata->displaybitmap == NULL)
830 * displaybitmap == NULL means we were in passthrough mode before,
831 * or have just changed display mode - set up screen for composition.
833 DTOGGLE(bug("[Compositor:%s] Initialising Display-Compositor..\n", __PRETTY_FUNCTION__));
835 if (compdata->fb)
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.
843 DTOGGLE(bug("[Compositor:%s] Using Display Famebuffer HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__, compdata->fb));
845 /* Do this comparison in order not to show the framebuffer twice */
846 if (oldcompositedbitmap != compdata->fb)
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.
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);
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;
863 else
866 * There's no framebuffer.
867 * Create a new bitmap that will be used for compositing.
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)
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));
879 /* Mode changed, this bitmap will be shown later */
880 newsdispbitmap = compdata->displaybitmap;
882 /* NewBitMap can fail, handle this */
883 if (!newsdispbitmap)
884 ok = FALSE;
888 else /* if (compdata->displaybitmap == NULL) */
891 * We are already in compositing mode and will stay in it.
892 * Do not destroy our working bitmap.
894 oldcompositedbitmap = NULL;
897 if ((compdata->flags & COMPSTATEF_HASALPHA) && !(compdata->intermedbitmap))
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)
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));
910 * (c) Here composition is turned on (displaybitmap != NULL).
911 * Redraw bitmap stack - compensate possible changes
913 if (ok)
914 HIDDCompositorRedrawVisibleRegions(compdata, NULL);
916 else if (oldcompositedbitmap || newtop)
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.
925 newsdispbitmap = compdata->topbitmap;
926 compdata->displaybitmap = NULL;
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));
933 * (e) If the screenbitmap changed, show the new screenbitmap.
934 * We do it after refreshing, for better visual appearance.
936 if (newsdispbitmap)
938 IPTR w, h;
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));
943 /* After Show we need Update for mirroring drivers */
944 if (compdata->screenbitmap)
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);
953 * (a) - disposing of oldcompositingbitmap needs to happen after mode switch
954 * since it could have been the current screenbitmap
956 if (oldcompositedbitmap && (oldcompositedbitmap != compdata->fb))
958 struct BitMap *freebm;
960 DTOGGLE(bug("[Compositor:%s] Disposing old working bitmap 0x%p\n", __PRETTY_FUNCTION__, oldcompositedbitmap));
962 OOP_GetAttr(oldcompositedbitmap, aHidd_BitMap_BMStruct, (IPTR *)&freebm);
963 if (freebm != NULL)
965 FreeBitMap(freebm);
967 else
968 HIDD_Gfx_DisposeBitMap(compdata->gfx, oldcompositedbitmap);
972 /* Handled */
973 compdata->modeschanged = FALSE;
975 return ok;
978 static VOID HIDDCompositorPurgeBitMapStack(struct HIDDCompositorData * compdata)
980 struct StackBitMapNode * curr, * next;
982 ForeachNodeSafe(&compdata->bitmapstack, curr, next)
984 if (curr->screenregion)
985 DisposeRegion(curr->screenregion);
987 FreeMem(curr, sizeof(struct StackBitMapNode));
990 NEWLIST(&compdata->bitmapstack);
993 static void HIDDCompositorShowSingle(struct HIDDCompositorData *compdata, OOP_Object *bm)
995 /* Show the single top bitmap */
996 compdata->topbitmap = bm;
997 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, bm, fHidd_Gfx_Show_CopyBack);
999 /* Dispose working bitmap (if any) */
1000 if (compdata->displaybitmap)
1002 /* Be careful with the framebuffer */
1003 if (compdata->displaybitmap != compdata->fb)
1004 HIDD_Gfx_DisposeBitMap(compdata->gfx, compdata->displaybitmap);
1006 /* This will deactivate us */
1007 compdata->displaybitmap = NULL;
1011 /* Emergency error recovery function */
1012 static void HIDDCompositorReset(struct HIDDCompositorData *compdata)
1014 /* Purge bitmap stack */
1015 HIDDCompositorPurgeBitMapStack(compdata);
1018 * Reset our internal state so that next BitMapStackChanged
1019 * causes complete reinitialization.
1021 compdata->displaymode = vHidd_ModeID_Invalid;
1022 compdata->screenbitmap = NULL;
1024 compdata->flags &= ~COMPSTATEF_HASALPHA;
1027 VOID CompositorParseConfig(struct HIDDCompositorData *compdata)
1029 struct RDArgs *rdargs;
1030 IPTR CompArgs[NOOFARGS] = { 0 };
1031 TEXT CompConfig[1024];
1033 /* use default amiga-like capabailities */
1034 compdata->capabilities = COMPF_ABOVE;
1036 rdargs = AllocDosObjectTags(DOS_RDARGS, TAG_END);
1037 if (rdargs != NULL)
1039 if (GetVar(COMPOSITOR_PREFS, CompConfig, 1024, GVF_GLOBAL_ONLY) != -1)
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;
1049 if (ReadArgs(COMPOSITOR_PEFSTEMPLATE, CompArgs, rdargs) != NULL)
1051 if (CompArgs[ARG_ABOVE])
1052 compdata->capabilities |= COMPF_ABOVE;
1053 else
1054 compdata->capabilities &= ~COMPF_ABOVE;
1056 if (CompArgs[ARG_BELOW])
1057 compdata->capabilities |= COMPF_BELOW;
1058 else
1059 compdata->capabilities &= ~COMPF_BELOW;
1061 if (CompArgs[ARG_LEFT])
1062 compdata->capabilities |= COMPF_LEFT;
1063 else
1064 compdata->capabilities &= ~COMPF_LEFT;
1066 if (CompArgs[ARG_RIGHT])
1067 compdata->capabilities |= COMPF_RIGHT;
1068 else
1069 compdata->capabilities &= ~COMPF_RIGHT;
1071 if (CompArgs[ARG_ALPHA])
1072 compdata->capabilities |= COMPF_ALPHA;
1073 else
1074 compdata->capabilities &= ~COMPF_ALPHA;
1076 FreeArgs(rdargs);
1079 FreeDosObject(DOS_RDARGS, rdargs);
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))
1088 AROS_USERFUNC_INIT
1090 struct HIDDCompositorData *compdata = h->h_Data;
1092 D(bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata));
1094 HIDDCompositorFillRect(compdata, HIDD_BM_OBJ(bm), msg->bounds->MinX, msg->bounds->MinY, msg->bounds->MaxX, msg->bounds->MaxY);
1096 AROS_USERFUNC_EXIT
1099 /* PUBLIC METHODS */
1100 OOP_Object *METHOD(Compositor, Root, New)
1102 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
1104 if (o)
1106 OOP_MethodID disposemid;
1107 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1109 D(bug("[%s] Compositor @ 0x%p, data @ 0x%p\n", __PRETTY_FUNCTION__, o, compdata));
1111 CompositorParseConfig(compdata);
1113 compdata->capabilities = (ULONG)GetTagData(aHidd_Compositor_State, compdata->capabilities, msg->attrList);
1115 D(bug("[%s] Compositor Capabilities: %08lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
1117 compdata->displaymode = vHidd_ModeID_Invalid;
1119 NEWLIST(&compdata->bitmapstack);
1121 compdata->defaultbackfill.h_Entry = (HOOKFUNC)AROS_ASMSYMNAME(CompositorDefaultBackFillFunc);
1122 compdata->defaultbackfill.h_Data = compdata;
1123 compdata->backfillhook = &compdata->defaultbackfill;
1125 InitSemaphore(&compdata->semaphore);
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);
1131 D(bug("[%s] DisplayID %08lx for Gfx Driver @ 0x%p\n", __PRETTY_FUNCTION__, compdata->displayid, compdata->gfx));
1133 GfxBase = (APTR)OpenLibrary("graphics.library", 41);
1134 IntuitionBase = (APTR)OpenLibrary("intuition.library", 50);
1136 /* GfxHidd is mandatory */
1137 if ((compdata->GraphicsBase) && (compdata->gfx != NULL))
1139 /* Create GC object that will be used for drawing operations */
1140 compdata->gc = HIDD_Gfx_NewGC(compdata->gfx, NULL);
1142 D(bug("[%s] Compositor GC @ %p\n", __PRETTY_FUNCTION__, compdata->gc));
1144 if ((compdata->gfx) && (compdata->gc))
1145 return o;
1148 /* Creation failed */
1149 disposemid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
1150 OOP_CoerceMethod(cl, o, &disposemid);
1153 return NULL;
1156 void METHOD(Compositor, Root, Dispose)
1160 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1161 bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata);
1164 OOP_DoSuperMethod(cl, o, &msg->mID);
1167 VOID METHOD(Compositor, Root, Get)
1169 ULONG idx;
1171 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1173 if (IS_COMPOSITOR_ATTR(msg->attrID, idx))
1175 switch (idx)
1177 case aoHidd_Compositor_Capabilities:
1179 *msg->storage = (IPTR)CAPABILITY_FLAGS;
1180 D(bug("[%s] Compositor Capabilities: %lx\n", __PRETTY_FUNCTION__, *msg->storage));
1181 return;
1183 case aoHidd_Compositor_State:
1185 *msg->storage = (IPTR)(compdata->capabilities & CAPABILITY_FLAGS);
1186 D(bug("[%s] Compositor State: %lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
1187 return;
1189 case aoHidd_Compositor_BackFillHook:
1191 D(bug("[%s] BackFillHook: 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook));
1192 *msg->storage = (IPTR)compdata->backfillhook;
1193 return;
1197 OOP_DoSuperMethod(cl, o, &msg->mID);
1200 VOID METHOD(Compositor, Root, Set)
1202 ULONG idx;
1204 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1205 struct TagItem *tag, *tstate = msg->attrList;
1207 while ((tag = NextTagItem(&tstate)))
1209 if (IS_COMPOSITOR_ATTR(tag->ti_Tag, idx))
1211 switch (idx)
1213 case aoHidd_Compositor_State:
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;
1220 case aoHidd_Compositor_BackFillHook:
1222 if (tag->ti_Data)
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;
1227 else
1229 D(bug("[%s] Default BackFillHook\n", __PRETTY_FUNCTION__));
1230 compdata->backfillhook = &compdata->defaultbackfill;
1232 break;
1238 OOP_DoSuperMethod(cl, o, &msg->mID);
1241 OOP_Object *METHOD(Compositor, Hidd_Compositor, BitMapStackChanged)
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;
1252 DSTACK(bug("[Compositor] %s: Top bitmap: 0x%lx\n", __PRETTY_FUNCTION__, msg->data->Bitmap));
1254 LOCK_COMPOSITOR_WRITE
1256 /* Free all items which are already on the list */
1257 HIDDCompositorPurgeBitMapStack(compdata);
1259 if (!msg->data)
1261 UNLOCK_COMPOSITOR
1263 DSTACK(bug("[Compositor] %s: No ViewPort specified\n", __PRETTY_FUNCTION__));
1265 /* Blank screen */
1266 HIDDCompositorShowSingle(compdata, NULL);
1268 /* We know we are inactive after this */
1269 *msg->active = FALSE;
1270 /* This can return NULL, it's okay */
1271 return compdata->screenbitmap;
1274 /* Copy bitmaps pointers to our stack */
1275 for (vpdata = msg->data; vpdata; vpdata = vpdata->Next)
1277 n = AllocMem(sizeof(struct StackBitMapNode), MEMF_ANY | MEMF_CLEAR);
1278 if (!n)
1281 * Error happened.
1282 * We need to reset own state and return NULL. graphics.library
1283 * falls back to no composition in this case.
1285 DSTACK(bug("[Compositor] %s: Error allocating StackBitMapNode!!!\n", __PRETTY_FUNCTION__));
1287 ok = FALSE;
1288 break;
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));
1293 n->bm = vpdata->Bitmap;
1294 n->sbmflags = STACKNODEF_DISPLAYABLE;
1295 n->leftedge = vpdata->vpe->ViewPort->DxOffset;
1296 n->topedge = vpdata->vpe->ViewPort->DyOffset;
1298 n->screenregion = NewRegion();
1300 if ((bmScreen = HIDDCompositorFindBitMapScreen(compdata, n->bm)) != NULL)
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)
1308 GetAttr(SA_AlphaPreCompositHook, (Object *)bmScreen, (IPTR *)&n->prealphacomphook);
1309 DSTACK(bug("[Compositor] %s: Pre-AlphaComposit Hook @ 0x%p\n", __PRETTY_FUNCTION__, n->prealphacomphook));
1313 if (n->sbmflags & COMPF_ALPHA)
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));
1319 switch (bmstdfmt)
1321 case vHidd_StdPixFmt_ARGB32:
1322 case vHidd_StdPixFmt_BGRA32:
1323 case vHidd_StdPixFmt_RGBA32:
1324 case vHidd_StdPixFmt_ABGR32:
1326 DSTACK(bug("[Compositor] %s: Screen BitMap has Alpha\n", __PRETTY_FUNCTION__));
1328 compdata->flags |= COMPSTATEF_HASALPHA;
1329 break;
1331 default:
1333 n->sbmflags &= ~COMPF_ALPHA;
1334 break;
1339 if (!(n->sbmflags & COMPF_ALPHA))
1341 if ((((BOOL)OOP_GET(n->bm, aHidd_BitMap_Displayable)) != TRUE))
1342 n->sbmflags &= ~STACKNODEF_DISPLAYABLE;
1344 AddTail((struct List *)&compdata->bitmapstack, (struct Node *)n);
1347 /* Switch mode if needed */
1348 UpdateDisplayMode(compdata);
1350 if (msg->data->Bitmap != compdata->topbitmap)
1352 /* Set the new pointer to top bitmap */
1353 compdata->topbitmap = msg->data->Bitmap;
1354 newtop = TRUE;
1357 if (ok)
1360 * Validate bitmap offsets - they might not match the compositing rules taking
1361 * new displayedwidth/displayedheight values
1363 ForeachNode(&compdata->bitmapstack, n)
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));
1372 /* Toogle compositing based on screen positions */
1373 ok = HIDDCompositorToggleCompositing(compdata, newtop);
1376 /* Handle error */
1377 if (!ok)
1379 HIDDCompositorReset(compdata);
1380 HIDDCompositorShowSingle(compdata, msg->data->Bitmap);
1383 UNLOCK_COMPOSITOR
1385 DSTACK(bug("[%s] Done, composited bitmap 0x%p\n", __PRETTY_FUNCTION__, compdata->displaybitmap));
1387 /* Tell if the composition is active */
1388 *msg->active = compdata->displaybitmap ? TRUE : FALSE;
1389 /* Return actually displayed bitmap */
1390 return compdata->screenbitmap;
1393 VOID METHOD(Compositor, Hidd_Compositor, BitMapRectChanged)
1395 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1396 OOP_Object *renderTarget;
1398 if (compdata->displaybitmap)
1400 /* Composition is active, handle redraw if the bitmap is on screen */
1401 struct StackBitMapNode *n;
1403 DUPDATE(bug("[%s] Bitmap 0x%p\n", __PRETTY_FUNCTION__, msg->bm));
1405 LOCK_COMPOSITOR_READ
1407 if (compdata->intermedbitmap)
1408 renderTarget = compdata->intermedbitmap;
1409 else
1410 renderTarget = compdata->displaybitmap;
1412 n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1413 if (n && (n->sbmflags & STACKNODEF_VISIBLE))
1415 struct Rectangle srcrect, dstandvisrect;
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));
1423 DUPDATE(bug("[%s] Screen-relative rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(srcrect)));
1425 struct RegionRectangle * srrect = n->screenregion->RegionRectangle;
1426 while (srrect)
1428 BOOL updateAlphaBmps = FALSE;
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;
1435 if (AndRectRect(&srcrect, &dstandvisrect, &dstandvisrect))
1437 /* Intersection is valid. Blit. */
1438 DUPDATE(bug("[%s] Clipped rect (%d, %d) - (%d, %d)\n", __PRETTY_FUNCTION__, _RECT(dstandvisrect)));
1440 if (!(n->sbmflags & COMPF_ALPHA))
1442 if ((compdata->alpharegion) && (isRectInRegion(compdata->alpharegion, &dstandvisrect)))
1444 DUPDATE(bug("[%s] ** Bitmap in Alpha Region!\n", __PRETTY_FUNCTION__));
1445 updateAlphaBmps = TRUE;
1447 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &dstandvisrect);
1449 else
1451 updateAlphaBmps = FALSE;
1452 HIDDCompositorRedrawVisibleRegions(compdata, &dstandvisrect);
1455 if (updateAlphaBmps)
1456 HIDDCompositorRedrawAlphaRegions(compdata, &dstandvisrect);
1458 if (renderTarget != compdata->displaybitmap)
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);
1469 HIDD_BM_UpdateRect(compdata->displaybitmap,
1470 dstandvisrect.MinX, dstandvisrect.MinY,
1471 dstandvisrect.MaxX - dstandvisrect.MinX + 1,
1472 dstandvisrect.MaxY - dstandvisrect.MinY + 1);
1474 srrect = srrect->Next;
1478 UNLOCK_COMPOSITOR
1480 DUPDATE(bug("[%s] Done\n", __PRETTY_FUNCTION__));
1482 else
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);
1489 IPTR METHOD(Compositor, Hidd_Compositor, BitMapPositionChange)
1491 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1492 struct StackBitMapNode *n;
1493 IPTR disp_width, disp_height;
1495 LOCK_COMPOSITOR_READ
1497 n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1498 if (n)
1500 /* The bitmap is on display. Validate against screen size */
1501 disp_width = compdata->displayrect.MaxX + 1;
1502 disp_height = compdata->displayrect.MaxY + 1;
1504 else
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;
1510 OOP_GetAttr(msg->bm, aHidd_BitMap_ModeID, &modeid);
1512 if ((modeid == vHidd_ModeID_Invalid) && (OOP_GET(msg->bm, aHidd_BitMap_Compositable)))
1514 OOP_GetAttr(msg->bm, aHidd_BitMap_Friend, (IPTR *)&bmfriend);
1515 if (bmfriend)
1516 OOP_GetAttr(bmfriend, aHidd_BitMap_ModeID, &modeid);
1519 if (modeid == vHidd_ModeID_Invalid)
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...
1526 UNLOCK_COMPOSITOR
1527 return FALSE;
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);
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));
1538 HIDDCompositorValidateBitMapPositionChange(msg->bm, msg->newxoffset, msg->newyoffset,
1539 disp_width, disp_height);
1541 DMOVE(bug("[%s] Validated position (%ld, %ld)\n", __PRETTY_FUNCTION__, *msg->newxoffset, *msg->newyoffset));
1543 if (n && ((*msg->newxoffset != n->leftedge) || (*msg->newyoffset != n->topedge)))
1545 DMOVE(bug("[%s] Old position (%ld, %ld)\n", __PRETTY_FUNCTION__, n->leftedge, n->topedge));
1547 /* Reflect the change if it happened */
1548 n->leftedge = *msg->newxoffset;
1549 n->topedge = *msg->newyoffset;
1551 if (compdata->topbitmap == msg->bm)
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.
1560 HIDDCompositorToggleCompositing(compdata, FALSE);
1562 else
1563 HIDDCompositorRedrawVisibleRegions(compdata, NULL);
1566 UNLOCK_COMPOSITOR
1568 /* Return active state */
1569 return compdata->displaybitmap ? TRUE : FALSE;
1572 IPTR METHOD(Compositor, Hidd_Compositor, BitMapValidate)
1574 if (IS_HIDD_BM(msg->bm))
1575 return TRUE;
1577 return FALSE;
1580 IPTR METHOD(Compositor, Hidd_Compositor, BitMapEnable)
1582 if (IS_HIDD_BM(msg->bm))
1584 if (!(OOP_GET(HIDD_BM_OBJ(msg->bm), aHidd_BitMap_Displayable)))
1586 struct TagItem composittags[] = {
1587 {aHidd_BitMap_Compositable, TRUE},
1588 {TAG_DONE , 0 }
1591 D(bug("[GfxCompositor]: Marking BitMap 0x%lx as Compositable\n", msg->bm));
1592 OOP_SetAttrs(HIDD_BM_OBJ(msg->bm), composittags);
1594 return TRUE;
1597 return FALSE;
1600 #define NUM_Compositor_Root_METHODS 4
1602 static const struct OOP_MethodDescr Compositor_Root_descr[] =
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}
1611 #define NUM_Compositor_Hidd_Compositor_METHODS 5
1613 static const struct OOP_MethodDescr Compositor_Hidd_Compositor_descr[] =
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}
1623 const struct OOP_InterfaceDescr Compositor_ifdescr[] =
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}