change behaviour so that external code will receive a struct BitMap to operate with.
[AROS.git] / workbench / devs / monitors / Compositor / compositorclass.c
blob79e1cb93dafc09a2ce8a1d6e4730710b235b83fb
1 /*
2 Copyright © 2010-2013, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 0
7 #if (DEBUG)
8 #define DTOGGLE(x) x
9 #define DMODE(x) x
10 #define DMOVE(x) x
11 #define DRECALC(x) x
12 #define DREDRAWBM(x) x
13 #define DREDRAWSCR(x) x
14 #define DSTACK(x) x
15 #define DUPDATE(x) x
16 #else
17 #define DTOGGLE(x)
18 #define DMODE(x)
19 #define DMOVE(x)
20 #define DRECALC(x)
21 #define DREDRAWBM(x)
22 #define DREDRAWSCR(x)
23 #define DSTACK(x)
24 #define DUPDATE(x)
25 #endif
27 #include <aros/debug.h>
29 #include <clib/alib_protos.h>
30 #include <proto/exec.h>
31 #include <proto/dos.h>
32 #include <proto/graphics.h>
33 #include <proto/intuition.h>
34 #include <proto/oop.h>
35 #include <proto/utility.h>
37 #include <graphics/view.h>
38 #include <hidd/graphics.h>
40 #include "compositor_intern.h"
42 #define COMPOSITOR_PREFS "SYS/compositor.prefs"
43 #define COMPOSITOR_PEFSTEMPLATE "ABOVE/S,BELOW/S,LEFT/S,RIGHT/S,ALPHA/S"
45 #define CAPABILITY_FLAGS (COMPF_ABOVE|COMPF_BELOW|COMPF_LEFT|COMPF_RIGHT|COMPF_ALPHA)
47 enum
49 ARG_ABOVE = 0,
50 ARG_BELOW,
51 ARG_LEFT,
52 ARG_RIGHT,
53 ARG_ALPHA,
54 NOOFARGS
58 #ifdef GfxBase
59 #undef GfxBase
60 #endif
61 #define GfxBase compdata->GraphicsBase
62 #ifdef IntuitionBase
63 #undef IntuitionBase
64 #endif
65 #define IntuitionBase compdata->IntuitionBase
67 #define _RECT(x) x.MinX, x.MinY, x.MaxX, x.MaxY
69 #define MAX(a,b) a > b ? a : b
70 #define MIN(a,b) a < b ? a : b
72 BOOL isRectInRegion(struct Region *region, struct Rectangle *rect)
74 struct RegionRectangle *rrect = region->RegionRectangle;
76 while (rrect)
78 if (AndRectRect(&rrect->bounds, rect, NULL))
79 return TRUE;
81 rrect = rrect->Next;
83 return FALSE;
86 static struct StackBitMapNode * HIDDCompositorFindBitMapStackNode(struct HIDDCompositorData * compdata, OOP_Object * bm)
88 struct StackBitMapNode * n = NULL;
90 ForeachNode(&compdata->bitmapstack, n)
92 if (n->bm == bm)
93 return n;
96 return NULL;
99 struct Screen *HIDDCompositorFindBitMapScreen(struct HIDDCompositorData *compdata, OOP_Object *bm)
101 struct Screen *curScreen = NULL;
103 for (curScreen = IntuitionBase->FirstScreen; curScreen != NULL; curScreen = curScreen->NextScreen)
105 if (bm == HIDD_BM_OBJ(curScreen->RastPort.BitMap))
106 return curScreen;
109 return (struct Screen *)NULL;
112 static VOID HIDDCompositorValidateBitMapPositionChange(OOP_Object * bm, SIPTR *newxoffset, SIPTR *newyoffset, LONG displayedwidth, LONG displayedheight)
114 IPTR width, height;
115 LONG neglimit, poslimit;
117 OOP_GetAttr(bm, aHidd_BitMap_Width, &width);
118 OOP_GetAttr(bm, aHidd_BitMap_Height, &height);
120 /* Check x position */
121 if (width > displayedwidth)
123 neglimit = displayedwidth - width;
124 poslimit = 0;
126 else
128 neglimit = 0;
129 poslimit = displayedwidth - width;
132 if (*(newxoffset) > poslimit)
133 *(newxoffset) = poslimit;
134 if (*(newxoffset) < neglimit)
135 *(newxoffset) = neglimit;
137 /* Check y position */
138 if (height > displayedheight)
139 neglimit = displayedheight - height; /* Limit for scroll */
140 else
141 neglimit = 0;
142 poslimit = displayedheight - 15; /* Limit for drag */
144 if (*(newyoffset) > poslimit)
145 *(newyoffset) = poslimit;
146 if (*(newyoffset) < neglimit)
147 *(newyoffset) = neglimit;
150 static VOID HIDDCompositorRecalculateVisibleRegions(struct HIDDCompositorData *compdata)
152 struct StackBitMapNode *n = NULL, *tmpn;
153 struct Region *dispvisregion = NULL;
154 ULONG oldflags = compdata->flags;
156 DRECALC(bug("[Compositor:%s] Display rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(compdata->displayrect)));
159 * This function assumes bitmapstack is in correct Z order:
160 * from topmost to bottom most
162 if ((dispvisregion = NewRegion()) != NULL)
164 OrRectRegion(dispvisregion, &compdata->displayrect);
166 compdata->flags &= ~COMPSTATEF_HASALPHA;
167 if (compdata->alpharegion)
169 DisposeRegion(compdata->alpharegion);
170 compdata->alpharegion = NULL;
172 DRECALC(bug("[Compositor:%s] DisplayRegion @ 0x%p\n", __PRETTY_FUNCTION__, dispvisregion));
174 ForeachNodeSafe(&compdata->bitmapstack, n, tmpn)
176 /* Get bitmap bounding box in screen coordinates */
177 struct Rectangle tmprect;
179 n->sbmflags &= ~STACKNODEF_VISIBLE;
181 if (n->screenregion)
182 ClearRegion(n->screenregion);
183 else
184 n->screenregion = NewRegion();
186 if (n->screenregion)
188 tmprect.MinX = n->leftedge;
189 tmprect.MaxX = n->leftedge + OOP_GET(n->bm, aHidd_BitMap_Width) - 1;
190 tmprect.MinY = n->topedge;
191 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
193 DRECALC(bug("[Compositor:%s] Screen Rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
195 OrRectRegion(n->screenregion, &tmprect); // Start with the Screen's dimensions ..
196 AndRegionRegion(dispvisregion, n->screenregion); // And adjust for the "Display"
198 if (n->screenregion->RegionRectangle)
200 AndRectRect(&n->screenregion->bounds, &compdata->displayrect, &n->screenvisiblerect);
202 if (!(n->sbmflags & COMPF_ALPHA))
203 ClearRectRegion(dispvisregion, &n->screenvisiblerect);
204 else
206 compdata->flags |= COMPSTATEF_HASALPHA;
207 if (!(compdata->alpharegion))
208 compdata->alpharegion = NewRegion();
210 OrRectRegion(compdata->alpharegion, &n->screenvisiblerect);
213 if (!(compdata->capabilities & COMPF_ABOVE) && !(n->sbmflags & COMPF_ABOVE))
215 tmprect.MinX = compdata->displayrect.MinX;
216 tmprect.MaxX = compdata->displayrect.MaxX;
217 tmprect.MinY = compdata->displayrect.MinY;
218 tmprect.MaxY = n->topedge - 1;
219 ClearRectRegion(dispvisregion, &tmprect);
221 if (!(compdata->capabilities & COMPF_BELOW) && !(n->sbmflags & COMPF_BELOW))
223 tmprect.MinX = compdata->displayrect.MinX;
224 tmprect.MaxX = compdata->displayrect.MaxX;
225 tmprect.MinY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height);
226 tmprect.MaxY = compdata->displayrect.MaxY;
227 ClearRectRegion(dispvisregion, &tmprect);
229 if (!(compdata->capabilities & COMPF_LEFT) && !(n->sbmflags & COMPF_LEFT))
231 tmprect.MinX = compdata->displayrect.MinX;
232 tmprect.MaxX = n->leftedge - 1;
233 tmprect.MinY = n->topedge;
234 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
235 ClearRectRegion(dispvisregion, &tmprect);
237 if (!(compdata->capabilities & COMPF_RIGHT) && !(n->sbmflags & COMPF_RIGHT))
239 tmprect.MinX = n->leftedge + OOP_GET(n->bm, aHidd_BitMap_Width);
240 tmprect.MaxX = compdata->displayrect.MaxX;
241 tmprect.MinY = n->topedge;
242 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
243 ClearRectRegion(dispvisregion, &tmprect);
245 n->sbmflags |= STACKNODEF_VISIBLE;
248 DRECALC(bug("[Compositor:%s] HiddBitmap 0x%p, topedge %d, visible %d, [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
249 n->bm, n->topedge, (n->sbmflags & STACKNODEF_VISIBLE), _RECT(n->screenvisiblerect)));
251 else
253 DRECALC(bug("[Compositor:%s] Failed to create Screen Region\n", __PRETTY_FUNCTION__));
256 DisposeRegion(dispvisregion);
257 if (compdata->flags != oldflags)
259 ULONG newflags = (~oldflags) & compdata->flags;
260 DRECALC(bug("[Compositor:%s] Newly set flags %08x\n", __PRETTY_FUNCTION__, newflags));
261 if ((!(newflags & COMPSTATEF_HASALPHA)) && (oldflags & COMPSTATEF_HASALPHA))
263 DRECALC(bug("[Compositor:%s] Alpha removed\n", __PRETTY_FUNCTION__));
264 if (compdata->alpharegion)
265 DisposeRegion(compdata->alpharegion);
267 if (compdata->intermedbitmap)
268 HIDD_Gfx_DisposeBitMap(compdata->gfx, compdata->intermedbitmap);
270 compdata->alpharegion = NULL;
271 compdata->intermedbitmap = NULL;
275 else
277 DRECALC(bug("[Compositor:%s] Failed to create Display Region\n", __PRETTY_FUNCTION__));
281 static HIDDT_ModeID FindBestHiddMode(struct HIDDCompositorData *compdata, ULONG width, ULONG height, ULONG depth, ULONG *res_depth)
283 HIDDT_ModeID mode = vHidd_ModeID_Invalid;
284 OOP_Object *sync, *pf;
285 IPTR w, h, d;
286 ULONG dw, dh, delta;
287 ULONG found_delta = -1;
288 ULONG found_width = 0;
289 ULONG found_height = 0;
290 ULONG found_depth = 0;
291 HIDDT_ModeID found_mode = vHidd_ModeID_Invalid;
293 DMODE(bug("[%s] Finding best match for mode %ux%ux%u\n", __PRETTY_FUNCTION__, width, height, depth));
295 while ((mode = HIDD_Gfx_NextModeID(compdata->gfx, mode, &sync, &pf)) != vHidd_ModeID_Invalid)
297 BOOL match;
299 DMODE(bug("[%s] Checking mode 0x%08X... ", __PRETTY_FUNCTION__, mode));
300 if (OOP_GET(pf, aHidd_PixFmt_ColorModel) != vHidd_ColorModel_TrueColor)
302 DMODE(bug("Skipped (not truecolor)\n"));
303 continue;
306 OOP_GetAttr(sync, aHidd_Sync_HDisp, &w);
307 OOP_GetAttr(sync, aHidd_Sync_VDisp, &h);
308 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &d);
310 dw = w > width ? w - width : w < width ? width - w : 1;
311 dh = h > height ? h - height : h < height ? height - h : 1;
312 delta = dw * dh;
314 match = FALSE;
315 if (delta < found_delta)
317 /* If mode resolution is closer to the needed one, we've got a better match */
318 found_delta = delta;
319 found_width = w;
320 found_height = h;
322 match = TRUE;
324 else if (delta == found_delta)
326 /* If resolution is the same as that of current candidate mode, we can look at depth. */
327 if (found_depth > depth)
330 * Candidate mode if deeper than requested. We can supersede it with another mode
331 * of smaller depth, but which still matches our request.
333 if ((d < found_depth) && (d >= depth))
334 match = TRUE;
336 else if (found_depth < depth)
339 * We want better depth than current candidate.
340 * In this case anything deeper will do.
342 if (d > found_depth)
343 match = TRUE;
347 if (match)
350 * Mode with the same delta, but larger depth, may supersede
351 * previous mode, if we prefer deeper ones.
353 DMODE(bug("Selected (%ldx%ldx%ld, delta = %u)", w, h, d, delta));
354 found_depth = d;
355 found_mode = mode;
357 DMODE(bug("\n"));
360 /* Store mode information */
361 compdata->displayrect.MinX = 0;
362 compdata->displayrect.MinY = 0;
363 compdata->displayrect.MaxX = found_width - 1;
364 compdata->displayrect.MaxY = found_height - 1;
365 *res_depth = found_depth;
367 return found_mode;
370 static void UpdateDisplayMode(struct HIDDCompositorData *compdata)
372 struct StackBitMapNode *n;
373 IPTR modeid, width = 0, height = 0, depth;
374 OOP_Object *sync, *pf;
375 UBYTE comp_depth = 16;
376 ULONG found_depth;
378 DSTACK(bug("[Compositor] %s()\n", __PRETTY_FUNCTION__));
381 * Examine all bitmaps in the stack to figure out the needed depth.
382 * We need a maximum depth of all depths in order to keep correct colors.
383 * But not less than 16 bits, because we can't compose on a LUT screen.
385 * If a LUT bitmap is present in the stack (depth < 9), we request truecolor
386 * screen for better color presentation.
388 * We examine bitmaps in reverse order, in this case 'sync' will hold
389 * information about the top bitmap when we exit the loop.
390 * Size of our composited mode needs to be as close as possible to that one.
392 for (n = (struct StackBitMapNode *)compdata->bitmapstack.mlh_TailPred;
393 n->n.mln_Pred; n = (struct StackBitMapNode *)n->n.mln_Pred)
395 if ((!(n->sbmflags & COMPF_ALPHA)) && (n->sbmflags & STACKNODEF_DISPLAYABLE))
397 OOP_GetAttr(n->bm, aHidd_BitMap_ModeID, &modeid);
398 HIDD_Gfx_GetMode(compdata->gfx, modeid, &sync, &pf);
400 if (OOP_GET(pf, aHidd_PixFmt_ColorModel) == vHidd_ColorModel_TrueColor)
402 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
403 if (depth > comp_depth)
404 comp_depth = depth;
406 else
409 * If we have a LUT bitmap on stack, we request 24-bit screen
410 * for better color transfer.
412 comp_depth = 24;
415 else
417 IPTR curwidth, curheight;
418 OOP_GetAttr(n->bm, aHidd_BitMap_Width, &curwidth);
419 OOP_GetAttr(n->bm, aHidd_BitMap_Height, &curheight);
420 if (curwidth > width)
421 width = curwidth;
422 if (curheight > height)
423 height = curheight;
427 if (sync)
429 /* Get the needed size */
430 OOP_GetAttr(sync, aHidd_Sync_HDisp, &width);
431 OOP_GetAttr(sync, aHidd_Sync_VDisp, &height);
434 DSTACK(bug("[%s] Prefered mode %ldx%ldx%d\n", __PRETTY_FUNCTION__, width, height, comp_depth));
436 modeid = FindBestHiddMode(compdata, width, height, comp_depth, &found_depth);
437 DSTACK(bug("[%s] Composition Display ModeID 0x%08X [current 0x%08X]\n", __PRETTY_FUNCTION__, modeid, compdata->displaymode));
439 if (modeid != compdata->displaymode)
441 /* The mode is different. Need to prepare information needed for compositing */
442 struct TagItem gctags[] =
444 { aHidd_GC_Foreground, 0x99999999 },
445 { TAG_DONE , 0 }
448 /* Signal mode change */
449 compdata->displaymode = modeid;
450 compdata->displaydepth = comp_depth;
451 compdata->modeschanged = TRUE;
453 /* Get gray foregound */
454 if (found_depth < 24)
455 gctags[0].ti_Data = 0x9492;
457 OOP_SetAttrs(compdata->gc, gctags);
461 static inline void HIDDCompositorRedrawBitmap(struct HIDDCompositorData *compdata, OOP_Object *renderTarget, struct StackBitMapNode *n, struct Rectangle *rect)
463 /* The given rectangle is already in screen coordinate system here */
464 ULONG blitwidth = rect->MaxX - rect->MinX + 1;
465 ULONG blitheight = rect->MaxY - rect->MinY + 1;
467 DREDRAWBM(bug("[Compositor:%s] Redraw HiddBitMap 0x%p, Rect[%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, n->bm,
468 rect->MinX, rect->MinY, rect->MaxX, rect->MaxY));
470 if (!(n->sbmflags & COMPF_ALPHA))
472 DREDRAWBM(bug("[Compositor:%s] Blitting %dx%d [from %d, %d]\n", __PRETTY_FUNCTION__, blitwidth, blitheight,
473 rect->MinX - n->leftedge, rect->MinY - n->topedge));
475 HIDD_Gfx_CopyBox(compdata->gfx, n->bm,
476 /* Transform to source bitmap coord system */
477 rect->MinX - n->leftedge, rect->MinY - n->topedge,
478 renderTarget,
479 rect->MinX, rect->MinY, blitwidth, blitheight,
480 compdata->gc);
482 else
484 UBYTE *baseaddress;
485 ULONG width, height, banksize, memsize;
486 IPTR modulo;
488 DREDRAWBM(bug("[Compositor:%s] AlphaBlending %dx%d @ %d,%d to %d,%d\n", __PRETTY_FUNCTION__,
489 blitwidth, blitheight,
490 rect->MinX - n->leftedge, rect->MinY - n->topedge, rect->MinX, rect->MinY));
492 if (HIDD_BM_ObtainDirectAccess(n->bm, &baseaddress, &width, &height, &banksize, &memsize))
494 DREDRAWBM(bug("[Compositor:%s] Alpha baseaddress @ 0x%p\n", __PRETTY_FUNCTION__, baseaddress));
495 OOP_GetAttr(n->bm, aHidd_BitMap_BytesPerRow, &modulo);
496 HIDD_BM_PutAlphaImage(renderTarget, compdata->gfx , baseaddress + ((rect->MinY - n->topedge) * modulo) + ((rect->MinX - n->leftedge) << 2), modulo,
497 rect->MinX, rect->MinY, blitwidth, blitheight);
498 HIDD_BM_ReleaseDirectAccess(n->bm);
503 static inline void HIDDCompositorFillRect(struct HIDDCompositorData *compdata, OOP_Object *renderTarget, ULONG MinX, ULONG MinY, ULONG MaxX, ULONG MaxY)
505 DREDRAWSCR(bug("[Compositor:%s] Filling [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
506 MinX, MinY, MaxX, MaxY));
508 HIDD_BM_FillRect(renderTarget, compdata->gc,
509 MinX, MinY, MaxX, MaxY);
513 static VOID HIDDCompositorRedrawAlphaRegions(struct HIDDCompositorData *compdata, struct Rectangle *drawrect)
515 OOP_Object *renderTarget = compdata->displaybitmap;
516 struct Rectangle alpharect;
517 struct StackBitMapNode *n;
518 struct BitMap *backbm;
520 if (compdata->intermedbitmap)
521 renderTarget = compdata->intermedbitmap;
523 DREDRAWSCR(if (drawrect){ bug("[Compositor:%s] Rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT((*drawrect))); })
525 OOP_GetAttr(renderTarget, aHidd_BitMap_BMStruct, (IPTR *)&backbm);
527 // Alpha Regions are drawn in reverse order incase they overlap..
528 for (n = (struct StackBitMapNode *)compdata->bitmapstack.mlh_TailPred;
529 n->n.mln_Pred; n = (struct StackBitMapNode *)n->n.mln_Pred)
531 if ((n->sbmflags & STACKNODEF_VISIBLE) &&
532 (n->sbmflags & COMPF_ALPHA) &&
533 (n->screenregion))
535 DREDRAWSCR(bug("[Compositor:%s] Alpha Screen Region @ 0x%p HiddBitMap @ 0x%p [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
536 n->screenregion, n->bm, _RECT(n->screenvisiblerect)));
538 DREDRAWSCR(bug("[Compositor:%s] Compositing Visible Alpha Regions..\n", __PRETTY_FUNCTION__));
540 struct RegionRectangle *srrect = n->screenregion->RegionRectangle;
541 while (srrect)
543 alpharect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
544 alpharect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
545 alpharect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
546 alpharect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
548 if (!(drawrect) || AndRectRect(drawrect, &alpharect, &alpharect))
550 DREDRAWSCR(bug("[Compositor:%s] Alpha-Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(alpharect)));
552 if ((n->prealphacomphook) && (backbm != NULL))
554 struct HIDD_BackFillHookMsg preprocessmsg;
555 preprocessmsg.bounds = &alpharect;
556 preprocessmsg.offsetx = 0;
557 preprocessmsg.offsety = 0;
558 CallHookPkt(n->prealphacomphook, backbm, &preprocessmsg);
561 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &alpharect);
562 if (renderTarget == compdata->displaybitmap)
563 HIDD_BM_UpdateRect(compdata->displaybitmap,
564 alpharect.MinX, alpharect.MinY,
565 alpharect.MaxX - alpharect.MinX + 1,
566 alpharect.MaxY - alpharect.MinY + 1);
568 srrect = srrect->Next;
574 static VOID HIDDCompositorRedrawVisibleRegions(struct HIDDCompositorData *compdata, struct Rectangle *drawrect)
576 OOP_Object *renderTarget = compdata->displaybitmap;
577 struct Region *dispvisregion = NULL;
578 struct Rectangle tmprect;
579 struct BitMap *clearbm;
580 struct StackBitMapNode *n;
582 DREDRAWSCR(bug("[Compositor:%s] Redrawing Display (GfxBase @ 0x%p)\n", __PRETTY_FUNCTION__, GfxBase));
584 if (!(drawrect))
586 /* Recalculate visible regions */
587 HIDDCompositorRecalculateVisibleRegions(compdata);
590 if ((compdata->flags & COMPSTATEF_HASALPHA) && (compdata->intermedbitmap))
591 renderTarget = compdata->intermedbitmap;
593 if ((dispvisregion = NewRegion()) != NULL)
595 if (drawrect)
596 OrRectRegion(dispvisregion, drawrect);
597 else
598 OrRectRegion(dispvisregion, &compdata->displayrect);
600 DRECALC(bug("[Compositor:%s] Display rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(compdata->displayrect)));
602 ForeachNode(&compdata->bitmapstack, n)
604 if ((n->sbmflags & STACKNODEF_VISIBLE) &&
605 (!(n->sbmflags & COMPF_ALPHA)) &&
606 (n->screenregion))
608 DREDRAWSCR(bug("[Compositor:%s] Screen Region @ 0x%p HiddBitMap @ 0x%p [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
609 n->screenregion, n->bm, _RECT(n->screenvisiblerect)));
611 DREDRAWSCR(bug("[Compositor:%s] Redrawing Visible Screen Regions..\n", __PRETTY_FUNCTION__));
612 // Render the visable regions ..
613 struct RegionRectangle * srrect = n->screenregion->RegionRectangle;
614 while (srrect)
616 tmprect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
617 tmprect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
618 tmprect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
619 tmprect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
621 if (!(drawrect) || AndRectRect(drawrect, &tmprect, &tmprect))
623 DREDRAWSCR(bug("[Compositor:%s] Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
625 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &tmprect);
626 if (renderTarget == compdata->displaybitmap)
627 HIDD_BM_UpdateRect(compdata->displaybitmap,
628 tmprect.MinX, tmprect.MinY,
629 tmprect.MaxX - tmprect.MinX + 1,
630 tmprect.MaxY - tmprect.MinY + 1);
632 srrect = srrect->Next;
634 ClearRegionRegion(n->screenregion, dispvisregion);
637 OOP_GetAttr(renderTarget, aHidd_BitMap_BMStruct, (IPTR *)&clearbm);
639 struct RegionRectangle * dispclrrect = dispvisregion->RegionRectangle;
640 while (dispclrrect)
642 struct HIDD_BackFillHookMsg clearmsg;
644 tmprect.MinX = dispclrrect->bounds.MinX + dispvisregion->bounds.MinX;
645 tmprect.MinY = dispclrrect->bounds.MinY + dispvisregion->bounds.MinY;
646 tmprect.MaxX = dispclrrect->bounds.MaxX + dispvisregion->bounds.MinX;
647 tmprect.MaxY = dispclrrect->bounds.MaxY + dispvisregion->bounds.MinY;
649 if (!(drawrect) || AndRectRect(drawrect, &tmprect, &tmprect))
651 DREDRAWSCR(bug("[Compositor:%s] Render Display Void Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
653 if (clearbm != NULL)
655 clearmsg.bounds = &tmprect;
656 clearmsg.offsetx = 0;
657 clearmsg.offsety = 0;
658 CallHookPkt(compdata->backfillhook, clearbm, &clearmsg);
661 if (renderTarget == compdata->displaybitmap)
662 HIDD_BM_UpdateRect(compdata->displaybitmap,
663 tmprect.MinX, tmprect.MinY,
664 tmprect.MaxX - tmprect.MinX + 1,
665 tmprect.MaxY - tmprect.MinY + 1);
667 dispclrrect = dispclrrect->Next;
669 if (compdata->flags & COMPSTATEF_HASALPHA)
671 HIDDCompositorRedrawAlphaRegions(compdata, drawrect);
673 DisposeRegion(dispvisregion);
675 if (renderTarget != compdata->displaybitmap)
677 DREDRAWSCR(bug("[Compositor:%s] Copying Alpha Intermediary BitMap\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
678 if (!(drawrect))
680 HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
681 compdata->displayrect.MinX, compdata->displayrect.MinY,
682 compdata->displaybitmap,
683 compdata->displayrect.MinX, compdata->displayrect.MinY,
684 compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
685 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
686 compdata->gc);
687 HIDD_BM_UpdateRect(compdata->displaybitmap,
688 compdata->displayrect.MinX, compdata->displayrect.MinY,
689 compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
690 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1);
692 else
694 HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
695 drawrect->MinX, drawrect->MinY,
696 compdata->displaybitmap,
697 drawrect->MinX, drawrect->MinY,
698 drawrect->MaxX - drawrect->MinX + 1,
699 drawrect->MaxY - drawrect->MinY + 1,
700 compdata->gc);
701 HIDD_BM_UpdateRect(compdata->displaybitmap,
702 drawrect->MinX, drawrect->MinY,
703 drawrect->MaxX - drawrect->MinX + 1,
704 drawrect->MaxY - drawrect->MinY + 1);
711 There are several cases that needs to be handled in this code. They are documented
712 below. Please read it before making changes.
713 etb = existing topbitmap
714 ntb = new top bitmap
715 sb = screen bitmap
716 cb = composited bitmap
717 fs = covers full screen
718 nfs = not covers full screen
719 mA = mode "A"
720 mB = mode "B"
721 disp() = dispose
722 new() = new
724 The resulting mode is always that of screen bitmap as set in "effect" column.
725 The composited bitmap always matches the resulting screen mode or is NULL.
727 | exiting screen situation | change | effect |
728 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - SAME MODE |
729 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mA | sb==ntb, cb==NULL |
730 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
731 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
732 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb, cb!=NULL |
733 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
734 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - SAME MODE |
735 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
736 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
737 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
738 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
739 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
742 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - DIFFERENT MODES |
743 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mB | sb==ntb, cb==NULL |
744 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
745 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
746 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mB | new(cb), sb==cb, cb!=NULL |
747 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
748 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - DIFFERENT MODES |
749 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
750 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
751 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
752 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
753 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
756 | USE CASE: DRAGGING SCREEN DOWN |
757 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb |
758 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb |
759 | USE CASE: DRAGGING SCREEN UP |
760 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==etb |
761 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
763 Resulting rules (order matters):
765 (a) if ((cb!=NULL) && (etb->mode!=ntb->mode)) {dispose(cb), cb=NULL}
766 (b) if ((ntb->nfs) && (cb==NULL)) new(cb)
767 (c) if (ntb->nfs) sb=cb
768 (d) if (ntb->fs) sb=ntb
770 Additional rule:
771 (e) if (oldsb!=sb) modeswitch(sb)
773 02.09.2011: we don't remember sb any more because we don't handle it in any way. Instead
774 we either have or don't have displaybitmap. If we have it, composition
775 is on (sb = cb). If we don't have it, composition is off (sb = ntb).
777 static BOOL HIDDCompositorToggleCompositing(struct HIDDCompositorData *compdata, BOOL newtop)
780 * If the topbitmap covers the complete screen, show it instead of
781 * displaybitmap. Remember that screen bitmap -> composited bitmap
782 * mirroring has a negative impact on performance.
784 OOP_Object *oldcompositedbitmap = compdata->displaybitmap;
785 struct StackBitMapNode *topnode = (struct StackBitMapNode *)compdata->bitmapstack.mlh_Head;
786 OOP_Object *newsdispbitmap = NULL;
787 struct BitMap *tmpBM;
788 struct TagItem bmtags[2];
790 BOOL ok = TRUE, composit = FALSE;
792 /* (a) If mode change is needed, enforce opening a new screen */
793 if (compdata->modeschanged)
795 DTOGGLE(bug("[Compositor:%s] Display Mode changed\n", __PRETTY_FUNCTION__));
796 compdata->displaybitmap = NULL;
799 bmtags[0].ti_Tag = BMATags_DisplayID; bmtags[0].ti_Data = (compdata->displayid | compdata->displaymode);
800 bmtags[1].ti_Tag = TAG_DONE; bmtags[1].ti_Data = TAG_DONE;
802 if ((topnode->topedge > 0) || ((compdata->displayrect.MaxY - compdata->displayrect.MinY + 1) > OOP_GET(topnode->bm, aHidd_BitMap_Height)))
803 composit = TRUE;
804 else if ((topnode->leftedge > 0) || ((compdata->displayrect.MaxX - compdata->displayrect.MinX + 1) > OOP_GET(topnode->bm, aHidd_BitMap_Width)))
805 composit = TRUE;
806 else if (topnode->sbmflags & COMPF_ALPHA)
807 composit = TRUE;
809 if (composit)
811 /* (b) */
812 if (compdata->displaybitmap == NULL)
815 * displaybitmap == NULL means we were in passthrough mode before,
816 * or have just changed display mode - set up screen for composition.
818 DTOGGLE(bug("[Compositor:%s] Initialising Display-Compositor..\n", __PRETTY_FUNCTION__));
820 if (compdata->fb)
823 * If our display driver uses a framebuffer, we can reuse it.
824 * Copy its original contents back into the bitmap which it replaced,
825 * then change framebuffer's video mode.
826 * Framebuffer is the only bitmap which can change its ModeID on the fly.
828 DTOGGLE(bug("[Compositor:%s] Using Display Famebuffer HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__, compdata->fb));
830 /* Do this comparison in order not to show the framebuffer twice */
831 if (oldcompositedbitmap != compdata->fb)
834 * 1. It's legal to show the framebuffer itself. This causes copying
835 * back old bitmap contents and detaching from it.
836 * 2. The result of this will always match compdata->fb.
837 * 3. Internally this is a simple blit operation, it can't fail.
839 DTOGGLE(bug("[Compositor:%s] Copying old Famebuffer BitMap\n", __PRETTY_FUNCTION__));
840 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, compdata->fb, fHidd_Gfx_Show_CopyBack);
843 /* Switch display mode on the framebuffer. */
844 OOP_SetAttrsTags(compdata->fb, aHidd_BitMap_ModeID, compdata->displaymode, TAG_DONE);
845 /* We are now compositing on the framebuffer */
846 compdata->displaybitmap = compdata->fb;
848 else
851 * There's no framebuffer.
852 * Create a new bitmap that will be used for compositing.
855 tmpBM = AllocBitMap(compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
856 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
857 compdata->displaydepth,
858 BMF_DISPLAYABLE|BMF_CHECKVALUE, (struct BitMap *)bmtags);
859 if (tmpBM)
861 compdata->displaybitmap = HIDD_BM_OBJ(tmpBM);
862 DTOGGLE(bug("[Compositor:%s] Created Compositor Display BitMap @ 0x%p [HiddBitMap @ 0x%p]\n", __PRETTY_FUNCTION__, tmpBM, compdata->displaybitmap));
864 /* Mode changed, this bitmap will be shown later */
865 newsdispbitmap = compdata->displaybitmap;
867 /* NewBitMap can fail, handle this */
868 if (!newsdispbitmap)
869 ok = FALSE;
873 else /* if (compdata->displaybitmap == NULL) */
876 * We are already in compositing mode and will stay in it.
877 * Do not destroy our working bitmap.
879 oldcompositedbitmap = NULL;
882 if ((compdata->flags & COMPSTATEF_HASALPHA) && !(compdata->intermedbitmap))
884 tmpBM = AllocBitMap(compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
885 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
886 compdata->displaydepth,
887 BMF_CHECKVALUE, (struct BitMap *)bmtags);
888 if (tmpBM)
890 compdata->intermedbitmap = HIDD_BM_OBJ(tmpBM);
891 DTOGGLE(bug("[Compositor:%s] Allocated Alpha Intermediary BitMap @ 0x%p [HiddBitMap @ 0x%p]\n", __PRETTY_FUNCTION__, tmpBM, compdata->intermedbitmap));
895 * (c) Here composition is turned on (displaybitmap != NULL).
896 * Redraw bitmap stack - compensate possible changes
898 if (ok)
899 HIDDCompositorRedrawVisibleRegions(compdata, NULL);
901 else if (oldcompositedbitmap || newtop)
904 * (d) Set passthrough mode and display the frontmost bitmap.
905 * This is also triggered by 'newtop' parameter, which tells us
906 * that frontmost bitmap has been changed, and we need to display a new one.
907 * Old displaybitmap has been remembered in the beginning. If it's not
908 * NULL, it will be destroyed in the end.
910 newsdispbitmap = compdata->topbitmap;
911 compdata->displaybitmap = NULL;
914 DTOGGLE(bug("[Compositor:%s] oldcompbm 0x%p, topbm 0x%p, dispbm 0x%p, newscreenbm 0x%p\n", __PRETTY_FUNCTION__,
915 oldcompositedbitmap, compdata->topbitmap, compdata->displaybitmap, newsdispbitmap));
918 * (e) If the screenbitmap changed, show the new screenbitmap.
919 * We do it after refreshing, for better visual appearance.
921 if (newsdispbitmap)
923 IPTR w, h;
925 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, newsdispbitmap, fHidd_Gfx_Show_CopyBack);
926 DTOGGLE(bug("[Compositor:%s] Displayed HiddBitMap 0x%p, Show returned 0x%p\n", __PRETTY_FUNCTION__, newsdispbitmap, compdata->screenbitmap));
928 /* After Show we need Update for mirroring drivers */
929 if (compdata->screenbitmap)
931 OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Width, &w);
932 OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Height, &h);
933 HIDD_BM_UpdateRect(compdata->screenbitmap, 0, 0, w, h);
938 * (a) - disposing of oldcompositingbitmap needs to happen after mode switch
939 * since it could have been the current screenbitmap
941 if (oldcompositedbitmap && (oldcompositedbitmap != compdata->fb))
943 struct BitMap *freebm;
945 DTOGGLE(bug("[Compositor:%s] Disposing old working bitmap 0x%p\n", __PRETTY_FUNCTION__, oldcompositedbitmap));
947 OOP_GetAttr(oldcompositedbitmap, aHidd_BitMap_BMStruct, (IPTR *)&freebm);
948 if (freebm != NULL)
950 FreeBitMap(freebm);
952 else
953 HIDD_Gfx_DisposeBitMap(compdata->gfx, oldcompositedbitmap);
957 /* Handled */
958 compdata->modeschanged = FALSE;
960 return ok;
963 static VOID HIDDCompositorPurgeBitMapStack(struct HIDDCompositorData * compdata)
965 struct StackBitMapNode * curr, * next;
967 ForeachNodeSafe(&compdata->bitmapstack, curr, next)
969 if (curr->screenregion)
970 DisposeRegion(curr->screenregion);
972 FreeMem(curr, sizeof(struct StackBitMapNode));
975 NEWLIST(&compdata->bitmapstack);
978 static void HIDDCompositorShowSingle(struct HIDDCompositorData *compdata, OOP_Object *bm)
980 /* Show the single top bitmap */
981 compdata->topbitmap = bm;
982 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, bm, fHidd_Gfx_Show_CopyBack);
984 /* Dispose working bitmap (if any) */
985 if (compdata->displaybitmap)
987 /* Be careful with the framebuffer */
988 if (compdata->displaybitmap != compdata->fb)
989 HIDD_Gfx_DisposeBitMap(compdata->gfx, compdata->displaybitmap);
991 /* This will deactivate us */
992 compdata->displaybitmap = NULL;
996 /* Emergency error recovery function */
997 static void HIDDCompositorReset(struct HIDDCompositorData *compdata)
999 /* Purge bitmap stack */
1000 HIDDCompositorPurgeBitMapStack(compdata);
1003 * Reset our internal state so that next BitMapStackChanged
1004 * causes complete reinitialization.
1006 compdata->displaymode = vHidd_ModeID_Invalid;
1007 compdata->screenbitmap = NULL;
1009 compdata->flags &= ~COMPSTATEF_HASALPHA;
1012 VOID CompositorParseConfig(struct HIDDCompositorData *compdata)
1014 struct RDArgs *rdargs;
1015 IPTR CompArgs[NOOFARGS] = { 0 };
1016 TEXT CompConfig[1024];
1018 /* use default amiga-like capabailities */
1019 compdata->capabilities = COMPF_ABOVE;
1021 rdargs = AllocDosObjectTags(DOS_RDARGS, TAG_END);
1022 if (rdargs != NULL)
1024 if (GetVar(COMPOSITOR_PREFS, CompConfig, 1024, GVF_GLOBAL_ONLY) != -1)
1026 rdargs->RDA_Source.CS_Buffer = CompConfig;
1027 rdargs->RDA_Source.CS_Length = strlen(rdargs->RDA_Source.CS_Buffer);
1028 rdargs->RDA_DAList = (IPTR)NULL;
1029 rdargs->RDA_Buffer = NULL;
1030 rdargs->RDA_BufSiz = 0;
1031 rdargs->RDA_ExtHelp = NULL;
1032 rdargs->RDA_Flags = 0;
1034 if (ReadArgs(COMPOSITOR_PEFSTEMPLATE, CompArgs, rdargs) != NULL)
1036 if (CompArgs[ARG_ABOVE])
1037 compdata->capabilities |= COMPF_ABOVE;
1038 else
1039 compdata->capabilities &= ~COMPF_ABOVE;
1041 if (CompArgs[ARG_BELOW])
1042 compdata->capabilities |= COMPF_BELOW;
1043 else
1044 compdata->capabilities &= ~COMPF_BELOW;
1046 if (CompArgs[ARG_LEFT])
1047 compdata->capabilities |= COMPF_LEFT;
1048 else
1049 compdata->capabilities &= ~COMPF_LEFT;
1051 if (CompArgs[ARG_RIGHT])
1052 compdata->capabilities |= COMPF_RIGHT;
1053 else
1054 compdata->capabilities &= ~COMPF_RIGHT;
1056 if (CompArgs[ARG_ALPHA])
1057 compdata->capabilities |= COMPF_ALPHA;
1058 else
1059 compdata->capabilities &= ~COMPF_ALPHA;
1061 FreeArgs(rdargs);
1064 FreeDosObject(DOS_RDARGS, rdargs);
1068 AROS_UFH3(void, CompositorDefaultBackFillFunc,
1069 AROS_UFHA(struct Hook * , h, A0),
1070 AROS_UFHA(struct BitMap * , bm, A2),
1071 AROS_UFHA(struct HIDD_BackFillHookMsg * , msg, A1))
1073 AROS_USERFUNC_INIT
1075 struct HIDDCompositorData *compdata = h->h_Data;
1077 D(bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata));
1079 HIDDCompositorFillRect(compdata, HIDD_BM_OBJ(bm), msg->bounds->MinX, msg->bounds->MinY, msg->bounds->MaxX, msg->bounds->MaxY);
1081 AROS_USERFUNC_EXIT
1084 /* PUBLIC METHODS */
1085 OOP_Object *METHOD(Compositor, Root, New)
1087 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
1089 if (o)
1091 OOP_MethodID disposemid;
1092 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1094 D(bug("[%s] Compositor @ 0x%p, data @ 0x%p\n", __PRETTY_FUNCTION__, o, compdata));
1096 CompositorParseConfig(compdata);
1098 compdata->capabilities = (ULONG)GetTagData(aHidd_Compositor_State, compdata->capabilities, msg->attrList);
1100 D(bug("[%s] Compositor Capabilities: %08lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
1102 compdata->displaymode = vHidd_ModeID_Invalid;
1104 NEWLIST(&compdata->bitmapstack);
1106 compdata->defaultbackfill.h_Entry = (HOOKFUNC)AROS_ASMSYMNAME(CompositorDefaultBackFillFunc);
1107 compdata->defaultbackfill.h_Data = compdata;
1108 compdata->backfillhook = &compdata->defaultbackfill;
1110 InitSemaphore(&compdata->semaphore);
1112 compdata->displayid = (ULONG)GetTagData(aHidd_Compositor_DisplayID, 0, msg->attrList);
1113 compdata->gfx = (OOP_Object *)GetTagData(aHidd_Compositor_GfxHidd, 0, msg->attrList);
1114 compdata->fb = (OOP_Object *)GetTagData(aHidd_Compositor_FrameBuffer, 0, msg->attrList);
1116 D(bug("[%s] DisplayID %08lx for Gfx Driver @ 0x%p\n", __PRETTY_FUNCTION__, compdata->displayid, compdata->gfx));
1118 GfxBase = (APTR)OpenLibrary("graphics.library", 41);
1119 IntuitionBase = (APTR)OpenLibrary("intuition.library", 50);
1121 /* GfxHidd is mandatory */
1122 if ((compdata->GraphicsBase) && (compdata->gfx != NULL))
1124 /* Create GC object that will be used for drawing operations */
1125 compdata->gc = HIDD_Gfx_NewGC(compdata->gfx, NULL);
1127 D(bug("[%s] Compositor GC @ %p\n", __PRETTY_FUNCTION__, compdata->gc));
1129 if ((compdata->gfx) && (compdata->gc))
1130 return o;
1133 /* Creation failed */
1134 disposemid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
1135 OOP_CoerceMethod(cl, o, &disposemid);
1138 return NULL;
1141 void METHOD(Compositor, Root, Dispose)
1145 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1146 bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata);
1149 OOP_DoSuperMethod(cl, o, &msg->mID);
1152 VOID METHOD(Compositor, Root, Get)
1154 ULONG idx;
1156 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1158 if (IS_COMPOSITOR_ATTR(msg->attrID, idx))
1160 switch (idx)
1162 case aoHidd_Compositor_Capabilities:
1164 *msg->storage = (IPTR)CAPABILITY_FLAGS;
1165 D(bug("[%s] Compositor Capabilities: %lx\n", __PRETTY_FUNCTION__, *msg->storage));
1166 return;
1168 case aoHidd_Compositor_State:
1170 *msg->storage = (IPTR)(compdata->capabilities & CAPABILITY_FLAGS);
1171 D(bug("[%s] Compositor State: %lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
1172 return;
1174 case aoHidd_Compositor_BackFillHook:
1176 D(bug("[%s] BackFillHook: 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook));
1177 *msg->storage = (IPTR)compdata->backfillhook;
1178 return;
1182 OOP_DoSuperMethod(cl, o, &msg->mID);
1185 VOID METHOD(Compositor, Root, Set)
1187 ULONG idx;
1189 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1190 struct TagItem *tag, *tstate = msg->attrList;
1192 while ((tag = NextTagItem(&tstate)))
1194 if (IS_COMPOSITOR_ATTR(tag->ti_Tag, idx))
1196 switch (idx)
1198 case aoHidd_Compositor_State:
1200 D(bug("[%s] Compositor Capabilities State: %lx -> ", __PRETTY_FUNCTION__, compdata->capabilities));
1201 compdata->capabilities = (ULONG)(tag->ti_Data & CAPABILITY_FLAGS);
1202 D(bug("%lx\n", compdata->capabilities));
1203 break;
1205 case aoHidd_Compositor_BackFillHook:
1207 if (tag->ti_Data)
1209 D(bug("[%s] BackFillHook: 0x%p -> 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook, tag->ti_Data));
1210 compdata->backfillhook = (struct Hook *)tag->ti_Data;
1212 else
1214 D(bug("[%s] Default BackFillHook\n", __PRETTY_FUNCTION__));
1215 compdata->backfillhook = &compdata->defaultbackfill;
1217 break;
1223 OOP_DoSuperMethod(cl, o, &msg->mID);
1226 OOP_Object *METHOD(Compositor, Hidd_Compositor, BitMapStackChanged)
1228 struct HIDD_ViewPortData *vpdata;
1229 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1230 struct StackBitMapNode *n;
1231 struct Screen *bmScreen;
1232 OOP_Object *bmpxfmt;
1233 int bmstdfmt;
1234 BOOL newtop = FALSE;
1235 BOOL ok = TRUE;
1237 DSTACK(bug("[Compositor] %s: Top bitmap: 0x%lx\n", __PRETTY_FUNCTION__, msg->data->Bitmap));
1239 LOCK_COMPOSITOR_WRITE
1241 /* Free all items which are already on the list */
1242 HIDDCompositorPurgeBitMapStack(compdata);
1244 if (!msg->data)
1246 UNLOCK_COMPOSITOR
1248 DSTACK(bug("[Compositor] %s: No ViewPort specified\n", __PRETTY_FUNCTION__));
1250 /* Blank screen */
1251 HIDDCompositorShowSingle(compdata, NULL);
1253 /* We know we are inactive after this */
1254 *msg->active = FALSE;
1255 /* This can return NULL, it's okay */
1256 return compdata->screenbitmap;
1259 /* Copy bitmaps pointers to our stack */
1260 for (vpdata = msg->data; vpdata; vpdata = vpdata->Next)
1262 n = AllocMem(sizeof(struct StackBitMapNode), MEMF_ANY | MEMF_CLEAR);
1263 if (!n)
1266 * Error happened.
1267 * We need to reset own state and return NULL. graphics.library
1268 * falls back to no composition in this case.
1270 DSTACK(bug("[Compositor] %s: Error allocating StackBitMapNode!!!\n", __PRETTY_FUNCTION__));
1272 ok = FALSE;
1273 break;
1276 DSTACK(bug("[Compositor] %s: ViewPort 0x%p, offset (%d, %d)\n", __PRETTY_FUNCTION__, vpdata->vpe->ViewPort, vpdata->vpe->ViewPort->DxOffset, vpdata->vpe->ViewPort->DyOffset));
1278 n->bm = vpdata->Bitmap;
1279 n->sbmflags = STACKNODEF_DISPLAYABLE;
1280 n->leftedge = vpdata->vpe->ViewPort->DxOffset;
1281 n->topedge = vpdata->vpe->ViewPort->DyOffset;
1283 n->screenregion = NewRegion();
1285 if ((bmScreen = HIDDCompositorFindBitMapScreen(compdata, n->bm)) != NULL)
1287 DSTACK(bug("[Compositor] %s: Screen @ 0x%p\n", __PRETTY_FUNCTION__, bmScreen));
1288 GetAttr(SA_CompositingFlags, (Object *)bmScreen, &n->sbmflags);
1289 DSTACK(bug("[Compositor] %s: CompositingFlags %08x\n", __PRETTY_FUNCTION__, n->sbmflags));
1290 n->sbmflags |= STACKNODEF_DISPLAYABLE;
1291 if (n->sbmflags & COMPF_ALPHA)
1293 GetAttr(SA_AlphaPreCompositHook, (Object *)bmScreen, (IPTR *)&n->prealphacomphook);
1294 DSTACK(bug("[Compositor] %s: Pre-AlphaComposit Hook @ 0x%p\n", __PRETTY_FUNCTION__, n->prealphacomphook));
1298 if (n->sbmflags & COMPF_ALPHA)
1300 bmpxfmt = (OOP_Object *)OOP_GET(n->bm, aHidd_BitMap_PixFmt);
1301 bmstdfmt = (int)OOP_GET(bmpxfmt, aHidd_PixFmt_StdPixFmt);
1302 DSTACK(bug("[Compositor] %s: Screen BitMap PixFmt %lx @ 0x%p\n", __PRETTY_FUNCTION__, bmstdfmt, bmpxfmt));
1304 switch (bmstdfmt)
1306 case vHidd_StdPixFmt_ARGB32:
1307 case vHidd_StdPixFmt_BGRA32:
1308 case vHidd_StdPixFmt_RGBA32:
1309 case vHidd_StdPixFmt_ABGR32:
1311 DSTACK(bug("[Compositor] %s: Screen BitMap has Alpha\n", __PRETTY_FUNCTION__));
1313 compdata->flags |= COMPSTATEF_HASALPHA;
1314 break;
1316 default:
1318 n->sbmflags &= ~COMPF_ALPHA;
1319 break;
1324 if (!(n->sbmflags & COMPF_ALPHA))
1326 if ((((BOOL)OOP_GET(n->bm, aHidd_BitMap_Displayable)) != TRUE))
1327 n->sbmflags &= ~STACKNODEF_DISPLAYABLE;
1329 AddTail((struct List *)&compdata->bitmapstack, (struct Node *)n);
1332 /* Switch mode if needed */
1333 UpdateDisplayMode(compdata);
1335 if (msg->data->Bitmap != compdata->topbitmap)
1337 /* Set the new pointer to top bitmap */
1338 compdata->topbitmap = msg->data->Bitmap;
1339 newtop = TRUE;
1342 if (ok)
1345 * Validate bitmap offsets - they might not match the compositing rules taking
1346 * new displayedwidth/displayedheight values
1348 ForeachNode(&compdata->bitmapstack, n)
1350 HIDDCompositorValidateBitMapPositionChange(n->bm, &n->leftedge, &n->topedge,
1351 compdata->displayrect.MaxX + 1, compdata->displayrect.MaxY + 1);
1352 DSTACK(bug("[Compositor] %s: Bitmap 0x%p, display size %d x %d, validated position (%ld, %ld)\n", __PRETTY_FUNCTION__,
1353 n->bm, compdata->displayrect.MaxX + 1, compdata->displayrect.MaxY + 1,
1354 n->leftedge, n->topedge));
1357 /* Toogle compositing based on screen positions */
1358 ok = HIDDCompositorToggleCompositing(compdata, newtop);
1361 /* Handle error */
1362 if (!ok)
1364 HIDDCompositorReset(compdata);
1365 HIDDCompositorShowSingle(compdata, msg->data->Bitmap);
1368 UNLOCK_COMPOSITOR
1370 DSTACK(bug("[%s] Done, composited bitmap 0x%p\n", __PRETTY_FUNCTION__, compdata->displaybitmap));
1372 /* Tell if the composition is active */
1373 *msg->active = compdata->displaybitmap ? TRUE : FALSE;
1374 /* Return actually displayed bitmap */
1375 return compdata->screenbitmap;
1378 VOID METHOD(Compositor, Hidd_Compositor, BitMapRectChanged)
1380 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1381 OOP_Object *renderTarget;
1383 if (compdata->displaybitmap)
1385 /* Composition is active, handle redraw if the bitmap is on screen */
1386 struct StackBitMapNode *n;
1388 DUPDATE(bug("[%s] Bitmap 0x%p\n", __PRETTY_FUNCTION__, msg->bm));
1390 LOCK_COMPOSITOR_READ
1392 if (compdata->intermedbitmap)
1393 renderTarget = compdata->intermedbitmap;
1394 else
1395 renderTarget = compdata->displaybitmap;
1397 n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1398 if (n && (n->sbmflags & STACKNODEF_VISIBLE))
1400 struct Rectangle srcrect, dstandvisrect;
1402 srcrect.MinX = n->leftedge + msg->x;
1403 srcrect.MinY = n->topedge + msg->y;
1404 srcrect.MaxX = srcrect.MinX + msg->width - 1;
1405 srcrect.MaxY = srcrect.MinY + msg->height - 1;
1406 DUPDATE(bug("[%s] Bitmap rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, msg->x, msg->y, msg->x + msg->width - 1, msg->y + msg->height - 1));
1408 DUPDATE(bug("[%s] Screen-relative rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(srcrect)));
1410 struct RegionRectangle * srrect = n->screenregion->RegionRectangle;
1411 while (srrect)
1413 BOOL updateAlphaBmps = FALSE;
1415 dstandvisrect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
1416 dstandvisrect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
1417 dstandvisrect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
1418 dstandvisrect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
1420 if (AndRectRect(&srcrect, &dstandvisrect, &dstandvisrect))
1422 /* Intersection is valid. Blit. */
1423 DUPDATE(bug("[%s] Clipped rect (%d, %d) - (%d, %d)\n", __PRETTY_FUNCTION__, _RECT(dstandvisrect)));
1425 if (!(n->sbmflags & COMPF_ALPHA))
1427 if ((compdata->alpharegion) && (isRectInRegion(compdata->alpharegion, &dstandvisrect)))
1429 DUPDATE(bug("[%s] ** Bitmap in Alpha Region!\n", __PRETTY_FUNCTION__));
1430 updateAlphaBmps = TRUE;
1432 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &dstandvisrect);
1434 else
1436 updateAlphaBmps = FALSE;
1437 HIDDCompositorRedrawVisibleRegions(compdata, &dstandvisrect);
1440 if (updateAlphaBmps)
1441 HIDDCompositorRedrawAlphaRegions(compdata, &dstandvisrect);
1443 if (renderTarget != compdata->displaybitmap)
1445 HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
1446 dstandvisrect.MinX, dstandvisrect.MinY,
1447 compdata->displaybitmap,
1448 dstandvisrect.MinX, dstandvisrect.MinY,
1449 dstandvisrect.MaxX - dstandvisrect.MinX + 1,
1450 dstandvisrect.MaxY - dstandvisrect.MinY + 1,
1451 compdata->gc);
1454 HIDD_BM_UpdateRect(compdata->displaybitmap,
1455 dstandvisrect.MinX, dstandvisrect.MinY,
1456 dstandvisrect.MaxX - dstandvisrect.MinX + 1,
1457 dstandvisrect.MaxY - dstandvisrect.MinY + 1);
1459 srrect = srrect->Next;
1463 UNLOCK_COMPOSITOR
1465 DUPDATE(bug("[%s] Done\n", __PRETTY_FUNCTION__));
1467 else
1469 /* In order to speed things up, we handle passthrough ourselves here. */
1470 HIDD_BM_UpdateRect(msg->bm, msg->x, msg->y, msg->width, msg->height);
1474 IPTR METHOD(Compositor, Hidd_Compositor, BitMapPositionChange)
1476 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1477 struct StackBitMapNode *n;
1478 IPTR disp_width, disp_height;
1480 LOCK_COMPOSITOR_READ
1482 n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1483 if (n)
1485 /* The bitmap is on display. Validate against screen size */
1486 disp_width = compdata->displayrect.MaxX + 1;
1487 disp_height = compdata->displayrect.MaxY + 1;
1489 else
1491 /* The bitmap is not displayed yet. Validate against its own ModeID size. */
1492 HIDDT_ModeID modeid = vHidd_ModeID_Invalid;
1493 OOP_Object *bmfriend, *sync, *pf;
1495 OOP_GetAttr(msg->bm, aHidd_BitMap_ModeID, &modeid);
1497 if ((modeid == vHidd_ModeID_Invalid) && (OOP_GET(msg->bm, aHidd_BitMap_Compositable)))
1499 OOP_GetAttr(msg->bm, aHidd_BitMap_Friend, (IPTR *)&bmfriend);
1500 if (bmfriend)
1501 OOP_GetAttr(bmfriend, aHidd_BitMap_ModeID, &modeid);
1504 if (modeid == vHidd_ModeID_Invalid)
1507 * Nondisplayable bitmaps don't scroll.
1508 * In fact they simply can't get in here because MakeVPort() performs the validation.
1509 * But who knows what bug can slip into someone's software...
1511 UNLOCK_COMPOSITOR
1512 return FALSE;
1515 HIDD_Gfx_GetMode(compdata->gfx, modeid, &sync, &pf);
1516 OOP_GetAttr(sync, aHidd_Sync_HDisp, &disp_width);
1517 OOP_GetAttr(sync, aHidd_Sync_VDisp, &disp_height);
1520 DMOVE(bug("[%s] Validating bitmap 0x%p, position (%ld, %ld), limits %ld x %ld\n", __PRETTY_FUNCTION__,
1521 msg->bm, *msg->newxoffset, *msg->newyoffset, disp_width, disp_height));
1523 HIDDCompositorValidateBitMapPositionChange(msg->bm, msg->newxoffset, msg->newyoffset,
1524 disp_width, disp_height);
1526 DMOVE(bug("[%s] Validated position (%ld, %ld)\n", __PRETTY_FUNCTION__, *msg->newxoffset, *msg->newyoffset));
1528 if (n && ((*msg->newxoffset != n->leftedge) || (*msg->newyoffset != n->topedge)))
1530 DMOVE(bug("[%s] Old position (%ld, %ld)\n", __PRETTY_FUNCTION__, n->leftedge, n->topedge));
1532 /* Reflect the change if it happened */
1533 n->leftedge = *msg->newxoffset;
1534 n->topedge = *msg->newyoffset;
1536 if (compdata->topbitmap == msg->bm)
1539 * If this is the frontmost bitmap, we may want to toggle compositing,
1540 * if it starts/stops covering the whole screen at one point.
1541 * We don't need to call HIDDCompositorRedrawVisibleRegions() here because
1542 * HIDDCompositorToggleCompositing() does this itself, for improved
1543 * visual appearance.
1545 HIDDCompositorToggleCompositing(compdata, FALSE);
1547 else
1548 HIDDCompositorRedrawVisibleRegions(compdata, NULL);
1551 UNLOCK_COMPOSITOR
1553 /* Return active state */
1554 return compdata->displaybitmap ? TRUE : FALSE;
1557 IPTR METHOD(Compositor, Hidd_Compositor, BitMapValidate)
1559 if (IS_HIDD_BM(msg->bm))
1560 return TRUE;
1562 return FALSE;
1565 IPTR METHOD(Compositor, Hidd_Compositor, BitMapEnable)
1567 if (IS_HIDD_BM(msg->bm))
1569 if (!(OOP_GET(HIDD_BM_OBJ(msg->bm), aHidd_BitMap_Displayable)))
1571 struct TagItem composittags[] = {
1572 {aHidd_BitMap_Compositable, TRUE},
1573 {TAG_DONE , 0 }
1576 D(bug("[GfxCompositor]: Marking BitMap 0x%lx as Compositable\n", msg->bm));
1577 OOP_SetAttrs(HIDD_BM_OBJ(msg->bm), composittags);
1579 return TRUE;
1582 return FALSE;
1585 #define NUM_Compositor_Root_METHODS 4
1587 static const struct OOP_MethodDescr Compositor_Root_descr[] =
1589 {(OOP_MethodFunc)Compositor__Root__New, moRoot_New},
1590 {(OOP_MethodFunc)Compositor__Root__Dispose, moRoot_Dispose},
1591 {(OOP_MethodFunc)Compositor__Root__Get, moRoot_Get},
1592 {(OOP_MethodFunc)Compositor__Root__Set, moRoot_Set},
1593 {NULL, 0}
1596 #define NUM_Compositor_Hidd_Compositor_METHODS 5
1598 static const struct OOP_MethodDescr Compositor_Hidd_Compositor_descr[] =
1600 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapStackChanged, moHidd_Compositor_BitMapStackChanged},
1601 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapRectChanged, moHidd_Compositor_BitMapRectChanged},
1602 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapPositionChange, moHidd_Compositor_BitMapPositionChange},
1603 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapValidate, moHidd_Compositor_BitMapValidate},
1604 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapEnable, moHidd_Compositor_BitMapEnable},
1605 {NULL, 0}
1608 const struct OOP_InterfaceDescr Compositor_ifdescr[] =
1610 {Compositor_Root_descr, IID_Root, NUM_Compositor_Root_METHODS},
1611 {Compositor_Hidd_Compositor_descr, IID_Hidd_Compositor, NUM_Compositor_Hidd_Compositor_METHODS},
1612 {NULL, NULL}