"Composit" -> "Compositing"
[AROS.git] / workbench / devs / monitors / Compositor / compositorclass.c
blobf7ca4bed0c169ce7ac0c9fc578db3cb4a2fcbfc3
1 /*
2 Copyright © 2010-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 0
7 #if (DEBUG)
8 #define DTOGGLE(x) x
9 #define DMOVE(x) x
10 #define DRECALC(x) x
11 #define DREDRAWBM(x) x
12 #define DREDRAWSCR(x) x
13 #define DSTACK(x) x
14 #define DUPDATE(x) x
15 #else
16 #define DTOGGLE(x)
17 #define DMOVE(x)
18 #define DRECALC(x)
19 #define DREDRAWBM(x)
20 #define DREDRAWSCR(x)
21 #define DSTACK(x)
22 #define DUPDATE(x)
23 #endif
25 #include <aros/debug.h>
27 #include <clib/alib_protos.h>
28 #include <proto/exec.h>
29 #include <proto/dos.h>
30 #include <proto/graphics.h>
31 #include <proto/intuition.h>
32 #include <proto/oop.h>
33 #include <proto/utility.h>
35 #include <graphics/view.h>
36 #include <hidd/graphics.h>
38 #include "compositor_intern.h"
40 #define COMPOSITOR_PREFS "SYS/compositor.prefs"
41 #define COMPOSITOR_PEFSTEMPLATE "ABOVE/S,BELOW/S,LEFT/S,RIGHT/S,ALPHA/S"
43 #define CAPABILITY_FLAGS (COMPF_ABOVE|COMPF_BELOW|COMPF_LEFT|COMPF_RIGHT|COMPF_ALPHA)
45 enum
47 ARG_ABOVE = 0,
48 ARG_BELOW,
49 ARG_LEFT,
50 ARG_RIGHT,
51 ARG_ALPHA,
52 NOOFARGS
56 #ifdef GfxBase
57 #undef GfxBase
58 #endif
59 #define GfxBase compdata->GraphicsBase
60 #ifdef IntuitionBase
61 #undef IntuitionBase
62 #endif
63 #define IntuitionBase compdata->IntuitionBase
65 #define _RECT(x) x.MinX, x.MinY, x.MaxX, x.MaxY
67 #define MAX(a,b) a > b ? a : b
68 #define MIN(a,b) a < b ? a : b
70 BOOL isRectInRegion(struct Region *region, struct Rectangle *rect)
72 struct RegionRectangle *rrect = region->RegionRectangle;
74 while (rrect)
76 if (AndRectRect(&rrect->bounds, rect, NULL))
77 return TRUE;
79 rrect = rrect->Next;
81 return FALSE;
84 static struct StackBitMapNode * HIDDCompositorFindBitMapStackNode(struct HIDDCompositorData * compdata, OOP_Object * bm)
86 struct StackBitMapNode * n = NULL;
88 ForeachNode(&compdata->bitmapstack, n)
90 if (n->bm == bm)
91 return n;
94 return NULL;
97 struct Screen *HIDDCompositorFindBitMapScreen(struct HIDDCompositorData *compdata, OOP_Object *bm)
99 struct Screen *curScreen = NULL;
101 for (curScreen = IntuitionBase->FirstScreen; curScreen != NULL; curScreen = curScreen->NextScreen)
103 if (bm == HIDD_BM_OBJ(curScreen->RastPort.BitMap))
104 return curScreen;
107 return (struct Screen *)NULL;
110 static VOID HIDDCompositorValidateBitMapPositionChange(OOP_Object * bm, SIPTR *newxoffset, SIPTR *newyoffset, LONG displayedwidth, LONG displayedheight)
112 IPTR width, height;
113 LONG neglimit, poslimit;
115 OOP_GetAttr(bm, aHidd_BitMap_Width, &width);
116 OOP_GetAttr(bm, aHidd_BitMap_Height, &height);
118 /* Check x position */
119 if (width > displayedwidth)
121 neglimit = displayedwidth - width;
122 poslimit = 0;
124 else
126 neglimit = 0;
127 poslimit = displayedwidth - width;
130 if (*(newxoffset) > poslimit)
131 *(newxoffset) = poslimit;
132 if (*(newxoffset) < neglimit)
133 *(newxoffset) = neglimit;
135 /* Check y position */
136 if (height > displayedheight)
137 neglimit = displayedheight - height; /* Limit for scroll */
138 else
139 neglimit = 0;
140 poslimit = displayedheight - 15; /* Limit for drag */
142 if (*(newyoffset) > poslimit)
143 *(newyoffset) = poslimit;
144 if (*(newyoffset) < neglimit)
145 *(newyoffset) = neglimit;
148 static VOID HIDDCompositorRecalculateVisibleRegions(struct HIDDCompositorData *compdata)
150 struct StackBitMapNode *n = NULL, *tmpn;
151 struct Region *dispvisregion = NULL;
152 ULONG oldflags = compdata->flags;
154 DRECALC(bug("[Compositor:%s] Display rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(compdata->displayrect)));
157 * This function assumes bitmapstack is in correct Z order:
158 * from topmost to bottom most
160 if ((dispvisregion = NewRegion()) != NULL)
162 OrRectRegion(dispvisregion, &compdata->displayrect);
164 compdata->flags &= ~COMPSTATEF_HASALPHA;
165 if (compdata->alpharegion)
167 DisposeRegion(compdata->alpharegion);
168 compdata->alpharegion = NULL;
170 DRECALC(bug("[Compositor:%s] DisplayRegion @ 0x%p\n", __PRETTY_FUNCTION__, dispvisregion));
172 ForeachNodeSafe(&compdata->bitmapstack, n, tmpn)
174 /* Get bitmap bounding box in screen coordinates */
175 struct Rectangle tmprect;
177 n->sbmflags &= ~STACKNODEF_VISIBLE;
179 if (n->screenregion)
180 ClearRegion(n->screenregion);
181 else
182 n->screenregion = NewRegion();
184 if (n->screenregion)
186 struct RegionRectangle *srrect;
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 ((srrect = n->screenregion->RegionRectangle) != NULL)
200 while (srrect)
202 tmprect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
203 tmprect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
204 tmprect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
205 tmprect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
207 if (!(n->sbmflags & COMPF_ALPHA))
208 ClearRectRegion(dispvisregion, &tmprect);
209 else
211 compdata->flags |= COMPSTATEF_HASALPHA;
212 if (!(compdata->alpharegion))
213 compdata->alpharegion = NewRegion();
215 OrRectRegion(compdata->alpharegion, &tmprect);
217 srrect = srrect->Next;
220 if (!(compdata->capabilities & COMPF_ABOVE) && !(n->sbmflags & COMPF_ABOVE))
222 tmprect.MinX = compdata->displayrect.MinX;
223 tmprect.MaxX = compdata->displayrect.MaxX;
224 tmprect.MinY = compdata->displayrect.MinY;
225 tmprect.MaxY = n->topedge - 1;
226 ClearRectRegion(dispvisregion, &tmprect);
228 if (!(compdata->capabilities & COMPF_BELOW) && !(n->sbmflags & COMPF_BELOW))
230 tmprect.MinX = compdata->displayrect.MinX;
231 tmprect.MaxX = compdata->displayrect.MaxX;
232 tmprect.MinY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height);
233 tmprect.MaxY = compdata->displayrect.MaxY;
234 ClearRectRegion(dispvisregion, &tmprect);
236 if (!(compdata->capabilities & COMPF_LEFT) && !(n->sbmflags & COMPF_LEFT))
238 tmprect.MinX = compdata->displayrect.MinX;
239 tmprect.MaxX = n->leftedge - 1;
240 tmprect.MinY = n->topedge;
241 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
242 ClearRectRegion(dispvisregion, &tmprect);
244 if (!(compdata->capabilities & COMPF_RIGHT) && !(n->sbmflags & COMPF_RIGHT))
246 tmprect.MinX = n->leftedge + OOP_GET(n->bm, aHidd_BitMap_Width);
247 tmprect.MaxX = compdata->displayrect.MaxX;
248 tmprect.MinY = n->topedge;
249 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
250 ClearRectRegion(dispvisregion, &tmprect);
252 n->sbmflags |= STACKNODEF_VISIBLE;
255 DRECALC(bug("[Compositor:%s] HiddBitmap 0x%p, topedge %d, visible %d\n", __PRETTY_FUNCTION__,
256 n->bm, n->topedge, (n->sbmflags & STACKNODEF_VISIBLE)));
258 else
260 DRECALC(bug("[Compositor:%s] Failed to create Screen Region\n", __PRETTY_FUNCTION__));
263 DisposeRegion(dispvisregion);
264 if (compdata->flags != oldflags)
266 ULONG newflags = (~oldflags) & compdata->flags;
267 DRECALC(bug("[Compositor:%s] Newly set flags %08x\n", __PRETTY_FUNCTION__, newflags));
268 if ((!(newflags & COMPSTATEF_HASALPHA)) && (oldflags & COMPSTATEF_HASALPHA))
270 DRECALC(bug("[Compositor:%s] Alpha removed\n", __PRETTY_FUNCTION__));
271 if (compdata->alpharegion)
272 DisposeRegion(compdata->alpharegion);
274 compdata->alpharegion = NULL;
278 else
280 DRECALC(bug("[Compositor:%s] Failed to create Display Region\n", __PRETTY_FUNCTION__));
284 static inline void HIDDCompositorRedrawBitmap(struct HIDDCompositorData *compdata, OOP_Object *renderTarget, struct StackBitMapNode *n, struct Rectangle *rect)
286 /* The given rectangle is already in screen coordinate system here */
287 ULONG blitwidth = rect->MaxX - rect->MinX + 1;
288 ULONG blitheight = rect->MaxY - rect->MinY + 1;
290 DREDRAWBM(bug("[Compositor:%s] Redraw HiddBitMap 0x%p, Rect[%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, n->bm,
291 rect->MinX, rect->MinY, rect->MaxX, rect->MaxY));
293 if (!(n->sbmflags & COMPF_ALPHA))
295 DREDRAWBM(bug("[Compositor:%s] Blitting %dx%d [from %d, %d]\n", __PRETTY_FUNCTION__, blitwidth, blitheight,
296 rect->MinX - n->leftedge, rect->MinY - n->topedge));
298 HIDD_Gfx_CopyBox(compdata->gfx, n->bm,
299 /* Transform to source bitmap coord system */
300 rect->MinX - n->leftedge, rect->MinY - n->topedge,
301 renderTarget,
302 rect->MinX, rect->MinY, blitwidth, blitheight,
303 compdata->gc);
305 else
307 UBYTE *baseaddress;
308 ULONG width, height, banksize, memsize;
309 IPTR modulo;
311 DREDRAWBM(bug("[Compositor:%s] AlphaBlending %dx%d @ %d,%d to %d,%d\n", __PRETTY_FUNCTION__,
312 blitwidth, blitheight,
313 rect->MinX - n->leftedge, rect->MinY - n->topedge, rect->MinX, rect->MinY));
315 if (HIDD_BM_ObtainDirectAccess(n->bm, &baseaddress, &width, &height, &banksize, &memsize))
317 DREDRAWBM(bug("[Compositor:%s] Alpha baseaddress @ 0x%p\n", __PRETTY_FUNCTION__, baseaddress));
318 OOP_GetAttr(n->bm, aHidd_BitMap_BytesPerRow, &modulo);
319 HIDD_BM_PutAlphaImage(renderTarget, compdata->gfx , baseaddress + ((rect->MinY - n->topedge) * modulo) + ((rect->MinX - n->leftedge) << 2), modulo,
320 rect->MinX, rect->MinY, blitwidth, blitheight);
321 HIDD_BM_ReleaseDirectAccess(n->bm);
326 static inline void HIDDCompositorFillRect(struct HIDDCompositorData *compdata, OOP_Object *renderTarget, ULONG MinX, ULONG MinY, ULONG MaxX, ULONG MaxY)
328 DREDRAWSCR(bug("[Compositor:%s] Filling [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
329 MinX, MinY, MaxX, MaxY));
331 HIDD_BM_FillRect(renderTarget, compdata->gc,
332 MinX, MinY, MaxX, MaxY);
336 static VOID HIDDCompositorRedrawAlphaRegions(struct HIDDCompositorData *compdata, struct Rectangle *drawrect)
338 OOP_Object *renderTarget = compdata->displaybitmap;
339 struct Rectangle alpharect;
340 struct StackBitMapNode *n;
341 struct BitMap *backbm;
343 if (compdata->intermedbitmap)
344 renderTarget = compdata->intermedbitmap;
346 DREDRAWSCR(if (drawrect){ bug("[Compositor:%s] Rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT((*drawrect))); })
348 OOP_GetAttr(renderTarget, aHidd_BitMap_BMStruct, (IPTR *)&backbm);
350 // Alpha Regions are drawn in reverse order incase they overlap..
351 for (n = (struct StackBitMapNode *)compdata->bitmapstack.mlh_TailPred;
352 n->n.mln_Pred; n = (struct StackBitMapNode *)n->n.mln_Pred)
354 if ((n->sbmflags & STACKNODEF_VISIBLE) &&
355 (n->sbmflags & COMPF_ALPHA) &&
356 (n->screenregion))
358 struct RegionRectangle *srrect;
360 DREDRAWSCR(bug("[Compositor:%s] Alpha Screen Region @ 0x%p HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__,
361 n->screenregion, n->bm));
363 if ((srrect = n->screenregion->RegionRectangle) != NULL)
365 DREDRAWSCR(bug("[Compositor:%s] Compositing Visible Alpha Regions..\n", __PRETTY_FUNCTION__));
366 while (srrect)
368 alpharect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
369 alpharect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
370 alpharect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
371 alpharect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
373 if (!(drawrect) || AndRectRect(drawrect, &alpharect, &alpharect))
375 DREDRAWSCR(bug("[Compositor:%s] Alpha-Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(alpharect)));
377 if ((n->prealphacomphook) && (backbm != NULL))
379 struct HIDD_BackFillHookMsg preprocessmsg;
380 preprocessmsg.bounds = &alpharect;
381 preprocessmsg.offsetx = 0;
382 preprocessmsg.offsety = 0;
383 CallHookPkt(n->prealphacomphook, backbm, &preprocessmsg);
386 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &alpharect);
387 if (renderTarget == compdata->displaybitmap)
388 HIDD_BM_UpdateRect(compdata->displaybitmap,
389 alpharect.MinX, alpharect.MinY,
390 alpharect.MaxX - alpharect.MinX + 1,
391 alpharect.MaxY - alpharect.MinY + 1);
393 srrect = srrect->Next;
400 static VOID HIDDCompositorRedrawVisibleRegions(struct HIDDCompositorData *compdata, struct Rectangle *drawrect)
402 OOP_Object *renderTarget = compdata->displaybitmap;
403 struct Region *dispvisregion = NULL;
404 struct Rectangle tmprect;
405 struct BitMap *clearbm;
406 struct StackBitMapNode *n;
408 DREDRAWSCR(bug("[Compositor:%s] Redrawing Display (GfxBase @ 0x%p)\n", __PRETTY_FUNCTION__, GfxBase));
410 if (!(drawrect))
412 /* Recalculate visible regions */
413 HIDDCompositorRecalculateVisibleRegions(compdata);
416 if ((compdata->flags & COMPSTATEF_HASALPHA) && (compdata->intermedbitmap))
417 renderTarget = compdata->intermedbitmap;
419 if ((dispvisregion = NewRegion()) != NULL)
421 if (drawrect)
422 OrRectRegion(dispvisregion, drawrect);
423 else
424 OrRectRegion(dispvisregion, &compdata->displayrect);
426 DRECALC(bug("[Compositor:%s] Display rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(compdata->displayrect)));
428 ForeachNode(&compdata->bitmapstack, n)
430 if ((n->sbmflags & STACKNODEF_VISIBLE) &&
431 (!(n->sbmflags & COMPF_ALPHA)) &&
432 (n->screenregion))
434 struct RegionRectangle * srrect;
435 DREDRAWSCR(bug("[Compositor:%s] Screen Region @ 0x%p HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__,
436 n->screenregion, n->bm));
438 // Render the visable regions ..
439 if ((srrect = n->screenregion->RegionRectangle) != NULL)
441 DREDRAWSCR(bug("[Compositor:%s] Redrawing Visible Screen Regions..\n", __PRETTY_FUNCTION__));
442 while (srrect)
444 tmprect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
445 tmprect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
446 tmprect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
447 tmprect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
449 if (!(drawrect) || AndRectRect(drawrect, &tmprect, &tmprect))
451 DREDRAWSCR(bug("[Compositor:%s] Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
453 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &tmprect);
454 if (renderTarget == compdata->displaybitmap)
455 HIDD_BM_UpdateRect(compdata->displaybitmap,
456 tmprect.MinX, tmprect.MinY,
457 tmprect.MaxX - tmprect.MinX + 1,
458 tmprect.MaxY - tmprect.MinY + 1);
460 srrect = srrect->Next;
462 ClearRegionRegion(n->screenregion, dispvisregion);
466 OOP_GetAttr(renderTarget, aHidd_BitMap_BMStruct, (IPTR *)&clearbm);
468 struct RegionRectangle * dispclrrect = dispvisregion->RegionRectangle;
469 while (dispclrrect)
471 struct HIDD_BackFillHookMsg clearmsg;
473 tmprect.MinX = dispclrrect->bounds.MinX + dispvisregion->bounds.MinX;
474 tmprect.MinY = dispclrrect->bounds.MinY + dispvisregion->bounds.MinY;
475 tmprect.MaxX = dispclrrect->bounds.MaxX + dispvisregion->bounds.MinX;
476 tmprect.MaxY = dispclrrect->bounds.MaxY + dispvisregion->bounds.MinY;
478 if (!(drawrect) || AndRectRect(drawrect, &tmprect, &tmprect))
480 DREDRAWSCR(bug("[Compositor:%s] Render Display Void Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
482 if (clearbm)
484 clearmsg.bounds = &tmprect;
485 clearmsg.offsetx = 0;
486 clearmsg.offsety = 0;
487 CallHookPkt(compdata->backfillhook, clearbm, &clearmsg);
489 else
490 HIDDCompositorFillRect(compdata, renderTarget, tmprect.MinX, tmprect.MinY, tmprect.MaxX, tmprect.MaxY);
492 if (renderTarget == compdata->displaybitmap)
493 HIDD_BM_UpdateRect(compdata->displaybitmap,
494 tmprect.MinX, tmprect.MinY,
495 tmprect.MaxX - tmprect.MinX + 1,
496 tmprect.MaxY - tmprect.MinY + 1);
498 dispclrrect = dispclrrect->Next;
500 if (compdata->flags & COMPSTATEF_HASALPHA)
502 HIDDCompositorRedrawAlphaRegions(compdata, drawrect);
504 DisposeRegion(dispvisregion);
506 if (renderTarget != compdata->displaybitmap)
508 DREDRAWSCR(bug("[Compositor:%s] Copying Alpha Intermediary BitMap\n", __PRETTY_FUNCTION__, _RECT(tmprect)));
509 if (!(drawrect))
511 HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
512 compdata->displayrect.MinX, compdata->displayrect.MinY,
513 compdata->displaybitmap,
514 compdata->displayrect.MinX, compdata->displayrect.MinY,
515 compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
516 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
517 compdata->gc);
518 HIDD_BM_UpdateRect(compdata->displaybitmap,
519 compdata->displayrect.MinX, compdata->displayrect.MinY,
520 compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
521 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1);
523 else
525 HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
526 drawrect->MinX, drawrect->MinY,
527 compdata->displaybitmap,
528 drawrect->MinX, drawrect->MinY,
529 drawrect->MaxX - drawrect->MinX + 1,
530 drawrect->MaxY - drawrect->MinY + 1,
531 compdata->gc);
532 HIDD_BM_UpdateRect(compdata->displaybitmap,
533 drawrect->MinX, drawrect->MinY,
534 drawrect->MaxX - drawrect->MinX + 1,
535 drawrect->MaxY - drawrect->MinY + 1);
542 There are several cases that needs to be handled in this code. They are documented
543 below. Please read it before making changes.
544 etb = existing topbitmap
545 ntb = new top bitmap
546 sb = screen bitmap
547 cb = composited bitmap
548 fs = covers full screen
549 nfs = not covers full screen
550 mA = mode "A"
551 mB = mode "B"
552 disp() = dispose
553 new() = new
555 The resulting mode is always that of screen bitmap as set in "effect" column.
556 The composited bitmap always matches the resulting screen mode or is NULL.
558 | exiting screen situation | change | effect |
559 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - SAME MODE |
560 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mA | sb==ntb, cb==NULL |
561 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
562 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
563 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb, cb!=NULL |
564 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
565 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - SAME MODE |
566 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
567 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
568 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
569 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
570 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
573 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - DIFFERENT MODES |
574 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mB | sb==ntb, cb==NULL |
575 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
576 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
577 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mB | new(cb), sb==cb, cb!=NULL |
578 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
579 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - DIFFERENT MODES |
580 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
581 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
582 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
583 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
584 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
587 | USE CASE: DRAGGING SCREEN DOWN |
588 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb |
589 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb |
590 | USE CASE: DRAGGING SCREEN UP |
591 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==etb |
592 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
594 Resulting rules (order matters):
596 (a) if ((cb!=NULL) && (etb->mode!=ntb->mode)) {dispose(cb), cb=NULL}
597 (b) if ((ntb->nfs) && (cb==NULL)) new(cb)
598 (c) if (ntb->nfs) sb=cb
599 (d) if (ntb->fs) sb=ntb
601 Additional rule:
602 (e) if (oldsb!=sb) modeswitch(sb)
604 02.09.2011: we don't remember sb any more because we don't handle it in any way. Instead
605 we either have or don't have displaybitmap. If we have it, composition
606 is on (sb = cb). If we don't have it, composition is off (sb = ntb).
608 static BOOL HIDDCompositorToggleCompositing(struct HIDDCompositorData *compdata, BOOL newtop)
611 * If the topbitmap covers the complete screen, show it instead of
612 * displaybitmap. Remember that screen bitmap -> composited bitmap
613 * mirroring has a negative impact on performance.
615 OOP_Object *olddisplaybitmap = compdata->displaybitmap;
616 OOP_Object *oldintermedbitmap = compdata->intermedbitmap;
617 struct StackBitMapNode *topnode = (struct StackBitMapNode *)compdata->bitmapstack.mlh_Head;
618 OOP_Object *newsdispbitmap = NULL;
619 struct BitMap *tmpBM;
620 struct TagItem bmtags[2];
622 BOOL ok = TRUE, composit = FALSE;
624 /* (a) If mode change is needed, enforce opening a new screen */
625 if (compdata->modeschanged)
627 DTOGGLE(bug("[Compositor:%s] Display Mode changed\n", __PRETTY_FUNCTION__));
628 compdata->displaybitmap = NULL;
631 bmtags[0].ti_Tag = BMATags_DisplayID; bmtags[0].ti_Data = (compdata->displayid | compdata->displaymode);
632 bmtags[1].ti_Tag = TAG_DONE; bmtags[1].ti_Data = TAG_DONE;
634 if ((topnode->topedge > 0) || ((compdata->displayrect.MaxY - compdata->displayrect.MinY + 1) > OOP_GET(topnode->bm, aHidd_BitMap_Height)))
635 composit = TRUE;
636 else if ((topnode->leftedge > 0) || ((compdata->displayrect.MaxX - compdata->displayrect.MinX + 1) > OOP_GET(topnode->bm, aHidd_BitMap_Width)))
637 composit = TRUE;
638 else if (topnode->sbmflags & COMPF_ALPHA)
639 composit = TRUE;
641 if (composit)
643 /* (b) */
644 if (compdata->displaybitmap == NULL)
647 * displaybitmap == NULL means we were in passthrough mode before,
648 * or have just changed display mode - set up screen for composition.
650 DTOGGLE(bug("[Compositor:%s] Initialising Display-Compositor..\n", __PRETTY_FUNCTION__));
652 if (compdata->fb)
655 * If our display driver uses a framebuffer, we can reuse it.
656 * Copy its original contents back into the bitmap which it replaced,
657 * then change framebuffer's video mode.
658 * Framebuffer is the only bitmap which can change its ModeID on the fly.
660 DTOGGLE(bug("[Compositor:%s] Using Display Famebuffer HiddBitMap @ 0x%p\n", __PRETTY_FUNCTION__, compdata->fb));
662 /* Do this comparison in order not to show the framebuffer twice */
663 if (olddisplaybitmap != compdata->fb)
666 * 1. It's legal to show the framebuffer itself. This causes copying
667 * back old bitmap contents and detaching from it.
668 * 2. The result of this will always match compdata->fb.
669 * 3. Internally this is a simple blit operation, it can't fail.
671 DTOGGLE(bug("[Compositor:%s] Copying old Famebuffer BitMap\n", __PRETTY_FUNCTION__));
672 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, compdata->fb, fHidd_Gfx_Show_CopyBack);
675 /* Switch display mode on the framebuffer. */
676 OOP_SetAttrsTags(compdata->fb, aHidd_BitMap_ModeID, compdata->displaymode, TAG_DONE);
677 /* We are now compositing on the framebuffer */
678 compdata->displaybitmap = compdata->fb;
680 else
683 * There's no framebuffer.
684 * Create a new bitmap that will be used for compositing.
687 tmpBM = AllocBitMap(compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
688 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
689 compdata->displaydepth,
690 BMF_DISPLAYABLE|BMF_CHECKVALUE, (struct BitMap *)bmtags);
691 if (tmpBM)
693 compdata->displaybitmap = HIDD_BM_OBJ(tmpBM);
694 DTOGGLE(bug("[Compositor:%s] Created Compositor Display BitMap @ 0x%p [HiddBitMap @ 0x%p]\n", __PRETTY_FUNCTION__, tmpBM, compdata->displaybitmap));
696 /* Mode changed, this bitmap will be shown later */
697 newsdispbitmap = compdata->displaybitmap;
699 /* NewBitMap can fail, handle this */
700 if (!newsdispbitmap)
701 ok = FALSE;
705 else /* if (compdata->displaybitmap == NULL) */
708 * We are already in compositing mode and will stay in it.
709 * Do not destroy our working bitmap.
711 olddisplaybitmap = NULL;
714 if ((compdata->flags & COMPSTATEF_HASALPHA) && !(compdata->intermedbitmap))
716 tmpBM = AllocBitMap(compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
717 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
718 compdata->displaydepth,
719 BMF_CHECKVALUE, (struct BitMap *)bmtags);
720 if (tmpBM)
722 compdata->intermedbitmap = HIDD_BM_OBJ(tmpBM);
723 DTOGGLE(bug("[Compositor:%s] Allocated Alpha Intermediary BitMap @ 0x%p [HiddBitMap @ 0x%p]\n", __PRETTY_FUNCTION__, tmpBM, compdata->intermedbitmap));
726 else if (!(compdata->flags & COMPSTATEF_HASALPHA) && (compdata->intermedbitmap))
727 compdata->intermedbitmap = NULL;
730 * (c) Here composition is turned on (displaybitmap != NULL).
731 * Redraw bitmap stack - compensate possible changes
733 if (ok)
734 HIDDCompositorRedrawVisibleRegions(compdata, NULL);
736 else if (olddisplaybitmap || newtop)
739 * (d) Set passthrough mode and display the frontmost bitmap.
740 * This is also triggered by 'newtop' parameter, which tells us
741 * that frontmost bitmap has been changed, and we need to display a new one.
742 * Old displaybitmap has been remembered in the beginning. If it's not
743 * NULL, it will be destroyed in the end.
745 newsdispbitmap = compdata->topbitmap;
746 compdata->displaybitmap = NULL;
749 DTOGGLE(bug("[Compositor:%s] oldcompbm 0x%p, topbm 0x%p, dispbm 0x%p, newdispbm 0x%p\n", __PRETTY_FUNCTION__,
750 olddisplaybitmap, compdata->topbitmap, compdata->displaybitmap, newsdispbitmap));
753 * (e) If the screenbitmap changed, show the new screenbitmap.
754 * We do it after refreshing, for better visual appearance.
756 if (newsdispbitmap)
758 IPTR w, h;
760 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, newsdispbitmap, fHidd_Gfx_Show_CopyBack);
761 DTOGGLE(bug("[Compositor:%s] Displayed HiddBitMap 0x%p, Show returned 0x%p\n", __PRETTY_FUNCTION__, newsdispbitmap, compdata->screenbitmap));
763 /* After Show we need Update for mirroring drivers */
764 if (compdata->screenbitmap)
766 OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Width, &w);
767 OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Height, &h);
768 HIDD_BM_UpdateRect(compdata->screenbitmap, 0, 0, w, h);
773 * (a) - disposing of previous compositing buffers needs to happen after mode switch
774 * since it could have been the current screenbitmap
776 if (!(compdata->flags & COMPSTATEF_HASALPHA) && (oldintermedbitmap))
778 struct BitMap *freebm;
780 DTOGGLE(bug("[Compositor:%s] Disposing old alpha-intermediate bitmap 0x%p\n", __PRETTY_FUNCTION__, oldintermedbitmap));
782 OOP_GetAttr(oldintermedbitmap, aHidd_BitMap_BMStruct, (IPTR *)&freebm);
783 if (freebm)
784 FreeBitMap(freebm);
785 else
786 HIDD_Gfx_DisposeBitMap(compdata->gfx, oldintermedbitmap);
788 compdata->intermedbitmap = NULL;
791 if (olddisplaybitmap && (olddisplaybitmap != compdata->fb))
793 struct BitMap *freebm;
795 DTOGGLE(bug("[Compositor:%s] Disposing old display bitmap 0x%p\n", __PRETTY_FUNCTION__, olddisplaybitmap));
797 OOP_GetAttr(olddisplaybitmap, aHidd_BitMap_BMStruct, (IPTR *)&freebm);
798 if (freebm)
799 FreeBitMap(freebm);
800 else
801 HIDD_Gfx_DisposeBitMap(compdata->gfx, olddisplaybitmap);
804 /* Handled */
805 compdata->modeschanged = FALSE;
807 return ok;
810 static VOID HIDDCompositorPurgeBitMapStack(struct HIDDCompositorData * compdata)
812 struct StackBitMapNode * curr, * next;
814 ForeachNodeSafe(&compdata->bitmapstack, curr, next)
816 if (curr->screenregion)
817 DisposeRegion(curr->screenregion);
819 FreeMem(curr, sizeof(struct StackBitMapNode));
822 NEWLIST(&compdata->bitmapstack);
825 static void HIDDCompositorShowSingle(struct HIDDCompositorData *compdata, OOP_Object *bm)
827 /* Show the single top bitmap */
828 compdata->topbitmap = bm;
829 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, bm, fHidd_Gfx_Show_CopyBack);
831 /* Dispose working bitmap (if any) */
832 if (compdata->displaybitmap)
834 /* Be careful with the framebuffer */
835 if (compdata->displaybitmap != compdata->fb)
836 HIDD_Gfx_DisposeBitMap(compdata->gfx, compdata->displaybitmap);
838 /* This will deactivate us */
839 compdata->displaybitmap = NULL;
843 /* Emergency error recovery function */
844 static void HIDDCompositorReset(struct HIDDCompositorData *compdata)
846 /* Purge bitmap stack */
847 HIDDCompositorPurgeBitMapStack(compdata);
850 * Reset our internal state so that next BitMapStackChanged
851 * causes complete reinitialization.
853 compdata->displaymode = vHidd_ModeID_Invalid;
854 compdata->screenbitmap = NULL;
856 compdata->flags &= ~COMPSTATEF_HASALPHA;
859 VOID CompositorParseConfig(struct HIDDCompositorData *compdata)
861 struct RDArgs *rdargs;
862 IPTR CompArgs[NOOFARGS] = { 0 };
863 TEXT CompConfig[1024];
865 /* use default amiga-like capabailities */
866 compdata->capabilities = COMPF_ABOVE;
868 rdargs = AllocDosObjectTags(DOS_RDARGS, TAG_END);
869 if (rdargs != NULL)
871 if (GetVar(COMPOSITOR_PREFS, CompConfig, 1024, GVF_GLOBAL_ONLY) != -1)
873 rdargs->RDA_Source.CS_Buffer = CompConfig;
874 rdargs->RDA_Source.CS_Length = strlen(rdargs->RDA_Source.CS_Buffer);
875 rdargs->RDA_DAList = (IPTR)NULL;
876 rdargs->RDA_Buffer = NULL;
877 rdargs->RDA_BufSiz = 0;
878 rdargs->RDA_ExtHelp = NULL;
879 rdargs->RDA_Flags = 0;
881 if (ReadArgs(COMPOSITOR_PEFSTEMPLATE, CompArgs, rdargs) != NULL)
883 if (CompArgs[ARG_ABOVE])
884 compdata->capabilities |= COMPF_ABOVE;
885 else
886 compdata->capabilities &= ~COMPF_ABOVE;
888 if (CompArgs[ARG_BELOW])
889 compdata->capabilities |= COMPF_BELOW;
890 else
891 compdata->capabilities &= ~COMPF_BELOW;
893 if (CompArgs[ARG_LEFT])
894 compdata->capabilities |= COMPF_LEFT;
895 else
896 compdata->capabilities &= ~COMPF_LEFT;
898 if (CompArgs[ARG_RIGHT])
899 compdata->capabilities |= COMPF_RIGHT;
900 else
901 compdata->capabilities &= ~COMPF_RIGHT;
903 if (CompArgs[ARG_ALPHA])
904 compdata->capabilities |= COMPF_ALPHA;
905 else
906 compdata->capabilities &= ~COMPF_ALPHA;
908 FreeArgs(rdargs);
911 FreeDosObject(DOS_RDARGS, rdargs);
915 AROS_UFH3(void, CompositorDefaultBackFillFunc,
916 AROS_UFHA(struct Hook * , h, A0),
917 AROS_UFHA(struct BitMap * , bm, A2),
918 AROS_UFHA(struct HIDD_BackFillHookMsg * , msg, A1))
920 AROS_USERFUNC_INIT
922 struct HIDDCompositorData *compdata = h->h_Data;
924 D(bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata));
926 HIDDCompositorFillRect(compdata, HIDD_BM_OBJ(bm), msg->bounds->MinX, msg->bounds->MinY, msg->bounds->MaxX, msg->bounds->MaxY);
928 AROS_USERFUNC_EXIT
931 /* PUBLIC METHODS */
932 OOP_Object *METHOD(Compositor, Root, New)
934 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
936 if (o)
938 OOP_MethodID disposemid;
939 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
941 D(bug("[%s] Compositor @ 0x%p, data @ 0x%p\n", __PRETTY_FUNCTION__, o, compdata));
943 CompositorParseConfig(compdata);
945 compdata->capabilities = (ULONG)GetTagData(aHidd_Compositor_State, compdata->capabilities, msg->attrList);
946 compdata->flags |= COMPSTATEF_DEEPLUT;
948 D(bug("[%s] Compositor Capabilities: %08lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
950 compdata->displaymode = vHidd_ModeID_Invalid;
952 NEWLIST(&compdata->bitmapstack);
954 compdata->defaultbackfill.h_Entry = (HOOKFUNC)AROS_ASMSYMNAME(CompositorDefaultBackFillFunc);
955 compdata->defaultbackfill.h_Data = compdata;
956 compdata->backfillhook = &compdata->defaultbackfill;
958 InitSemaphore(&compdata->semaphore);
960 compdata->displayid = (ULONG)GetTagData(aHidd_Compositor_DisplayID, 0, msg->attrList);
961 compdata->gfx = (OOP_Object *)GetTagData(aHidd_Compositor_GfxHidd, 0, msg->attrList);
962 compdata->fb = (OOP_Object *)GetTagData(aHidd_Compositor_FrameBuffer, 0, msg->attrList);
964 D(bug("[%s] DisplayID %08lx for Gfx Driver @ 0x%p\n", __PRETTY_FUNCTION__, compdata->displayid, compdata->gfx));
966 GfxBase = (APTR)OpenLibrary("graphics.library", 41);
967 IntuitionBase = (APTR)OpenLibrary("intuition.library", 50);
969 /* GfxHidd is mandatory */
970 if ((compdata->GraphicsBase) && (compdata->gfx != NULL))
972 /* Create GC object that will be used for drawing operations */
973 compdata->gc = HIDD_Gfx_NewGC(compdata->gfx, NULL);
975 D(bug("[%s] Compositor GC @ %p\n", __PRETTY_FUNCTION__, compdata->gc));
977 if ((compdata->gfx) && (compdata->gc))
978 return o;
981 /* Creation failed */
982 disposemid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
983 OOP_CoerceMethod(cl, o, &disposemid);
986 return NULL;
989 void METHOD(Compositor, Root, Dispose)
993 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
994 bug("[%s] HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata);
997 OOP_DoSuperMethod(cl, o, &msg->mID);
1000 VOID METHOD(Compositor, Root, Get)
1002 ULONG idx;
1004 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1006 if (IS_COMPOSITOR_ATTR(msg->attrID, idx))
1008 switch (idx)
1010 case aoHidd_Compositor_Capabilities:
1012 *msg->storage = (IPTR)CAPABILITY_FLAGS;
1013 D(bug("[%s] Compositor Capabilities: %lx\n", __PRETTY_FUNCTION__, *msg->storage));
1014 return;
1016 case aoHidd_Compositor_State:
1018 *msg->storage = (IPTR)(compdata->capabilities & CAPABILITY_FLAGS);
1019 D(bug("[%s] Compositor State: %lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
1020 return;
1022 case aoHidd_Compositor_BackFillHook:
1024 D(bug("[%s] BackFillHook: 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook));
1025 *msg->storage = (IPTR)compdata->backfillhook;
1026 return;
1030 OOP_DoSuperMethod(cl, o, &msg->mID);
1033 VOID METHOD(Compositor, Root, Set)
1035 ULONG idx;
1037 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1038 struct TagItem *tag, *tstate = msg->attrList;
1040 while ((tag = NextTagItem(&tstate)))
1042 if (IS_COMPOSITOR_ATTR(tag->ti_Tag, idx))
1044 switch (idx)
1046 case aoHidd_Compositor_State:
1048 D(bug("[%s] Compositor Capabilities State: %lx -> ", __PRETTY_FUNCTION__, compdata->capabilities));
1049 compdata->capabilities = (ULONG)(tag->ti_Data & CAPABILITY_FLAGS);
1050 D(bug("%lx\n", compdata->capabilities));
1051 break;
1053 case aoHidd_Compositor_BackFillHook:
1055 if (tag->ti_Data)
1057 D(bug("[%s] BackFillHook: 0x%p -> 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook, tag->ti_Data));
1058 compdata->backfillhook = (struct Hook *)tag->ti_Data;
1060 else
1062 D(bug("[%s] Default BackFillHook\n", __PRETTY_FUNCTION__));
1063 compdata->backfillhook = &compdata->defaultbackfill;
1065 break;
1071 OOP_DoSuperMethod(cl, o, &msg->mID);
1074 OOP_Object *METHOD(Compositor, Hidd_Compositor, BitMapStackChanged)
1076 struct HIDD_ViewPortData *vpdata;
1077 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1078 struct StackBitMapNode *n;
1079 struct Screen *bmScreen;
1080 OOP_Object *bmpxfmt;
1081 int bmstdfmt;
1082 BOOL newtop = FALSE;
1083 BOOL ok = TRUE;
1085 DSTACK(bug("[Compositor] %s: Top bitmap: 0x%lx\n", __PRETTY_FUNCTION__, msg->data->Bitmap));
1087 LOCK_COMPOSITOR_WRITE
1089 /* Free all items which are already on the list */
1090 HIDDCompositorPurgeBitMapStack(compdata);
1092 if (!msg->data)
1094 UNLOCK_COMPOSITOR
1096 DSTACK(bug("[Compositor] %s: No ViewPort specified\n", __PRETTY_FUNCTION__));
1098 /* Blank screen */
1099 HIDDCompositorShowSingle(compdata, NULL);
1101 /* We know we are inactive after this */
1102 *msg->active = FALSE;
1103 /* This can return NULL, it's okay */
1104 return compdata->screenbitmap;
1107 /* Copy bitmaps pointers to our stack */
1108 for (vpdata = msg->data; vpdata; vpdata = vpdata->Next)
1110 n = AllocMem(sizeof(struct StackBitMapNode), MEMF_ANY | MEMF_CLEAR);
1111 if (!n)
1114 * Error happened.
1115 * We need to reset own state and return NULL. graphics.library
1116 * falls back to no composition in this case.
1118 DSTACK(bug("[Compositor] %s: Error allocating StackBitMapNode!!!\n", __PRETTY_FUNCTION__));
1120 ok = FALSE;
1121 break;
1124 DSTACK(bug("[Compositor] %s: ViewPort 0x%p, offset (%d, %d)\n", __PRETTY_FUNCTION__, vpdata->vpe->ViewPort, vpdata->vpe->ViewPort->DxOffset, vpdata->vpe->ViewPort->DyOffset));
1126 n->bm = vpdata->Bitmap;
1127 n->sbmflags = STACKNODEF_DISPLAYABLE;
1128 n->leftedge = vpdata->vpe->ViewPort->DxOffset;
1129 n->topedge = vpdata->vpe->ViewPort->DyOffset;
1131 n->screenregion = NewRegion();
1133 if ((bmScreen = HIDDCompositorFindBitMapScreen(compdata, n->bm)) != NULL)
1135 DSTACK(bug("[Compositor] %s: Screen @ 0x%p\n", __PRETTY_FUNCTION__, bmScreen));
1136 GetAttr(SA_CompositingFlags, (Object *)bmScreen, &n->sbmflags);
1137 DSTACK(bug("[Compositor] %s: CompositingFlags %08x\n", __PRETTY_FUNCTION__, n->sbmflags));
1138 n->sbmflags |= STACKNODEF_DISPLAYABLE;
1139 if (n->sbmflags & COMPF_ALPHA)
1141 GetAttr(SA_AlphaPreCompositingHook, (Object *)bmScreen, (IPTR *)&n->prealphacomphook);
1142 DSTACK(bug("[Compositor] %s: Pre-AlphaCompositing Hook @ 0x%p\n", __PRETTY_FUNCTION__, n->prealphacomphook));
1146 if (n->sbmflags & COMPF_ALPHA)
1148 bmpxfmt = (OOP_Object *)OOP_GET(n->bm, aHidd_BitMap_PixFmt);
1149 bmstdfmt = (int)OOP_GET(bmpxfmt, aHidd_PixFmt_StdPixFmt);
1150 DSTACK(bug("[Compositor] %s: Screen BitMap PixFmt %lx @ 0x%p\n", __PRETTY_FUNCTION__, bmstdfmt, bmpxfmt));
1152 switch (bmstdfmt)
1154 case vHidd_StdPixFmt_ARGB32:
1155 case vHidd_StdPixFmt_BGRA32:
1156 case vHidd_StdPixFmt_RGBA32:
1157 case vHidd_StdPixFmt_ABGR32:
1159 DSTACK(bug("[Compositor] %s: Screen BitMap has Alpha\n", __PRETTY_FUNCTION__));
1161 compdata->flags |= COMPSTATEF_HASALPHA;
1162 break;
1164 default:
1166 n->sbmflags &= ~COMPF_ALPHA;
1167 break;
1172 if (!(n->sbmflags & COMPF_ALPHA))
1174 if ((((BOOL)OOP_GET(n->bm, aHidd_BitMap_Displayable)) != TRUE))
1175 n->sbmflags &= ~STACKNODEF_DISPLAYABLE;
1177 AddTail((struct List *)&compdata->bitmapstack, (struct Node *)n);
1180 /* Switch mode if needed */
1181 UpdateDisplayMode(compdata);
1183 if (msg->data->Bitmap != compdata->topbitmap)
1185 /* Set the new pointer to top bitmap */
1186 compdata->topbitmap = msg->data->Bitmap;
1187 newtop = TRUE;
1190 if (ok)
1193 * Validate bitmap offsets - they might not match the compositing rules taking
1194 * new displayedwidth/displayedheight values
1196 ForeachNode(&compdata->bitmapstack, n)
1198 HIDDCompositorValidateBitMapPositionChange(n->bm, &n->leftedge, &n->topedge,
1199 compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
1200 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1);
1201 DSTACK(bug("[Compositor] %s: Bitmap 0x%p, display size %d x %d, validated position (%ld, %ld)\n", __PRETTY_FUNCTION__,
1202 n->bm, compdata->displayrect.MaxX - compdata->displayrect.MinX + 1, compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
1203 n->leftedge, n->topedge));
1206 /* Toogle compositing based on screen positions */
1207 ok = HIDDCompositorToggleCompositing(compdata, newtop);
1210 /* Handle error */
1211 if (!ok)
1213 HIDDCompositorReset(compdata);
1214 HIDDCompositorShowSingle(compdata, msg->data->Bitmap);
1217 UNLOCK_COMPOSITOR
1219 DSTACK(bug("[%s] Done, composited bitmap 0x%p\n", __PRETTY_FUNCTION__, compdata->displaybitmap));
1221 /* Tell if the composition is active */
1222 *msg->active = compdata->displaybitmap ? TRUE : FALSE;
1223 /* Return actually displayed bitmap */
1224 return compdata->screenbitmap;
1227 VOID METHOD(Compositor, Hidd_Compositor, BitMapRectChanged)
1229 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1230 OOP_Object *renderTarget = compdata->displaybitmap;
1232 if (compdata->displaybitmap)
1234 /* Composition is active, handle redraw if the bitmap is on screen */
1235 struct StackBitMapNode *n;
1237 DUPDATE(bug("[%s] Bitmap 0x%p\n", __PRETTY_FUNCTION__, msg->bm));
1239 LOCK_COMPOSITOR_READ
1241 if (compdata->intermedbitmap)
1242 renderTarget = compdata->intermedbitmap;
1244 n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1245 if (n && (n->sbmflags & STACKNODEF_VISIBLE))
1247 struct Rectangle dstandvisrect;
1248 struct Rectangle srcrect;
1250 srcrect.MinX = n->leftedge + msg->x;
1251 srcrect.MinY = n->topedge + msg->y;
1252 srcrect.MaxX = srcrect.MinX + msg->width - 1;
1253 srcrect.MaxY = srcrect.MinY + msg->height - 1;
1254 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));
1256 DUPDATE(bug("[%s] Screen-relative rect [%d, %d -> %d, %d]\n", __PRETTY_FUNCTION__, _RECT(srcrect)));
1258 struct RegionRectangle * srrect = n->screenregion->RegionRectangle;
1259 while (srrect)
1261 BOOL updateAlphaBmps = FALSE;
1263 dstandvisrect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
1264 dstandvisrect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
1265 dstandvisrect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
1266 dstandvisrect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
1268 if (AndRectRect(&srcrect, &dstandvisrect, &dstandvisrect))
1270 /* Intersection is valid. Blit. */
1271 DUPDATE(bug("[%s] Clipped rect (%d, %d) - (%d, %d)\n", __PRETTY_FUNCTION__, _RECT(dstandvisrect)));
1273 if (!(n->sbmflags & COMPF_ALPHA))
1275 if ((compdata->alpharegion) && (isRectInRegion(compdata->alpharegion, &dstandvisrect)))
1277 DUPDATE(bug("[%s] ** BitMap in Alpha Region!\n", __PRETTY_FUNCTION__));
1278 updateAlphaBmps = TRUE;
1280 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &dstandvisrect);
1282 else
1284 HIDDCompositorRedrawVisibleRegions(compdata, &dstandvisrect);
1287 if (updateAlphaBmps)
1288 HIDDCompositorRedrawAlphaRegions(compdata, &dstandvisrect);
1290 if (renderTarget != compdata->displaybitmap)
1292 HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
1293 dstandvisrect.MinX, dstandvisrect.MinY,
1294 compdata->displaybitmap,
1295 dstandvisrect.MinX, dstandvisrect.MinY,
1296 dstandvisrect.MaxX - dstandvisrect.MinX + 1,
1297 dstandvisrect.MaxY - dstandvisrect.MinY + 1,
1298 compdata->gc);
1301 srrect = srrect->Next;
1303 HIDD_BM_UpdateRect(compdata->displaybitmap,
1304 srcrect.MinX, srcrect.MinY,
1305 srcrect.MaxX - srcrect.MinX + 1,
1306 srcrect.MaxY - srcrect.MinY + 1);
1309 UNLOCK_COMPOSITOR
1311 DUPDATE(bug("[%s] Done\n", __PRETTY_FUNCTION__));
1313 else
1315 /* In order to speed things up, we handle passthrough ourselves here. */
1316 HIDD_BM_UpdateRect(msg->bm, msg->x, msg->y, msg->width, msg->height);
1320 IPTR METHOD(Compositor, Hidd_Compositor, BitMapPositionChange)
1322 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1323 struct StackBitMapNode *n;
1324 IPTR disp_width, disp_height;
1326 LOCK_COMPOSITOR_READ
1328 n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1329 if (n)
1331 /* The bitmap is on display. Validate against screen size */
1332 disp_width = compdata->displayrect.MaxX + 1;
1333 disp_height = compdata->displayrect.MaxY + 1;
1335 else
1337 /* The bitmap is not displayed yet. Validate against its own ModeID size. */
1338 HIDDT_ModeID modeid = vHidd_ModeID_Invalid;
1339 OOP_Object *bmfriend, *sync, *pf;
1341 OOP_GetAttr(msg->bm, aHidd_BitMap_ModeID, &modeid);
1343 if ((modeid == vHidd_ModeID_Invalid) && (OOP_GET(msg->bm, aHidd_BitMap_Compositable)))
1345 OOP_GetAttr(msg->bm, aHidd_BitMap_Friend, (IPTR *)&bmfriend);
1346 if (bmfriend)
1347 OOP_GetAttr(bmfriend, aHidd_BitMap_ModeID, &modeid);
1350 if (modeid == vHidd_ModeID_Invalid)
1353 * Nondisplayable bitmaps don't scroll.
1354 * In fact they simply can't get in here because MakeVPort() performs the validation.
1355 * But who knows what bug can slip into someone's software...
1357 UNLOCK_COMPOSITOR
1358 return FALSE;
1361 HIDD_Gfx_GetMode(compdata->gfx, modeid, &sync, &pf);
1362 OOP_GetAttr(sync, aHidd_Sync_HDisp, &disp_width);
1363 OOP_GetAttr(sync, aHidd_Sync_VDisp, &disp_height);
1366 DMOVE(bug("[%s] Validating bitmap 0x%p, position (%ld, %ld), limits %ld x %ld\n", __PRETTY_FUNCTION__,
1367 msg->bm, *msg->newxoffset, *msg->newyoffset, disp_width, disp_height));
1369 HIDDCompositorValidateBitMapPositionChange(msg->bm, msg->newxoffset, msg->newyoffset,
1370 disp_width, disp_height);
1372 DMOVE(bug("[%s] Validated position (%ld, %ld)\n", __PRETTY_FUNCTION__, *msg->newxoffset, *msg->newyoffset));
1374 if (n && ((*msg->newxoffset != n->leftedge) || (*msg->newyoffset != n->topedge)))
1376 DMOVE(bug("[%s] Old position (%ld, %ld)\n", __PRETTY_FUNCTION__, n->leftedge, n->topedge));
1378 /* Reflect the change if it happened */
1379 n->leftedge = *msg->newxoffset;
1380 n->topedge = *msg->newyoffset;
1382 if (compdata->topbitmap == msg->bm)
1385 * If this is the frontmost bitmap, we may want to toggle compositing,
1386 * if it starts/stops covering the whole screen at one point.
1387 * We don't need to call HIDDCompositorRedrawVisibleRegions() here because
1388 * HIDDCompositorToggleCompositing() does this itself, for improved
1389 * visual appearance.
1391 HIDDCompositorToggleCompositing(compdata, FALSE);
1393 else
1394 HIDDCompositorRedrawVisibleRegions(compdata, NULL);
1397 UNLOCK_COMPOSITOR
1399 /* Return active state */
1400 return compdata->displaybitmap ? TRUE : FALSE;
1403 IPTR METHOD(Compositor, Hidd_Compositor, BitMapValidate)
1405 if (IS_HIDD_BM(msg->bm))
1406 return TRUE;
1408 return FALSE;
1411 IPTR METHOD(Compositor, Hidd_Compositor, BitMapEnable)
1413 if (IS_HIDD_BM(msg->bm))
1415 if (!(OOP_GET(HIDD_BM_OBJ(msg->bm), aHidd_BitMap_Displayable)))
1417 struct TagItem composittags[] = {
1418 {aHidd_BitMap_Compositable, TRUE},
1419 {TAG_DONE , 0 }
1422 D(bug("[%s] Marking BitMap 0x%lx as Compositable\n", __PRETTY_FUNCTION__, msg->bm));
1423 OOP_SetAttrs(HIDD_BM_OBJ(msg->bm), composittags);
1425 return TRUE;
1428 return FALSE;
1431 #define NUM_Compositor_Root_METHODS 4
1433 static const struct OOP_MethodDescr Compositor_Root_descr[] =
1435 {(OOP_MethodFunc)Compositor__Root__New, moRoot_New},
1436 {(OOP_MethodFunc)Compositor__Root__Dispose, moRoot_Dispose},
1437 {(OOP_MethodFunc)Compositor__Root__Get, moRoot_Get},
1438 {(OOP_MethodFunc)Compositor__Root__Set, moRoot_Set},
1439 {NULL, 0}
1442 #define NUM_Compositor_Hidd_Compositor_METHODS 5
1444 static const struct OOP_MethodDescr Compositor_Hidd_Compositor_descr[] =
1446 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapStackChanged, moHidd_Compositor_BitMapStackChanged},
1447 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapRectChanged, moHidd_Compositor_BitMapRectChanged},
1448 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapPositionChange, moHidd_Compositor_BitMapPositionChange},
1449 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapValidate, moHidd_Compositor_BitMapValidate},
1450 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapEnable, moHidd_Compositor_BitMapEnable},
1451 {NULL, 0}
1454 const struct OOP_InterfaceDescr Compositor_ifdescr[] =
1456 {Compositor_Root_descr, IID_Root, NUM_Compositor_Root_METHODS},
1457 {Compositor_Hidd_Compositor_descr, IID_Hidd_Compositor, NUM_Compositor_Hidd_Compositor_METHODS},
1458 {NULL, NULL}