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 struct RegionRectangle *srrect;
190 tmprect.MinX = n->leftedge;
191 tmprect.MaxX = n->leftedge + OOP_GET(n->bm, aHidd_BitMap_Width) - 1;
192 tmprect.MinY = n->topedge;
193 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
195 DRECALC(bug("[Compositor:%s] Screen Rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
197 OrRectRegion(n->screenregion, &tmprect); // Start with the Screen's dimensions ..
198 AndRegionRegion(dispvisregion, n->screenregion); // And adjust for the "Display"
200 if ((srrect = n->screenregion->RegionRectangle) != NULL)
204 tmprect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
205 tmprect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
206 tmprect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
207 tmprect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
209 if (!(n->sbmflags & COMPF_ALPHA))
210 ClearRectRegion(dispvisregion, &tmprect);
213 compdata->flags |= COMPSTATEF_HASALPHA;
214 if (!(compdata->alpharegion))
215 compdata->alpharegion = NewRegion();
217 OrRectRegion(compdata->alpharegion, &tmprect);
219 srrect = srrect->Next;
222 if (!(compdata->capabilities & COMPF_ABOVE) && !(n->sbmflags & COMPF_ABOVE))
224 tmprect.MinX = compdata->displayrect.MinX;
225 tmprect.MaxX = compdata->displayrect.MaxX;
226 tmprect.MinY = compdata->displayrect.MinY;
227 tmprect.MaxY = n->topedge - 1;
228 ClearRectRegion(dispvisregion, &tmprect);
230 if (!(compdata->capabilities & COMPF_BELOW) && !(n->sbmflags & COMPF_BELOW))
232 tmprect.MinX = compdata->displayrect.MinX;
233 tmprect.MaxX = compdata->displayrect.MaxX;
234 tmprect.MinY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height);
235 tmprect.MaxY = compdata->displayrect.MaxY;
236 ClearRectRegion(dispvisregion, &tmprect);
238 if (!(compdata->capabilities & COMPF_LEFT) && !(n->sbmflags & COMPF_LEFT))
240 tmprect.MinX = compdata->displayrect.MinX;
241 tmprect.MaxX = n->leftedge - 1;
242 tmprect.MinY = n->topedge;
243 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
244 ClearRectRegion(dispvisregion, &tmprect);
246 if (!(compdata->capabilities & COMPF_RIGHT) && !(n->sbmflags & COMPF_RIGHT))
248 tmprect.MinX = n->leftedge + OOP_GET(n->bm, aHidd_BitMap_Width);
249 tmprect.MaxX = compdata->displayrect.MaxX;
250 tmprect.MinY = n->topedge;
251 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
252 ClearRectRegion(dispvisregion, &tmprect);
254 n->sbmflags |= STACKNODEF_VISIBLE;
257 DRECALC(bug("[Compositor:%s] HiddBitmap 0x%p, topedge %d, visible %d\n", __PRETTY_FUNCTION__,
258 n->bm, n->topedge, (n->sbmflags & STACKNODEF_VISIBLE)));
262 DRECALC(bug("[Compositor:%s] Failed to create Screen Region\n", __PRETTY_FUNCTION__));
265 DisposeRegion(dispvisregion);
266 if (compdata->flags != oldflags)
268 ULONG newflags = (~oldflags) & compdata->flags;
269 DRECALC(bug("[Compositor:%s] Newly set flags %08x\n", __PRETTY_FUNCTION__, newflags));
270 if ((!(newflags & COMPSTATEF_HASALPHA)) && (oldflags & COMPSTATEF_HASALPHA))
272 DRECALC(bug("[Compositor:%s] Alpha removed\n", __PRETTY_FUNCTION__));
273 if (compdata->alpharegion)
274 DisposeRegion(compdata->alpharegion);
276 if (compdata->intermedbitmap)
277 HIDD_Gfx_DisposeBitMap(compdata->gfx, compdata->intermedbitmap);
279 compdata->alpharegion = NULL;
280 compdata->intermedbitmap = NULL;
286 DRECALC(bug("[Compositor:%s] Failed to create Display Region\n", __PRETTY_FUNCTION__));
290 static HIDDT_ModeID FindBestHiddMode(struct HIDDCompositorData *compdata, ULONG width, ULONG height, ULONG depth, ULONG *res_depth)
292 HIDDT_ModeID mode = vHidd_ModeID_Invalid;
293 OOP_Object *sync, *pf;
296 ULONG found_delta = -1;
297 ULONG found_width = 0;
298 ULONG found_height = 0;
299 ULONG found_depth = 0;
300 HIDDT_ModeID found_mode = vHidd_ModeID_Invalid;
302 DMODE(bug("[%s] Finding best match for mode %ux%ux%u\n", __PRETTY_FUNCTION__, width, height, depth));
304 while ((mode = HIDD_Gfx_NextModeID(compdata->gfx, mode, &sync, &pf)) != vHidd_ModeID_Invalid)
308 DMODE(bug("[%s] Checking mode 0x%08X... ", __PRETTY_FUNCTION__, mode));
309 if (OOP_GET(pf, aHidd_PixFmt_ColorModel) != vHidd_ColorModel_TrueColor)
311 DMODE(bug("Skipped (not truecolor)\n"));
315 OOP_GetAttr(sync, aHidd_Sync_HDisp, &w);
316 OOP_GetAttr(sync, aHidd_Sync_VDisp, &h);
317 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &d);
319 dw = w > width ? w - width : w < width ? width - w : 1;
320 dh = h > height ? h - height : h < height ? height - h : 1;
324 if (delta < found_delta)
326 /* If mode resolution is closer to the needed one, we've got a better match */
333 else if (delta == found_delta)
335 /* If resolution is the same as that of current candidate mode, we can look at depth. */
336 if (found_depth > depth)
339 * Candidate mode if deeper than requested. We can supersede it with another mode
340 * of smaller depth, but which still matches our request.
342 if ((d < found_depth) && (d >= depth))
345 else if (found_depth < depth)
348 * We want better depth than current candidate.
349 * In this case anything deeper will do.
359 * Mode with the same delta, but larger depth, may supersede
360 * previous mode, if we prefer deeper ones.
362 DMODE(bug("Selected (%ldx%ldx%ld, delta = %u)", w, h, d, delta));
369 /* Store mode information */
370 compdata->displayrect.MinX = 0;
371 compdata->displayrect.MinY = 0;
372 compdata->displayrect.MaxX = found_width - 1;
373 compdata->displayrect.MaxY = found_height - 1;
374 *res_depth = found_depth;
379 static void UpdateDisplayMode(struct HIDDCompositorData *compdata)
381 struct StackBitMapNode *n;
382 IPTR modeid, width = 0, height = 0, depth;
383 OOP_Object *sync, *pf;
384 UBYTE comp_depth = 16;
387 DSTACK(bug("[Compositor] %s()\n", __PRETTY_FUNCTION__));
390 * Examine all bitmaps in the stack to figure out the needed depth.
391 * We need a maximum depth of all depths in order to keep correct colors.
392 * But not less than 16 bits, because we can't compose on a LUT screen.
394 * If a LUT bitmap is present in the stack (depth < 9), we request truecolor
395 * screen for better color presentation.
397 * We examine bitmaps in reverse order, in this case 'sync' will hold
398 * information about the top bitmap when we exit the loop.
399 * Size of our composited mode needs to be as close as possible to that one.
401 for (n = (struct StackBitMapNode *)compdata->bitmapstack.mlh_TailPred;
402 n->n.mln_Pred; n = (struct StackBitMapNode *)n->n.mln_Pred)
404 if ((!(n->sbmflags & COMPF_ALPHA)) && (n->sbmflags & STACKNODEF_DISPLAYABLE))
406 OOP_GetAttr(n->bm, aHidd_BitMap_ModeID, &modeid);
407 HIDD_Gfx_GetMode(compdata->gfx, modeid, &sync, &pf);
409 if (OOP_GET(pf, aHidd_PixFmt_ColorModel) == vHidd_ColorModel_TrueColor)
411 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
412 if (depth > comp_depth)
418 * If we have a LUT bitmap on stack, we request 24-bit screen
419 * for better color transfer.
426 IPTR curwidth, curheight;
427 OOP_GetAttr(n->bm, aHidd_BitMap_Width, &curwidth);
428 OOP_GetAttr(n->bm, aHidd_BitMap_Height, &curheight);
429 if (curwidth > width)
431 if (curheight > height)
438 /* Get the needed size */
439 OOP_GetAttr(sync, aHidd_Sync_HDisp, &width);
440 OOP_GetAttr(sync, aHidd_Sync_VDisp, &height);
443 DSTACK(bug("[%s] Prefered mode %ldx%ldx%d\n", __PRETTY_FUNCTION__, width, height, comp_depth));
445 modeid = FindBestHiddMode(compdata, width, height, comp_depth, &found_depth);
446 DSTACK(bug("[%s] Composition Display ModeID 0x%08X [current 0x%08X]\n", __PRETTY_FUNCTION__, modeid, compdata->displaymode));
448 if (modeid != compdata->displaymode)
450 /* The mode is different. Need to prepare information needed for compositing */
451 struct TagItem gctags[] =
453 { aHidd_GC_Foreground, 0x99999999 },
457 /* Signal mode change */
458 compdata->displaymode = modeid;
459 compdata->displaydepth = comp_depth;
460 compdata->modeschanged = TRUE;
462 /* Get gray foregound */
463 if (found_depth < 24)
464 gctags[0].ti_Data = 0x9492;
466 OOP_SetAttrs(compdata->gc, gctags);
470 static inline void HIDDCompositorRedrawBitmap(struct HIDDCompositorData *compdata, OOP_Object *renderTarget, struct StackBitMapNode *n, struct Rectangle *rect)
472 /* The given rectangle is already in screen coordinate system here */
473 ULONG blitwidth = rect->MaxX - rect->MinX + 1;
474 ULONG blitheight = rect->MaxY - rect->MinY + 1;
476 DREDRAWBM(bug("[Compositor:%s] Redraw HiddBitMap 0x%p, Rect[%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, n->bm,
477 rect->MinX, rect->MinY, rect->MaxX, rect->MaxY));
479 if (!(n->sbmflags & COMPF_ALPHA))
481 DREDRAWBM(bug("[Compositor:%s] Blitting %dx%d [from %d, %d]\n", __PRETTY_FUNCTION__, blitwidth, blitheight,
482 rect->MinX - n->leftedge, rect->MinY - n->topedge));
484 HIDD_Gfx_CopyBox(compdata->gfx, n->bm,
485 /* Transform to source bitmap coord system */
486 rect->MinX - n->leftedge, rect->MinY - n->topedge,
488 rect->MinX, rect->MinY, blitwidth, blitheight,
494 ULONG width, height, banksize, memsize;
497 DREDRAWBM(bug("[Compositor:%s] AlphaBlending %dx%d @ %d,%d to %d,%d\n", __PRETTY_FUNCTION__,
498 blitwidth, blitheight,
499 rect->MinX - n->leftedge, rect->MinY - n->topedge, rect->MinX, rect->MinY));
501 if (HIDD_BM_ObtainDirectAccess(n->bm, &baseaddress, &width, &height, &banksize, &memsize))
503 DREDRAWBM(bug("[Compositor:%s] Alpha baseaddress @ 0x%p\n", __PRETTY_FUNCTION__, baseaddress));
504 OOP_GetAttr(n->bm, aHidd_BitMap_BytesPerRow, &modulo);
505 HIDD_BM_PutAlphaImage(renderTarget, compdata->gfx , baseaddress + ((rect->MinY - n->topedge) * modulo) + ((rect->MinX - n->leftedge) << 2), modulo,
506 rect->MinX, rect->MinY, blitwidth, blitheight);
507 HIDD_BM_ReleaseDirectAccess(n->bm);
512 static inline void HIDDCompositorFillRect(struct HIDDCompositorData *compdata, OOP_Object *renderTarget, ULONG MinX, ULONG MinY, ULONG MaxX, ULONG MaxY)
514 DREDRAWSCR(bug("[Compositor:%s] Filling [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
515 MinX, MinY, MaxX, MaxY));
517 HIDD_BM_FillRect(renderTarget, compdata->gc,
518 MinX, MinY, MaxX, MaxY);
522 static VOID HIDDCompositorRedrawAlphaRegions(struct HIDDCompositorData *compdata, struct Rectangle *drawrect)
524 OOP_Object *renderTarget = compdata->displaybitmap;
525 struct Rectangle alpharect;
526 struct StackBitMapNode *n;
527 struct BitMap *backbm;
529 if (compdata->intermedbitmap)
530 renderTarget = compdata->intermedbitmap;
532 DREDRAWSCR(if (drawrect){ bug("[Compositor:%s] Rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT((*drawrect))); })
534 OOP_GetAttr(renderTarget, aHidd_BitMap_BMStruct, (IPTR *)&backbm);
536 // Alpha Regions are drawn in reverse order incase they overlap..
537 for (n = (struct StackBitMapNode *)compdata->bitmapstack.mlh_TailPred;
538 n->n.mln_Pred; n = (struct StackBitMapNode *)n->n.mln_Pred)
540 if ((n->sbmflags & STACKNODEF_VISIBLE) &&
541 (n->sbmflags & COMPF_ALPHA) &&
544 struct RegionRectangle *srrect;
546 DREDRAWSCR(bug("[Compositor:%s] Alpha Screen Region @ 0x%p HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__,
547 n->screenregion, n->bm));
549 if ((srrect = n->screenregion->RegionRectangle) != NULL)
551 DREDRAWSCR(bug("[Compositor:%s] Compositing Visible Alpha Regions..\n", __PRETTY_FUNCTION__));
554 alpharect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
555 alpharect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
556 alpharect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
557 alpharect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
559 if (!(drawrect) || AndRectRect(drawrect, &alpharect, &alpharect))
561 DREDRAWSCR(bug("[Compositor:%s] Alpha-Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(alpharect)));
563 if ((n->prealphacomphook) && (backbm != NULL))
565 struct HIDD_BackFillHookMsg preprocessmsg;
566 preprocessmsg.bounds = &alpharect;
567 preprocessmsg.offsetx = 0;
568 preprocessmsg.offsety = 0;
569 CallHookPkt(n->prealphacomphook, backbm, &preprocessmsg);
572 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &alpharect);
573 if (renderTarget == compdata->displaybitmap)
574 HIDD_BM_UpdateRect(compdata->displaybitmap,
575 alpharect.MinX, alpharect.MinY,
576 alpharect.MaxX - alpharect.MinX + 1,
577 alpharect.MaxY - alpharect.MinY + 1);
579 srrect = srrect->Next;
586 static VOID HIDDCompositorRedrawVisibleRegions(struct HIDDCompositorData *compdata, struct Rectangle *drawrect)
588 OOP_Object *renderTarget = compdata->displaybitmap;
589 struct Region *dispvisregion = NULL;
590 struct Rectangle tmprect;
591 struct BitMap *clearbm;
592 struct StackBitMapNode *n;
594 DREDRAWSCR(bug("[Compositor:%s] Redrawing Display (GfxBase @ 0x%p)\n", __PRETTY_FUNCTION__, GfxBase));
598 /* Recalculate visible regions */
599 HIDDCompositorRecalculateVisibleRegions(compdata);
602 if ((compdata->flags & COMPSTATEF_HASALPHA) && (compdata->intermedbitmap))
603 renderTarget = compdata->intermedbitmap;
605 if ((dispvisregion = NewRegion()) != NULL)
608 OrRectRegion(dispvisregion, drawrect);
610 OrRectRegion(dispvisregion, &compdata->displayrect);
612 DRECALC(bug("[Compositor:%s] Display rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(compdata->displayrect)));
614 ForeachNode(&compdata->bitmapstack, n)
616 if ((n->sbmflags & STACKNODEF_VISIBLE) &&
617 (!(n->sbmflags & COMPF_ALPHA)) &&
620 struct RegionRectangle * srrect;
621 DREDRAWSCR(bug("[Compositor:%s] Screen Region @ 0x%p HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__,
622 n->screenregion, n->bm));
624 // Render the visable regions ..
625 if ((srrect = n->screenregion->RegionRectangle) != NULL)
627 DREDRAWSCR(bug("[Compositor:%s] Redrawing Visible Screen Regions..\n", __PRETTY_FUNCTION__));
630 tmprect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
631 tmprect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
632 tmprect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
633 tmprect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
635 if (!(drawrect) || AndRectRect(drawrect, &tmprect, &tmprect))
637 DREDRAWSCR(bug("[Compositor:%s] Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
639 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &tmprect);
640 if (renderTarget == compdata->displaybitmap)
641 HIDD_BM_UpdateRect(compdata->displaybitmap,
642 tmprect.MinX, tmprect.MinY,
643 tmprect.MaxX - tmprect.MinX + 1,
644 tmprect.MaxY - tmprect.MinY + 1);
646 srrect = srrect->Next;
648 ClearRegionRegion(n->screenregion, dispvisregion);
652 OOP_GetAttr(renderTarget, aHidd_BitMap_BMStruct, (IPTR *)&clearbm);
654 struct RegionRectangle * dispclrrect = dispvisregion->RegionRectangle;
657 struct HIDD_BackFillHookMsg clearmsg;
659 tmprect.MinX = dispclrrect->bounds.MinX + dispvisregion->bounds.MinX;
660 tmprect.MinY = dispclrrect->bounds.MinY + dispvisregion->bounds.MinY;
661 tmprect.MaxX = dispclrrect->bounds.MaxX + dispvisregion->bounds.MinX;
662 tmprect.MaxY = dispclrrect->bounds.MaxY + dispvisregion->bounds.MinY;
664 if (!(drawrect) || AndRectRect(drawrect, &tmprect, &tmprect))
666 DREDRAWSCR(bug("[Compositor:%s] Render Display Void Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
670 clearmsg.bounds = &tmprect;
671 clearmsg.offsetx = 0;
672 clearmsg.offsety = 0;
673 CallHookPkt(compdata->backfillhook, clearbm, &clearmsg);
676 if (renderTarget == compdata->displaybitmap)
677 HIDD_BM_UpdateRect(compdata->displaybitmap,
678 tmprect.MinX, tmprect.MinY,
679 tmprect.MaxX - tmprect.MinX + 1,
680 tmprect.MaxY - tmprect.MinY + 1);
682 dispclrrect = dispclrrect->Next;
684 if (compdata->flags & COMPSTATEF_HASALPHA)
686 HIDDCompositorRedrawAlphaRegions(compdata, drawrect);
688 DisposeRegion(dispvisregion);
690 if (renderTarget != compdata->displaybitmap)
692 DREDRAWSCR(bug("[Compositor:%s] Copying Alpha Intermediary BitMap\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
695 HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
696 compdata->displayrect.MinX, compdata->displayrect.MinY,
697 compdata->displaybitmap,
698 compdata->displayrect.MinX, compdata->displayrect.MinY,
699 compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
700 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
702 HIDD_BM_UpdateRect(compdata->displaybitmap,
703 compdata->displayrect.MinX, compdata->displayrect.MinY,
704 compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
705 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1);
709 HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
710 drawrect->MinX, drawrect->MinY,
711 compdata->displaybitmap,
712 drawrect->MinX, drawrect->MinY,
713 drawrect->MaxX - drawrect->MinX + 1,
714 drawrect->MaxY - drawrect->MinY + 1,
716 HIDD_BM_UpdateRect(compdata->displaybitmap,
717 drawrect->MinX, drawrect->MinY,
718 drawrect->MaxX - drawrect->MinX + 1,
719 drawrect->MaxY - drawrect->MinY + 1);
726 There are several cases that needs to be handled in this code. They are documented
727 below. Please read it before making changes.
728 etb = existing topbitmap
731 cb = composited bitmap
732 fs = covers full screen
733 nfs = not covers full screen
739 The resulting mode is always that of screen bitmap as set in "effect" column.
740 The composited bitmap always matches the resulting screen mode or is NULL.
742 | exiting screen situation | change | effect |
743 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - SAME MODE |
744 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mA | sb==ntb, cb==NULL |
745 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
746 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
747 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb, cb!=NULL |
748 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
749 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - SAME MODE |
750 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
751 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
752 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
753 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
754 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
757 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - DIFFERENT MODES |
758 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mB | sb==ntb, cb==NULL |
759 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
760 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
761 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mB | new(cb), sb==cb, cb!=NULL |
762 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
763 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - DIFFERENT MODES |
764 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
765 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
766 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
767 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
768 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
771 | USE CASE: DRAGGING SCREEN DOWN |
772 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb |
773 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb |
774 | USE CASE: DRAGGING SCREEN UP |
775 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==etb |
776 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
778 Resulting rules (order matters):
780 (a) if ((cb!=NULL) && (etb->mode!=ntb->mode)) {dispose(cb), cb=NULL}
781 (b) if ((ntb->nfs) && (cb==NULL)) new(cb)
782 (c) if (ntb->nfs) sb=cb
783 (d) if (ntb->fs) sb=ntb
786 (e) if (oldsb!=sb) modeswitch(sb)
788 02.09.2011: we don't remember sb any more because we don't handle it in any way. Instead
789 we either have or don't have displaybitmap. If we have it, composition
790 is on (sb = cb). If we don't have it, composition is off (sb = ntb).
792 static BOOL HIDDCompositorToggleCompositing(struct HIDDCompositorData *compdata, BOOL newtop)
795 * If the topbitmap covers the complete screen, show it instead of
796 * displaybitmap. Remember that screen bitmap -> composited bitmap
797 * mirroring has a negative impact on performance.
799 OOP_Object *oldcompositedbitmap = compdata->displaybitmap;
800 struct StackBitMapNode *topnode = (struct StackBitMapNode *)compdata->bitmapstack.mlh_Head;
801 OOP_Object *newsdispbitmap = NULL;
802 struct BitMap *tmpBM;
803 struct TagItem bmtags[2];
805 BOOL ok = TRUE, composit = FALSE;
807 /* (a) If mode change is needed, enforce opening a new screen */
808 if (compdata->modeschanged)
810 DTOGGLE(bug("[Compositor:%s] Display Mode changed\n", __PRETTY_FUNCTION__));
811 compdata->displaybitmap = NULL;
814 bmtags[0].ti_Tag = BMATags_DisplayID; bmtags[0].ti_Data = (compdata->displayid | compdata->displaymode);
815 bmtags[1].ti_Tag = TAG_DONE; bmtags[1].ti_Data = TAG_DONE;
817 if ((topnode->topedge > 0) || ((compdata->displayrect.MaxY - compdata->displayrect.MinY + 1) > OOP_GET(topnode->bm, aHidd_BitMap_Height)))
819 else if ((topnode->leftedge > 0) || ((compdata->displayrect.MaxX - compdata->displayrect.MinX + 1) > OOP_GET(topnode->bm, aHidd_BitMap_Width)))
821 else if (topnode->sbmflags & COMPF_ALPHA)
827 if (compdata->displaybitmap == NULL)
830 * displaybitmap == NULL means we were in passthrough mode before,
831 * or have just changed display mode - set up screen for composition.
833 DTOGGLE(bug("[Compositor:%s] Initialising Display-Compositor..\n", __PRETTY_FUNCTION__));
838 * If our display driver uses a framebuffer, we can reuse it.
839 * Copy its original contents back into the bitmap which it replaced,
840 * then change framebuffer's video mode.
841 * Framebuffer is the only bitmap which can change its ModeID on the fly.
843 DTOGGLE(bug("[Compositor:%s] Using Display Famebuffer HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__, compdata->fb));
845 /* Do this comparison in order not to show the framebuffer twice */
846 if (oldcompositedbitmap != compdata->fb)
849 * 1. It's legal to show the framebuffer itself. This causes copying
850 * back old bitmap contents and detaching from it.
851 * 2. The result of this will always match compdata->fb.
852 * 3. Internally this is a simple blit operation, it can't fail.
854 DTOGGLE(bug("[Compositor:%s] Copying old Famebuffer BitMap\n", __PRETTY_FUNCTION__));
855 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, compdata->fb, fHidd_Gfx_Show_CopyBack);
858 /* Switch display mode on the framebuffer. */
859 OOP_SetAttrsTags(compdata->fb, aHidd_BitMap_ModeID, compdata->displaymode, TAG_DONE);
860 /* We are now compositing on the framebuffer */
861 compdata->displaybitmap = compdata->fb;
866 * There's no framebuffer.
867 * Create a new bitmap that will be used for compositing.
870 tmpBM = AllocBitMap(compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
871 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
872 compdata->displaydepth,
873 BMF_DISPLAYABLE|BMF_CHECKVALUE, (struct BitMap *)bmtags);
876 compdata->displaybitmap = HIDD_BM_OBJ(tmpBM);
877 DTOGGLE(bug("[Compositor:%s] Created Compositor Display BitMap @ 0x%p [HiddBitMap @ 0x%p]\n", __PRETTY_FUNCTION__, tmpBM, compdata->displaybitmap));
879 /* Mode changed, this bitmap will be shown later */
880 newsdispbitmap = compdata->displaybitmap;
882 /* NewBitMap can fail, handle this */
888 else /* if (compdata->displaybitmap == NULL) */
891 * We are already in compositing mode and will stay in it.
892 * Do not destroy our working bitmap.
894 oldcompositedbitmap = NULL;
897 if ((compdata->flags & COMPSTATEF_HASALPHA) && !(compdata->intermedbitmap))
899 tmpBM = AllocBitMap(compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
900 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
901 compdata->displaydepth,
902 BMF_CHECKVALUE, (struct BitMap *)bmtags);
905 compdata->intermedbitmap = HIDD_BM_OBJ(tmpBM);
906 DTOGGLE(bug("[Compositor:%s] Allocated Alpha Intermediary BitMap @ 0x%p [HiddBitMap @ 0x%p]\n", __PRETTY_FUNCTION__, tmpBM, compdata->intermedbitmap));
910 * (c) Here composition is turned on (displaybitmap != NULL).
911 * Redraw bitmap stack - compensate possible changes
914 HIDDCompositorRedrawVisibleRegions(compdata, NULL);
916 else if (oldcompositedbitmap || newtop)
919 * (d) Set passthrough mode and display the frontmost bitmap.
920 * This is also triggered by 'newtop' parameter, which tells us
921 * that frontmost bitmap has been changed, and we need to display a new one.
922 * Old displaybitmap has been remembered in the beginning. If it's not
923 * NULL, it will be destroyed in the end.
925 newsdispbitmap = compdata->topbitmap;
926 compdata->displaybitmap = NULL;
929 DTOGGLE(bug("[Compositor:%s] oldcompbm 0x%p, topbm 0x%p, dispbm 0x%p, newscreenbm 0x%p\n", __PRETTY_FUNCTION__,
930 oldcompositedbitmap, compdata->topbitmap, compdata->displaybitmap, newsdispbitmap));
933 * (e) If the screenbitmap changed, show the new screenbitmap.
934 * We do it after refreshing, for better visual appearance.
940 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, newsdispbitmap, fHidd_Gfx_Show_CopyBack);
941 DTOGGLE(bug("[Compositor:%s] Displayed HiddBitMap 0x%p, Show returned 0x%p\n", __PRETTY_FUNCTION__, newsdispbitmap, compdata->screenbitmap));
943 /* After Show we need Update for mirroring drivers */
944 if (compdata->screenbitmap)
946 OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Width, &w);
947 OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Height, &h);
948 HIDD_BM_UpdateRect(compdata->screenbitmap, 0, 0, w, h);
953 * (a) - disposing of oldcompositingbitmap needs to happen after mode switch
954 * since it could have been the current screenbitmap
956 if (oldcompositedbitmap && (oldcompositedbitmap != compdata->fb))
958 struct BitMap *freebm;
960 DTOGGLE(bug("[Compositor:%s] Disposing old working bitmap 0x%p\n", __PRETTY_FUNCTION__, oldcompositedbitmap));
962 OOP_GetAttr(oldcompositedbitmap, aHidd_BitMap_BMStruct, (IPTR *)&freebm);
968 HIDD_Gfx_DisposeBitMap(compdata->gfx, oldcompositedbitmap);
973 compdata->modeschanged = FALSE;
978 static VOID HIDDCompositorPurgeBitMapStack(struct HIDDCompositorData * compdata)
980 struct StackBitMapNode * curr, * next;
982 ForeachNodeSafe(&compdata->bitmapstack, curr, next)
984 if (curr->screenregion)
985 DisposeRegion(curr->screenregion);
987 FreeMem(curr, sizeof(struct StackBitMapNode));
990 NEWLIST(&compdata->bitmapstack);
993 static void HIDDCompositorShowSingle(struct HIDDCompositorData *compdata, OOP_Object *bm)
995 /* Show the single top bitmap */
996 compdata->topbitmap = bm;
997 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, bm, fHidd_Gfx_Show_CopyBack);
999 /* Dispose working bitmap (if any) */
1000 if (compdata->displaybitmap)
1002 /* Be careful with the framebuffer */
1003 if (compdata->displaybitmap != compdata->fb)
1004 HIDD_Gfx_DisposeBitMap(compdata->gfx, compdata->displaybitmap);
1006 /* This will deactivate us */
1007 compdata->displaybitmap = NULL;
1011 /* Emergency error recovery function */
1012 static void HIDDCompositorReset(struct HIDDCompositorData *compdata)
1014 /* Purge bitmap stack */
1015 HIDDCompositorPurgeBitMapStack(compdata);
1018 * Reset our internal state so that next BitMapStackChanged
1019 * causes complete reinitialization.
1021 compdata->displaymode = vHidd_ModeID_Invalid;
1022 compdata->screenbitmap = NULL;
1024 compdata->flags &= ~COMPSTATEF_HASALPHA;
1027 VOID CompositorParseConfig(struct HIDDCompositorData *compdata)
1029 struct RDArgs *rdargs;
1030 IPTR CompArgs[NOOFARGS] = { 0 };
1031 TEXT CompConfig[1024];
1033 /* use default amiga-like capabailities */
1034 compdata->capabilities = COMPF_ABOVE;
1036 rdargs = AllocDosObjectTags(DOS_RDARGS, TAG_END);
1039 if (GetVar(COMPOSITOR_PREFS, CompConfig, 1024, GVF_GLOBAL_ONLY) != -1)
1041 rdargs->RDA_Source.CS_Buffer = CompConfig;
1042 rdargs->RDA_Source.CS_Length = strlen(rdargs->RDA_Source.CS_Buffer);
1043 rdargs->RDA_DAList = (IPTR)NULL;
1044 rdargs->RDA_Buffer = NULL;
1045 rdargs->RDA_BufSiz = 0;
1046 rdargs->RDA_ExtHelp = NULL;
1047 rdargs->RDA_Flags = 0;
1049 if (ReadArgs(COMPOSITOR_PEFSTEMPLATE, CompArgs, rdargs) != NULL)
1051 if (CompArgs[ARG_ABOVE])
1052 compdata->capabilities |= COMPF_ABOVE;
1054 compdata->capabilities &= ~COMPF_ABOVE;
1056 if (CompArgs[ARG_BELOW])
1057 compdata->capabilities |= COMPF_BELOW;
1059 compdata->capabilities &= ~COMPF_BELOW;
1061 if (CompArgs[ARG_LEFT])
1062 compdata->capabilities |= COMPF_LEFT;
1064 compdata->capabilities &= ~COMPF_LEFT;
1066 if (CompArgs[ARG_RIGHT])
1067 compdata->capabilities |= COMPF_RIGHT;
1069 compdata->capabilities &= ~COMPF_RIGHT;
1071 if (CompArgs[ARG_ALPHA])
1072 compdata->capabilities |= COMPF_ALPHA;
1074 compdata->capabilities &= ~COMPF_ALPHA;
1079 FreeDosObject(DOS_RDARGS, rdargs);
1083 AROS_UFH3(void, CompositorDefaultBackFillFunc,
1084 AROS_UFHA(struct Hook * , h, A0),
1085 AROS_UFHA(struct BitMap * , bm, A2),
1086 AROS_UFHA(struct HIDD_BackFillHookMsg * , msg, A1))
1090 struct HIDDCompositorData *compdata = h->h_Data;
1092 D(bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata));
1094 HIDDCompositorFillRect(compdata, HIDD_BM_OBJ(bm), msg->bounds->MinX, msg->bounds->MinY, msg->bounds->MaxX, msg->bounds->MaxY);
1099 /* PUBLIC METHODS */
1100 OOP_Object *METHOD(Compositor, Root, New)
1102 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
1106 OOP_MethodID disposemid;
1107 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1109 D(bug("[%s] Compositor @ 0x%p, data @ 0x%p\n", __PRETTY_FUNCTION__, o, compdata));
1111 CompositorParseConfig(compdata);
1113 compdata->capabilities = (ULONG)GetTagData(aHidd_Compositor_State, compdata->capabilities, msg->attrList);
1115 D(bug("[%s] Compositor Capabilities: %08lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
1117 compdata->displaymode = vHidd_ModeID_Invalid;
1119 NEWLIST(&compdata->bitmapstack);
1121 compdata->defaultbackfill.h_Entry = (HOOKFUNC)AROS_ASMSYMNAME(CompositorDefaultBackFillFunc);
1122 compdata->defaultbackfill.h_Data = compdata;
1123 compdata->backfillhook = &compdata->defaultbackfill;
1125 InitSemaphore(&compdata->semaphore);
1127 compdata->displayid = (ULONG)GetTagData(aHidd_Compositor_DisplayID, 0, msg->attrList);
1128 compdata->gfx = (OOP_Object *)GetTagData(aHidd_Compositor_GfxHidd, 0, msg->attrList);
1129 compdata->fb = (OOP_Object *)GetTagData(aHidd_Compositor_FrameBuffer, 0, msg->attrList);
1131 D(bug("[%s] DisplayID %08lx for Gfx Driver @ 0x%p\n", __PRETTY_FUNCTION__, compdata->displayid, compdata->gfx));
1133 GfxBase = (APTR)OpenLibrary("graphics.library", 41);
1134 IntuitionBase = (APTR)OpenLibrary("intuition.library", 50);
1136 /* GfxHidd is mandatory */
1137 if ((compdata->GraphicsBase) && (compdata->gfx != NULL))
1139 /* Create GC object that will be used for drawing operations */
1140 compdata->gc = HIDD_Gfx_NewGC(compdata->gfx, NULL);
1142 D(bug("[%s] Compositor GC @ %p\n", __PRETTY_FUNCTION__, compdata->gc));
1144 if ((compdata->gfx) && (compdata->gc))
1148 /* Creation failed */
1149 disposemid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
1150 OOP_CoerceMethod(cl, o, &disposemid);
1156 void METHOD(Compositor, Root, Dispose)
1160 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1161 bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata);
1164 OOP_DoSuperMethod(cl, o, &msg->mID);
1167 VOID METHOD(Compositor, Root, Get)
1171 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1173 if (IS_COMPOSITOR_ATTR(msg->attrID, idx))
1177 case aoHidd_Compositor_Capabilities:
1179 *msg->storage = (IPTR)CAPABILITY_FLAGS;
1180 D(bug("[%s] Compositor Capabilities: %lx\n", __PRETTY_FUNCTION__, *msg->storage));
1183 case aoHidd_Compositor_State:
1185 *msg->storage = (IPTR)(compdata->capabilities & CAPABILITY_FLAGS);
1186 D(bug("[%s] Compositor State: %lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
1189 case aoHidd_Compositor_BackFillHook:
1191 D(bug("[%s] BackFillHook: 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook));
1192 *msg->storage = (IPTR)compdata->backfillhook;
1197 OOP_DoSuperMethod(cl, o, &msg->mID);
1200 VOID METHOD(Compositor, Root, Set)
1204 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1205 struct TagItem *tag, *tstate = msg->attrList;
1207 while ((tag = NextTagItem(&tstate)))
1209 if (IS_COMPOSITOR_ATTR(tag->ti_Tag, idx))
1213 case aoHidd_Compositor_State:
1215 D(bug("[%s] Compositor Capabilities State: %lx -> ", __PRETTY_FUNCTION__, compdata->capabilities));
1216 compdata->capabilities = (ULONG)(tag->ti_Data & CAPABILITY_FLAGS);
1217 D(bug("%lx\n", compdata->capabilities));
1220 case aoHidd_Compositor_BackFillHook:
1224 D(bug("[%s] BackFillHook: 0x%p -> 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook, tag->ti_Data));
1225 compdata->backfillhook = (struct Hook *)tag->ti_Data;
1229 D(bug("[%s] Default BackFillHook\n", __PRETTY_FUNCTION__));
1230 compdata->backfillhook = &compdata->defaultbackfill;
1238 OOP_DoSuperMethod(cl, o, &msg->mID);
1241 OOP_Object *METHOD(Compositor, Hidd_Compositor, BitMapStackChanged)
1243 struct HIDD_ViewPortData *vpdata;
1244 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1245 struct StackBitMapNode *n;
1246 struct Screen *bmScreen;
1247 OOP_Object *bmpxfmt;
1249 BOOL newtop = FALSE;
1252 DSTACK(bug("[Compositor] %s: Top bitmap: 0x%lx\n", __PRETTY_FUNCTION__, msg->data->Bitmap));
1254 LOCK_COMPOSITOR_WRITE
1256 /* Free all items which are already on the list */
1257 HIDDCompositorPurgeBitMapStack(compdata);
1263 DSTACK(bug("[Compositor] %s: No ViewPort specified\n", __PRETTY_FUNCTION__));
1266 HIDDCompositorShowSingle(compdata, NULL);
1268 /* We know we are inactive after this */
1269 *msg->active = FALSE;
1270 /* This can return NULL, it's okay */
1271 return compdata->screenbitmap;
1274 /* Copy bitmaps pointers to our stack */
1275 for (vpdata = msg->data; vpdata; vpdata = vpdata->Next)
1277 n = AllocMem(sizeof(struct StackBitMapNode), MEMF_ANY | MEMF_CLEAR);
1282 * We need to reset own state and return NULL. graphics.library
1283 * falls back to no composition in this case.
1285 DSTACK(bug("[Compositor] %s: Error allocating StackBitMapNode!!!\n", __PRETTY_FUNCTION__));
1291 DSTACK(bug("[Compositor] %s: ViewPort 0x%p, offset (%d, %d)\n", __PRETTY_FUNCTION__, vpdata->vpe->ViewPort, vpdata->vpe->ViewPort->DxOffset, vpdata->vpe->ViewPort->DyOffset));
1293 n->bm = vpdata->Bitmap;
1294 n->sbmflags = STACKNODEF_DISPLAYABLE;
1295 n->leftedge = vpdata->vpe->ViewPort->DxOffset;
1296 n->topedge = vpdata->vpe->ViewPort->DyOffset;
1298 n->screenregion = NewRegion();
1300 if ((bmScreen = HIDDCompositorFindBitMapScreen(compdata, n->bm)) != NULL)
1302 DSTACK(bug("[Compositor] %s: Screen @ 0x%p\n", __PRETTY_FUNCTION__, bmScreen));
1303 GetAttr(SA_CompositingFlags, (Object *)bmScreen, &n->sbmflags);
1304 DSTACK(bug("[Compositor] %s: CompositingFlags %08x\n", __PRETTY_FUNCTION__, n->sbmflags));
1305 n->sbmflags |= STACKNODEF_DISPLAYABLE;
1306 if (n->sbmflags & COMPF_ALPHA)
1308 GetAttr(SA_AlphaPreCompositHook, (Object *)bmScreen, (IPTR *)&n->prealphacomphook);
1309 DSTACK(bug("[Compositor] %s: Pre-AlphaComposit Hook @ 0x%p\n", __PRETTY_FUNCTION__, n->prealphacomphook));
1313 if (n->sbmflags & COMPF_ALPHA)
1315 bmpxfmt = (OOP_Object *)OOP_GET(n->bm, aHidd_BitMap_PixFmt);
1316 bmstdfmt = (int)OOP_GET(bmpxfmt, aHidd_PixFmt_StdPixFmt);
1317 DSTACK(bug("[Compositor] %s: Screen BitMap PixFmt %lx @ 0x%p\n", __PRETTY_FUNCTION__, bmstdfmt, bmpxfmt));
1321 case vHidd_StdPixFmt_ARGB32:
1322 case vHidd_StdPixFmt_BGRA32:
1323 case vHidd_StdPixFmt_RGBA32:
1324 case vHidd_StdPixFmt_ABGR32:
1326 DSTACK(bug("[Compositor] %s: Screen BitMap has Alpha\n", __PRETTY_FUNCTION__));
1328 compdata->flags |= COMPSTATEF_HASALPHA;
1333 n->sbmflags &= ~COMPF_ALPHA;
1339 if (!(n->sbmflags & COMPF_ALPHA))
1341 if ((((BOOL)OOP_GET(n->bm, aHidd_BitMap_Displayable)) != TRUE))
1342 n->sbmflags &= ~STACKNODEF_DISPLAYABLE;
1344 AddTail((struct List *)&compdata->bitmapstack, (struct Node *)n);
1347 /* Switch mode if needed */
1348 UpdateDisplayMode(compdata);
1350 if (msg->data->Bitmap != compdata->topbitmap)
1352 /* Set the new pointer to top bitmap */
1353 compdata->topbitmap = msg->data->Bitmap;
1360 * Validate bitmap offsets - they might not match the compositing rules taking
1361 * new displayedwidth/displayedheight values
1363 ForeachNode(&compdata->bitmapstack, n)
1365 HIDDCompositorValidateBitMapPositionChange(n->bm, &n->leftedge, &n->topedge,
1366 compdata->displayrect.MaxX + 1, compdata->displayrect.MaxY + 1);
1367 DSTACK(bug("[Compositor] %s: Bitmap 0x%p, display size %d x %d, validated position (%ld, %ld)\n", __PRETTY_FUNCTION__,
1368 n->bm, compdata->displayrect.MaxX + 1, compdata->displayrect.MaxY + 1,
1369 n->leftedge, n->topedge));
1372 /* Toogle compositing based on screen positions */
1373 ok = HIDDCompositorToggleCompositing(compdata, newtop);
1379 HIDDCompositorReset(compdata);
1380 HIDDCompositorShowSingle(compdata, msg->data->Bitmap);
1385 DSTACK(bug("[%s] Done, composited bitmap 0x%p\n", __PRETTY_FUNCTION__, compdata->displaybitmap));
1387 /* Tell if the composition is active */
1388 *msg->active = compdata->displaybitmap ? TRUE : FALSE;
1389 /* Return actually displayed bitmap */
1390 return compdata->screenbitmap;
1393 VOID METHOD(Compositor, Hidd_Compositor, BitMapRectChanged)
1395 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1396 OOP_Object *renderTarget;
1398 if (compdata->displaybitmap)
1400 /* Composition is active, handle redraw if the bitmap is on screen */
1401 struct StackBitMapNode *n;
1403 DUPDATE(bug("[%s] Bitmap 0x%p\n", __PRETTY_FUNCTION__, msg->bm));
1405 LOCK_COMPOSITOR_READ
1407 if (compdata->intermedbitmap)
1408 renderTarget = compdata->intermedbitmap;
1410 renderTarget = compdata->displaybitmap;
1412 n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1413 if (n && (n->sbmflags & STACKNODEF_VISIBLE))
1415 struct Rectangle srcrect, dstandvisrect;
1417 srcrect.MinX = n->leftedge + msg->x;
1418 srcrect.MinY = n->topedge + msg->y;
1419 srcrect.MaxX = srcrect.MinX + msg->width - 1;
1420 srcrect.MaxY = srcrect.MinY + msg->height - 1;
1421 DUPDATE(bug("[%s] Bitmap rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, msg->x, msg->y, msg->x + msg->width - 1, msg->y + msg->height - 1));
1423 DUPDATE(bug("[%s] Screen-relative rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(srcrect)));
1425 struct RegionRectangle * srrect = n->screenregion->RegionRectangle;
1428 BOOL updateAlphaBmps = FALSE;
1430 dstandvisrect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
1431 dstandvisrect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
1432 dstandvisrect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
1433 dstandvisrect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
1435 if (AndRectRect(&srcrect, &dstandvisrect, &dstandvisrect))
1437 /* Intersection is valid. Blit. */
1438 DUPDATE(bug("[%s] Clipped rect (%d, %d) - (%d, %d)\n", __PRETTY_FUNCTION__, _RECT(dstandvisrect)));
1440 if (!(n->sbmflags & COMPF_ALPHA))
1442 if ((compdata->alpharegion) && (isRectInRegion(compdata->alpharegion, &dstandvisrect)))
1444 DUPDATE(bug("[%s] ** Bitmap in Alpha Region!\n", __PRETTY_FUNCTION__));
1445 updateAlphaBmps = TRUE;
1447 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &dstandvisrect);
1451 updateAlphaBmps = FALSE;
1452 HIDDCompositorRedrawVisibleRegions(compdata, &dstandvisrect);
1455 if (updateAlphaBmps)
1456 HIDDCompositorRedrawAlphaRegions(compdata, &dstandvisrect);
1458 if (renderTarget != compdata->displaybitmap)
1460 HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
1461 dstandvisrect.MinX, dstandvisrect.MinY,
1462 compdata->displaybitmap,
1463 dstandvisrect.MinX, dstandvisrect.MinY,
1464 dstandvisrect.MaxX - dstandvisrect.MinX + 1,
1465 dstandvisrect.MaxY - dstandvisrect.MinY + 1,
1469 HIDD_BM_UpdateRect(compdata->displaybitmap,
1470 dstandvisrect.MinX, dstandvisrect.MinY,
1471 dstandvisrect.MaxX - dstandvisrect.MinX + 1,
1472 dstandvisrect.MaxY - dstandvisrect.MinY + 1);
1474 srrect = srrect->Next;
1480 DUPDATE(bug("[%s] Done\n", __PRETTY_FUNCTION__));
1484 /* In order to speed things up, we handle passthrough ourselves here. */
1485 HIDD_BM_UpdateRect(msg->bm, msg->x, msg->y, msg->width, msg->height);
1489 IPTR METHOD(Compositor, Hidd_Compositor, BitMapPositionChange)
1491 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1492 struct StackBitMapNode *n;
1493 IPTR disp_width, disp_height;
1495 LOCK_COMPOSITOR_READ
1497 n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1500 /* The bitmap is on display. Validate against screen size */
1501 disp_width = compdata->displayrect.MaxX + 1;
1502 disp_height = compdata->displayrect.MaxY + 1;
1506 /* The bitmap is not displayed yet. Validate against its own ModeID size. */
1507 HIDDT_ModeID modeid = vHidd_ModeID_Invalid;
1508 OOP_Object *bmfriend, *sync, *pf;
1510 OOP_GetAttr(msg->bm, aHidd_BitMap_ModeID, &modeid);
1512 if ((modeid == vHidd_ModeID_Invalid) && (OOP_GET(msg->bm, aHidd_BitMap_Compositable)))
1514 OOP_GetAttr(msg->bm, aHidd_BitMap_Friend, (IPTR *)&bmfriend);
1516 OOP_GetAttr(bmfriend, aHidd_BitMap_ModeID, &modeid);
1519 if (modeid == vHidd_ModeID_Invalid)
1522 * Nondisplayable bitmaps don't scroll.
1523 * In fact they simply can't get in here because MakeVPort() performs the validation.
1524 * But who knows what bug can slip into someone's software...
1530 HIDD_Gfx_GetMode(compdata->gfx, modeid, &sync, &pf);
1531 OOP_GetAttr(sync, aHidd_Sync_HDisp, &disp_width);
1532 OOP_GetAttr(sync, aHidd_Sync_VDisp, &disp_height);
1535 DMOVE(bug("[%s] Validating bitmap 0x%p, position (%ld, %ld), limits %ld x %ld\n", __PRETTY_FUNCTION__,
1536 msg->bm, *msg->newxoffset, *msg->newyoffset, disp_width, disp_height));
1538 HIDDCompositorValidateBitMapPositionChange(msg->bm, msg->newxoffset, msg->newyoffset,
1539 disp_width, disp_height);
1541 DMOVE(bug("[%s] Validated position (%ld, %ld)\n", __PRETTY_FUNCTION__, *msg->newxoffset, *msg->newyoffset));
1543 if (n && ((*msg->newxoffset != n->leftedge) || (*msg->newyoffset != n->topedge)))
1545 DMOVE(bug("[%s] Old position (%ld, %ld)\n", __PRETTY_FUNCTION__, n->leftedge, n->topedge));
1547 /* Reflect the change if it happened */
1548 n->leftedge = *msg->newxoffset;
1549 n->topedge = *msg->newyoffset;
1551 if (compdata->topbitmap == msg->bm)
1554 * If this is the frontmost bitmap, we may want to toggle compositing,
1555 * if it starts/stops covering the whole screen at one point.
1556 * We don't need to call HIDDCompositorRedrawVisibleRegions() here because
1557 * HIDDCompositorToggleCompositing() does this itself, for improved
1558 * visual appearance.
1560 HIDDCompositorToggleCompositing(compdata, FALSE);
1563 HIDDCompositorRedrawVisibleRegions(compdata, NULL);
1568 /* Return active state */
1569 return compdata->displaybitmap ? TRUE : FALSE;
1572 IPTR METHOD(Compositor, Hidd_Compositor, BitMapValidate)
1574 if (IS_HIDD_BM(msg->bm))
1580 IPTR METHOD(Compositor, Hidd_Compositor, BitMapEnable)
1582 if (IS_HIDD_BM(msg->bm))
1584 if (!(OOP_GET(HIDD_BM_OBJ(msg->bm), aHidd_BitMap_Displayable)))
1586 struct TagItem composittags[] = {
1587 {aHidd_BitMap_Compositable, TRUE},
1591 D(bug("[GfxCompositor]: Marking BitMap 0x%lx as Compositable\n", msg->bm));
1592 OOP_SetAttrs(HIDD_BM_OBJ(msg->bm), composittags);
1600 #define NUM_Compositor_Root_METHODS 4
1602 static const struct OOP_MethodDescr Compositor_Root_descr[] =
1604 {(OOP_MethodFunc)Compositor__Root__New, moRoot_New},
1605 {(OOP_MethodFunc)Compositor__Root__Dispose, moRoot_Dispose},
1606 {(OOP_MethodFunc)Compositor__Root__Get, moRoot_Get},
1607 {(OOP_MethodFunc)Compositor__Root__Set, moRoot_Set},
1611 #define NUM_Compositor_Hidd_Compositor_METHODS 5
1613 static const struct OOP_MethodDescr Compositor_Hidd_Compositor_descr[] =
1615 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapStackChanged, moHidd_Compositor_BitMapStackChanged},
1616 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapRectChanged, moHidd_Compositor_BitMapRectChanged},
1617 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapPositionChange, moHidd_Compositor_BitMapPositionChange},
1618 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapValidate, moHidd_Compositor_BitMapValidate},
1619 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapEnable, moHidd_Compositor_BitMapEnable},
1623 const struct OOP_InterfaceDescr Compositor_ifdescr[] =
1625 {Compositor_Root_descr, IID_Root, NUM_Compositor_Root_METHODS},
1626 {Compositor_Hidd_Compositor_descr, IID_Hidd_Compositor, NUM_Compositor_Hidd_Compositor_METHODS},