2 Copyright © 2010-2013, The AROS Development Team. All rights reserved.
12 #define DREDRAWBM(x) x
13 #define DREDRAWSCR(x) x
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)
61 #define GfxBase compdata->GraphicsBase
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
;
78 if (AndRectRect(&rrect
->bounds
, rect
, NULL
))
86 static struct StackBitMapNode
* HIDDCompositorFindBitMapStackNode(struct HIDDCompositorData
* compdata
, OOP_Object
* bm
)
88 struct StackBitMapNode
* n
= NULL
;
90 ForeachNode(&compdata
->bitmapstack
, n
)
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
))
109 return (struct Screen
*)NULL
;
112 static VOID
HIDDCompositorValidateBitMapPositionChange(OOP_Object
* bm
, SIPTR
*newxoffset
, SIPTR
*newyoffset
, LONG displayedwidth
, LONG displayedheight
)
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
;
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 */
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
;
182 ClearRegion(n
->screenregion
);
184 n
->screenregion
= NewRegion();
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
);
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] HiddBitmap 0x%p, topedge %d, visible %d, [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__
,
249 n
->bm
, n
->topedge
, (n
->sbmflags
& STACKNODEF_VISIBLE
), _RECT(n
->screenvisiblerect
)));
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
;
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
;
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
)
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"));
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;
315 if (delta
< found_delta
)
317 /* If mode resolution is closer to the needed one, we've got a better match */
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
))
336 else if (found_depth
< depth
)
339 * We want better depth than current candidate.
340 * In this case anything deeper will do.
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
));
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
;
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;
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
)
409 * If we have a LUT bitmap on stack, we request 24-bit screen
410 * for better color transfer.
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
)
422 if (curheight
> height
)
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
->displaymode
));
439 if (modeid
!= compdata
->displaymode
)
441 /* The mode is different. Need to prepare information needed for compositing */
442 struct TagItem gctags
[] =
444 { aHidd_GC_Foreground
, 0x99999999 },
448 /* Signal mode change */
449 compdata
->displaymode
= modeid
;
450 compdata
->displaydepth
= comp_depth
;
451 compdata
->modeschanged
= TRUE
;
453 /* Get gray foregound */
454 if (found_depth
< 24)
455 gctags
[0].ti_Data
= 0x9492;
457 OOP_SetAttrs(compdata
->gc
, gctags
);
461 static inline void HIDDCompositorRedrawBitmap(struct HIDDCompositorData
*compdata
, OOP_Object
*renderTarget
, struct StackBitMapNode
*n
, struct Rectangle
*rect
)
463 /* The given rectangle is already in screen coordinate system here */
464 ULONG blitwidth
= rect
->MaxX
- rect
->MinX
+ 1;
465 ULONG blitheight
= rect
->MaxY
- rect
->MinY
+ 1;
467 DREDRAWBM(bug("[Compositor:%s] Redraw HiddBitMap 0x%p, Rect[%d, %d - %d, %d]\n", __PRETTY_FUNCTION__
, n
->bm
,
468 rect
->MinX
, rect
->MinY
, rect
->MaxX
, rect
->MaxY
));
470 if (!(n
->sbmflags
& COMPF_ALPHA
))
472 DREDRAWBM(bug("[Compositor:%s] Blitting %dx%d [from %d, %d]\n", __PRETTY_FUNCTION__
, blitwidth
, blitheight
,
473 rect
->MinX
- n
->leftedge
, rect
->MinY
- n
->topedge
));
475 HIDD_Gfx_CopyBox(compdata
->gfx
, n
->bm
,
476 /* Transform to source bitmap coord system */
477 rect
->MinX
- n
->leftedge
, rect
->MinY
- n
->topedge
,
479 rect
->MinX
, rect
->MinY
, blitwidth
, blitheight
,
485 ULONG width
, height
, banksize
, memsize
;
488 DREDRAWBM(bug("[Compositor:%s] AlphaBlending %dx%d @ %d,%d to %d,%d\n", __PRETTY_FUNCTION__
,
489 blitwidth
, blitheight
,
490 rect
->MinX
- n
->leftedge
, rect
->MinY
- n
->topedge
, rect
->MinX
, rect
->MinY
));
492 if (HIDD_BM_ObtainDirectAccess(n
->bm
, &baseaddress
, &width
, &height
, &banksize
, &memsize
))
494 DREDRAWBM(bug("[Compositor:%s] Alpha baseaddress @ 0x%p\n", __PRETTY_FUNCTION__
, baseaddress
));
495 OOP_GetAttr(n
->bm
, aHidd_BitMap_BytesPerRow
, &modulo
);
496 HIDD_BM_PutAlphaImage(renderTarget
, compdata
->gfx
, baseaddress
+ ((rect
->MinY
- n
->topedge
) * modulo
) + ((rect
->MinX
- n
->leftedge
) << 2), modulo
,
497 rect
->MinX
, rect
->MinY
, blitwidth
, blitheight
);
498 HIDD_BM_ReleaseDirectAccess(n
->bm
);
503 static inline void HIDDCompositorFillRect(struct HIDDCompositorData
*compdata
, OOP_Object
*renderTarget
, ULONG MinX
, ULONG MinY
, ULONG MaxX
, ULONG MaxY
)
505 DREDRAWSCR(bug("[Compositor:%s] Filling [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__
,
506 MinX
, MinY
, MaxX
, MaxY
));
508 HIDD_BM_FillRect(renderTarget
, compdata
->gc
,
509 MinX
, MinY
, MaxX
, MaxY
);
513 static VOID
HIDDCompositorRedrawAlphaRegions(struct HIDDCompositorData
*compdata
, struct Rectangle
*drawrect
)
515 OOP_Object
*renderTarget
= compdata
->displaybitmap
;
516 struct Rectangle alpharect
;
517 struct StackBitMapNode
*n
;
518 struct BitMap
*backbm
;
520 if (compdata
->intermedbitmap
)
521 renderTarget
= compdata
->intermedbitmap
;
523 DREDRAWSCR(if (drawrect
){ bug("[Compositor:%s] Rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__
, _RECT((*drawrect
))); })
525 OOP_GetAttr(renderTarget
, aHidd_BitMap_BMStruct
, (IPTR
*)&backbm
);
527 // Alpha Regions are drawn in reverse order incase they overlap..
528 for (n
= (struct StackBitMapNode
*)compdata
->bitmapstack
.mlh_TailPred
;
529 n
->n
.mln_Pred
; n
= (struct StackBitMapNode
*)n
->n
.mln_Pred
)
531 if ((n
->sbmflags
& STACKNODEF_VISIBLE
) &&
532 (n
->sbmflags
& COMPF_ALPHA
) &&
535 DREDRAWSCR(bug("[Compositor:%s] Alpha Screen Region @ 0x%p HiddBitMap @ 0x%p [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__
,
536 n
->screenregion
, n
->bm
, _RECT(n
->screenvisiblerect
)));
538 DREDRAWSCR(bug("[Compositor:%s] Compositing Visible Alpha Regions..\n", __PRETTY_FUNCTION__
));
540 struct RegionRectangle
*srrect
= n
->screenregion
->RegionRectangle
;
543 alpharect
.MinX
= srrect
->bounds
.MinX
+ n
->screenregion
->bounds
.MinX
;
544 alpharect
.MinY
= srrect
->bounds
.MinY
+ n
->screenregion
->bounds
.MinY
;
545 alpharect
.MaxX
= srrect
->bounds
.MaxX
+ n
->screenregion
->bounds
.MinX
;
546 alpharect
.MaxY
= srrect
->bounds
.MaxY
+ n
->screenregion
->bounds
.MinY
;
548 if (!(drawrect
) || AndRectRect(drawrect
, &alpharect
, &alpharect
))
550 DREDRAWSCR(bug("[Compositor:%s] Alpha-Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__
, _RECT(alpharect
)));
552 if ((n
->prealphacomphook
) && (backbm
!= NULL
))
554 struct HIDD_BackFillHookMsg preprocessmsg
;
555 preprocessmsg
.bounds
= &alpharect
;
556 preprocessmsg
.offsetx
= 0;
557 preprocessmsg
.offsety
= 0;
558 CallHookPkt(n
->prealphacomphook
, backbm
, &preprocessmsg
);
561 HIDDCompositorRedrawBitmap(compdata
, renderTarget
, n
, &alpharect
);
562 if (renderTarget
== compdata
->displaybitmap
)
563 HIDD_BM_UpdateRect(compdata
->displaybitmap
,
564 alpharect
.MinX
, alpharect
.MinY
,
565 alpharect
.MaxX
- alpharect
.MinX
+ 1,
566 alpharect
.MaxY
- alpharect
.MinY
+ 1);
568 srrect
= srrect
->Next
;
574 static VOID
HIDDCompositorRedrawVisibleRegions(struct HIDDCompositorData
*compdata
, struct Rectangle
*drawrect
)
576 OOP_Object
*renderTarget
= compdata
->displaybitmap
;
577 struct Region
*dispvisregion
= NULL
;
578 struct Rectangle tmprect
;
579 struct BitMap
*clearbm
;
580 struct StackBitMapNode
*n
;
582 DREDRAWSCR(bug("[Compositor:%s] Redrawing Display (GfxBase @ 0x%p)\n", __PRETTY_FUNCTION__
, GfxBase
));
586 /* Recalculate visible regions */
587 HIDDCompositorRecalculateVisibleRegions(compdata
);
590 if ((compdata
->flags
& COMPSTATEF_HASALPHA
) && (compdata
->intermedbitmap
))
591 renderTarget
= compdata
->intermedbitmap
;
593 if ((dispvisregion
= NewRegion()) != NULL
)
596 OrRectRegion(dispvisregion
, drawrect
);
598 OrRectRegion(dispvisregion
, &compdata
->displayrect
);
600 DRECALC(bug("[Compositor:%s] Display rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__
, _RECT(compdata
->displayrect
)));
602 ForeachNode(&compdata
->bitmapstack
, n
)
604 if ((n
->sbmflags
& STACKNODEF_VISIBLE
) &&
605 (!(n
->sbmflags
& COMPF_ALPHA
)) &&
608 DREDRAWSCR(bug("[Compositor:%s] Screen Region @ 0x%p HiddBitMap @ 0x%p [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__
,
609 n
->screenregion
, n
->bm
, _RECT(n
->screenvisiblerect
)));
611 DREDRAWSCR(bug("[Compositor:%s] Redrawing Visible Screen Regions..\n", __PRETTY_FUNCTION__
));
612 // Render the visable regions ..
613 struct RegionRectangle
* srrect
= n
->screenregion
->RegionRectangle
;
616 tmprect
.MinX
= srrect
->bounds
.MinX
+ n
->screenregion
->bounds
.MinX
;
617 tmprect
.MinY
= srrect
->bounds
.MinY
+ n
->screenregion
->bounds
.MinY
;
618 tmprect
.MaxX
= srrect
->bounds
.MaxX
+ n
->screenregion
->bounds
.MinX
;
619 tmprect
.MaxY
= srrect
->bounds
.MaxY
+ n
->screenregion
->bounds
.MinY
;
621 if (!(drawrect
) || AndRectRect(drawrect
, &tmprect
, &tmprect
))
623 DREDRAWSCR(bug("[Compositor:%s] Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__
, _RECT(tmprect
)));
625 HIDDCompositorRedrawBitmap(compdata
, renderTarget
, n
, &tmprect
);
626 if (renderTarget
== compdata
->displaybitmap
)
627 HIDD_BM_UpdateRect(compdata
->displaybitmap
,
628 tmprect
.MinX
, tmprect
.MinY
,
629 tmprect
.MaxX
- tmprect
.MinX
+ 1,
630 tmprect
.MaxY
- tmprect
.MinY
+ 1);
632 srrect
= srrect
->Next
;
634 ClearRegionRegion(n
->screenregion
, dispvisregion
);
637 OOP_GetAttr(renderTarget
, aHidd_BitMap_BMStruct
, (IPTR
*)&clearbm
);
639 struct RegionRectangle
* dispclrrect
= dispvisregion
->RegionRectangle
;
642 struct HIDD_BackFillHookMsg clearmsg
;
644 tmprect
.MinX
= dispclrrect
->bounds
.MinX
+ dispvisregion
->bounds
.MinX
;
645 tmprect
.MinY
= dispclrrect
->bounds
.MinY
+ dispvisregion
->bounds
.MinY
;
646 tmprect
.MaxX
= dispclrrect
->bounds
.MaxX
+ dispvisregion
->bounds
.MinX
;
647 tmprect
.MaxY
= dispclrrect
->bounds
.MaxY
+ dispvisregion
->bounds
.MinY
;
649 if (!(drawrect
) || AndRectRect(drawrect
, &tmprect
, &tmprect
))
651 DREDRAWSCR(bug("[Compositor:%s] Render Display Void Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__
, _RECT(tmprect
)));
655 clearmsg
.bounds
= &tmprect
;
656 clearmsg
.offsetx
= 0;
657 clearmsg
.offsety
= 0;
658 CallHookPkt(compdata
->backfillhook
, clearbm
, &clearmsg
);
661 if (renderTarget
== compdata
->displaybitmap
)
662 HIDD_BM_UpdateRect(compdata
->displaybitmap
,
663 tmprect
.MinX
, tmprect
.MinY
,
664 tmprect
.MaxX
- tmprect
.MinX
+ 1,
665 tmprect
.MaxY
- tmprect
.MinY
+ 1);
667 dispclrrect
= dispclrrect
->Next
;
669 if (compdata
->flags
& COMPSTATEF_HASALPHA
)
671 HIDDCompositorRedrawAlphaRegions(compdata
, drawrect
);
673 DisposeRegion(dispvisregion
);
675 if (renderTarget
!= compdata
->displaybitmap
)
677 DREDRAWSCR(bug("[Compositor:%s] Copying Alpha Intermediary BitMap\n", __PRETTY_FUNCTION__
, _RECT(tmprect
)));
680 HIDD_Gfx_CopyBox(compdata
->gfx
, renderTarget
,
681 compdata
->displayrect
.MinX
, compdata
->displayrect
.MinY
,
682 compdata
->displaybitmap
,
683 compdata
->displayrect
.MinX
, compdata
->displayrect
.MinY
,
684 compdata
->displayrect
.MaxX
- compdata
->displayrect
.MinX
+ 1,
685 compdata
->displayrect
.MaxY
- compdata
->displayrect
.MinY
+ 1,
687 HIDD_BM_UpdateRect(compdata
->displaybitmap
,
688 compdata
->displayrect
.MinX
, compdata
->displayrect
.MinY
,
689 compdata
->displayrect
.MaxX
- compdata
->displayrect
.MinX
+ 1,
690 compdata
->displayrect
.MaxY
- compdata
->displayrect
.MinY
+ 1);
694 HIDD_Gfx_CopyBox(compdata
->gfx
, renderTarget
,
695 drawrect
->MinX
, drawrect
->MinY
,
696 compdata
->displaybitmap
,
697 drawrect
->MinX
, drawrect
->MinY
,
698 drawrect
->MaxX
- drawrect
->MinX
+ 1,
699 drawrect
->MaxY
- drawrect
->MinY
+ 1,
701 HIDD_BM_UpdateRect(compdata
->displaybitmap
,
702 drawrect
->MinX
, drawrect
->MinY
,
703 drawrect
->MaxX
- drawrect
->MinX
+ 1,
704 drawrect
->MaxY
- drawrect
->MinY
+ 1);
711 There are several cases that needs to be handled in this code. They are documented
712 below. Please read it before making changes.
713 etb = existing topbitmap
716 cb = composited bitmap
717 fs = covers full screen
718 nfs = not covers full screen
724 The resulting mode is always that of screen bitmap as set in "effect" column.
725 The composited bitmap always matches the resulting screen mode or is NULL.
727 | exiting screen situation | change | effect |
728 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - SAME MODE |
729 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mA | sb==ntb, cb==NULL |
730 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
731 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
732 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb, cb!=NULL |
733 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
734 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - SAME MODE |
735 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
736 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
737 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
738 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
739 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
742 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - DIFFERENT MODES |
743 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mB | sb==ntb, cb==NULL |
744 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
745 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
746 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mB | new(cb), sb==cb, cb!=NULL |
747 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
748 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - DIFFERENT MODES |
749 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
750 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
751 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
752 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
753 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
756 | USE CASE: DRAGGING SCREEN DOWN |
757 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb |
758 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb |
759 | USE CASE: DRAGGING SCREEN UP |
760 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==etb |
761 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
763 Resulting rules (order matters):
765 (a) if ((cb!=NULL) && (etb->mode!=ntb->mode)) {dispose(cb), cb=NULL}
766 (b) if ((ntb->nfs) && (cb==NULL)) new(cb)
767 (c) if (ntb->nfs) sb=cb
768 (d) if (ntb->fs) sb=ntb
771 (e) if (oldsb!=sb) modeswitch(sb)
773 02.09.2011: we don't remember sb any more because we don't handle it in any way. Instead
774 we either have or don't have displaybitmap. If we have it, composition
775 is on (sb = cb). If we don't have it, composition is off (sb = ntb).
777 static BOOL
HIDDCompositorToggleCompositing(struct HIDDCompositorData
*compdata
, BOOL newtop
)
780 * If the topbitmap covers the complete screen, show it instead of
781 * displaybitmap. Remember that screen bitmap -> composited bitmap
782 * mirroring has a negative impact on performance.
784 OOP_Object
*oldcompositedbitmap
= compdata
->displaybitmap
;
785 struct StackBitMapNode
*topnode
= (struct StackBitMapNode
*)compdata
->bitmapstack
.mlh_Head
;
786 OOP_Object
*newsdispbitmap
= NULL
;
787 struct BitMap
*tmpBM
;
788 struct TagItem bmtags
[2];
790 BOOL ok
= TRUE
, composit
= FALSE
;
792 /* (a) If mode change is needed, enforce opening a new screen */
793 if (compdata
->modeschanged
)
795 DTOGGLE(bug("[Compositor:%s] Display Mode changed\n", __PRETTY_FUNCTION__
));
796 compdata
->displaybitmap
= NULL
;
799 bmtags
[0].ti_Tag
= BMATags_DisplayID
; bmtags
[0].ti_Data
= (compdata
->displayid
| compdata
->displaymode
);
800 bmtags
[1].ti_Tag
= TAG_DONE
; bmtags
[1].ti_Data
= TAG_DONE
;
802 if ((topnode
->topedge
> 0) || ((compdata
->displayrect
.MaxY
- compdata
->displayrect
.MinY
+ 1) > OOP_GET(topnode
->bm
, aHidd_BitMap_Height
)))
804 else if ((topnode
->leftedge
> 0) || ((compdata
->displayrect
.MaxX
- compdata
->displayrect
.MinX
+ 1) > OOP_GET(topnode
->bm
, aHidd_BitMap_Width
)))
806 else if (topnode
->sbmflags
& COMPF_ALPHA
)
812 if (compdata
->displaybitmap
== NULL
)
815 * displaybitmap == NULL means we were in passthrough mode before,
816 * or have just changed display mode - set up screen for composition.
818 DTOGGLE(bug("[Compositor:%s] Initialising Display-Compositor..\n", __PRETTY_FUNCTION__
));
823 * If our display driver uses a framebuffer, we can reuse it.
824 * Copy its original contents back into the bitmap which it replaced,
825 * then change framebuffer's video mode.
826 * Framebuffer is the only bitmap which can change its ModeID on the fly.
828 DTOGGLE(bug("[Compositor:%s] Using Display Famebuffer HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__
, compdata
->fb
));
830 /* Do this comparison in order not to show the framebuffer twice */
831 if (oldcompositedbitmap
!= compdata
->fb
)
834 * 1. It's legal to show the framebuffer itself. This causes copying
835 * back old bitmap contents and detaching from it.
836 * 2. The result of this will always match compdata->fb.
837 * 3. Internally this is a simple blit operation, it can't fail.
839 DTOGGLE(bug("[Compositor:%s] Copying old Famebuffer BitMap\n", __PRETTY_FUNCTION__
));
840 compdata
->screenbitmap
= HIDD_Gfx_Show(compdata
->gfx
, compdata
->fb
, fHidd_Gfx_Show_CopyBack
);
843 /* Switch display mode on the framebuffer. */
844 OOP_SetAttrsTags(compdata
->fb
, aHidd_BitMap_ModeID
, compdata
->displaymode
, TAG_DONE
);
845 /* We are now compositing on the framebuffer */
846 compdata
->displaybitmap
= compdata
->fb
;
851 * There's no framebuffer.
852 * Create a new bitmap that will be used for compositing.
855 tmpBM
= AllocBitMap(compdata
->displayrect
.MaxX
- compdata
->displayrect
.MinX
+ 1,
856 compdata
->displayrect
.MaxY
- compdata
->displayrect
.MinY
+ 1,
857 compdata
->displaydepth
,
858 BMF_DISPLAYABLE
|BMF_CHECKVALUE
, (struct BitMap
*)bmtags
);
861 compdata
->displaybitmap
= HIDD_BM_OBJ(tmpBM
);
862 DTOGGLE(bug("[Compositor:%s] Created Compositor Display BitMap @ 0x%p [HiddBitMap @ 0x%p]\n", __PRETTY_FUNCTION__
, tmpBM
, compdata
->displaybitmap
));
864 /* Mode changed, this bitmap will be shown later */
865 newsdispbitmap
= compdata
->displaybitmap
;
867 /* NewBitMap can fail, handle this */
873 else /* if (compdata->displaybitmap == NULL) */
876 * We are already in compositing mode and will stay in it.
877 * Do not destroy our working bitmap.
879 oldcompositedbitmap
= NULL
;
882 if ((compdata
->flags
& COMPSTATEF_HASALPHA
) && !(compdata
->intermedbitmap
))
884 tmpBM
= AllocBitMap(compdata
->displayrect
.MaxX
- compdata
->displayrect
.MinX
+ 1,
885 compdata
->displayrect
.MaxY
- compdata
->displayrect
.MinY
+ 1,
886 compdata
->displaydepth
,
887 BMF_CHECKVALUE
, (struct BitMap
*)bmtags
);
890 compdata
->intermedbitmap
= HIDD_BM_OBJ(tmpBM
);
891 DTOGGLE(bug("[Compositor:%s] Allocated Alpha Intermediary BitMap @ 0x%p [HiddBitMap @ 0x%p]\n", __PRETTY_FUNCTION__
, tmpBM
, compdata
->intermedbitmap
));
895 * (c) Here composition is turned on (displaybitmap != NULL).
896 * Redraw bitmap stack - compensate possible changes
899 HIDDCompositorRedrawVisibleRegions(compdata
, NULL
);
901 else if (oldcompositedbitmap
|| newtop
)
904 * (d) Set passthrough mode and display the frontmost bitmap.
905 * This is also triggered by 'newtop' parameter, which tells us
906 * that frontmost bitmap has been changed, and we need to display a new one.
907 * Old displaybitmap has been remembered in the beginning. If it's not
908 * NULL, it will be destroyed in the end.
910 newsdispbitmap
= compdata
->topbitmap
;
911 compdata
->displaybitmap
= NULL
;
914 DTOGGLE(bug("[Compositor:%s] oldcompbm 0x%p, topbm 0x%p, dispbm 0x%p, newscreenbm 0x%p\n", __PRETTY_FUNCTION__
,
915 oldcompositedbitmap
, compdata
->topbitmap
, compdata
->displaybitmap
, newsdispbitmap
));
918 * (e) If the screenbitmap changed, show the new screenbitmap.
919 * We do it after refreshing, for better visual appearance.
925 compdata
->screenbitmap
= HIDD_Gfx_Show(compdata
->gfx
, newsdispbitmap
, fHidd_Gfx_Show_CopyBack
);
926 DTOGGLE(bug("[Compositor:%s] Displayed HiddBitMap 0x%p, Show returned 0x%p\n", __PRETTY_FUNCTION__
, newsdispbitmap
, compdata
->screenbitmap
));
928 /* After Show we need Update for mirroring drivers */
929 if (compdata
->screenbitmap
)
931 OOP_GetAttr(compdata
->screenbitmap
, aHidd_BitMap_Width
, &w
);
932 OOP_GetAttr(compdata
->screenbitmap
, aHidd_BitMap_Height
, &h
);
933 HIDD_BM_UpdateRect(compdata
->screenbitmap
, 0, 0, w
, h
);
938 * (a) - disposing of oldcompositingbitmap needs to happen after mode switch
939 * since it could have been the current screenbitmap
941 if (oldcompositedbitmap
&& (oldcompositedbitmap
!= compdata
->fb
))
943 struct BitMap
*freebm
;
945 DTOGGLE(bug("[Compositor:%s] Disposing old working bitmap 0x%p\n", __PRETTY_FUNCTION__
, oldcompositedbitmap
));
947 OOP_GetAttr(oldcompositedbitmap
, aHidd_BitMap_BMStruct
, (IPTR
*)&freebm
);
953 HIDD_Gfx_DisposeBitMap(compdata
->gfx
, oldcompositedbitmap
);
958 compdata
->modeschanged
= FALSE
;
963 static VOID
HIDDCompositorPurgeBitMapStack(struct HIDDCompositorData
* compdata
)
965 struct StackBitMapNode
* curr
, * next
;
967 ForeachNodeSafe(&compdata
->bitmapstack
, curr
, next
)
969 if (curr
->screenregion
)
970 DisposeRegion(curr
->screenregion
);
972 FreeMem(curr
, sizeof(struct StackBitMapNode
));
975 NEWLIST(&compdata
->bitmapstack
);
978 static void HIDDCompositorShowSingle(struct HIDDCompositorData
*compdata
, OOP_Object
*bm
)
980 /* Show the single top bitmap */
981 compdata
->topbitmap
= bm
;
982 compdata
->screenbitmap
= HIDD_Gfx_Show(compdata
->gfx
, bm
, fHidd_Gfx_Show_CopyBack
);
984 /* Dispose working bitmap (if any) */
985 if (compdata
->displaybitmap
)
987 /* Be careful with the framebuffer */
988 if (compdata
->displaybitmap
!= compdata
->fb
)
989 HIDD_Gfx_DisposeBitMap(compdata
->gfx
, compdata
->displaybitmap
);
991 /* This will deactivate us */
992 compdata
->displaybitmap
= NULL
;
996 /* Emergency error recovery function */
997 static void HIDDCompositorReset(struct HIDDCompositorData
*compdata
)
999 /* Purge bitmap stack */
1000 HIDDCompositorPurgeBitMapStack(compdata
);
1003 * Reset our internal state so that next BitMapStackChanged
1004 * causes complete reinitialization.
1006 compdata
->displaymode
= vHidd_ModeID_Invalid
;
1007 compdata
->screenbitmap
= NULL
;
1009 compdata
->flags
&= ~COMPSTATEF_HASALPHA
;
1012 VOID
CompositorParseConfig(struct HIDDCompositorData
*compdata
)
1014 struct RDArgs
*rdargs
;
1015 IPTR CompArgs
[NOOFARGS
] = { 0 };
1016 TEXT CompConfig
[1024];
1018 /* use default amiga-like capabailities */
1019 compdata
->capabilities
= COMPF_ABOVE
;
1021 rdargs
= AllocDosObjectTags(DOS_RDARGS
, TAG_END
);
1024 if (GetVar(COMPOSITOR_PREFS
, CompConfig
, 1024, GVF_GLOBAL_ONLY
) != -1)
1026 rdargs
->RDA_Source
.CS_Buffer
= CompConfig
;
1027 rdargs
->RDA_Source
.CS_Length
= strlen(rdargs
->RDA_Source
.CS_Buffer
);
1028 rdargs
->RDA_DAList
= (IPTR
)NULL
;
1029 rdargs
->RDA_Buffer
= NULL
;
1030 rdargs
->RDA_BufSiz
= 0;
1031 rdargs
->RDA_ExtHelp
= NULL
;
1032 rdargs
->RDA_Flags
= 0;
1034 if (ReadArgs(COMPOSITOR_PEFSTEMPLATE
, CompArgs
, rdargs
) != NULL
)
1036 if (CompArgs
[ARG_ABOVE
])
1037 compdata
->capabilities
|= COMPF_ABOVE
;
1039 compdata
->capabilities
&= ~COMPF_ABOVE
;
1041 if (CompArgs
[ARG_BELOW
])
1042 compdata
->capabilities
|= COMPF_BELOW
;
1044 compdata
->capabilities
&= ~COMPF_BELOW
;
1046 if (CompArgs
[ARG_LEFT
])
1047 compdata
->capabilities
|= COMPF_LEFT
;
1049 compdata
->capabilities
&= ~COMPF_LEFT
;
1051 if (CompArgs
[ARG_RIGHT
])
1052 compdata
->capabilities
|= COMPF_RIGHT
;
1054 compdata
->capabilities
&= ~COMPF_RIGHT
;
1056 if (CompArgs
[ARG_ALPHA
])
1057 compdata
->capabilities
|= COMPF_ALPHA
;
1059 compdata
->capabilities
&= ~COMPF_ALPHA
;
1064 FreeDosObject(DOS_RDARGS
, rdargs
);
1068 AROS_UFH3(void, CompositorDefaultBackFillFunc
,
1069 AROS_UFHA(struct Hook
* , h
, A0
),
1070 AROS_UFHA(struct BitMap
* , bm
, A2
),
1071 AROS_UFHA(struct HIDD_BackFillHookMsg
* , msg
, A1
))
1075 struct HIDDCompositorData
*compdata
= h
->h_Data
;
1077 D(bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__
, compdata
));
1079 HIDDCompositorFillRect(compdata
, HIDD_BM_OBJ(bm
), msg
->bounds
->MinX
, msg
->bounds
->MinY
, msg
->bounds
->MaxX
, msg
->bounds
->MaxY
);
1084 /* PUBLIC METHODS */
1085 OOP_Object
*METHOD(Compositor
, Root
, New
)
1087 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
1091 OOP_MethodID disposemid
;
1092 struct HIDDCompositorData
*compdata
= OOP_INST_DATA(cl
, o
);
1094 D(bug("[%s] Compositor @ 0x%p, data @ 0x%p\n", __PRETTY_FUNCTION__
, o
, compdata
));
1096 CompositorParseConfig(compdata
);
1098 compdata
->capabilities
= (ULONG
)GetTagData(aHidd_Compositor_State
, compdata
->capabilities
, msg
->attrList
);
1100 D(bug("[%s] Compositor Capabilities: %08lx\n", __PRETTY_FUNCTION__
, compdata
->capabilities
));
1102 compdata
->displaymode
= vHidd_ModeID_Invalid
;
1104 NEWLIST(&compdata
->bitmapstack
);
1106 compdata
->defaultbackfill
.h_Entry
= (HOOKFUNC
)AROS_ASMSYMNAME(CompositorDefaultBackFillFunc
);
1107 compdata
->defaultbackfill
.h_Data
= compdata
;
1108 compdata
->backfillhook
= &compdata
->defaultbackfill
;
1110 InitSemaphore(&compdata
->semaphore
);
1112 compdata
->displayid
= (ULONG
)GetTagData(aHidd_Compositor_DisplayID
, 0, msg
->attrList
);
1113 compdata
->gfx
= (OOP_Object
*)GetTagData(aHidd_Compositor_GfxHidd
, 0, msg
->attrList
);
1114 compdata
->fb
= (OOP_Object
*)GetTagData(aHidd_Compositor_FrameBuffer
, 0, msg
->attrList
);
1116 D(bug("[%s] DisplayID %08lx for Gfx Driver @ 0x%p\n", __PRETTY_FUNCTION__
, compdata
->displayid
, compdata
->gfx
));
1118 GfxBase
= (APTR
)OpenLibrary("graphics.library", 41);
1119 IntuitionBase
= (APTR
)OpenLibrary("intuition.library", 50);
1121 /* GfxHidd is mandatory */
1122 if ((compdata
->GraphicsBase
) && (compdata
->gfx
!= NULL
))
1124 /* Create GC object that will be used for drawing operations */
1125 compdata
->gc
= HIDD_Gfx_NewGC(compdata
->gfx
, NULL
);
1127 D(bug("[%s] Compositor GC @ %p\n", __PRETTY_FUNCTION__
, compdata
->gc
));
1129 if ((compdata
->gfx
) && (compdata
->gc
))
1133 /* Creation failed */
1134 disposemid
= OOP_GetMethodID(IID_Root
, moRoot_Dispose
);
1135 OOP_CoerceMethod(cl
, o
, &disposemid
);
1141 void METHOD(Compositor
, Root
, Dispose
)
1145 struct HIDDCompositorData
*compdata
= OOP_INST_DATA(cl
, o
);
1146 bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__
, compdata
);
1149 OOP_DoSuperMethod(cl
, o
, &msg
->mID
);
1152 VOID
METHOD(Compositor
, Root
, Get
)
1156 struct HIDDCompositorData
*compdata
= OOP_INST_DATA(cl
, o
);
1158 if (IS_COMPOSITOR_ATTR(msg
->attrID
, idx
))
1162 case aoHidd_Compositor_Capabilities
:
1164 *msg
->storage
= (IPTR
)CAPABILITY_FLAGS
;
1165 D(bug("[%s] Compositor Capabilities: %lx\n", __PRETTY_FUNCTION__
, *msg
->storage
));
1168 case aoHidd_Compositor_State
:
1170 *msg
->storage
= (IPTR
)(compdata
->capabilities
& CAPABILITY_FLAGS
);
1171 D(bug("[%s] Compositor State: %lx\n", __PRETTY_FUNCTION__
, compdata
->capabilities
));
1174 case aoHidd_Compositor_BackFillHook
:
1176 D(bug("[%s] BackFillHook: 0x%p\n", __PRETTY_FUNCTION__
, compdata
->backfillhook
));
1177 *msg
->storage
= (IPTR
)compdata
->backfillhook
;
1182 OOP_DoSuperMethod(cl
, o
, &msg
->mID
);
1185 VOID
METHOD(Compositor
, Root
, Set
)
1189 struct HIDDCompositorData
*compdata
= OOP_INST_DATA(cl
, o
);
1190 struct TagItem
*tag
, *tstate
= msg
->attrList
;
1192 while ((tag
= NextTagItem(&tstate
)))
1194 if (IS_COMPOSITOR_ATTR(tag
->ti_Tag
, idx
))
1198 case aoHidd_Compositor_State
:
1200 D(bug("[%s] Compositor Capabilities State: %lx -> ", __PRETTY_FUNCTION__
, compdata
->capabilities
));
1201 compdata
->capabilities
= (ULONG
)(tag
->ti_Data
& CAPABILITY_FLAGS
);
1202 D(bug("%lx\n", compdata
->capabilities
));
1205 case aoHidd_Compositor_BackFillHook
:
1209 D(bug("[%s] BackFillHook: 0x%p -> 0x%p\n", __PRETTY_FUNCTION__
, compdata
->backfillhook
, tag
->ti_Data
));
1210 compdata
->backfillhook
= (struct Hook
*)tag
->ti_Data
;
1214 D(bug("[%s] Default BackFillHook\n", __PRETTY_FUNCTION__
));
1215 compdata
->backfillhook
= &compdata
->defaultbackfill
;
1223 OOP_DoSuperMethod(cl
, o
, &msg
->mID
);
1226 OOP_Object
*METHOD(Compositor
, Hidd_Compositor
, BitMapStackChanged
)
1228 struct HIDD_ViewPortData
*vpdata
;
1229 struct HIDDCompositorData
*compdata
= OOP_INST_DATA(cl
, o
);
1230 struct StackBitMapNode
*n
;
1231 struct Screen
*bmScreen
;
1232 OOP_Object
*bmpxfmt
;
1234 BOOL newtop
= FALSE
;
1237 DSTACK(bug("[Compositor] %s: Top bitmap: 0x%lx\n", __PRETTY_FUNCTION__
, msg
->data
->Bitmap
));
1239 LOCK_COMPOSITOR_WRITE
1241 /* Free all items which are already on the list */
1242 HIDDCompositorPurgeBitMapStack(compdata
);
1248 DSTACK(bug("[Compositor] %s: No ViewPort specified\n", __PRETTY_FUNCTION__
));
1251 HIDDCompositorShowSingle(compdata
, NULL
);
1253 /* We know we are inactive after this */
1254 *msg
->active
= FALSE
;
1255 /* This can return NULL, it's okay */
1256 return compdata
->screenbitmap
;
1259 /* Copy bitmaps pointers to our stack */
1260 for (vpdata
= msg
->data
; vpdata
; vpdata
= vpdata
->Next
)
1262 n
= AllocMem(sizeof(struct StackBitMapNode
), MEMF_ANY
| MEMF_CLEAR
);
1267 * We need to reset own state and return NULL. graphics.library
1268 * falls back to no composition in this case.
1270 DSTACK(bug("[Compositor] %s: Error allocating StackBitMapNode!!!\n", __PRETTY_FUNCTION__
));
1276 DSTACK(bug("[Compositor] %s: ViewPort 0x%p, offset (%d, %d)\n", __PRETTY_FUNCTION__
, vpdata
->vpe
->ViewPort
, vpdata
->vpe
->ViewPort
->DxOffset
, vpdata
->vpe
->ViewPort
->DyOffset
));
1278 n
->bm
= vpdata
->Bitmap
;
1279 n
->sbmflags
= STACKNODEF_DISPLAYABLE
;
1280 n
->leftedge
= vpdata
->vpe
->ViewPort
->DxOffset
;
1281 n
->topedge
= vpdata
->vpe
->ViewPort
->DyOffset
;
1283 n
->screenregion
= NewRegion();
1285 if ((bmScreen
= HIDDCompositorFindBitMapScreen(compdata
, n
->bm
)) != NULL
)
1287 DSTACK(bug("[Compositor] %s: Screen @ 0x%p\n", __PRETTY_FUNCTION__
, bmScreen
));
1288 GetAttr(SA_CompositingFlags
, (Object
*)bmScreen
, &n
->sbmflags
);
1289 DSTACK(bug("[Compositor] %s: CompositingFlags %08x\n", __PRETTY_FUNCTION__
, n
->sbmflags
));
1290 n
->sbmflags
|= STACKNODEF_DISPLAYABLE
;
1291 if (n
->sbmflags
& COMPF_ALPHA
)
1293 GetAttr(SA_AlphaPreCompositHook
, (Object
*)bmScreen
, (IPTR
*)&n
->prealphacomphook
);
1294 DSTACK(bug("[Compositor] %s: Pre-AlphaComposit Hook @ 0x%p\n", __PRETTY_FUNCTION__
, n
->prealphacomphook
));
1298 if (n
->sbmflags
& COMPF_ALPHA
)
1300 bmpxfmt
= (OOP_Object
*)OOP_GET(n
->bm
, aHidd_BitMap_PixFmt
);
1301 bmstdfmt
= (int)OOP_GET(bmpxfmt
, aHidd_PixFmt_StdPixFmt
);
1302 DSTACK(bug("[Compositor] %s: Screen BitMap PixFmt %lx @ 0x%p\n", __PRETTY_FUNCTION__
, bmstdfmt
, bmpxfmt
));
1306 case vHidd_StdPixFmt_ARGB32
:
1307 case vHidd_StdPixFmt_BGRA32
:
1308 case vHidd_StdPixFmt_RGBA32
:
1309 case vHidd_StdPixFmt_ABGR32
:
1311 DSTACK(bug("[Compositor] %s: Screen BitMap has Alpha\n", __PRETTY_FUNCTION__
));
1313 compdata
->flags
|= COMPSTATEF_HASALPHA
;
1318 n
->sbmflags
&= ~COMPF_ALPHA
;
1324 if (!(n
->sbmflags
& COMPF_ALPHA
))
1326 if ((((BOOL
)OOP_GET(n
->bm
, aHidd_BitMap_Displayable
)) != TRUE
))
1327 n
->sbmflags
&= ~STACKNODEF_DISPLAYABLE
;
1329 AddTail((struct List
*)&compdata
->bitmapstack
, (struct Node
*)n
);
1332 /* Switch mode if needed */
1333 UpdateDisplayMode(compdata
);
1335 if (msg
->data
->Bitmap
!= compdata
->topbitmap
)
1337 /* Set the new pointer to top bitmap */
1338 compdata
->topbitmap
= msg
->data
->Bitmap
;
1345 * Validate bitmap offsets - they might not match the compositing rules taking
1346 * new displayedwidth/displayedheight values
1348 ForeachNode(&compdata
->bitmapstack
, n
)
1350 HIDDCompositorValidateBitMapPositionChange(n
->bm
, &n
->leftedge
, &n
->topedge
,
1351 compdata
->displayrect
.MaxX
+ 1, compdata
->displayrect
.MaxY
+ 1);
1352 DSTACK(bug("[Compositor] %s: Bitmap 0x%p, display size %d x %d, validated position (%ld, %ld)\n", __PRETTY_FUNCTION__
,
1353 n
->bm
, compdata
->displayrect
.MaxX
+ 1, compdata
->displayrect
.MaxY
+ 1,
1354 n
->leftedge
, n
->topedge
));
1357 /* Toogle compositing based on screen positions */
1358 ok
= HIDDCompositorToggleCompositing(compdata
, newtop
);
1364 HIDDCompositorReset(compdata
);
1365 HIDDCompositorShowSingle(compdata
, msg
->data
->Bitmap
);
1370 DSTACK(bug("[%s] Done, composited bitmap 0x%p\n", __PRETTY_FUNCTION__
, compdata
->displaybitmap
));
1372 /* Tell if the composition is active */
1373 *msg
->active
= compdata
->displaybitmap
? TRUE
: FALSE
;
1374 /* Return actually displayed bitmap */
1375 return compdata
->screenbitmap
;
1378 VOID
METHOD(Compositor
, Hidd_Compositor
, BitMapRectChanged
)
1380 struct HIDDCompositorData
*compdata
= OOP_INST_DATA(cl
, o
);
1381 OOP_Object
*renderTarget
;
1383 if (compdata
->displaybitmap
)
1385 /* Composition is active, handle redraw if the bitmap is on screen */
1386 struct StackBitMapNode
*n
;
1388 DUPDATE(bug("[%s] Bitmap 0x%p\n", __PRETTY_FUNCTION__
, msg
->bm
));
1390 LOCK_COMPOSITOR_READ
1392 if (compdata
->intermedbitmap
)
1393 renderTarget
= compdata
->intermedbitmap
;
1395 renderTarget
= compdata
->displaybitmap
;
1397 n
= HIDDCompositorFindBitMapStackNode(compdata
, msg
->bm
);
1398 if (n
&& (n
->sbmflags
& STACKNODEF_VISIBLE
))
1400 struct Rectangle srcrect
, dstandvisrect
;
1402 srcrect
.MinX
= n
->leftedge
+ msg
->x
;
1403 srcrect
.MinY
= n
->topedge
+ msg
->y
;
1404 srcrect
.MaxX
= srcrect
.MinX
+ msg
->width
- 1;
1405 srcrect
.MaxY
= srcrect
.MinY
+ msg
->height
- 1;
1406 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));
1408 DUPDATE(bug("[%s] Screen-relative rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__
, _RECT(srcrect
)));
1410 struct RegionRectangle
* srrect
= n
->screenregion
->RegionRectangle
;
1413 BOOL updateAlphaBmps
= FALSE
;
1415 dstandvisrect
.MinX
= srrect
->bounds
.MinX
+ n
->screenregion
->bounds
.MinX
;
1416 dstandvisrect
.MinY
= srrect
->bounds
.MinY
+ n
->screenregion
->bounds
.MinY
;
1417 dstandvisrect
.MaxX
= srrect
->bounds
.MaxX
+ n
->screenregion
->bounds
.MinX
;
1418 dstandvisrect
.MaxY
= srrect
->bounds
.MaxY
+ n
->screenregion
->bounds
.MinY
;
1420 if (AndRectRect(&srcrect
, &dstandvisrect
, &dstandvisrect
))
1422 /* Intersection is valid. Blit. */
1423 DUPDATE(bug("[%s] Clipped rect (%d, %d) - (%d, %d)\n", __PRETTY_FUNCTION__
, _RECT(dstandvisrect
)));
1425 if (!(n
->sbmflags
& COMPF_ALPHA
))
1427 if ((compdata
->alpharegion
) && (isRectInRegion(compdata
->alpharegion
, &dstandvisrect
)))
1429 DUPDATE(bug("[%s] ** Bitmap in Alpha Region!\n", __PRETTY_FUNCTION__
));
1430 updateAlphaBmps
= TRUE
;
1432 HIDDCompositorRedrawBitmap(compdata
, renderTarget
, n
, &dstandvisrect
);
1436 updateAlphaBmps
= FALSE
;
1437 HIDDCompositorRedrawVisibleRegions(compdata
, &dstandvisrect
);
1440 if (updateAlphaBmps
)
1441 HIDDCompositorRedrawAlphaRegions(compdata
, &dstandvisrect
);
1443 if (renderTarget
!= compdata
->displaybitmap
)
1445 HIDD_Gfx_CopyBox(compdata
->gfx
, renderTarget
,
1446 dstandvisrect
.MinX
, dstandvisrect
.MinY
,
1447 compdata
->displaybitmap
,
1448 dstandvisrect
.MinX
, dstandvisrect
.MinY
,
1449 dstandvisrect
.MaxX
- dstandvisrect
.MinX
+ 1,
1450 dstandvisrect
.MaxY
- dstandvisrect
.MinY
+ 1,
1454 HIDD_BM_UpdateRect(compdata
->displaybitmap
,
1455 dstandvisrect
.MinX
, dstandvisrect
.MinY
,
1456 dstandvisrect
.MaxX
- dstandvisrect
.MinX
+ 1,
1457 dstandvisrect
.MaxY
- dstandvisrect
.MinY
+ 1);
1459 srrect
= srrect
->Next
;
1465 DUPDATE(bug("[%s] Done\n", __PRETTY_FUNCTION__
));
1469 /* In order to speed things up, we handle passthrough ourselves here. */
1470 HIDD_BM_UpdateRect(msg
->bm
, msg
->x
, msg
->y
, msg
->width
, msg
->height
);
1474 IPTR
METHOD(Compositor
, Hidd_Compositor
, BitMapPositionChange
)
1476 struct HIDDCompositorData
*compdata
= OOP_INST_DATA(cl
, o
);
1477 struct StackBitMapNode
*n
;
1478 IPTR disp_width
, disp_height
;
1480 LOCK_COMPOSITOR_READ
1482 n
= HIDDCompositorFindBitMapStackNode(compdata
, msg
->bm
);
1485 /* The bitmap is on display. Validate against screen size */
1486 disp_width
= compdata
->displayrect
.MaxX
+ 1;
1487 disp_height
= compdata
->displayrect
.MaxY
+ 1;
1491 /* The bitmap is not displayed yet. Validate against its own ModeID size. */
1492 HIDDT_ModeID modeid
= vHidd_ModeID_Invalid
;
1493 OOP_Object
*bmfriend
, *sync
, *pf
;
1495 OOP_GetAttr(msg
->bm
, aHidd_BitMap_ModeID
, &modeid
);
1497 if ((modeid
== vHidd_ModeID_Invalid
) && (OOP_GET(msg
->bm
, aHidd_BitMap_Compositable
)))
1499 OOP_GetAttr(msg
->bm
, aHidd_BitMap_Friend
, (IPTR
*)&bmfriend
);
1501 OOP_GetAttr(bmfriend
, aHidd_BitMap_ModeID
, &modeid
);
1504 if (modeid
== vHidd_ModeID_Invalid
)
1507 * Nondisplayable bitmaps don't scroll.
1508 * In fact they simply can't get in here because MakeVPort() performs the validation.
1509 * But who knows what bug can slip into someone's software...
1515 HIDD_Gfx_GetMode(compdata
->gfx
, modeid
, &sync
, &pf
);
1516 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &disp_width
);
1517 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &disp_height
);
1520 DMOVE(bug("[%s] Validating bitmap 0x%p, position (%ld, %ld), limits %ld x %ld\n", __PRETTY_FUNCTION__
,
1521 msg
->bm
, *msg
->newxoffset
, *msg
->newyoffset
, disp_width
, disp_height
));
1523 HIDDCompositorValidateBitMapPositionChange(msg
->bm
, msg
->newxoffset
, msg
->newyoffset
,
1524 disp_width
, disp_height
);
1526 DMOVE(bug("[%s] Validated position (%ld, %ld)\n", __PRETTY_FUNCTION__
, *msg
->newxoffset
, *msg
->newyoffset
));
1528 if (n
&& ((*msg
->newxoffset
!= n
->leftedge
) || (*msg
->newyoffset
!= n
->topedge
)))
1530 DMOVE(bug("[%s] Old position (%ld, %ld)\n", __PRETTY_FUNCTION__
, n
->leftedge
, n
->topedge
));
1532 /* Reflect the change if it happened */
1533 n
->leftedge
= *msg
->newxoffset
;
1534 n
->topedge
= *msg
->newyoffset
;
1536 if (compdata
->topbitmap
== msg
->bm
)
1539 * If this is the frontmost bitmap, we may want to toggle compositing,
1540 * if it starts/stops covering the whole screen at one point.
1541 * We don't need to call HIDDCompositorRedrawVisibleRegions() here because
1542 * HIDDCompositorToggleCompositing() does this itself, for improved
1543 * visual appearance.
1545 HIDDCompositorToggleCompositing(compdata
, FALSE
);
1548 HIDDCompositorRedrawVisibleRegions(compdata
, NULL
);
1553 /* Return active state */
1554 return compdata
->displaybitmap
? TRUE
: FALSE
;
1557 IPTR
METHOD(Compositor
, Hidd_Compositor
, BitMapValidate
)
1559 if (IS_HIDD_BM(msg
->bm
))
1565 IPTR
METHOD(Compositor
, Hidd_Compositor
, BitMapEnable
)
1567 if (IS_HIDD_BM(msg
->bm
))
1569 if (!(OOP_GET(HIDD_BM_OBJ(msg
->bm
), aHidd_BitMap_Displayable
)))
1571 struct TagItem composittags
[] = {
1572 {aHidd_BitMap_Compositable
, TRUE
},
1576 D(bug("[GfxCompositor]: Marking BitMap 0x%lx as Compositable\n", msg
->bm
));
1577 OOP_SetAttrs(HIDD_BM_OBJ(msg
->bm
), composittags
);
1585 #define NUM_Compositor_Root_METHODS 4
1587 static const struct OOP_MethodDescr Compositor_Root_descr
[] =
1589 {(OOP_MethodFunc
)Compositor__Root__New
, moRoot_New
},
1590 {(OOP_MethodFunc
)Compositor__Root__Dispose
, moRoot_Dispose
},
1591 {(OOP_MethodFunc
)Compositor__Root__Get
, moRoot_Get
},
1592 {(OOP_MethodFunc
)Compositor__Root__Set
, moRoot_Set
},
1596 #define NUM_Compositor_Hidd_Compositor_METHODS 5
1598 static const struct OOP_MethodDescr Compositor_Hidd_Compositor_descr
[] =
1600 {(OOP_MethodFunc
)Compositor__Hidd_Compositor__BitMapStackChanged
, moHidd_Compositor_BitMapStackChanged
},
1601 {(OOP_MethodFunc
)Compositor__Hidd_Compositor__BitMapRectChanged
, moHidd_Compositor_BitMapRectChanged
},
1602 {(OOP_MethodFunc
)Compositor__Hidd_Compositor__BitMapPositionChange
, moHidd_Compositor_BitMapPositionChange
},
1603 {(OOP_MethodFunc
)Compositor__Hidd_Compositor__BitMapValidate
, moHidd_Compositor_BitMapValidate
},
1604 {(OOP_MethodFunc
)Compositor__Hidd_Compositor__BitMapEnable
, moHidd_Compositor_BitMapEnable
},
1608 const struct OOP_InterfaceDescr Compositor_ifdescr
[] =
1610 {Compositor_Root_descr
, IID_Root
, NUM_Compositor_Root_METHODS
},
1611 {Compositor_Hidd_Compositor_descr
, IID_Hidd_Compositor
, NUM_Compositor_Hidd_Compositor_METHODS
},