rename
[AROS.git] / workbench / devs / monitors / Compositor / compositor_class.c
blob3396671699d9d71dae7bae9245c8bc5545ecdb0c
1 /*
2 Copyright © 2010-2017, 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/gfx.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 OOP_DisposeObject(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 OOP_DisposeObject(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 OOP_DisposeObject(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 struct Process *me;
863 IPTR CompArgs[NOOFARGS] = { 0 };
864 TEXT CompConfig[1024];
865 APTR old_windowptr;
866 int len;
868 D(bug("[Composit] %s(0x%p)\n", __PRETTY_FUNCTION__, compdata));
870 /* Disable DOS Requesters (GetVar() -> "Please insert volume ENV:"),
871 because this can hang boot process if WB screen is not open
872 yet. Opening of WB screen (when requester tries to open) would
873 hang because display database semaphore is locked in AddDisplayDriverA(). */
875 me = (struct Process *)FindTask(NULL);
876 old_windowptr = me->pr_WindowPtr;
877 me->pr_WindowPtr = (APTR)-1;
879 /* use default amiga-like capabailities */
880 compdata->capabilities = COMPF_ABOVE;
882 rdargs = AllocDosObjectTags(DOS_RDARGS, TAG_END);
883 if (rdargs != NULL)
885 D(bug("[Composit] %s: RDArgs @ 0x%p\n", __PRETTY_FUNCTION__, rdargs));
887 if ((len = GetVar(COMPOSITOR_PREFS, CompConfig, 1024, GVF_GLOBAL_ONLY)) != -1)
889 rdargs->RDA_Source.CS_Buffer = CompConfig;
890 rdargs->RDA_Source.CS_Length = len;
891 rdargs->RDA_DAList = (IPTR)NULL;
892 rdargs->RDA_Buffer = NULL;
893 rdargs->RDA_BufSiz = 0;
894 rdargs->RDA_ExtHelp = NULL;
895 rdargs->RDA_Flags = 0;
897 if (ReadArgs(COMPOSITOR_PEFSTEMPLATE, CompArgs, rdargs) != NULL)
899 if (CompArgs[ARG_ABOVE])
900 compdata->capabilities |= COMPF_ABOVE;
901 else
902 compdata->capabilities &= ~COMPF_ABOVE;
904 if (CompArgs[ARG_BELOW])
905 compdata->capabilities |= COMPF_BELOW;
906 else
907 compdata->capabilities &= ~COMPF_BELOW;
909 if (CompArgs[ARG_LEFT])
910 compdata->capabilities |= COMPF_LEFT;
911 else
912 compdata->capabilities &= ~COMPF_LEFT;
914 if (CompArgs[ARG_RIGHT])
915 compdata->capabilities |= COMPF_RIGHT;
916 else
917 compdata->capabilities &= ~COMPF_RIGHT;
919 if (CompArgs[ARG_ALPHA])
920 compdata->capabilities |= COMPF_ALPHA;
921 else
922 compdata->capabilities &= ~COMPF_ALPHA;
924 FreeArgs(rdargs);
927 FreeDosObject(DOS_RDARGS, rdargs);
930 me->pr_WindowPtr = old_windowptr;
933 AROS_UFH3(void, CompositorDefaultBackFillFunc,
934 AROS_UFHA(struct Hook * , h, A0),
935 AROS_UFHA(struct BitMap * , bm, A2),
936 AROS_UFHA(struct HIDD_BackFillHookMsg * , msg, A1))
938 AROS_USERFUNC_INIT
940 struct HIDDCompositorData *compdata = h->h_Data;
942 D(bug("[Composit] %s: HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata));
944 HIDDCompositorFillRect(compdata, HIDD_BM_OBJ(bm), msg->bounds->MinX, msg->bounds->MinY, msg->bounds->MaxX, msg->bounds->MaxY);
946 AROS_USERFUNC_EXIT
949 /* PUBLIC METHODS */
950 OOP_Object *METHOD(Compositor, Root, New)
952 D(bug("[Composit] %s()\n", __PRETTY_FUNCTION__));
954 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
956 if (o)
958 OOP_MethodID disposemid;
959 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
961 D(bug("[Composit] %s: Compositor @ 0x%p, data @ 0x%p\n", __PRETTY_FUNCTION__, o, compdata));
963 CompositorParseConfig(compdata);
965 compdata->capabilities = (ULONG)GetTagData(aHidd_Compositor_State, compdata->capabilities, msg->attrList);
966 compdata->flags |= COMPSTATEF_DEEPLUT;
968 D(bug("[Composit] %s: Compositor Capabilities: %08lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
970 compdata->displaymode = vHidd_ModeID_Invalid;
972 NEWLIST(&compdata->bitmapstack);
974 compdata->defaultbackfill.h_Entry = (HOOKFUNC)AROS_ASMSYMNAME(CompositorDefaultBackFillFunc);
975 compdata->defaultbackfill.h_Data = compdata;
976 compdata->backfillhook = &compdata->defaultbackfill;
978 InitSemaphore(&compdata->semaphore);
980 compdata->displayid = (ULONG)GetTagData(aHidd_Compositor_DisplayID, 0, msg->attrList);
981 compdata->gfx = (OOP_Object *)GetTagData(aHidd_Compositor_GfxHidd, 0, msg->attrList);
982 compdata->fb = (OOP_Object *)GetTagData(aHidd_Compositor_FrameBuffer, 0, msg->attrList);
984 D(bug("[Composit] %s: DisplayID %08lx for Gfx Driver @ 0x%p\n", __PRETTY_FUNCTION__, compdata->displayid, compdata->gfx));
986 GfxBase = (APTR)OpenLibrary("graphics.library", 41);
987 IntuitionBase = (APTR)OpenLibrary("intuition.library", 50);
989 /* GfxHidd is mandatory */
990 if ((compdata->GraphicsBase) && (compdata->gfx != NULL))
992 /* Create GC object that will be used for drawing operations */
993 compdata->gc = HIDD_Gfx_CreateObject(compdata->gfx, OOP_FindClass(CLID_Hidd_GC), NULL);
995 D(bug("[Composit] %s: Compositor GC @ %p\n", __PRETTY_FUNCTION__, compdata->gc));
997 if ((compdata->gfx) && (compdata->gc))
998 return o;
1001 /* Creation failed */
1002 disposemid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
1003 OOP_CoerceMethod(cl, o, &disposemid);
1006 return NULL;
1009 void METHOD(Compositor, Root, Dispose)
1013 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1014 bug("[Composit] %s: HIDDCompositorData @ 0x%p\n", __PRETTY_FUNCTION__, compdata);
1017 OOP_DoSuperMethod(cl, o, &msg->mID);
1020 VOID METHOD(Compositor, Root, Get)
1022 ULONG idx;
1024 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1026 if (IS_COMPOSITOR_ATTR(msg->attrID, idx))
1028 switch (idx)
1030 case aoHidd_Compositor_Capabilities:
1032 *msg->storage = (IPTR)CAPABILITY_FLAGS;
1033 D(bug("[Composit] %s: Compositor Capabilities: %lx\n", __PRETTY_FUNCTION__, *msg->storage));
1034 return;
1036 case aoHidd_Compositor_State:
1038 *msg->storage = (IPTR)(compdata->capabilities & CAPABILITY_FLAGS);
1039 D(bug("[Composit] %s: Compositor State: %lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
1040 return;
1042 case aoHidd_Compositor_BackFillHook:
1044 D(bug("[Composit] %s: BackFillHook: 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook));
1045 *msg->storage = (IPTR)compdata->backfillhook;
1046 return;
1050 OOP_DoSuperMethod(cl, o, &msg->mID);
1053 VOID METHOD(Compositor, Root, Set)
1055 ULONG idx;
1057 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1058 struct TagItem *tag, *tstate = msg->attrList;
1060 while ((tag = NextTagItem(&tstate)))
1062 if (IS_COMPOSITOR_ATTR(tag->ti_Tag, idx))
1064 switch (idx)
1066 case aoHidd_Compositor_State:
1068 D(bug("[Composit] %s: Compositor Capabilities State: %lx -> ", __PRETTY_FUNCTION__, compdata->capabilities));
1069 compdata->capabilities = (ULONG)(tag->ti_Data & CAPABILITY_FLAGS);
1070 D(bug("%lx\n", compdata->capabilities));
1071 break;
1073 case aoHidd_Compositor_BackFillHook:
1075 if (tag->ti_Data)
1077 D(bug("[Composit] %s: BackFillHook: 0x%p -> 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook, tag->ti_Data));
1078 compdata->backfillhook = (struct Hook *)tag->ti_Data;
1080 else
1082 D(bug("[Composit] %s: Default BackFillHook\n", __PRETTY_FUNCTION__));
1083 compdata->backfillhook = &compdata->defaultbackfill;
1085 break;
1091 OOP_DoSuperMethod(cl, o, &msg->mID);
1094 OOP_Object *METHOD(Compositor, Hidd_Compositor, BitMapStackChanged)
1096 struct HIDD_ViewPortData *vpdata;
1097 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1098 struct StackBitMapNode *n;
1099 struct Screen *bmScreen;
1100 OOP_Object *bmpxfmt;
1101 int bmstdfmt;
1102 BOOL newtop = FALSE;
1103 BOOL ok = TRUE;
1105 DSTACK(bug("[Compositor] %s: Top bitmap: 0x%lx\n", __PRETTY_FUNCTION__, msg->data->Bitmap));
1107 LOCK_COMPOSITOR_WRITE
1109 /* Free all items which are already on the list */
1110 HIDDCompositorPurgeBitMapStack(compdata);
1112 if (!msg->data)
1114 UNLOCK_COMPOSITOR
1116 DSTACK(bug("[Compositor] %s: No ViewPort specified\n", __PRETTY_FUNCTION__));
1118 /* Blank screen */
1119 HIDDCompositorShowSingle(compdata, NULL);
1121 /* We know we are inactive after this */
1122 *msg->active = FALSE;
1123 /* This can return NULL, it's okay */
1124 return compdata->screenbitmap;
1127 /* Copy bitmaps pointers to our stack */
1128 for (vpdata = msg->data; vpdata; vpdata = vpdata->Next)
1130 n = AllocMem(sizeof(struct StackBitMapNode), MEMF_ANY | MEMF_CLEAR);
1131 if (!n)
1134 * Error happened.
1135 * We need to reset own state and return NULL. graphics.library
1136 * falls back to no composition in this case.
1138 DSTACK(bug("[Compositor] %s: Error allocating StackBitMapNode!!!\n", __PRETTY_FUNCTION__));
1140 ok = FALSE;
1141 break;
1144 DSTACK(bug("[Compositor] %s: ViewPort 0x%p, offset (%d, %d)\n", __PRETTY_FUNCTION__, vpdata->vpe->ViewPort, vpdata->vpe->ViewPort->DxOffset, vpdata->vpe->ViewPort->DyOffset));
1146 n->bm = vpdata->Bitmap;
1147 n->sbmflags = STACKNODEF_DISPLAYABLE;
1148 n->leftedge = vpdata->vpe->ViewPort->DxOffset;
1149 n->topedge = vpdata->vpe->ViewPort->DyOffset;
1151 n->screenregion = NewRegion();
1153 if ((bmScreen = HIDDCompositorFindBitMapScreen(compdata, n->bm)) != NULL)
1155 DSTACK(bug("[Compositor] %s: Screen @ 0x%p\n", __PRETTY_FUNCTION__, bmScreen));
1156 GetAttr(SA_CompositingFlags, (Object *)bmScreen, &n->sbmflags);
1157 DSTACK(bug("[Compositor] %s: CompositingFlags %08x\n", __PRETTY_FUNCTION__, n->sbmflags));
1158 n->sbmflags |= STACKNODEF_DISPLAYABLE;
1159 if (n->sbmflags & COMPF_ALPHA)
1161 GetAttr(SA_AlphaPreCompositingHook, (Object *)bmScreen, (IPTR *)&n->prealphacomphook);
1162 DSTACK(bug("[Compositor] %s: Pre-AlphaCompositing Hook @ 0x%p\n", __PRETTY_FUNCTION__, n->prealphacomphook));
1166 if (n->sbmflags & COMPF_ALPHA)
1168 bmpxfmt = (OOP_Object *)OOP_GET(n->bm, aHidd_BitMap_PixFmt);
1169 bmstdfmt = (int)OOP_GET(bmpxfmt, aHidd_PixFmt_StdPixFmt);
1170 DSTACK(bug("[Compositor] %s: Screen BitMap PixFmt %lx @ 0x%p\n", __PRETTY_FUNCTION__, bmstdfmt, bmpxfmt));
1172 switch (bmstdfmt)
1174 case vHidd_StdPixFmt_ARGB32:
1175 case vHidd_StdPixFmt_BGRA32:
1176 case vHidd_StdPixFmt_RGBA32:
1177 case vHidd_StdPixFmt_ABGR32:
1179 DSTACK(bug("[Compositor] %s: Screen BitMap has Alpha\n", __PRETTY_FUNCTION__));
1181 compdata->flags |= COMPSTATEF_HASALPHA;
1182 break;
1184 default:
1186 n->sbmflags &= ~COMPF_ALPHA;
1187 break;
1192 if (!(n->sbmflags & COMPF_ALPHA))
1194 if ((((BOOL)OOP_GET(n->bm, aHidd_BitMap_Displayable)) != TRUE))
1195 n->sbmflags &= ~STACKNODEF_DISPLAYABLE;
1197 AddTail((struct List *)&compdata->bitmapstack, (struct Node *)n);
1200 /* Switch mode if needed */
1201 UpdateDisplayMode(compdata);
1203 if (msg->data->Bitmap != compdata->topbitmap)
1205 /* Set the new pointer to top bitmap */
1206 compdata->topbitmap = msg->data->Bitmap;
1207 newtop = TRUE;
1210 if (ok)
1213 * Validate bitmap offsets - they might not match the compositing rules taking
1214 * new displayedwidth/displayedheight values
1216 ForeachNode(&compdata->bitmapstack, n)
1218 HIDDCompositorValidateBitMapPositionChange(n->bm, &n->leftedge, &n->topedge,
1219 compdata->displayrect.MaxX - compdata->displayrect.MinX + 1,
1220 compdata->displayrect.MaxY - compdata->displayrect.MinY + 1);
1221 DSTACK(bug("[Compositor] %s: Bitmap 0x%p, display size %d x %d, validated position (%ld, %ld)\n", __PRETTY_FUNCTION__,
1222 n->bm, compdata->displayrect.MaxX - compdata->displayrect.MinX + 1, compdata->displayrect.MaxY - compdata->displayrect.MinY + 1,
1223 n->leftedge, n->topedge));
1226 /* Toogle compositing based on screen positions */
1227 ok = HIDDCompositorToggleCompositing(compdata, newtop);
1230 /* Handle error */
1231 if (!ok)
1233 HIDDCompositorReset(compdata);
1234 HIDDCompositorShowSingle(compdata, msg->data->Bitmap);
1237 UNLOCK_COMPOSITOR
1239 DSTACK(bug("[Composit] %s: Done, composited bitmap 0x%p\n", __PRETTY_FUNCTION__, compdata->displaybitmap));
1241 /* Tell if the composition is active */
1242 *msg->active = compdata->displaybitmap ? TRUE : FALSE;
1243 /* Return actually displayed bitmap */
1244 return compdata->screenbitmap;
1247 VOID METHOD(Compositor, Hidd_Compositor, BitMapRectChanged)
1249 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1250 OOP_Object *renderTarget = compdata->displaybitmap;
1252 if (compdata->displaybitmap)
1254 /* Composition is active, handle redraw if the bitmap is on screen */
1255 struct StackBitMapNode *n;
1257 DUPDATE(bug("[Composit] %s: Bitmap 0x%p\n", __PRETTY_FUNCTION__, msg->bm));
1259 LOCK_COMPOSITOR_READ
1261 if (compdata->intermedbitmap)
1262 renderTarget = compdata->intermedbitmap;
1264 n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1265 if (n && (n->sbmflags & STACKNODEF_VISIBLE))
1267 struct Rectangle dstandvisrect;
1268 struct Rectangle srcrect;
1270 srcrect.MinX = n->leftedge + msg->x;
1271 srcrect.MinY = n->topedge + msg->y;
1272 srcrect.MaxX = srcrect.MinX + msg->width - 1;
1273 srcrect.MaxY = srcrect.MinY + msg->height - 1;
1274 DUPDATE(bug("[Composit] %s: Bitmap rect [%d, %d -> %d, %d]\n", __PRETTY_FUNCTION__, msg->x, msg->y, msg->x + msg->width - 1, msg->y + msg->height - 1));
1276 DUPDATE(bug("[Composit] %s: Screen-relative rect [%d, %d -> %d, %d]\n", __PRETTY_FUNCTION__, _RECT(srcrect)));
1278 struct RegionRectangle * srrect = n->screenregion->RegionRectangle;
1279 while (srrect)
1281 BOOL updateAlphaBmps = FALSE;
1283 dstandvisrect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
1284 dstandvisrect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
1285 dstandvisrect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
1286 dstandvisrect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
1288 if (AndRectRect(&srcrect, &dstandvisrect, &dstandvisrect))
1290 /* Intersection is valid. Blit. */
1291 DUPDATE(bug("[Composit] %s: Clipped rect (%d, %d) - (%d, %d)\n", __PRETTY_FUNCTION__, _RECT(dstandvisrect)));
1293 if (!(n->sbmflags & COMPF_ALPHA))
1295 if ((compdata->alpharegion) && (isRectInRegion(compdata->alpharegion, &dstandvisrect)))
1297 DUPDATE(bug("[Composit] %s: ** BitMap in Alpha Region!\n", __PRETTY_FUNCTION__));
1298 updateAlphaBmps = TRUE;
1300 HIDDCompositorRedrawBitmap(compdata, renderTarget, n, &dstandvisrect);
1302 else
1304 HIDDCompositorRedrawVisibleRegions(compdata, &dstandvisrect);
1307 if (updateAlphaBmps)
1308 HIDDCompositorRedrawAlphaRegions(compdata, &dstandvisrect);
1310 if (renderTarget != compdata->displaybitmap)
1312 HIDD_Gfx_CopyBox(compdata->gfx, renderTarget,
1313 dstandvisrect.MinX, dstandvisrect.MinY,
1314 compdata->displaybitmap,
1315 dstandvisrect.MinX, dstandvisrect.MinY,
1316 dstandvisrect.MaxX - dstandvisrect.MinX + 1,
1317 dstandvisrect.MaxY - dstandvisrect.MinY + 1,
1318 compdata->gc);
1321 srrect = srrect->Next;
1323 HIDD_BM_UpdateRect(compdata->displaybitmap,
1324 srcrect.MinX, srcrect.MinY,
1325 srcrect.MaxX - srcrect.MinX + 1,
1326 srcrect.MaxY - srcrect.MinY + 1);
1329 UNLOCK_COMPOSITOR
1331 DUPDATE(bug("[Composit] %s: Done\n", __PRETTY_FUNCTION__));
1333 else
1335 /* In order to speed things up, we handle passthrough ourselves here. */
1336 HIDD_BM_UpdateRect(msg->bm, msg->x, msg->y, msg->width, msg->height);
1340 IPTR METHOD(Compositor, Hidd_Compositor, BitMapPositionChange)
1342 struct HIDDCompositorData *compdata = OOP_INST_DATA(cl, o);
1343 struct StackBitMapNode *n;
1344 IPTR disp_width, disp_height;
1346 LOCK_COMPOSITOR_READ
1348 n = HIDDCompositorFindBitMapStackNode(compdata, msg->bm);
1349 if (n)
1351 /* The bitmap is on display. Validate against screen size */
1352 disp_width = compdata->displayrect.MaxX + 1;
1353 disp_height = compdata->displayrect.MaxY + 1;
1355 else
1357 /* The bitmap is not displayed yet. Validate against its own ModeID size. */
1358 HIDDT_ModeID modeid = vHidd_ModeID_Invalid;
1359 OOP_Object *bmfriend, *sync, *pf;
1361 OOP_GetAttr(msg->bm, aHidd_BitMap_ModeID, &modeid);
1363 if ((modeid == vHidd_ModeID_Invalid) && (OOP_GET(msg->bm, aHidd_BitMap_Compositable)))
1365 OOP_GetAttr(msg->bm, aHidd_BitMap_Friend, (IPTR *)&bmfriend);
1366 if (bmfriend)
1367 OOP_GetAttr(bmfriend, aHidd_BitMap_ModeID, &modeid);
1370 if (modeid == vHidd_ModeID_Invalid)
1373 * Nondisplayable bitmaps don't scroll.
1374 * In fact they simply can't get in here because MakeVPort() performs the validation.
1375 * But who knows what bug can slip into someone's software...
1377 UNLOCK_COMPOSITOR
1378 return FALSE;
1381 HIDD_Gfx_GetMode(compdata->gfx, modeid, &sync, &pf);
1382 OOP_GetAttr(sync, aHidd_Sync_HDisp, &disp_width);
1383 OOP_GetAttr(sync, aHidd_Sync_VDisp, &disp_height);
1386 DMOVE(bug("[Composit] %s: Validating bitmap 0x%p, position (%ld, %ld), limits %ld x %ld\n", __PRETTY_FUNCTION__,
1387 msg->bm, *msg->newxoffset, *msg->newyoffset, disp_width, disp_height));
1389 HIDDCompositorValidateBitMapPositionChange(msg->bm, msg->newxoffset, msg->newyoffset,
1390 disp_width, disp_height);
1392 DMOVE(bug("[Composit] %s: Validated position (%ld, %ld)\n", __PRETTY_FUNCTION__, *msg->newxoffset, *msg->newyoffset));
1394 if (n && ((*msg->newxoffset != n->leftedge) || (*msg->newyoffset != n->topedge)))
1396 DMOVE(bug("[Composit] %s: Old position (%ld, %ld)\n", __PRETTY_FUNCTION__, n->leftedge, n->topedge));
1398 /* Reflect the change if it happened */
1399 n->leftedge = *msg->newxoffset;
1400 n->topedge = *msg->newyoffset;
1402 if (compdata->topbitmap == msg->bm)
1405 * If this is the frontmost bitmap, we may want to toggle compositing,
1406 * if it starts/stops covering the whole screen at one point.
1407 * We don't need to call HIDDCompositorRedrawVisibleRegions() here because
1408 * HIDDCompositorToggleCompositing() does this itself, for improved
1409 * visual appearance.
1411 HIDDCompositorToggleCompositing(compdata, FALSE);
1413 else
1414 HIDDCompositorRedrawVisibleRegions(compdata, NULL);
1417 UNLOCK_COMPOSITOR
1419 /* Return active state */
1420 return compdata->displaybitmap ? TRUE : FALSE;
1423 IPTR METHOD(Compositor, Hidd_Compositor, BitMapValidate)
1425 if (IS_HIDD_BM(msg->bm))
1426 return TRUE;
1428 return FALSE;
1431 IPTR METHOD(Compositor, Hidd_Compositor, BitMapEnable)
1433 if (IS_HIDD_BM(msg->bm))
1435 if (!(OOP_GET(HIDD_BM_OBJ(msg->bm), aHidd_BitMap_Displayable)))
1437 struct TagItem composittags[] = {
1438 {aHidd_BitMap_Compositable, TRUE},
1439 {TAG_DONE , 0 }
1442 D(bug("[Composit] %s: Marking BitMap 0x%lx as Compositable\n", __PRETTY_FUNCTION__, msg->bm));
1443 OOP_SetAttrs(HIDD_BM_OBJ(msg->bm), composittags);
1445 return TRUE;
1448 return FALSE;
1451 #define NUM_Compositor_Root_METHODS 4
1453 static const struct OOP_MethodDescr Compositor_Root_descr[] =
1455 {(OOP_MethodFunc)Compositor__Root__New, moRoot_New},
1456 {(OOP_MethodFunc)Compositor__Root__Dispose, moRoot_Dispose},
1457 {(OOP_MethodFunc)Compositor__Root__Get, moRoot_Get},
1458 {(OOP_MethodFunc)Compositor__Root__Set, moRoot_Set},
1459 {NULL, 0}
1462 #define NUM_Compositor_Hidd_Compositor_METHODS 5
1464 static const struct OOP_MethodDescr Compositor_Hidd_Compositor_descr[] =
1466 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapStackChanged, moHidd_Compositor_BitMapStackChanged},
1467 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapRectChanged, moHidd_Compositor_BitMapRectChanged},
1468 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapPositionChange, moHidd_Compositor_BitMapPositionChange},
1469 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapValidate, moHidd_Compositor_BitMapValidate},
1470 {(OOP_MethodFunc)Compositor__Hidd_Compositor__BitMapEnable, moHidd_Compositor_BitMapEnable},
1471 {NULL, 0}
1474 const struct OOP_InterfaceDescr Compositor_ifdescr[] =
1476 {Compositor_Root_descr, IID_Root, NUM_Compositor_Root_METHODS},
1477 {Compositor_Hidd_Compositor_descr, IID_Hidd_Compositor, NUM_Compositor_Hidd_Compositor_METHODS},
1478 {NULL, NULL}