Reworked software screen compositing. Uses graphics library region primitives instead...
[AROS.git] / workbench / devs / monitors / Compositor / compositingclass.c
blobedf26245fa0994a03a18e91ef5b40b262f9abd9f
1 /*
2 Copyright © 2010-2012, The AROS Development Team. All rights reserved.
3 $Id: compositingclass.c 38905 2011-05-29 06:54:59Z deadwood $
4 */
6 #define DEBUG 0
7 #if (DEBUG)
8 #define DTOGGLE(x) x
9 #define DMODE(x) x
10 #define DMOVE(x) x
11 #define DRECALC(x) x
12 #define DREDRAWBM(x) x
13 #define DREDRAWSCR(x) x
14 #define DSTACK(x) x
15 #define DUPDATE(x) x
16 #else
17 #define DTOGGLE(x)
18 #define DMODE(x)
19 #define DMOVE(x)
20 #define DRECALC(x)
21 #define DREDRAWBM(x)
22 #define DREDRAWSCR(x)
23 #define DSTACK(x)
24 #define DUPDATE(x)
25 #endif
27 #include <aros/debug.h>
29 #include <graphics/view.h>
31 #include <hidd/graphics.h>
33 #include <proto/exec.h>
34 #include <proto/graphics.h>
35 #include <proto/oop.h>
36 #include <proto/utility.h>
38 #include "compositing_intern.h"
40 #ifdef GfxBase
41 #undef GfxBase
42 #endif
43 #define GfxBase compdata->GraphicsBase
45 #define _RECT(x) x.MinX, x.MinY, x.MaxX, x.MaxY
47 #define MAX(a,b) a > b ? a : b
48 #define MIN(a,b) a < b ? a : b
50 static BOOL AndRectRect(struct Rectangle * rect1, struct Rectangle * rect2,
51 struct Rectangle * intersect)
53 intersect->MinX = MAX(rect1->MinX, rect2->MinX);
54 intersect->MinY = MAX(rect1->MinY, rect2->MinY);
55 intersect->MaxX = MIN(rect1->MaxX, rect2->MaxX);
56 intersect->MaxY = MIN(rect1->MaxY, rect2->MaxY);
58 if ((intersect->MinX > intersect->MaxX) ||
59 (intersect->MinY > intersect->MaxY))
60 return FALSE;
61 else
62 return TRUE;
65 static struct StackBitMapNode * HIDDCompositingIsBitMapOnStack(struct HIDDCompositingData * compdata, OOP_Object * bm)
67 struct StackBitMapNode * n = NULL;
69 ForeachNode(&compdata->bitmapstack, n)
71 if (n->bm == bm)
72 return n;
75 return NULL;
78 static VOID HIDDCompositingValidateBitMapPositionChange(OOP_Object * bm, SIPTR *newxoffset, SIPTR *newyoffset, LONG displayedwidth, LONG displayedheight)
80 IPTR width, height;
81 LONG neglimit, poslimit;
83 OOP_GetAttr(bm, aHidd_BitMap_Width, &width);
84 OOP_GetAttr(bm, aHidd_BitMap_Height, &height);
86 /* Check x position */
87 if (width > displayedwidth)
89 neglimit = displayedwidth - width;
90 poslimit = 0;
92 else
94 neglimit = 0;
95 poslimit = displayedwidth - width;
98 if (*(newxoffset) > poslimit)
99 *(newxoffset) = poslimit;
100 if (*(newxoffset) < neglimit)
101 *(newxoffset) = neglimit;
103 /* Check y position */
104 if (height > displayedheight)
105 neglimit = displayedheight - height; /* Limit for scroll */
106 else
107 neglimit = 0;
108 poslimit = displayedheight - 15; /* Limit for drag */
110 if (*(newyoffset) > poslimit)
111 *(newyoffset) = poslimit;
112 if (*(newyoffset) < neglimit)
113 *(newyoffset) = neglimit;
116 static VOID HIDDCompositingRecalculateVisibleRegions(struct HIDDCompositingData *compdata)
118 struct StackBitMapNode *n = NULL, *tmpn;
119 struct Region *dispvisregion = NULL;
120 OOP_Object *bmpxfmt;
122 DRECALC(bug("[Compositing:%s] Display rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(compdata->screenrect)));
125 * This function assumes bitmapstack is in correct Z order:
126 * from topmost to bottom most
128 if ((dispvisregion = NewRegion()) != NULL)
130 OrRectRegion(dispvisregion, &compdata->screenrect);
132 DRECALC(bug("[Compositing:%s] DisplayRegion @ 0x%p\n", __PRETTY_FUNCTION__, dispvisregion));
134 ForeachNodeSafe(&compdata->bitmapstack, n, tmpn)
136 /* Get bitmap bounding box in screen coordinates */
137 struct Rectangle tmprect;
139 n->sbmflags &= ~STACKNODE_VISIBLE;
141 if (n->screenregion)
142 DisposeRegion(n->screenregion);
144 if ((n->screenregion = NewRegion()) != NULL)
146 tmprect.MinX = n->leftedge;
147 tmprect.MaxX = n->leftedge + OOP_GET(n->bm, aHidd_BitMap_Width) - 1;
148 tmprect.MinY = n->topedge;
149 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
151 DRECALC(bug("[Compositing:%s] Screen Rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(&tmprect)));
153 OrRectRegion(n->screenregion, &tmprect); // Start with the Screen's dimensions ..
154 AndRegionRegion(dispvisregion, n->screenregion); // And adjust for the "Display"
156 if (n->screenregion->RegionRectangle)
158 int bmpstdfmt;
159 bmpxfmt = (OOP_Object *)OOP_GET(n->bm, aHidd_BitMap_PixFmt);
160 bmpstdfmt = (int)OOP_GET(bmpxfmt, aHidd_PixFmt_StdPixFmt);
161 DRECALC(bug("[Compositing:%s] Screen BitMap PixFmt %lx @ 0x%p\n", __PRETTY_FUNCTION__, bmpstdfmt, bmpxfmt));
163 switch (bmpstdfmt)
165 case vHidd_StdPixFmt_ARGB32:
166 case vHidd_StdPixFmt_BGRA32:
167 case vHidd_StdPixFmt_RGBA32:
168 case vHidd_StdPixFmt_ABGR32:
170 DRECALC(bug("[Compositing:%s] BitMap has ALPHA\n", __PRETTY_FUNCTION__));
172 n->sbmflags |= STACKNODE_ALPHA;
174 if (!(compdata->alpharegion))
176 compdata->alpharegion = NewRegion();
177 DRECALC(bug("[Compositing:%s] AlphaRegion Allocated @ 0x%p\n", __PRETTY_FUNCTION__, compdata->alpharegion));
180 OrRegionRegion(compdata->alpharegion, n->screenregion);
181 break;
183 default:
185 n->sbmflags &= ~STACKNODE_ALPHA;
187 AndRectRect(&n->screenregion->bounds, &compdata->screenrect, &n->screenvisiblerect);
188 ClearRegionRegion(n->screenregion, dispvisregion);
190 if (!(compdata->capabilities & COMPF_ABOVE))
192 tmprect.MinX = compdata->screenrect.MinX;
193 tmprect.MaxX = compdata->screenrect.MaxX;
194 tmprect.MinY = compdata->screenrect.MinY;
195 tmprect.MaxY = n->topedge - 1;
196 ClearRectRegion(dispvisregion, &tmprect);
198 if (!(compdata->capabilities & COMPF_BELOW))
200 tmprect.MinX = compdata->screenrect.MinX;
201 tmprect.MaxX = compdata->screenrect.MaxX;
202 tmprect.MinY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height);
203 tmprect.MaxY = compdata->screenrect.MaxY;
204 ClearRectRegion(dispvisregion, &tmprect);
206 if (!(compdata->capabilities & COMPF_LEFT))
208 tmprect.MinX = compdata->screenrect.MinX;
209 tmprect.MaxX = n->leftedge - 1;
210 tmprect.MinY = n->topedge;
211 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
212 ClearRectRegion(dispvisregion, &tmprect);
214 if (!(compdata->capabilities & COMPF_RIGHT))
216 tmprect.MinX = n->leftedge + OOP_GET(n->bm, aHidd_BitMap_Width);
217 tmprect.MaxX = compdata->screenrect.MaxX;
218 tmprect.MinY = n->topedge;
219 tmprect.MaxY = n->topedge + OOP_GET(n->bm, aHidd_BitMap_Height) - 1;
220 ClearRectRegion(dispvisregion, &tmprect);
224 n->sbmflags |= STACKNODE_VISIBLE;
227 DRECALC(bug("[Compositing:%s] Bitmap 0x%x, topedge %d, visible %d, [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
228 n->bm, n->topedge, (n->sbmflags & STACKNODE_VISIBLE), _RECT(n->screenvisiblerect)));
230 else
232 DRECALC(bug("[Compositing:%s] Failed to create Screen Region\n", __PRETTY_FUNCTION__));
235 DisposeRegion(dispvisregion);
237 else
239 DRECALC(bug("[Compositing:%s] Failed to create Display Region\n", __PRETTY_FUNCTION__));
243 static HIDDT_ModeID FindBestHiddMode(struct HIDDCompositingData *compdata, ULONG width, ULONG height, ULONG depth, ULONG *res_depth)
245 HIDDT_ModeID mode = vHidd_ModeID_Invalid;
246 OOP_Object *sync, *pf;
247 IPTR w, h, d;
248 ULONG dw, dh, delta;
249 ULONG found_delta = -1;
250 ULONG found_width = 0;
251 ULONG found_height = 0;
252 ULONG found_depth = 0;
253 HIDDT_ModeID found_mode = vHidd_ModeID_Invalid;
255 DMODE(bug("[%s] Finding best match for mode %ux%ux%u\n", __PRETTY_FUNCTION__, width, height, depth));
257 while ((mode = HIDD_Gfx_NextModeID(compdata->gfx, mode, &sync, &pf)) != vHidd_ModeID_Invalid)
259 BOOL match;
261 DMODE(bug("[%s] Checking mode 0x%08X... ", __PRETTY_FUNCTION__, mode));
262 if (OOP_GET(pf, aHidd_PixFmt_ColorModel) != vHidd_ColorModel_TrueColor)
264 DMODE(bug("Skipped (not truecolor)\n"));
265 continue;
268 OOP_GetAttr(sync, aHidd_Sync_HDisp, &w);
269 OOP_GetAttr(sync, aHidd_Sync_VDisp, &h);
270 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &d);
272 dw = w > width ? w - width : w < width ? width - w : 1;
273 dh = h > height ? h - height : h < height ? height - h : 1;
274 delta = dw * dh;
276 match = FALSE;
277 if (delta < found_delta)
279 /* If mode resolution is closer to the needed one, we've got a better match */
280 found_delta = delta;
281 found_width = w;
282 found_height = h;
284 match = TRUE;
286 else if (delta == found_delta)
288 /* If resolution is the same as that of current candidate mode, we can look at depth. */
289 if (found_depth > depth)
292 * Candidate mode if deeper than requested. We can supersede it with another mode
293 * of smaller depth, but which still matches our request.
295 if ((d < found_depth) && (d >= depth))
296 match = TRUE;
298 else if (found_depth < depth)
301 * We want better depth than current candidate.
302 * In this case anything deeper will do.
304 if (d > found_depth)
305 match = TRUE;
309 if (match)
312 * Mode with the same delta, but larger depth, may supersede
313 * previous mode, if we prefer deeper ones.
315 DMODE(bug("Selected (%ldx%ldx%ld, delta = %u)", w, h, d, delta));
316 found_depth = d;
317 found_mode = mode;
319 DMODE(bug("\n"));
322 /* Store mode information */
323 compdata->screenrect.MinX = 0;
324 compdata->screenrect.MinY = 0;
325 compdata->screenrect.MaxX = found_width - 1;
326 compdata->screenrect.MaxY = found_height - 1;
327 *res_depth = found_depth;
329 return found_mode;
332 static void UpdateDisplayMode(struct HIDDCompositingData *compdata)
334 struct StackBitMapNode *n;
335 IPTR modeid, width, height, depth;
336 OOP_Object *sync, *pf;
337 UBYTE comp_depth = 16;
338 ULONG found_depth;
341 * Examine all bitmaps in the stack to figure out the needed depth.
342 * We need a maximum depth of all depths in order to keep correct colors.
343 * But not less than 16 bits, because we can't compose on a LUT screen.
345 * If a LUT bitmap is present in the stack (depth < 9), we request truecolor
346 * screen for better color presentation.
348 * We examine bitmaps in reverse order, in this case 'sync' will hold
349 * information about the top bitmap when we exit the loop.
350 * Size of our composited mode needs to be as close as possible to that one.
352 for (n = (struct StackBitMapNode *)compdata->bitmapstack.mlh_TailPred;
353 n->n.mln_Pred; n = (struct StackBitMapNode *)n->n.mln_Pred)
355 OOP_GetAttr(n->bm, aHidd_BitMap_ModeID, &modeid);
356 HIDD_Gfx_GetMode(compdata->gfx, modeid, &sync, &pf);
358 if (OOP_GET(pf, aHidd_PixFmt_ColorModel) == vHidd_ColorModel_TrueColor)
360 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
361 if (depth > comp_depth)
362 comp_depth = depth;
364 else
367 * If we have a LUT bitmap on stack, we request 24-bit screen
368 * for better color transfer.
370 comp_depth = 24;
374 /* Get the needed size */
375 OOP_GetAttr(sync, aHidd_Sync_HDisp, &width);
376 OOP_GetAttr(sync, aHidd_Sync_VDisp, &height);
378 DSTACK(bug("[%s] Requested mode %ldx%ldx%d\n", __PRETTY_FUNCTION__, width, height, comp_depth));
380 modeid = FindBestHiddMode(compdata, width, height, depth, &found_depth);
381 DSTACK(bug("[%s] Composition Display Mode 0x%08X [current 0x%08X]\n", __PRETTY_FUNCTION__, modeid, compdata->screenmodeid));
383 if (modeid != compdata->screenmodeid)
385 /* The mode is different. Need to prepare information needed for compositing */
386 struct TagItem gctags[] =
388 { aHidd_GC_Foreground, 0x99999999 },
389 { TAG_DONE , 0 }
392 /* Signal mode change */
393 compdata->screenmodeid = modeid;
394 compdata->modeschanged = TRUE;
396 /* Get gray foregound */
397 if (found_depth < 24)
398 gctags[0].ti_Data = 0x9492;
400 OOP_SetAttrs(compdata->gc, gctags);
404 static inline void HIDDCompositingRedrawBitmap(struct HIDDCompositingData *compdata, struct StackBitMapNode *n, struct Rectangle *rect)
406 /* The given rectangle is already in screen coordinate system here */
407 ULONG blitwidth = rect->MaxX - rect->MinX + 1;
408 ULONG blitheight = rect->MaxY - rect->MinY + 1;
410 DREDRAWBM(bug("[Compositing:%s] Redraw BitMap 0x%p, Rect[%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, n->bm,
411 rect->MinX, rect->MinY, rect->MaxX, rect->MaxY));
412 DREDRAWBM(bug("[Compositing:%s] Blitting %dx%d [from %d, %d]\n", __PRETTY_FUNCTION__, blitwidth, blitheight,
413 rect->MinX - n->leftedge, rect->MinY - n->topedge));
415 HIDD_Gfx_CopyBox(compdata->gfx, n->bm,
416 /* Transform to source bitmap coord system */
417 rect->MinX - n->leftedge, rect->MinY - n->topedge,
418 compdata->compositedbitmap,
419 rect->MinX, rect->MinY, blitwidth, blitheight,
420 compdata->gc);
423 static inline void ClearRect(struct HIDDCompositingData *compdata, ULONG MinX, ULONG MinY, ULONG MaxX, ULONG MaxY)
425 DREDRAWSCR(bug("[Compositing:%s] Clearing [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
426 MinX, MinY, MaxX, MaxY));
428 HIDD_BM_FillRect(compdata->compositedbitmap, compdata->gc,
429 MinX, MinY, MaxX, MaxY);
432 static VOID HIDDCompositingRedrawVisibleDisplay(struct HIDDCompositingData *compdata)
434 struct Region *dispvisregion = NULL;
435 struct Rectangle tmprect;
437 struct StackBitMapNode *n;
439 DREDRAWSCR(bug("[Compositing:%s] Redrawing screen (GfxBase @ 0x%p)\n", __PRETTY_FUNCTION__, GfxBase));
441 /* Recalculate visible regions */
442 HIDDCompositingRecalculateVisibleRegions(compdata);
444 if ((dispvisregion = NewRegion()) != NULL)
446 OrRectRegion(dispvisregion, &compdata->screenrect);
447 DRECALC(bug("[Compositing:%s] Display rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(compdata->screenrect)));
449 ForeachNode(&compdata->bitmapstack, n)
451 if ((n->sbmflags & STACKNODE_VISIBLE) &&
452 (!(n->sbmflags & STACKNODE_ALPHA)) &&
453 (n->screenregion))
455 DREDRAWSCR(bug("[Compositing:%s] ScreenRegion @ 0x%p ScreenBitMap @ 0x%p [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
456 n->screenregion, n->bm, _RECT(n->screenvisiblerect)));
458 DREDRAWSCR(bug("[Compositing:%s] Redrawing Visible Screen Regions..\n", __PRETTY_FUNCTION__));
459 // Render the visable regions ..
460 struct RegionRectangle * srrect = n->screenregion->RegionRectangle;
461 while (srrect)
463 tmprect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
464 tmprect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
465 tmprect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
466 tmprect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
468 DREDRAWSCR(bug("[Compositing:%s] Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(&tmprect)));
470 HIDDCompositingRedrawBitmap(compdata, n, &tmprect);
471 HIDD_BM_UpdateRect(compdata->compositedbitmap,
472 tmprect.MinX, tmprect.MinY,
473 tmprect.MaxX - tmprect.MinX + 1,
474 tmprect.MaxY - tmprect.MinY + 1);
476 srrect = srrect->Next;
478 ClearRegionRegion(n->screenregion, dispvisregion);
481 struct RegionRectangle * dispclrrect = dispvisregion->RegionRectangle;
482 while (dispclrrect)
484 struct HIDD_BackFillHookMsg clearmsg;
486 tmprect.MinX = dispclrrect->bounds.MinX + dispvisregion->bounds.MinX;
487 tmprect.MinY = dispclrrect->bounds.MinY + dispvisregion->bounds.MinY;
488 tmprect.MaxX = dispclrrect->bounds.MaxX + dispvisregion->bounds.MinX;
489 tmprect.MaxY = dispclrrect->bounds.MaxY + dispvisregion->bounds.MinY;
491 DREDRAWSCR(bug("[Compositing:%s] Render Display Void Region [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(&tmprect)));
493 clearmsg.bounds = &tmprect;
494 clearmsg.offsetx = 0;
495 clearmsg.offsety = 0;
496 CallHookPkt(compdata->backfillhook, compdata->compositedbitmap, &clearmsg);
497 HIDD_BM_UpdateRect(compdata->compositedbitmap,
498 tmprect.MinX, tmprect.MinY,
499 tmprect.MaxX - tmprect.MinX + 1,
500 tmprect.MaxY - tmprect.MinY + 1);
502 dispclrrect = dispclrrect->Next;
504 ForeachNode(&compdata->bitmapstack, n)
506 if ((n->sbmflags & STACKNODE_VISIBLE) &&
507 (n->sbmflags & STACKNODE_ALPHA) &&
508 (n->screenregion))
510 DREDRAWSCR(bug("[Compositing:%s] ALPHAScreenRegion @ 0x%p ScreenBitMap @ 0x%p [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__,
511 n->screenregion, n->bm, _RECT(n->screenvisiblerect)));
514 DisposeRegion(dispvisregion);
520 There are several cases that needs to be handled in this code. They are documented
521 below. Please read it before making changes.
522 etb = existing topbitmap
523 ntb = new top bitmap
524 sb = screen bitmap
525 cb = composited bitmap
526 fs = covers full screen
527 nfs = not covers full screen
528 mA = mode "A"
529 mB = mode "B"
530 disp() = dispose
531 new() = new
533 The resulting mode is always that of screen bitmap as set in "effect" column.
534 The composited bitmap always matches the resulting screen mode or is NULL.
536 | exiting screen situation | change | effect |
537 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - SAME MODE |
538 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mA | sb==ntb, cb==NULL |
539 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
540 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
541 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb, cb!=NULL |
542 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
543 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - SAME MODE |
544 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
545 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
546 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
547 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
548 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
551 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - DIFFERENT MODES |
552 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mB | sb==ntb, cb==NULL |
553 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
554 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
555 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mB | new(cb), sb==cb, cb!=NULL |
556 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
557 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - DIFFERENT MODES |
558 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
559 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
560 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
561 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
562 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
565 | USE CASE: DRAGGING SCREEN DOWN |
566 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb |
567 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb |
568 | USE CASE: DRAGGING SCREEN UP |
569 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==etb |
570 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
572 Resulting rules (order matters):
574 (a) if ((cb!=NULL) && (etb->mode!=ntb->mode)) {dispose(cb), cb=NULL}
575 (b) if ((ntb->nfs) && (cb==NULL)) new(cb)
576 (c) if (ntb->nfs) sb=cb
577 (d) if (ntb->fs) sb=ntb
579 Additional rule:
580 (e) if (oldsb!=sb) modeswitch(sb)
582 02.09.2011: we don't remember sb any more because we don't handle it in any way. Instead
583 we either have or don't have compositedbitmap. If we have it, composition
584 is on (sb = cb). If we don't have it, composition is off (sb = ntb).
586 static BOOL HIDDCompositingToggleCompositing(struct HIDDCompositingData *compdata, BOOL newtop)
589 * If the topbitmap covers the complete screen, show it instead of
590 * compositedbitmap. Remember that screen bitmap -> composited bitmap
591 * mirroring has a negative impact on performance.
593 OOP_Object *oldcompositedbitmap = compdata->compositedbitmap;
594 OOP_Object *newscreenbitmap = NULL;
595 BOOL ok = TRUE;
597 /* (a) If mode change is needed, enforce opening a new screen */
598 if (compdata->modeschanged)
600 D(bug("[Compositing:%s] Display Mode changed\n", __PRETTY_FUNCTION__));
601 compdata->compositedbitmap = NULL;
604 #if (0)
606 * This condition is enough as compositing allows only dragging screen down
607 * and not up/left/right at the moment.
609 if (topedge > 0)
611 #endif
612 /* (b) */
613 if (compdata->compositedbitmap == NULL)
616 * compositedbitmap == NULL means we were in passthrough mode before,
617 * or have just changed display mode - set up screen for composition.
619 D(bug("[Compositing:%s] Initialising Display-Compositor..\n", __PRETTY_FUNCTION__));
621 if (compdata->fb)
624 * If our display driver uses a framebuffer, we can reuse it.
625 * Copy its original contents back into the bitmap which it replaced,
626 * then change framebuffer's video mode.
627 * Framebuffer is the only bitmap which can change its ModeID on the fly.
629 D(bug("[Compositing:%s] Using Display Famebuffer BitMap @ 0x%p\n", __PRETTY_FUNCTION__, compdata->fb));
631 /* Do this comparison in order not to show the framebuffer twice */
632 if (oldcompositedbitmap != compdata->fb)
635 * 1. It's legal to show the framebuffer itself. This causes copying
636 * back old bitmap contents and detaching from it.
637 * 2. The result of this will always match compdata->fb.
638 * 3. Internally this is a simple blit operation, it can't fail.
640 D(bug("[Compositing:%s] Copying old Famebuffer BitMap\n", __PRETTY_FUNCTION__));
641 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, compdata->fb, fHidd_Gfx_Show_CopyBack);
644 /* Switch display mode on the framebuffer. */
645 OOP_SetAttrsTags(compdata->fb, aHidd_BitMap_ModeID, compdata->screenmodeid, TAG_DONE);
646 /* We are now compositing on the framebuffer */
647 compdata->compositedbitmap = compdata->fb;
649 else
652 * There's no framebuffer.
653 * Create a new bitmap that will be used for compositing.
655 struct TagItem bmtags[5];
657 bmtags[0].ti_Tag = aHidd_BitMap_Width; bmtags[0].ti_Data = compdata->screenrect.MaxX + 1;
658 bmtags[1].ti_Tag = aHidd_BitMap_Height; bmtags[1].ti_Data = compdata->screenrect.MaxY + 1;
659 bmtags[2].ti_Tag = aHidd_BitMap_Displayable; bmtags[2].ti_Data = TRUE;
660 bmtags[3].ti_Tag = aHidd_BitMap_ModeID; bmtags[3].ti_Data = compdata->screenmodeid;
661 bmtags[4].ti_Tag = TAG_DONE; bmtags[4].ti_Data = TAG_DONE;
663 compdata->compositedbitmap = HIDD_Gfx_NewBitMap(compdata->gfx, bmtags);
664 D(bug("[Compositing:%s] Created Compositor Display BitMap @ 0x%p\n", __PRETTY_FUNCTION__, compdata->compositedbitmap));
666 /* Mode changed, this bitmap will be shown later */
667 newscreenbitmap = compdata->compositedbitmap;
669 /* NewBitMap can fail, handle this */
670 if (!newscreenbitmap)
671 ok = FALSE;
674 else /* if (compdata->compositedbitmap == NULL) */
677 * We are already in compositing mode and will stay in it.
678 * Do not destroy our working bitmap.
680 oldcompositedbitmap = NULL;
684 * (c) Here composition is turned on (compositedbitmap != NULL).
685 * Redraw bitmap stack - compensate possible changes
687 if (ok)
688 HIDDCompositingRedrawVisibleDisplay(compdata);
689 #if(0)
691 else if (oldcompositedbitmap || newtop)
694 * (d) Set passthrough mode and display the frontmost bitmap.
695 * This is also triggered by 'newtop' parameter, which tells us
696 * that frontmost bitmap has been changed, and we need to display a new one.
697 * Old compositedbitmap has been remembered in the beginning. If it's not
698 * NULL, it will be destroyed in the end.
700 newscreenbitmap = compdata->topbitmap;
701 compdata->compositedbitmap = NULL;
703 #endif
705 DTOGGLE(bug("[Compositing:%s] oldcompbmp 0x%p, topbmp 0x%p, compbmp 0x%p, newscreenbmp 0x%p\n", __PRETTY_FUNCTION__,
706 oldcompositedbitmap, compdata->topbitmap, compdata->compositedbitmap, newscreenbitmap));
709 * (e) If the screenbitmap changed, show the new screenbitmap.
710 * We do it after refreshing, for better visual appearance.
712 if (newscreenbitmap)
714 IPTR w, h;
716 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, newscreenbitmap, fHidd_Gfx_Show_CopyBack);
717 D(bug("[Compositing:%s] Displayed bitmap 0x%p, Show returned 0x%p\n", __PRETTY_FUNCTION__, newscreenbitmap, compdata->screenbitmap));
719 /* After Show we need Update for mirroring drivers */
720 if (compdata->screenbitmap)
722 OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Width, &w);
723 OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Height, &h);
724 HIDD_BM_UpdateRect(compdata->screenbitmap, 0, 0, w, h);
729 * (a) - disposing of oldcompositingbitmap needs to happen after mode switch
730 * since it could have been the current screenbitmap
732 if (oldcompositedbitmap && (oldcompositedbitmap != compdata->fb))
734 D(bug("[Compositing:%s] Disposing old working bitmap 0x%p\n", __PRETTY_FUNCTION__, oldcompositedbitmap));
735 HIDD_Gfx_DisposeBitMap(compdata->gfx, oldcompositedbitmap);
738 /* Handled */
739 compdata->modeschanged = FALSE;
741 return ok;
744 static VOID HIDDCompositingPurgeBitMapStack(struct HIDDCompositingData * compdata)
746 struct StackBitMapNode * curr, * next;
748 ForeachNodeSafe(&compdata->bitmapstack, curr, next)
750 if (curr->screenregion)
751 DisposeRegion(curr->screenregion);
753 FreeMem(curr, sizeof(struct StackBitMapNode));
756 NEWLIST(&compdata->bitmapstack);
759 static void HIDDCompositingShowSingle(struct HIDDCompositingData *compdata, OOP_Object *bm)
761 /* Show the single top bitmap */
762 compdata->topbitmap = bm;
763 compdata->screenbitmap = HIDD_Gfx_Show(compdata->gfx, bm, fHidd_Gfx_Show_CopyBack);
765 /* Dispose working bitmap (if any) */
766 if (compdata->compositedbitmap)
768 /* Be careful with the framebuffer */
769 if (compdata->compositedbitmap != compdata->fb)
770 HIDD_Gfx_DisposeBitMap(compdata->gfx, compdata->compositedbitmap);
772 /* This will deactivate us */
773 compdata->compositedbitmap = NULL;
777 /* Emergency error recovery function */
778 static void HIDDCompositingReset(struct HIDDCompositingData *compdata)
780 /* Purge bitmap stack */
781 HIDDCompositingPurgeBitMapStack(compdata);
784 * Reset our internal state so that next BitMapStackChanged
785 * causes complete reinitialization.
787 compdata->screenmodeid = vHidd_ModeID_Invalid;
788 compdata->screenbitmap = NULL;
791 AROS_UFH3(void, CompositorDefaultBackFillFunc,
792 AROS_UFHA(struct Hook * , h, A0),
793 AROS_UFHA(OOP_Object * , bm, A2),
794 AROS_UFHA(struct HIDD_BackFillHookMsg * , msg, A1))
796 AROS_USERFUNC_INIT
798 struct HIDDCompositingData *compdata = h->h_Data;
800 D(bug("[%s] HIDDCompositingData @ 0x%p\n", __PRETTY_FUNCTION__, compdata));
802 ClearRect(compdata, msg->bounds->MinX, msg->bounds->MinY, msg->bounds->MaxX, msg->bounds->MaxY);
804 AROS_USERFUNC_EXIT
807 /* PUBLIC METHODS */
808 OOP_Object *METHOD(Compositing, Root, New)
810 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
812 if (o)
814 OOP_MethodID disposemid;
815 struct HIDDCompositingData *compdata = OOP_INST_DATA(cl, o);
817 /* use default amiga-like capabailities */
818 compdata->capabilities = COMPF_ABOVE;
820 D(bug("[%s] Compositor @ 0x%p, data @ 0x%p\n", __PRETTY_FUNCTION__, o, compdata));
821 D(bug("[%s] Composite Capabilities: %08lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
823 compdata->screenmodeid = vHidd_ModeID_Invalid;
825 NEWLIST(&compdata->bitmapstack);
827 compdata->defaultbackfill.h_Entry = (HOOKFUNC)AROS_ASMSYMNAME(CompositorDefaultBackFillFunc);
828 compdata->defaultbackfill.h_Data = compdata;
829 compdata->backfillhook = &compdata->defaultbackfill;
831 InitSemaphore(&compdata->semaphore);
833 compdata->gfx = (OOP_Object *)GetTagData(aHidd_Compositing_GfxHidd, 0, msg->attrList);
834 compdata->fb = (OOP_Object *)GetTagData(aHidd_Compositing_FrameBuffer, 0, msg->attrList);
836 compdata->GraphicsBase = OpenLibrary("graphics.library", 41);
838 /* GfxHidd is mandatory */
839 if ((compdata->GraphicsBase) && (compdata->gfx != NULL))
841 /* Create GC object that will be used for drawing operations */
842 compdata->gc = HIDD_Gfx_NewGC(compdata->gfx, NULL);
844 D(bug("[%s] Compositor GC @ %p\n", __PRETTY_FUNCTION__, compdata->gc));
846 if ((compdata->gfx) && (compdata->gc))
847 return o;
850 /* Creation failed */
851 disposemid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
852 OOP_CoerceMethod(cl, o, &disposemid);
855 return NULL;
858 void METHOD(Compositing, Root, Dispose)
862 struct HIDDCompositingData *compdata = OOP_INST_DATA(cl, o);
863 bug("[%s] HIDDCompositingData @ 0x%p\n", __PRETTY_FUNCTION__, compdata);
866 OOP_DoSuperMethod(cl, o, &msg->mID);
869 VOID METHOD(Compositing, Root, Get)
871 struct HIDDCompositingData *compdata = OOP_INST_DATA(cl, o);
873 switch (msg->attrID)
875 case aoHidd_Compositing_Capabilities:
877 D(bug("[%s] Composite Capabilities: %lx\n", __PRETTY_FUNCTION__, compdata->capabilities));
878 *msg->storage = (IPTR)COMPF_ABOVE|COMPF_BELOW|COMPF_LEFT|COMPF_RIGHT;
879 return;
881 case aoHidd_Compositing_BackFillHook:
883 D(bug("[%s] BackFillHook: 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook));
884 *msg->storage = (IPTR)compdata->backfillhook;
885 return;
889 OOP_DoSuperMethod(cl, o, &msg->mID);
892 VOID METHOD(Compositing, Root, Set)
894 struct HIDDCompositingData *compdata = OOP_INST_DATA(cl, o);
895 struct TagItem *tag, *tstate = msg->attrList;
897 while ((tag = NextTagItem(&tstate)))
899 switch (tag->ti_Tag)
901 case aoHidd_Compositing_Capabilities:
903 D(bug("[%s] Composite Capabilities: %lx -> %lx\n", __PRETTY_FUNCTION__, compdata->capabilities, tag->ti_Data));
904 compdata->capabilities = (ULONG)tag->ti_Data;
905 break;
907 case aoHidd_Compositing_BackFillHook:
909 if (tag->ti_Data)
911 D(bug("[%s] BackFillHook: 0x%p -> 0x%p\n", __PRETTY_FUNCTION__, compdata->backfillhook, tag->ti_Data));
912 compdata->backfillhook = (struct Hook *)tag->ti_Data;
914 else
916 D(bug("[%s] Default BackFillHook\n", __PRETTY_FUNCTION__));
917 compdata->backfillhook = &compdata->defaultbackfill;
920 break;
925 OOP_DoSuperMethod(cl, o, &msg->mID);
928 OOP_Object *METHOD(Compositing, Hidd_Compositing, BitMapStackChanged)
930 struct HIDD_ViewPortData *vpdata;
931 struct HIDDCompositingData *compdata = OOP_INST_DATA(cl, o);
932 struct StackBitMapNode *n;
933 BOOL newtop = FALSE;
934 BOOL ok = TRUE;
936 DSTACK(bug("[%s] Top bitmap: 0x%lx\n", __PRETTY_FUNCTION__, msg->data->Bitmap));
938 LOCK_COMPOSITING_WRITE
940 /* Free all items which are already on the list */
941 HIDDCompositingPurgeBitMapStack(compdata);
943 if (!msg->data)
945 UNLOCK_COMPOSITING
947 /* Blank screen */
948 HIDDCompositingShowSingle(compdata, NULL);
950 /* We know we are inactive after this */
951 *msg->active = FALSE;
952 /* This can return NULL, it's okay */
953 return compdata->screenbitmap;
956 /* Copy bitmaps pointers to our stack */
957 for (vpdata = msg->data; vpdata; vpdata = vpdata->Next)
959 n = AllocMem(sizeof(struct StackBitMapNode), MEMF_ANY | MEMF_CLEAR);
960 if (!n)
963 * Error happened.
964 * We need to reset own state and return NULL. graphics.library
965 * falls back to no composition in this case.
967 DSTACK(bug("[%s] Error allocating StackBitMapNode!!!\n", __PRETTY_FUNCTION__));
969 ok = FALSE;
970 break;
973 DSTACK(bug("[%s] ViewPort 0x%p, offset (%d, %d)\n", __PRETTY_FUNCTION__, vpdata->vpe->ViewPort, vpdata->vpe->ViewPort->DxOffset, vpdata->vpe->ViewPort->DyOffset));
975 n->bm = vpdata->Bitmap;
976 n->sbmflags = 0;
977 n->leftedge = vpdata->vpe->ViewPort->DxOffset;
978 n->topedge = vpdata->vpe->ViewPort->DyOffset;
980 AddTail((struct List *)&compdata->bitmapstack, (struct Node *)n);
983 /* Switch mode if needed */
984 UpdateDisplayMode(compdata);
986 if (msg->data->Bitmap != compdata->topbitmap)
988 /* Set the new pointer to top bitmap */
989 compdata->topbitmap = msg->data->Bitmap;
990 newtop = TRUE;
993 if (ok)
996 * Validate bitmap offsets - they might not match the compositing rules taking
997 * new displayedwidth/displayedheight values
999 ForeachNode(&compdata->bitmapstack, n)
1001 HIDDCompositingValidateBitMapPositionChange(n->bm, &n->leftedge, &n->topedge,
1002 compdata->screenrect.MaxX + 1, compdata->screenrect.MaxY + 1);
1003 DSTACK(bug("[%s] Bitmap 0x%p, display size %d x %d, validated position (%ld, %ld)\n", __PRETTY_FUNCTION__,
1004 n->bm, compdata->screenrect.MaxX + 1, compdata->screenrect.MaxY + 1,
1005 n->leftedge, n->topedge));
1008 /* Toogle compositing based on screen positions */
1009 ok = HIDDCompositingToggleCompositing(compdata, newtop);
1012 /* Handle error */
1013 if (!ok)
1015 HIDDCompositingReset(compdata);
1016 HIDDCompositingShowSingle(compdata, msg->data->Bitmap);
1019 UNLOCK_COMPOSITING
1021 DSTACK(bug("[%s] Done, composited bitmap 0x%p\n", __PRETTY_FUNCTION__, compdata->compositedbitmap));
1023 /* Tell if the composition is active */
1024 *msg->active = compdata->compositedbitmap ? TRUE : FALSE;
1025 /* Return actually displayed bitmap */
1026 return compdata->screenbitmap;
1029 VOID METHOD(Compositing, Hidd_Compositing, BitMapRectChanged)
1031 struct HIDDCompositingData * compdata = OOP_INST_DATA(cl, o);
1033 if (compdata->compositedbitmap)
1035 /* Composition is active, handle redraw if the bitmap is on screen */
1036 struct StackBitMapNode *n;
1038 DUPDATE(bug("[%s] Bitmap 0x%p\n", __PRETTY_FUNCTION__, msg->bm));
1040 LOCK_COMPOSITING_READ
1042 n = HIDDCompositingIsBitMapOnStack(compdata, msg->bm);
1043 if (n && (n->sbmflags & STACKNODE_VISIBLE))
1045 struct Rectangle srcrect, dstandvisrect;
1047 srcrect.MinX = n->leftedge + msg->x;
1048 srcrect.MinY = n->topedge + msg->y;
1049 srcrect.MaxX = n->leftedge + msg->x + msg->width - 1;
1050 srcrect.MaxY = n->topedge + msg->y + msg->height - 1;
1051 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));
1053 DUPDATE(bug("[%s] Screen-relative rect [%d, %d - %d, %d]\n", __PRETTY_FUNCTION__, _RECT(srcrect)));
1055 struct RegionRectangle * srrect = n->screenregion->RegionRectangle;
1056 while (srrect)
1058 dstandvisrect.MinX = srrect->bounds.MinX + n->screenregion->bounds.MinX;
1059 dstandvisrect.MinY = srrect->bounds.MinY + n->screenregion->bounds.MinY;
1060 dstandvisrect.MaxX = srrect->bounds.MaxX + n->screenregion->bounds.MinX;
1061 dstandvisrect.MaxY = srrect->bounds.MaxY + n->screenregion->bounds.MinY;
1063 if (AndRectRect(&srcrect, &dstandvisrect, &dstandvisrect))
1065 /* Intersection is valid. Blit. */
1066 DUPDATE(bug("[%s] Clipped rect (%d, %d) - (%d, %d)\n", __PRETTY_FUNCTION__, _RECT(dstandvisrect)));
1068 HIDDCompositingRedrawBitmap(compdata, n, &dstandvisrect);
1070 HIDD_BM_UpdateRect(compdata->compositedbitmap,
1071 dstandvisrect.MinX, dstandvisrect.MinY,
1072 dstandvisrect.MaxX - dstandvisrect.MinX + 1,
1073 dstandvisrect.MaxY - dstandvisrect.MinY + 1);
1075 srrect = srrect->Next;
1079 UNLOCK_COMPOSITING
1081 DUPDATE(bug("[%s] Done\n", __PRETTY_FUNCTION__));
1083 else
1086 * In order to speed things up, we handle passthrough ourselves here.
1087 * It's not difficult.
1089 HIDD_BM_UpdateRect(msg->bm, msg->x, msg->y, msg->width, msg->height);
1093 IPTR METHOD(Compositing, Hidd_Compositing, BitMapPositionChange)
1095 struct HIDDCompositingData *compdata = OOP_INST_DATA(cl, o);
1096 struct StackBitMapNode *n;
1097 IPTR disp_width, disp_height;
1099 LOCK_COMPOSITING_READ
1101 n = HIDDCompositingIsBitMapOnStack(compdata, msg->bm);
1102 if (n)
1104 /* The bitmap is on display. Validate against screen size */
1105 disp_width = compdata->screenrect.MaxX + 1;
1106 disp_height = compdata->screenrect.MaxY + 1;
1108 else
1110 /* The bitmap is not displayed yet. Validate against its own ModeID size. */
1111 HIDDT_ModeID modeid = vHidd_ModeID_Invalid;
1112 OOP_Object *sync, *pf;
1114 OOP_GetAttr(msg->bm, aHidd_BitMap_ModeID, &modeid);
1116 if (modeid == vHidd_ModeID_Invalid)
1119 * Nondisplayable bitmaps don't scroll.
1120 * In fact they simply can't get in here because MakeVPort() performs the validation.
1121 * But who knows what bug can slip into someone's software...
1123 UNLOCK_COMPOSITING
1124 return FALSE;
1127 HIDD_Gfx_GetMode(compdata->gfx, modeid, &sync, &pf);
1128 OOP_GetAttr(sync, aHidd_Sync_HDisp, &disp_width);
1129 OOP_GetAttr(sync, aHidd_Sync_VDisp, &disp_height);
1132 DMOVE(bug("[%s] Validating bitmap 0x%p, position (%ld, %ld), limits %ld x %ld\n", __PRETTY_FUNCTION__,
1133 msg->bm, *msg->newxoffset, *msg->newyoffset, disp_width, disp_height));
1135 HIDDCompositingValidateBitMapPositionChange(msg->bm, msg->newxoffset, msg->newyoffset,
1136 disp_width, disp_height);
1138 DMOVE(bug("[%s] Validated position (%ld, %ld)\n", __PRETTY_FUNCTION__, *msg->newxoffset, *msg->newyoffset));
1140 if (n && ((*msg->newxoffset != n->leftedge) || (*msg->newyoffset != n->topedge)))
1142 DMOVE(bug("[%s] Old position (%ld, %ld)\n", __PRETTY_FUNCTION__, n->leftedge, n->topedge));
1144 /* Reflect the change if it happened */
1145 n->leftedge = *msg->newxoffset;
1146 n->topedge = *msg->newyoffset;
1148 if (compdata->topbitmap == msg->bm)
1151 * If this is the frontmost bitmap, we may want to toggle compositing,
1152 * if it starts/stops covering the whole screen at one point.
1153 * We don't need to call HIDDCompositingRedrawVisibleDisplay() here because
1154 * HIDDCompositingToggleCompositing() does this itself, for improved
1155 * visual appearance.
1157 HIDDCompositingToggleCompositing(compdata, FALSE);
1159 else
1160 HIDDCompositingRedrawVisibleDisplay(compdata);
1163 UNLOCK_COMPOSITING
1165 /* Return active state */
1166 return compdata->compositedbitmap ? TRUE : FALSE;
1169 #define NUM_Compositing_Root_METHODS 4
1171 static const struct OOP_MethodDescr Compositing_Root_descr[] =
1173 {(OOP_MethodFunc)Compositing__Root__New, moRoot_New},
1174 {(OOP_MethodFunc)Compositing__Root__Dispose, moRoot_Dispose},
1175 {(OOP_MethodFunc)Compositing__Root__Get, moRoot_Get},
1176 {(OOP_MethodFunc)Compositing__Root__Set, moRoot_Set},
1177 {NULL, 0}
1180 #define NUM_Compositing_Hidd_Compositing_METHODS 3
1182 static const struct OOP_MethodDescr Compositing_Hidd_Compositing_descr[] =
1184 {(OOP_MethodFunc)Compositing__Hidd_Compositing__BitMapStackChanged, moHidd_Compositing_BitMapStackChanged},
1185 {(OOP_MethodFunc)Compositing__Hidd_Compositing__BitMapRectChanged, moHidd_Compositing_BitMapRectChanged},
1186 {(OOP_MethodFunc)Compositing__Hidd_Compositing__BitMapPositionChange, moHidd_Compositing_BitMapPositionChange},
1187 {NULL, 0}
1190 const struct OOP_InterfaceDescr Compositing_ifdescr[] =
1192 {Compositing_Root_descr, IID_Root, NUM_Compositing_Root_METHODS},
1193 {Compositing_Hidd_Compositing_descr, IID_Hidd_Compositing, NUM_Compositing_Hidd_Compositing_METHODS},
1194 {NULL, NULL}