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] 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
)));
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
->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 },
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
,
478 rect
->MinX
, rect
->MinY
, blitwidth
, blitheight
,
484 ULONG width
, height
, banksize
, memsize
;
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
) &&
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
;
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
));
572 /* Recalculate visible regions */
573 HIDDCompositorRecalculateVisibleRegions(compdata
);
576 if ((compdata
->flags
& COMPSTATEF_HASALPHA
) && (compdata
->intermedbitmap
))
577 renderTarget
= compdata
->intermedbitmap
;
579 if ((dispvisregion
= NewRegion()) != NULL
)
582 OrRectRegion(dispvisregion
, drawrect
);
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
)) &&
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
;
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
;
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
)));
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,
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);
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,
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
696 cb = composited bitmap
697 fs = covers full screen
698 nfs = not covers full screen
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
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
)))
787 if ((topnode
->leftedge
> 0) || (bmtags
[0].ti_Data
> OOP_GET(topnode
->bm
, aHidd_BitMap_Width
)))
790 if (topnode
->sbmflags
& COMPF_ALPHA
)
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__
));
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
;
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
)
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
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.
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
);
917 compdata
->modeschanged
= FALSE
;
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
);
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
;
998 compdata
->capabilities
&= ~COMPF_ABOVE
;
1000 if (CompArgs
[ARG_BELOW
])
1001 compdata
->capabilities
|= COMPF_BELOW
;
1003 compdata
->capabilities
&= ~COMPF_BELOW
;
1005 if (CompArgs
[ARG_LEFT
])
1006 compdata
->capabilities
|= COMPF_LEFT
;
1008 compdata
->capabilities
&= ~COMPF_LEFT
;
1010 if (CompArgs
[ARG_RIGHT
])
1011 compdata
->capabilities
|= COMPF_RIGHT
;
1013 compdata
->capabilities
&= ~COMPF_RIGHT
;
1015 if (CompArgs
[ARG_ALPHA
])
1016 compdata
->capabilities
|= COMPF_ALPHA
;
1018 compdata
->capabilities
&= ~COMPF_ALPHA
;
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
))
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
);
1043 /* PUBLIC METHODS */
1044 OOP_Object
*METHOD(Compositor
, Root
, New
)
1046 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
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
))
1089 /* Creation failed */
1090 disposemid
= OOP_GetMethodID(IID_Root
, moRoot_Dispose
);
1091 OOP_CoerceMethod(cl
, o
, &disposemid
);
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
)
1112 struct HIDDCompositorData
*compdata
= OOP_INST_DATA(cl
, o
);
1114 if (IS_COMPOSITOR_ATTR(msg
->attrID
, idx
))
1118 case aoHidd_Compositor_Capabilities
:
1120 *msg
->storage
= (IPTR
)CAPABILITY_FLAGS
;
1121 D(bug("[%s] Compositor Capabilities: %lx\n", __PRETTY_FUNCTION__
, *msg
->storage
));
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
));
1130 case aoHidd_Compositor_BackFillHook
:
1132 D(bug("[%s] BackFillHook: 0x%p\n", __PRETTY_FUNCTION__
, compdata
->backfillhook
));
1133 *msg
->storage
= (IPTR
)compdata
->backfillhook
;
1138 OOP_DoSuperMethod(cl
, o
, &msg
->mID
);
1141 VOID
METHOD(Compositor
, Root
, Set
)
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
))
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
));
1161 case aoHidd_Compositor_BackFillHook
:
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
;
1170 D(bug("[%s] Default BackFillHook\n", __PRETTY_FUNCTION__
));
1171 compdata
->backfillhook
= &compdata
->defaultbackfill
;
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
;
1190 BOOL newtop
= FALSE
;
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
);
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
);
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__
));
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
));
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
;
1267 n
->sbmflags
&= ~COMPF_ALPHA
;
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
;
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
);
1313 HIDDCompositorReset(compdata
);
1314 HIDDCompositorShowSingle(compdata
, msg
->data
->Bitmap
);
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
;
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
;
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
);
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,
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
;
1414 DUPDATE(bug("[%s] Done\n", __PRETTY_FUNCTION__
));
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
);
1434 /* The bitmap is on display. Validate against screen size */
1435 disp_width
= compdata
->displayrect
.MaxX
+ 1;
1436 disp_height
= compdata
->displayrect
.MaxY
+ 1;
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
);
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...
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
);
1497 HIDDCompositorRedrawVisibleRegions(compdata
, NULL
);
1502 /* Return active state */
1503 return compdata
->displaybitmap
? TRUE
: FALSE
;
1506 IPTR
METHOD(Compositor
, Hidd_Compositor
, BitMapValidate
)
1508 if (IS_HIDD_BM(msg
->bm
))
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
},
1525 D(bug("[GfxCompositor]: Marking BitMap 0x%lx as Compositable\n", msg
->bm
));
1526 OOP_SetAttrs(HIDD_BM_OBJ(msg
->bm
), composittags
);
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
},
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
},
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
},