enable pass through mode if the frontmost screen is fullscreen (and doesnt have alpha)
[AROS.git] / workbench / devs / monitors / Compositor / compositorclass.c
blobfbdb55645cb5c529ff788246acdebe28aef2086e
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 tmprect.MinX = n->leftedge;
189 tmprect.MaxX = n->leftedge + OOP_GET(n->bm, aHidd_BitMap_Width) - 1;
190 tmprect.MinY = n->topedge;
191 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
193 DRECALC(bug("[Compositor:%s] Screen Rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
195 OrRectRegion(n->screenregion, &tmprect); // Start with the Screen's dimensions ..
196 AndRegionRegion(dispvisregion, n->screenregion); // And adjust for the "Display"
198 if (n->screenregion->RegionRectangle)
200 AndRectRect(&n->screenregion->bounds, &compdata->displayrect, &n->screenvisiblerect);
202 if (!(n->sbmflags & COMPF_ALPHA))
203 ClearRectRegion(dispvisregion, &n->screenvisiblerect);
204 else
206 compdata->flags |= COMPSTATEF_HASALPHA;
207 if (!(compdata->alpharegion))
208 compdata->alpharegion = NewRegion();
210 OrRectRegion(compdata->alpharegion, &n->screenvisiblerect);
213 if (!(compdata->capabilities & COMPF_ABOVE) && !(n->sbmflags & COMPF_ABOVE))
215 tmprect.MinX = compdata->displayrect.MinX;
216 tmprect.MaxX = compdata->displayrect.MaxX;
217 tmprect.MinY = compdata->displayrect.MinY;
218 tmprect.MaxY = n->topedge - 1;
219 ClearRectRegion(dispvisregion, &tmprect);
221 if (!(compdata->capabilities & COMPF_BELOW) && !(n->sbmflags & COMPF_BELOW))
223 tmprect.MinX = compdata->displayrect.MinX;
224 tmprect.MaxX = compdata->displayrect.MaxX;
225 tmprect.MinY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height);
226 tmprect.MaxY = compdata->displayrect.MaxY;
227 ClearRectRegion(dispvisregion, &tmprect);
229 if (!(compdata->capabilities & COMPF_LEFT) && !(n->sbmflags & COMPF_LEFT))
231 tmprect.MinX = compdata->displayrect.MinX;
232 tmprect.MaxX = n->leftedge - 1;
233 tmprect.MinY = n->topedge;
234 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
235 ClearRectRegion(dispvisregion, &tmprect);
237 if (!(compdata->capabilities & COMPF_RIGHT) && !(n->sbmflags & COMPF_RIGHT))
239 tmprect.MinX = n->leftedge + OOP_GET(n->bm, aHidd_BitMap_Width);
240 tmprect.MaxX = compdata->displayrect.MaxX;
241 tmprect.MinY = n->topedge;
242 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
243 ClearRectRegion(dispvisregion, &tmprect);
245 n->sbmflags |= STACKNODEF_VISIBLE;
248 DRECALC(bug("[Compositor:%s] Bitmap 0x%x, topedge %d, visible %d, [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
249 n->bm, n->topedge, (n->sbmflags & STACKNODEF_VISIBLE), _RECT(n->screenvisiblerect)));
251 else
253 DRECALC(bug("[Compositor:%s] Failed to create Screen Region\n", __PRETTY_FUNCTION__));
256 DisposeRegion(dispvisregion);
257 if (compdata->flags != oldflags)
259 ULONG newflags = (~oldflags) & compdata->flags;
260 DRECALC(bug("[Compositor:%s] Newly set flags %08x\n", __PRETTY_FUNCTION__, newflags));
261 if ((!(newflags & COMPSTATEF_HASALPHA)) && (oldflags & COMPSTATEF_HASALPHA))
263 DRECALC(bug("[Compositor:%s] Alpha removed\n", __PRETTY_FUNCTION__));
264 if (compdata->alpharegion)
265 DisposeRegion(compdata->alpharegion);
267 if (compdata->intermedbitmap)
268 HIDD_Gfx_DisposeBitMap(compdata->gfx, compdata->intermedbitmap);
270 compdata->alpharegion = NULL;
271 compdata->intermedbitmap = NULL;
275 else
277 DRECALC(bug("[Compositor:%s] Failed to create Display Region\n", __PRETTY_FUNCTION__));
281 static HIDDT_ModeID FindBestHiddMode(struct HIDDCompositorData *compdata, ULONG width, ULONG height, ULONG depth, ULONG *res_depth)
283 HIDDT_ModeID mode = vHidd_ModeID_Invalid;
284 OOP_Object *sync, *pf;
285 IPTR w, h, d;
286 ULONG dw, dh, delta;
287 ULONG found_delta = -1;
288 ULONG found_width = 0;
289 ULONG found_height = 0;
290 ULONG found_depth = 0;
291 HIDDT_ModeID found_mode = vHidd_ModeID_Invalid;
293 DMODE(bug("[%s] Finding best match for mode %ux%ux%u\n", __PRETTY_FUNCTION__, width, height, depth));
295 while ((mode = HIDD_Gfx_NextModeID(compdata->gfx, mode, &sync, &pf)) != vHidd_ModeID_Invalid)
297 BOOL match;
299 DMODE(bug("[%s] Checking mode 0x%08X... ", __PRETTY_FUNCTION__, mode));
300 if (OOP_GET(pf, aHidd_PixFmt_ColorModel) != vHidd_ColorModel_TrueColor)
302 DMODE(bug("Skipped (not truecolor)\n"));
303 continue;
306 OOP_GetAttr(sync, aHidd_Sync_HDisp, &w);
307 OOP_GetAttr(sync, aHidd_Sync_VDisp, &h);
308 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &d);
310 dw = w > width ? w - width : w < width ? width - w : 1;
311 dh = h > height ? h - height : h < height ? height - h : 1;
312 delta = dw * dh;
314 match = FALSE;
315 if (delta < found_delta)
317 /* If mode resolution is closer to the needed one, we've got a better match */
318 found_delta = delta;
319 found_width = w;
320 found_height = h;
322 match = TRUE;
324 else if (delta == found_delta)
326 /* If resolution is the same as that of current candidate mode, we can look at depth. */
327 if (found_depth > depth)
330 * Candidate mode if deeper than requested. We can supersede it with another mode
331 * of smaller depth, but which still matches our request.
333 if ((d < found_depth) && (d >= depth))
334 match = TRUE;
336 else if (found_depth < depth)
339 * We want better depth than current candidate.
340 * In this case anything deeper will do.
342 if (d > found_depth)
343 match = TRUE;
347 if (match)
350 * Mode with the same delta, but larger depth, may supersede
351 * previous mode, if we prefer deeper ones.
353 DMODE(bug("Selected (%ldx%ldx%ld, delta = %u)", w, h, d, delta));
354 found_depth = d;
355 found_mode = mode;
357 DMODE(bug("\n"));
360 /* Store mode information */
361 compdata->displayrect.MinX = 0;
362 compdata->displayrect.MinY = 0;
363 compdata->displayrect.MaxX = found_width - 1;
364 compdata->displayrect.MaxY = found_height - 1;
365 *res_depth = found_depth;
367 return found_mode;
370 static void UpdateDisplayMode(struct HIDDCompositorData *compdata)
372 struct StackBitMapNode *n;
373 IPTR modeid, width = 0, height = 0, depth;
374 OOP_Object *sync, *pf;
375 UBYTE comp_depth = 16;
376 ULONG found_depth;
378 DSTACK(bug("[Compositor] %s()\n", __PRETTY_FUNCTION__));
381 * Examine all bitmaps in the stack to figure out the needed depth.
382 * We need a maximum depth of all depths in order to keep correct colors.
383 * But not less than 16 bits, because we can't compose on a LUT screen.
385 * If a LUT bitmap is present in the stack (depth < 9), we request truecolor
386 * screen for better color presentation.
388 * We examine bitmaps in reverse order, in this case 'sync' will hold
389 * information about the top bitmap when we exit the loop.
390 * Size of our composited mode needs to be as close as possible to that one.
392 for (n = (struct StackBitMapNode *)compdata->bitmapstack.mlh_TailPred;
393 n->n.mln_Pred; n = (struct StackBitMapNode *)n->n.mln_Pred)
395 if ((!(n->sbmflags & COMPF_ALPHA)) && (n->sbmflags & STACKNODEF_DISPLAYABLE))
397 OOP_GetAttr(n->bm, aHidd_BitMap_ModeID, &modeid);
398 HIDD_Gfx_GetMode(compdata->gfx, modeid, &sync, &pf);
400 if (OOP_GET(pf, aHidd_PixFmt_ColorModel) == vHidd_ColorModel_TrueColor)
402 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
403 if (depth > comp_depth)
404 comp_depth = depth;
406 else
409 * If we have a LUT bitmap on stack, we request 24-bit screen
410 * for better color transfer.
412 comp_depth = 24;
415 else
417 IPTR curwidth, curheight;
418 OOP_GetAttr(n->bm, aHidd_BitMap_Width, &curwidth);
419 OOP_GetAttr(n->bm, aHidd_BitMap_Height, &curheight);
420 if (curwidth > width)
421 width = curwidth;
422 if (curheight > height)
423 height = curheight;
427 if (sync)
429 /* Get the needed size */
430 OOP_GetAttr(sync, aHidd_Sync_HDisp, &width);
431 OOP_GetAttr(sync, aHidd_Sync_VDisp, &height);
434 DSTACK(bug("[%s] Prefered mode %ldx%ldx%d\n", __PRETTY_FUNCTION__, width, height, comp_depth));
436 modeid = FindBestHiddMode(compdata, width, height, comp_depth, &found_depth);
437 DSTACK(bug("[%s] Composition Display ModeID 0x%08X [current 0x%08X]\n", __PRETTY_FUNCTION__, modeid, compdata->screenmodeid));
439 if (modeid != compdata->screenmodeid)
441 /* The mode is different. Need to prepare information needed for compositing */
442 struct TagItem gctags[] =
444 { aHidd_GC_Foreground, 0x99999999 },
445 { TAG_DONE , 0 }
448 /* Signal mode change */
449 compdata->screenmodeid = modeid;
450 compdata->modeschanged = TRUE;
452 /* Get gray foregound */
453 if (found_depth < 24)
454 gctags[0].ti_Data = 0x9492;
456 OOP_SetAttrs(compdata->gc, gctags);
460 static inline void HIDDCompositorRedrawBitmap(struct HIDDCompositorData *compdata, OOP_Object *renderTarget, struct StackBitMapNode *n, struct Rectangle *rect)
462 /* The given rectangle is already in screen coordinate system here */
463 ULONG blitwidth = rect->MaxX - rect->MinX + 1;
464 ULONG blitheight = rect->MaxY - rect->MinY + 1;
466 DREDRAWBM(bug("[Compositor:%s] Redraw BitMap 0x%p, Rect[%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, n->bm,
467 rect->MinX, rect->MinY, rect->MaxX, rect->MaxY));
469 if (!(n->sbmflags & COMPF_ALPHA))
471 DREDRAWBM(bug("[Compositor:%s] Blitting %dx%d [from %d, %d]\n", __PRETTY_FUNCTION__, blitwidth, blitheight,
472 rect->MinX - n->leftedge, rect->MinY - n->topedge));
474 HIDD_Gfx_CopyBox(compdata->gfx, n->bm,
475 /* Transform to source bitmap coord system */
476 rect->MinX - n->leftedge, rect->MinY - n->topedge,
477 renderTarget,
478 rect->MinX, rect->MinY, blitwidth, blitheight,
479 compdata->gc);
481 else
483 UBYTE *baseaddress;
484 ULONG width, height, banksize, memsize;
485 IPTR modulo;
487 DREDRAWBM(bug("[Compositor:%s] AlphaBlending %dx%d @ %d,%d to %d,%d\n", __PRETTY_FUNCTION__,
488 blitwidth, blitheight,
489 rect->MinX - n->leftedge, rect->MinY - n->topedge, rect->MinX, rect->MinY));
491 if (HIDD_BM_ObtainDirectAccess(n->bm, &baseaddress, &width, &height, &banksize, &memsize))
493 DREDRAWBM(bug("[Compositor:%s] Alpha baseaddress @ 0x%p\n", __PRETTY_FUNCTION__, baseaddress));
494 OOP_GetAttr(n->bm, aHidd_BitMap_BytesPerRow, &modulo);
495 HIDD_BM_PutAlphaImage(renderTarget, compdata->gfx , baseaddress + ((rect->MinY - n->topedge) * modulo) + ((rect->MinX - n->leftedge) << 2), modulo,
496 rect->MinX, rect->MinY, blitwidth, blitheight);
497 HIDD_BM_ReleaseDirectAccess(n->bm);
502 static inline void ClearRect(struct HIDDCompositorData *compdata, OOP_Object *renderTarget, ULONG MinX, ULONG MinY, ULONG MaxX, ULONG MaxY)
504 DREDRAWSCR(bug("[Compositor:%s] Clearing [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
505 MinX, MinY, MaxX, MaxY));
507 HIDD_BM_FillRect(renderTarget, compdata->gc,
508 MinX, MinY, MaxX, MaxY);
512 static VOID HIDDCompositorRedrawAlphaRegions(struct HIDDCompositorData *compdata, struct Rectangle *drawrect)
514 struct Rectangle alpharect;
515 struct StackBitMapNode *n;
516 OOP_Object *renderTarget = compdata->displaybitmap;
518 if (compdata->intermedbitmap)
519 renderTarget = compdata->intermedbitmap;
521 DREDRAWSCR(if (drawrect){ bug("[Compositor:%s] Rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT((*drawrect))); })
523 // Alpha Regions are drawn in reverse order incase they overlap..
524 for (n = (struct StackBitMapNode *)compdata->bitmapstack.mlh_TailPred;
525 n->n.mln_Pred; n = (struct StackBitMapNode *)n->n.mln_Pred)
527 if ((n->sbmflags & STACKNODEF_VISIBLE) &&
528 (n->sbmflags & COMPF_ALPHA) &&
529 (n->screenregion))
531 DREDRAWSCR(bug("[Compositor:%s] Alpha-ScreenRegion @ 0x%p ScreenBitMap @ 0x%p [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
532 n->screenregion, n->bm, _RECT(n->screenvisiblerect)));
534 DREDRAWSCR(bug("[Compositor:%s] Compositing Visible Alpha Regions..\n", __PRETTY_FUNCTION__));
536 struct RegionRectangle * srrect = n->screenregion->RegionRectangle;
537 while (srrect)
539 alpharect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
540 alpharect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
541 alpharect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
542 alpharect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
544 if (!(drawrect) || AndRectRect(drawrect, &alpharect, &alpharect))
546 DREDRAWSCR(bug("[Compositor:%s] Alpha-Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(alpharect)));
548 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &alpharect);
549 if (renderTarget == compdata->displaybitmap)
550 HIDD_BM_UpdateRect(compdata->displaybitmap,
551 alpharect.MinX, alpharect.MinY,
552 alpharect.MaxX - alpharect.MinX + 1,
553 alpharect.MaxY - alpharect.MinY + 1);
555 srrect = srrect->Next;
561 static VOID HIDDCompositorRedrawVisibleRegions(struct HIDDCompositorData *compdata, struct Rectangle *drawrect)
563 struct Region *dispvisregion = NULL;
564 struct Rectangle tmprect;
565 OOP_Object *renderTarget = compdata->displaybitmap;
566 struct StackBitMapNode *n;
568 DREDRAWSCR(bug("[Compositor:%s] Redrawing screen (GfxBase @ 0x%p)\n", __PRETTY_FUNCTION__, GfxBase));
570 if (!(drawrect))
572 /* Recalculate visible regions */
573 HIDDCompositorRecalculateVisibleRegions(compdata);
576 if ((compdata->flags & COMPSTATEF_HASALPHA) && (compdata->intermedbitmap))
577 renderTarget = compdata->intermedbitmap;
579 if ((dispvisregion = NewRegion()) != NULL)
581 if (drawrect)
582 OrRectRegion(dispvisregion, drawrect);
583 else
584 OrRectRegion(dispvisregion, &compdata->displayrect);
586 DRECALC(bug("[Compositor:%s] Display rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(compdata->displayrect)));
588 ForeachNode(&compdata->bitmapstack, n)
590 if ((n->sbmflags & STACKNODEF_VISIBLE) &&
591 (!(n->sbmflags & COMPF_ALPHA)) &&
592 (n->screenregion))
594 DREDRAWSCR(bug("[Compositor:%s] ScreenRegion @ 0x%p ScreenBitMap @ 0x%p [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
595 n->screenregion, n->bm, _RECT(n->screenvisiblerect)));
597 DREDRAWSCR(bug("[Compositor:%s] Redrawing Visible Screen Regions..\n", __PRETTY_FUNCTION__));
598 // Render the visable regions ..
599 struct RegionRectangle * srrect = n->screenregion->RegionRectangle;
600 while (srrect)
602 tmprect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
603 tmprect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
604 tmprect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
605 tmprect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
607 if (!(drawrect) || AndRectRect(drawrect, &tmprect, &tmprect))
609 DREDRAWSCR(bug("[Compositor:%s] Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
611 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &tmprect);
612 if (renderTarget == compdata->displaybitmap)
613 HIDD_BM_UpdateRect(compdata->displaybitmap,
614 tmprect.MinX, tmprect.MinY,
615 tmprect.MaxX - tmprect.MinX + 1,
616 tmprect.MaxY - tmprect.MinY + 1);
618 srrect = srrect->Next;
620 ClearRegionRegion(n->screenregion, dispvisregion);
623 struct RegionRectangle * dispclrrect = dispvisregion->RegionRectangle;
624 while (dispclrrect)
626 struct HIDD_BackFillHookMsg clearmsg;
628 tmprect.MinX = dispclrrect->bounds.MinX + dispvisregion->bounds.MinX;
629 tmprect.MinY = dispclrrect->bounds.MinY + dispvisregion->bounds.MinY;
630 tmprect.MaxX = dispclrrect->bounds.MaxX + dispvisregion->bounds.MinX;
631 tmprect.MaxY = dispclrrect->bounds.MaxY + dispvisregion->bounds.MinY;
633 if (!(drawrect) || AndRectRect(drawrect, &tmprect, &tmprect))
635 DREDRAWSCR(bug("[Compositor:%s] Render Display Void Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
637 clearmsg.bounds = &tmprect;
638 clearmsg.offsetx = 0;
639 clearmsg.offsety = 0;
640 CallHookPkt(compdata->backfillhook, renderTarget, &clearmsg);
641 if (renderTarget == compdata->displaybitmap)
642 HIDD_BM_UpdateRect(compdata->displaybitmap,
643 tmprect.MinX, tmprect.MinY,
644 tmprect.MaxX - tmprect.MinX + 1,
645 tmprect.MaxY - tmprect.MinY + 1);
647 dispclrrect = dispclrrect->Next;
649 if (compdata->flags & COMPSTATEF_HASALPHA)
651 HIDDCompositorRedrawAlphaRegions(compdata, drawrect);
653 DisposeRegion(dispvisregion);
655 if (renderTarget != compdata->displaybitmap)
657 DREDRAWSCR(bug("[Compositor:%s] Copying Alpha Intermediary BitMap\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
658 if (!(drawrect))
660 HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
661 compdata->displayrect.MinX, compdata->displayrect.MinY,
662 compdata->displaybitmap,
663 compdata->displayrect.MinX, compdata->displayrect.MinY,
664 compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
665 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
666 compdata->gc);
667 HIDD_BM_UpdateRect(compdata->displaybitmap,
668 compdata->displayrect.MinX, compdata->displayrect.MinY,
669 compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
670 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1);
672 else
674 HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
675 drawrect->MinX, drawrect->MinY,
676 compdata->displaybitmap,
677 drawrect->MinX, drawrect->MinY,
678 drawrect->MaxX - drawrect->MinX + 1,
679 drawrect->MaxY - drawrect->MinY + 1,
680 compdata->gc);
681 HIDD_BM_UpdateRect(compdata->displaybitmap,
682 drawrect->MinX, drawrect->MinY,
683 drawrect->MaxX - drawrect->MinX + 1,
684 drawrect->MaxY - drawrect->MinY + 1);
691 There are several cases that needs to be handled in this code. They are documented
692 below. Please read it before making changes.
693 etb = existing topbitmap
694 ntb = new top bitmap
695 sb = screen bitmap
696 cb = composited bitmap
697 fs = covers full screen
698 nfs = not covers full screen
699 mA = mode "A"
700 mB = mode "B"
701 disp() = dispose
702 new() = new
704 The resulting mode is always that of screen bitmap as set in "effect" column.
705 The composited bitmap always matches the resulting screen mode or is NULL.
707 | exiting screen situation | change | effect |
708 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - SAME MODE |
709 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mA | sb==ntb, cb==NULL |
710 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
711 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
712 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb, cb!=NULL |
713 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
714 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - SAME MODE |
715 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
716 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
717 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
718 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
719 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
722 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - DIFFERENT MODES |
723 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mB | sb==ntb, cb==NULL |
724 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
725 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
726 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mB | new(cb), sb==cb, cb!=NULL |
727 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
728 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - DIFFERENT MODES |
729 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
730 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
731 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
732 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
733 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
736 | USE CASE: DRAGGING SCREEN DOWN |
737 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb |
738 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb |
739 | USE CASE: DRAGGING SCREEN UP |
740 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==etb |
741 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
743 Resulting rules (order matters):
745 (a) if ((cb!=NULL) && (etb->mode!=ntb->mode)) {dispose(cb), cb=NULL}
746 (b) if ((ntb->nfs) && (cb==NULL)) new(cb)
747 (c) if (ntb->nfs) sb=cb
748 (d) if (ntb->fs) sb=ntb
750 Additional rule:
751 (e) if (oldsb!=sb) modeswitch(sb)
753 02.09.2011: we don't remember sb any more because we don't handle it in any way. Instead
754 we either have or don't have displaybitmap. If we have it, composition
755 is on (sb = cb). If we don't have it, composition is off (sb = ntb).
757 static BOOL HIDDCompositorToggleCompositing(struct HIDDCompositorData *compdata, BOOL newtop)
760 * If the topbitmap covers the complete screen, show it instead of
761 * displaybitmap. Remember that screen bitmap -> composited bitmap
762 * mirroring has a negative impact on performance.
764 OOP_Object *oldcompositedbitmap = compdata->displaybitmap;
765 struct StackBitMapNode *topnode = compdata->bitmapstack.mlh_Head;
766 OOP_Object *newscreenbitmap = NULL;
767 struct TagItem bmtags[5];
769 BOOL ok = TRUE, composit = FALSE;
771 /* (a) If mode change is needed, enforce opening a new screen */
772 if (compdata->modeschanged)
774 DTOGGLE(bug("[Compositor:%s] Display Mode changed\n", __PRETTY_FUNCTION__));
775 compdata->displaybitmap = NULL;
778 bmtags[0].ti_Tag = aHidd_BitMap_Width; bmtags[0].ti_Data = compdata->displayrect.MaxX + 1;
779 bmtags[1].ti_Tag = aHidd_BitMap_Height; bmtags[1].ti_Data = compdata->displayrect.MaxY + 1;
780 bmtags[2].ti_Tag = aHidd_BitMap_Displayable; bmtags[2].ti_Data = TRUE;
781 bmtags[3].ti_Tag = aHidd_BitMap_ModeID; bmtags[3].ti_Data = compdata->screenmodeid;
782 bmtags[4].ti_Tag = TAG_DONE; bmtags[4].ti_Data = TAG_DONE;
784 if ((topnode->topedge > 0) || (bmtags[1].ti_Data > OOP_GET(topnode->bm, aHidd_BitMap_Height)))
785 composit = TRUE;
787 if ((topnode->leftedge > 0) || (bmtags[0].ti_Data > OOP_GET(topnode->bm, aHidd_BitMap_Width)))
788 composit = TRUE;
790 if (topnode->sbmflags & COMPF_ALPHA)
791 composit = TRUE;
793 if (composit)
795 /* (b) */
796 if (compdata->displaybitmap == NULL)
799 * displaybitmap == NULL means we were in passthrough mode before,
800 * or have just changed display mode - set up screen for composition.
802 DTOGGLE(bug("[Compositor:%s] Initialising Display-Compositor..\n", __PRETTY_FUNCTION__));
804 if (compdata->fb)
807 * If our display driver uses a framebuffer, we can reuse it.
808 * Copy its original contents back into the bitmap which it replaced,
809 * then change framebuffer's video mode.
810 * Framebuffer is the only bitmap which can change its ModeID on the fly.
812 DTOGGLE(bug("[Compositor:%s] Using Display Famebuffer BitMap @ 0x%p\n", __PRETTY_FUNCTION__, compdata->fb));
814 /* Do this comparison in order not to show the framebuffer twice */
815 if (oldcompositedbitmap != compdata->fb)
818 * 1. It's legal to show the framebuffer itself. This causes copying
819 * back old bitmap contents and detaching from it.
820 * 2. The result of this will always match compdata->fb.
821 * 3. Internally this is a simple blit operation, it can't fail.
823 DTOGGLE(bug("[Compositor:%s] Copying old Famebuffer BitMap\n", __PRETTY_FUNCTION__));
824 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, compdata->fb, fHidd_Gfx_Show_CopyBack);
827 /* Switch display mode on the framebuffer. */
828 OOP_SetAttrsTags(compdata->fb, aHidd_BitMap_ModeID, compdata->screenmodeid, TAG_DONE);
829 /* We are now compositing on the framebuffer */
830 compdata->displaybitmap = compdata->fb;
832 else
835 * There's no framebuffer.
836 * Create a new bitmap that will be used for compositing.
838 compdata->displaybitmap = HIDD_Gfx_NewBitMap(compdata->gfx, bmtags);
839 DTOGGLE(bug("[Compositor:%s] Created Compositor Display BitMap @ 0x%p\n", __PRETTY_FUNCTION__, compdata->displaybitmap));
841 /* Mode changed, this bitmap will be shown later */
842 newscreenbitmap = compdata->displaybitmap;
844 /* NewBitMap can fail, handle this */
845 if (!newscreenbitmap)
846 ok = FALSE;
849 else /* if (compdata->displaybitmap == NULL) */
852 * We are already in compositing mode and will stay in it.
853 * Do not destroy our working bitmap.
855 oldcompositedbitmap = NULL;
858 if ((compdata->flags & COMPSTATEF_HASALPHA) && !(compdata->intermedbitmap))
860 compdata->intermedbitmap = HIDD_Gfx_NewBitMap(compdata->gfx, bmtags);
861 DTOGGLE(bug("[Compositor:%s] Allocated Alpha Intermediary BitMap @ 0x%p\n", __PRETTY_FUNCTION__, compdata->intermedbitmap));
864 * (c) Here composition is turned on (displaybitmap != NULL).
865 * Redraw bitmap stack - compensate possible changes
867 if (ok)
868 HIDDCompositorRedrawVisibleRegions(compdata, NULL);
870 else if (oldcompositedbitmap || newtop)
873 * (d) Set passthrough mode and display the frontmost bitmap.
874 * This is also triggered by 'newtop' parameter, which tells us
875 * that frontmost bitmap has been changed, and we need to display a new one.
876 * Old displaybitmap has been remembered in the beginning. If it's not
877 * NULL, it will be destroyed in the end.
879 newscreenbitmap = compdata->topbitmap;
880 compdata->displaybitmap = NULL;
883 DTOGGLE(bug("[Compositor:%s] oldcompbmp 0x%p, topbmp 0x%p, compbmp 0x%p, newscreenbmp 0x%p\n", __PRETTY_FUNCTION__,
884 oldcompositedbitmap, compdata->topbitmap, compdata->displaybitmap, newscreenbitmap));
887 * (e) If the screenbitmap changed, show the new screenbitmap.
888 * We do it after refreshing, for better visual appearance.
890 if (newscreenbitmap)
892 IPTR w, h;
894 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, newscreenbitmap, fHidd_Gfx_Show_CopyBack);
895 DTOGGLE(bug("[Compositor:%s] Displayed bitmap 0x%p, Show returned 0x%p\n", __PRETTY_FUNCTION__, newscreenbitmap, compdata->screenbitmap));
897 /* After Show we need Update for mirroring drivers */
898 if (compdata->screenbitmap)
900 OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Width, &w);
901 OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Height, &h);
902 HIDD_BM_UpdateRect(compdata->screenbitmap, 0, 0, w, h);
907 * (a) - disposing of oldcompositingbitmap needs to happen after mode switch
908 * since it could have been the current screenbitmap
910 if (oldcompositedbitmap && (oldcompositedbitmap != compdata->fb))
912 DTOGGLE(bug("[Compositor:%s] Disposing old working bitmap 0x%p\n", __PRETTY_FUNCTION__, oldcompositedbitmap));
913 HIDD_Gfx_DisposeBitMap(compdata->gfx, oldcompositedbitmap);
916 /* Handled */
917 compdata->modeschanged = FALSE;
919 return ok;
922 static VOID HIDDCompositorPurgeBitMapStack(struct HIDDCompositorData * compdata)
924 struct StackBitMapNode * curr, * next;
926 ForeachNodeSafe(&compdata->bitmapstack, curr, next)
928 if (curr->screenregion)
929 DisposeRegion(curr->screenregion);
931 FreeMem(curr, sizeof(struct StackBitMapNode));
934 NEWLIST(&compdata->bitmapstack);
937 static void HIDDCompositorShowSingle(struct HIDDCompositorData *compdata, OOP_Object *bm)
939 /* Show the single top bitmap */
940 compdata->topbitmap = bm;
941 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, bm, fHidd_Gfx_Show_CopyBack);
943 /* Dispose working bitmap (if any) */
944 if (compdata->displaybitmap)
946 /* Be careful with the framebuffer */
947 if (compdata->displaybitmap != compdata->fb)
948 HIDD_Gfx_DisposeBitMap(compdata->gfx, compdata->displaybitmap);
950 /* This will deactivate us */
951 compdata->displaybitmap = NULL;
955 /* Emergency error recovery function */
956 static void HIDDCompositorReset(struct HIDDCompositorData *compdata)
958 /* Purge bitmap stack */
959 HIDDCompositorPurgeBitMapStack(compdata);
962 * Reset our internal state so that next BitMapStackChanged
963 * causes complete reinitialization.
965 compdata->screenmodeid = vHidd_ModeID_Invalid;
966 compdata->screenbitmap = NULL;
968 compdata->flags &= ~COMPSTATEF_HASALPHA;
971 VOID CompositorParseConfig(struct HIDDCompositorData *compdata)
973 struct RDArgs *rdargs;
974 IPTR CompArgs[NOOFARGS] = { 0 };
975 TEXT CompConfig[1024];
977 /* use default amiga-like capabailities */
978 compdata->capabilities = COMPF_ABOVE;
980 rdargs = AllocDosObjectTags(DOS_RDARGS, TAG_END);
981 if (rdargs != NULL)
983 if (GetVar(COMPOSITOR_PREFS, CompConfig, 1024, GVF_GLOBAL_ONLY) != -1)
985 rdargs->RDA_Source.CS_Buffer = CompConfig;
986 rdargs->RDA_Source.CS_Length = strlen(rdargs->RDA_Source.CS_Buffer);
987 rdargs->RDA_DAList = (IPTR)NULL;
988 rdargs->RDA_Buffer = NULL;
989 rdargs->RDA_BufSiz = 0;
990 rdargs->RDA_ExtHelp = NULL;
991 rdargs->RDA_Flags = 0;
993 if (ReadArgs(COMPOSITOR_PEFSTEMPLATE, CompArgs, rdargs) != NULL)
995 if (CompArgs[ARG_ABOVE])
996 compdata->capabilities |= COMPF_ABOVE;
997 else
998 compdata->capabilities &= ~COMPF_ABOVE;
1000 if (CompArgs[ARG_BELOW])
1001 compdata->capabilities |= COMPF_BELOW;
1002 else
1003 compdata->capabilities &= ~COMPF_BELOW;
1005 if (CompArgs[ARG_LEFT])
1006 compdata->capabilities |= COMPF_LEFT;
1007 else
1008 compdata->capabilities &= ~COMPF_LEFT;
1010 if (CompArgs[ARG_RIGHT])
1011 compdata->capabilities |= COMPF_RIGHT;
1012 else
1013 compdata->capabilities &= ~COMPF_RIGHT;
1015 if (CompArgs[ARG_ALPHA])
1016 compdata->capabilities |= COMPF_ALPHA;
1017 else
1018 compdata->capabilities &= ~COMPF_ALPHA;
1020 FreeArgs(rdargs);
1023 FreeDosObject(DOS_RDARGS, rdargs);
1027 AROS_UFH3(void, CompositorDefaultBackFillFunc,
1028 AROS_UFHA(struct Hook * , h, A0),
1029 AROS_UFHA(OOP_Object * , bm, A2),
1030 AROS_UFHA(struct HIDD_BackFillHookMsg * , msg, A1))
1032 AROS_USERFUNC_INIT
1034 struct HIDDCompositorData *compdata = h->h_Data;
1036 D(bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata));
1038 ClearRect(compdata, bm, msg->bounds->MinX, msg->bounds->MinY, msg->bounds->MaxX, msg->bounds->MaxY);
1040 AROS_USERFUNC_EXIT
1043 /* PUBLIC METHODS */
1044 OOP_Object *METHOD(Compositor, Root, New)
1046 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
1048 if (o)
1050 OOP_MethodID disposemid;
1051 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1053 D(bug("[%s] Compositor @ 0x%p, data @ 0x%p\n", __PRETTY_FUNCTION__, o, compdata));
1055 CompositorParseConfig(compdata);
1057 compdata->capabilities = (ULONG)GetTagData(aHidd_Compositor_State, compdata->capabilities, msg->attrList);
1059 D(bug("[%s] Compositor Capabilities: %08lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
1061 compdata->screenmodeid = vHidd_ModeID_Invalid;
1063 NEWLIST(&compdata->bitmapstack);
1065 compdata->defaultbackfill.h_Entry = (HOOKFUNC)AROS_ASMSYMNAME(CompositorDefaultBackFillFunc);
1066 compdata->defaultbackfill.h_Data = compdata;
1067 compdata->backfillhook = &compdata->defaultbackfill;
1069 InitSemaphore(&compdata->semaphore);
1071 compdata->gfx = (OOP_Object *)GetTagData(aHidd_Compositor_GfxHidd, 0, msg->attrList);
1072 compdata->fb = (OOP_Object *)GetTagData(aHidd_Compositor_FrameBuffer, 0, msg->attrList);
1074 GfxBase = (APTR)OpenLibrary("graphics.library", 41);
1075 IntuitionBase = (APTR)OpenLibrary("intuition.library", 50);
1077 /* GfxHidd is mandatory */
1078 if ((compdata->GraphicsBase) && (compdata->gfx != NULL))
1080 /* Create GC object that will be used for drawing operations */
1081 compdata->gc = HIDD_Gfx_NewGC(compdata->gfx, NULL);
1083 D(bug("[%s] Compositor GC @ %p\n", __PRETTY_FUNCTION__, compdata->gc));
1085 if ((compdata->gfx) && (compdata->gc))
1086 return o;
1089 /* Creation failed */
1090 disposemid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
1091 OOP_CoerceMethod(cl, o, &disposemid);
1094 return NULL;
1097 void METHOD(Compositor, Root, Dispose)
1101 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1102 bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata);
1105 OOP_DoSuperMethod(cl, o, &msg->mID);
1108 VOID METHOD(Compositor, Root, Get)
1110 ULONG idx;
1112 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1114 if (IS_COMPOSITOR_ATTR(msg->attrID, idx))
1116 switch (idx)
1118 case aoHidd_Compositor_Capabilities:
1120 *msg->storage = (IPTR)CAPABILITY_FLAGS;
1121 D(bug("[%s] Compositor Capabilities: %lx\n", __PRETTY_FUNCTION__, *msg->storage));
1122 return;
1124 case aoHidd_Compositor_State:
1126 *msg->storage = (IPTR)(compdata->capabilities & CAPABILITY_FLAGS);
1127 D(bug("[%s] Compositor State: %lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
1128 return;
1130 case aoHidd_Compositor_BackFillHook:
1132 D(bug("[%s] BackFillHook: 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook));
1133 *msg->storage = (IPTR)compdata->backfillhook;
1134 return;
1138 OOP_DoSuperMethod(cl, o, &msg->mID);
1141 VOID METHOD(Compositor, Root, Set)
1143 ULONG idx;
1145 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1146 struct TagItem *tag, *tstate = msg->attrList;
1148 while ((tag = NextTagItem(&tstate)))
1150 if (IS_COMPOSITOR_ATTR(tag->ti_Tag, idx))
1152 switch (idx)
1154 case aoHidd_Compositor_State:
1156 D(bug("[%s] Compositor Capabilities State: %lx -> ", __PRETTY_FUNCTION__, compdata->capabilities));
1157 compdata->capabilities = (ULONG)(tag->ti_Data & CAPABILITY_FLAGS);
1158 D(bug("%lx\n", compdata->capabilities));
1159 break;
1161 case aoHidd_Compositor_BackFillHook:
1163 if (tag->ti_Data)
1165 D(bug("[%s] BackFillHook: 0x%p -> 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook, tag->ti_Data));
1166 compdata->backfillhook = (struct Hook *)tag->ti_Data;
1168 else
1170 D(bug("[%s] Default BackFillHook\n", __PRETTY_FUNCTION__));
1171 compdata->backfillhook = &compdata->defaultbackfill;
1173 break;
1179 OOP_DoSuperMethod(cl, o, &msg->mID);
1182 OOP_Object *METHOD(Compositor, Hidd_Compositor, BitMapStackChanged)
1184 struct HIDD_ViewPortData *vpdata;
1185 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1186 struct StackBitMapNode *n;
1187 struct Screen *bmScreen;
1188 OOP_Object *bmpxfmt;
1189 int bmstdfmt;
1190 BOOL newtop = FALSE;
1191 BOOL ok = TRUE;
1193 DSTACK(bug("[Compositor] %s: Top bitmap: 0x%lx\n", __PRETTY_FUNCTION__, msg->data->Bitmap));
1195 LOCK_COMPOSITOR_WRITE
1197 /* Free all items which are already on the list */
1198 HIDDCompositorPurgeBitMapStack(compdata);
1200 if (!msg->data)
1202 UNLOCK_COMPOSITOR
1204 /* Blank screen */
1205 HIDDCompositorShowSingle(compdata, NULL);
1207 /* We know we are inactive after this */
1208 *msg->active = FALSE;
1209 /* This can return NULL, it's okay */
1210 return compdata->screenbitmap;
1213 /* Copy bitmaps pointers to our stack */
1214 for (vpdata = msg->data; vpdata; vpdata = vpdata->Next)
1216 n = AllocMem(sizeof(struct StackBitMapNode), MEMF_ANY | MEMF_CLEAR);
1217 if (!n)
1220 * Error happened.
1221 * We need to reset own state and return NULL. graphics.library
1222 * falls back to no composition in this case.
1224 DSTACK(bug("[Compositor] %s: Error allocating StackBitMapNode!!!\n", __PRETTY_FUNCTION__));
1226 ok = FALSE;
1227 break;
1230 DSTACK(bug("[Compositor] %s: ViewPort 0x%p, offset (%d, %d)\n", __PRETTY_FUNCTION__, vpdata->vpe->ViewPort, vpdata->vpe->ViewPort->DxOffset, vpdata->vpe->ViewPort->DyOffset));
1232 n->bm = vpdata->Bitmap;
1233 n->sbmflags = STACKNODEF_DISPLAYABLE;
1234 n->leftedge = vpdata->vpe->ViewPort->DxOffset;
1235 n->topedge = vpdata->vpe->ViewPort->DyOffset;
1237 n->screenregion = NewRegion();
1239 if ((bmScreen = HIDDCompositorFindBitMapScreen(compdata, n->bm)) != NULL)
1241 DSTACK(bug("[Compositor] %s: Screen @ 0x%p\n", __PRETTY_FUNCTION__, bmScreen));
1242 GetAttr(SA_CompositingFlags, (Object *)bmScreen, &n->sbmflags);
1243 DSTACK(bug("[Compositor] %s: CompositingFlags %08x\n", __PRETTY_FUNCTION__, n->sbmflags));
1244 n->sbmflags |= STACKNODEF_DISPLAYABLE;
1247 if (n->sbmflags & COMPF_ALPHA)
1249 bmpxfmt = (OOP_Object *)OOP_GET(n->bm, aHidd_BitMap_PixFmt);
1250 bmstdfmt = (int)OOP_GET(bmpxfmt, aHidd_PixFmt_StdPixFmt);
1251 DSTACK(bug("[Compositor] %s: Screen BitMap PixFmt %lx @ 0x%p\n", __PRETTY_FUNCTION__, bmstdfmt, bmpxfmt));
1253 switch (bmstdfmt)
1255 case vHidd_StdPixFmt_ARGB32:
1256 case vHidd_StdPixFmt_BGRA32:
1257 case vHidd_StdPixFmt_RGBA32:
1258 case vHidd_StdPixFmt_ABGR32:
1260 DSTACK(bug("[Compositor] %s: Screen BitMap has Alpha\n", __PRETTY_FUNCTION__));
1262 compdata->flags |= COMPSTATEF_HASALPHA;
1263 break;
1265 default:
1267 n->sbmflags &= ~COMPF_ALPHA;
1268 break;
1273 if (!(n->sbmflags & COMPF_ALPHA))
1275 if ((((BOOL)OOP_GET(n->bm, aHidd_BitMap_Displayable)) != TRUE))
1276 n->sbmflags &= ~STACKNODEF_DISPLAYABLE;
1278 AddTail((struct List *)&compdata->bitmapstack, (struct Node *)n);
1281 /* Switch mode if needed */
1282 UpdateDisplayMode(compdata);
1284 if (msg->data->Bitmap != compdata->topbitmap)
1286 /* Set the new pointer to top bitmap */
1287 compdata->topbitmap = msg->data->Bitmap;
1288 newtop = TRUE;
1291 if (ok)
1294 * Validate bitmap offsets - they might not match the compositing rules taking
1295 * new displayedwidth/displayedheight values
1297 ForeachNode(&compdata->bitmapstack, n)
1299 HIDDCompositorValidateBitMapPositionChange(n->bm, &n->leftedge, &n->topedge,
1300 compdata->displayrect.MaxX + 1, compdata->displayrect.MaxY + 1);
1301 DSTACK(bug("[Compositor] %s: Bitmap 0x%p, display size %d x %d, validated position (%ld, %ld)\n", __PRETTY_FUNCTION__,
1302 n->bm, compdata->displayrect.MaxX + 1, compdata->displayrect.MaxY + 1,
1303 n->leftedge, n->topedge));
1306 /* Toogle compositing based on screen positions */
1307 ok = HIDDCompositorToggleCompositing(compdata, newtop);
1310 /* Handle error */
1311 if (!ok)
1313 HIDDCompositorReset(compdata);
1314 HIDDCompositorShowSingle(compdata, msg->data->Bitmap);
1317 UNLOCK_COMPOSITOR
1319 DSTACK(bug("[%s] Done, composited bitmap 0x%p\n", __PRETTY_FUNCTION__, compdata->displaybitmap));
1321 /* Tell if the composition is active */
1322 *msg->active = compdata->displaybitmap ? TRUE : FALSE;
1323 /* Return actually displayed bitmap */
1324 return compdata->screenbitmap;
1327 VOID METHOD(Compositor, Hidd_Compositor, BitMapRectChanged)
1329 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1330 OOP_Object *renderTarget;
1332 if (compdata->displaybitmap)
1334 /* Composition is active, handle redraw if the bitmap is on screen */
1335 struct StackBitMapNode *n;
1337 DUPDATE(bug("[%s] Bitmap 0x%p\n", __PRETTY_FUNCTION__, msg->bm));
1339 LOCK_COMPOSITOR_READ
1341 if (compdata->intermedbitmap)
1342 renderTarget = compdata->intermedbitmap;
1343 else
1344 renderTarget = compdata->displaybitmap;
1346 n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1347 if (n && (n->sbmflags & STACKNODEF_VISIBLE))
1349 struct Rectangle srcrect, dstandvisrect;
1351 srcrect.MinX = n->leftedge + msg->x;
1352 srcrect.MinY = n->topedge + msg->y;
1353 srcrect.MaxX = srcrect.MinX + msg->width - 1;
1354 srcrect.MaxY = srcrect.MinY + msg->height - 1;
1355 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));
1357 DUPDATE(bug("[%s] Screen-relative rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(srcrect)));
1359 struct RegionRectangle * srrect = n->screenregion->RegionRectangle;
1360 while (srrect)
1362 BOOL updateAlphaBmps = FALSE;
1364 dstandvisrect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
1365 dstandvisrect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
1366 dstandvisrect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
1367 dstandvisrect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
1369 if (AndRectRect(&srcrect, &dstandvisrect, &dstandvisrect))
1371 /* Intersection is valid. Blit. */
1372 DUPDATE(bug("[%s] Clipped rect (%d, %d) - (%d, %d)\n", __PRETTY_FUNCTION__, _RECT(dstandvisrect)));
1374 if (!(n->sbmflags & COMPF_ALPHA))
1376 if ((compdata->alpharegion) && (isRectInRegion(compdata->alpharegion, &dstandvisrect)))
1378 DUPDATE(bug("[%s] ** Bitmap in Alpha Region!\n", __PRETTY_FUNCTION__));
1379 updateAlphaBmps = TRUE;
1381 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &dstandvisrect);
1383 else
1385 updateAlphaBmps = FALSE;
1386 HIDDCompositorRedrawVisibleRegions(compdata, &dstandvisrect);
1389 if (updateAlphaBmps)
1390 HIDDCompositorRedrawAlphaRegions(compdata, &dstandvisrect);
1392 if (renderTarget != compdata->displaybitmap)
1394 HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
1395 dstandvisrect.MinX, dstandvisrect.MinY,
1396 compdata->displaybitmap,
1397 dstandvisrect.MinX, dstandvisrect.MinY,
1398 dstandvisrect.MaxX - dstandvisrect.MinX + 1,
1399 dstandvisrect.MaxY - dstandvisrect.MinY + 1,
1400 compdata->gc);
1403 HIDD_BM_UpdateRect(compdata->displaybitmap,
1404 dstandvisrect.MinX, dstandvisrect.MinY,
1405 dstandvisrect.MaxX - dstandvisrect.MinX + 1,
1406 dstandvisrect.MaxY - dstandvisrect.MinY + 1);
1408 srrect = srrect->Next;
1412 UNLOCK_COMPOSITOR
1414 DUPDATE(bug("[%s] Done\n", __PRETTY_FUNCTION__));
1416 else
1418 /* In order to speed things up, we handle passthrough ourselves here. */
1419 HIDD_BM_UpdateRect(msg->bm, msg->x, msg->y, msg->width, msg->height);
1423 IPTR METHOD(Compositor, Hidd_Compositor, BitMapPositionChange)
1425 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1426 struct StackBitMapNode *n;
1427 IPTR disp_width, disp_height;
1429 LOCK_COMPOSITOR_READ
1431 n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1432 if (n)
1434 /* The bitmap is on display. Validate against screen size */
1435 disp_width = compdata->displayrect.MaxX + 1;
1436 disp_height = compdata->displayrect.MaxY + 1;
1438 else
1440 /* The bitmap is not displayed yet. Validate against its own ModeID size. */
1441 HIDDT_ModeID modeid = vHidd_ModeID_Invalid;
1442 OOP_Object *bmfriend, *sync, *pf;
1444 OOP_GetAttr(msg->bm, aHidd_BitMap_ModeID, &modeid);
1446 if ((modeid == vHidd_ModeID_Invalid) && (OOP_GET(msg->bm, aHidd_BitMap_Compositable)))
1448 OOP_GetAttr(msg->bm, aHidd_BitMap_Friend, (IPTR *)&bmfriend);
1449 if (bmfriend)
1450 OOP_GetAttr(bmfriend, aHidd_BitMap_ModeID, &modeid);
1453 if (modeid == vHidd_ModeID_Invalid)
1456 * Nondisplayable bitmaps don't scroll.
1457 * In fact they simply can't get in here because MakeVPort() performs the validation.
1458 * But who knows what bug can slip into someone's software...
1460 UNLOCK_COMPOSITOR
1461 return FALSE;
1464 HIDD_Gfx_GetMode(compdata->gfx, modeid, &sync, &pf);
1465 OOP_GetAttr(sync, aHidd_Sync_HDisp, &disp_width);
1466 OOP_GetAttr(sync, aHidd_Sync_VDisp, &disp_height);
1469 DMOVE(bug("[%s] Validating bitmap 0x%p, position (%ld, %ld), limits %ld x %ld\n", __PRETTY_FUNCTION__,
1470 msg->bm, *msg->newxoffset, *msg->newyoffset, disp_width, disp_height));
1472 HIDDCompositorValidateBitMapPositionChange(msg->bm, msg->newxoffset, msg->newyoffset,
1473 disp_width, disp_height);
1475 DMOVE(bug("[%s] Validated position (%ld, %ld)\n", __PRETTY_FUNCTION__, *msg->newxoffset, *msg->newyoffset));
1477 if (n && ((*msg->newxoffset != n->leftedge) || (*msg->newyoffset != n->topedge)))
1479 DMOVE(bug("[%s] Old position (%ld, %ld)\n", __PRETTY_FUNCTION__, n->leftedge, n->topedge));
1481 /* Reflect the change if it happened */
1482 n->leftedge = *msg->newxoffset;
1483 n->topedge = *msg->newyoffset;
1485 if (compdata->topbitmap == msg->bm)
1488 * If this is the frontmost bitmap, we may want to toggle compositing,
1489 * if it starts/stops covering the whole screen at one point.
1490 * We don't need to call HIDDCompositorRedrawVisibleRegions() here because
1491 * HIDDCompositorToggleCompositing() does this itself, for improved
1492 * visual appearance.
1494 HIDDCompositorToggleCompositing(compdata, FALSE);
1496 else
1497 HIDDCompositorRedrawVisibleRegions(compdata, NULL);
1500 UNLOCK_COMPOSITOR
1502 /* Return active state */
1503 return compdata->displaybitmap ? TRUE : FALSE;
1506 IPTR METHOD(Compositor, Hidd_Compositor, BitMapValidate)
1508 if (IS_HIDD_BM(msg->bm))
1509 return TRUE;
1511 return FALSE;
1514 IPTR METHOD(Compositor, Hidd_Compositor, BitMapEnable)
1516 if (IS_HIDD_BM(msg->bm))
1518 if (!(OOP_GET(HIDD_BM_OBJ(msg->bm), aHidd_BitMap_Displayable)))
1520 struct TagItem composittags[] = {
1521 {aHidd_BitMap_Compositable, TRUE},
1522 {TAG_DONE , 0 }
1525 D(bug("[GfxCompositor]: Marking BitMap 0x%lx as Compositable\n", msg->bm));
1526 OOP_SetAttrs(HIDD_BM_OBJ(msg->bm), composittags);
1528 return TRUE;
1531 return FALSE;
1534 #define NUM_Compositor_Root_METHODS 4
1536 static const struct OOP_MethodDescr Compositor_Root_descr[] =
1538 {(OOP_MethodFunc)Compositor__Root__New, moRoot_New},
1539 {(OOP_MethodFunc)Compositor__Root__Dispose, moRoot_Dispose},
1540 {(OOP_MethodFunc)Compositor__Root__Get, moRoot_Get},
1541 {(OOP_MethodFunc)Compositor__Root__Set, moRoot_Set},
1542 {NULL, 0}
1545 #define NUM_Compositor_Hidd_Compositor_METHODS 5
1547 static const struct OOP_MethodDescr Compositor_Hidd_Compositor_descr[] =
1549 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapStackChanged, moHidd_Compositor_BitMapStackChanged},
1550 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapRectChanged, moHidd_Compositor_BitMapRectChanged},
1551 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapPositionChange, moHidd_Compositor_BitMapPositionChange},
1552 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapValidate, moHidd_Compositor_BitMapValidate},
1553 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapEnable, moHidd_Compositor_BitMapEnable},
1554 {NULL, 0}
1557 const struct OOP_InterfaceDescr Compositor_ifdescr[] =
1559 {Compositor_Root_descr, IID_Root, NUM_Compositor_Root_METHODS},
1560 {Compositor_Hidd_Compositor_descr, IID_Hidd_Compositor, NUM_Compositor_Hidd_Compositor_METHODS},
1561 {NULL, NULL}