some further WIP polish localization.
[AROS.git] / workbench / hidds / nouveau / nouveau_compositorclass.c
blob1347fc5d4cb55c0568d55e93aa19abe2cb2e74db
1 /*
2 Copyright © 2010-2017, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /*
7 This is ment to be (in future) a generic class that will be capable of
8 compositor bitmaps on screen to get effects like screen dragging.
9 The code is generic where possible, using abstract OOP_Objects instead of
10 concrete driver structures. There are places where nouveau specific calls
11 are performed, however there are only few and can be generilized to
12 (private) methods that should be reimplemented by child classes in each of
13 the drivers.
16 /* Non generic part */
17 #include "nouveau_intern.h"
18 /* Non generic part */
20 #include "nouveau_compositor.h"
22 #include <proto/exec.h>
23 #include <aros/debug.h>
24 #include <proto/oop.h>
25 #include <proto/utility.h>
28 #undef HiddPixFmtAttrBase
29 #undef HiddSyncAttrBase
30 #undef HiddBitMapAttrBase
31 #undef HiddGCAttrBase
32 #undef HiddCompositorAttrBase
34 #define HiddPixFmtAttrBase (compdata->pixFmtAttrBase)
35 #define HiddSyncAttrBase (compdata->syncAttrBase)
36 #define HiddBitMapAttrBase (compdata->bitMapAttrBase)
37 #define HiddGCAttrBase (compdata->gcAttrBase)
38 #define HiddCompositorAttrBase (compdata->compositorAttrBase)
40 #define MAX(a,b) a > b ? a : b
41 #define MIN(a,b) a < b ? a : b
43 static BOOL AndRectRect(struct _Rectangle * rect1, struct _Rectangle * rect2,
44 struct _Rectangle * intersect)
46 intersect->MinX = MAX(rect1->MinX, rect2->MinX);
47 intersect->MinY = MAX(rect1->MinY, rect2->MinY);
48 intersect->MaxX = MIN(rect1->MaxX, rect2->MaxX);
49 intersect->MaxY = MIN(rect1->MaxY, rect2->MaxY);
51 if ((intersect->MinX > intersect->MaxX) ||
52 (intersect->MinY > intersect->MaxY))
53 return FALSE;
54 else
55 return TRUE;
58 static struct StackBitMapNode * HIDDCompositorIsBitMapOnStack(struct HIDDCompositorData * compdata, OOP_Object * bm)
60 struct StackBitMapNode * n = NULL;
62 ForeachNode(&compdata->bitmapstack, n)
64 if (n->bm == bm)
65 return n;
68 return NULL;
71 static VOID HIDDCompositorValidateBitMapPositionChange(struct HIDDCompositorData * compdata, OOP_Object * bm,
72 LONG * newxoffset, LONG * newyoffset)
74 struct StackBitMapNode * n = NULL;
76 /* Check if passed bitmap is in stack, ignore if not */
77 if ((n = HIDDCompositorIsBitMapOnStack(compdata, bm)) != NULL)
79 IPTR width, height;
80 LONG limit;
82 OOP_GetAttr(bm, aHidd_BitMap_Width, &width);
83 OOP_GetAttr(bm, aHidd_BitMap_Height, &height);
85 /* Check x position */
86 limit = n->displayedwidth - width;
87 if (*(newxoffset) > 0)
88 *(newxoffset) = 0;
90 if (*(newxoffset) < limit)
91 *(newxoffset) = limit;
93 /* Check y position */
94 limit = n->displayedheight - height;
95 if (*(newyoffset) > n->displayedheight - 15) /* Limit for drag */
96 *(newyoffset) = n->displayedheight - 15;
98 if (*(newyoffset) < limit) /* Limit for scroll */
99 *(newyoffset) = limit;
104 static VOID HIDDCompositorRecalculateVisibleRects(struct HIDDCompositorData * compdata)
106 ULONG lastscreenvisibleline = compdata->screenrect.MaxY;
107 struct StackBitMapNode * n = NULL;
109 /* This function assumes bitmapstack is in correct Z order:
110 from top most to bottom most */
112 ForeachNode(&compdata->bitmapstack, n)
114 /* Stack bitmap bounding boxes equal screen bounding box taking into
115 account topedge */
116 IPTR topedge;
117 struct _Rectangle tmprect;
119 OOP_GetAttr(n->bm, aHidd_BitMap_TopEdge, &topedge);
120 /* Copy screen rect */
121 tmprect = compdata->screenrect;
122 /* Set bottom and top values */
123 tmprect.MinY = topedge;
124 tmprect.MaxY = lastscreenvisibleline;
125 /* Intersect both to make sure values are withint screen limit */
126 if (AndRectRect(&tmprect, &compdata->screenrect, &n->screenvisiblerect))
128 lastscreenvisibleline = n->screenvisiblerect.MinY - 1;
129 n->isscreenvisible = TRUE;
131 else
132 n->isscreenvisible = FALSE;
134 D(bug("[Compositor] Bitmap 0x%x, visible %d, (%d, %d) , (%d, %d)\n",
135 n->bm, n->isscreenvisible,
136 n->screenvisiblerect.MinX, n->screenvisiblerect.MinY,
137 n->screenvisiblerect.MaxX, n->screenvisiblerect.MaxY));
141 static BOOL HIDDCompositorTopBitMapChanged(struct HIDDCompositorData * compdata, OOP_Object * bm)
143 OOP_Object * sync = NULL;
144 OOP_Object * pf = NULL;
145 IPTR modeid, hdisp, vdisp, e, depth;
147 OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, &e);
149 /* Sanity check */
150 if (compdata->gfx != (OOP_Object *)e)
152 /* Provided top bitmap is not using the same driver as compositor. Fail. */
153 D(bug("[Compositor] GfxHidd different than one used by compositor\n"));
154 return FALSE;
157 /* Read display mode properties */
158 OOP_GetAttr(bm, aHidd_BitMap_ModeID, &modeid);
159 if (modeid == vHidd_ModeID_Invalid)
161 D(bug("[Compositor] Invalid ModeID\n"));
162 return FALSE;
165 /* Invalidate screen bitmap if it is set to "previous" top bitmap, since this
166 "previous" top bitmap is already gone at this point */
167 if (compdata->screenbitmap == compdata->topbitmap)
168 compdata->screenbitmap = NULL;
170 /* Set the pointer to top bitmap */
171 compdata->topbitmap = bm;
173 /* If the mode is already visible do nothing */
174 if (modeid == compdata->screenmodeid)
175 return TRUE;
177 /* The mode is different. Need to prepare information needed for compositor */
179 /* Get width and height of mode */
180 struct pHidd_Gfx_GetMode __getmodemsg =
182 modeID: modeid,
183 syncPtr: &sync,
184 pixFmtPtr: &pf,
185 }, *getmodemsg = &__getmodemsg;
186 struct TagItem gctags[] =
188 { aHidd_GC_Foreground, (HIDDT_Pixel)0x99999999 },
189 { TAG_DONE, TAG_DONE }
193 getmodemsg->mID = OOP_GetMethodID(IID_Hidd_Gfx, moHidd_Gfx_GetMode);
194 OOP_DoMethod(compdata->gfx, (OOP_Msg)getmodemsg);
196 OOP_GetAttr(sync, aHidd_Sync_HDisp, &hdisp);
197 OOP_GetAttr(sync, aHidd_Sync_VDisp, &vdisp);
198 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
200 /* Store mode information */
201 compdata->screenmodeid = modeid;
202 compdata->screenrect.MinX = 0;
203 compdata->screenrect.MinY = 0;
204 compdata->screenrect.MaxX = hdisp - 1;
205 compdata->screenrect.MaxY = vdisp - 1;
206 compdata->modeschanged = TRUE;
208 /* Get gray foregound */
209 if (depth < 24) gctags[0].ti_Data = (HIDDT_Pixel)0x9492;
211 OOP_SetAttrs(compdata->gc, gctags);
214 return TRUE;
217 static BOOL HIDDCompositorCanCompositeWithScreenBitMap(struct HIDDCompositorData * compdata, OOP_Object * bm)
219 OOP_Object * screenbm = compdata->topbitmap; /* Tread top bitmap as screen bitmap */
220 IPTR screenbmwidth, screenbmheight, screenbmstdpixfmt;
221 IPTR bmgfx, bmmodeid, bmwidth, bmheight, bmstdpixfmt;
224 IPTR pf;
225 /* These two values cannot be obtained from topbitmap width/height, because
226 those can be larger than screen mode values and we are interested exaclty
227 in screen mode height/width */
228 screenbmwidth = compdata->screenrect.MaxX + 1;
229 screenbmheight = compdata->screenrect.MaxY + 1;
230 OOP_GetAttr(screenbm, aHidd_BitMap_PixFmt, &pf);
231 OOP_GetAttr((OOP_Object*)pf, aHidd_PixFmt_StdPixFmt, &screenbmstdpixfmt);
235 IPTR pf;
236 OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, &bmgfx);
237 OOP_GetAttr(bm, aHidd_BitMap_ModeID, &bmmodeid);
238 OOP_GetAttr(bm, aHidd_BitMap_Width, &bmwidth);
239 OOP_GetAttr(bm, aHidd_BitMap_Height, &bmheight);
240 OOP_GetAttr(bm, aHidd_BitMap_PixFmt, &pf);
241 OOP_GetAttr((OOP_Object*)pf, aHidd_PixFmt_StdPixFmt, &bmstdpixfmt);
244 /* If bm uses different instances of gfx hidd than screenbm(=composing), they cannot be composited */
245 if (compdata->gfx != (OOP_Object *)bmgfx)
246 return FALSE;
248 /* If bitmaps have the same modeid, they can be composited */
249 if (compdata->screenmodeid == bmmodeid)
250 return TRUE;
252 /* If bitmaps have different pixel formats, they cannot be composited */
253 /* FIXME: actually they can, but CopyBox for different formats is not
254 optimized so let's not make user experience worse */
255 if (screenbmstdpixfmt != bmstdpixfmt)
256 return FALSE;
258 /* If screenbm is not bigger than bm, bitmaps can be composited, because
259 bm will start scrolling on smaller resolution of screenbm */
260 /* FIXME: the opposite situation might also work - smaller bitmap on bigger
261 resolution. In such case, left out areas need to be cleared up. Also it
262 needs to be checked if mouse clicks outside of bitmap will not cause
263 problems */
264 if ((screenbmwidth <= bmwidth) && (screenbmheight <= bmheight))
265 return TRUE;
267 /* Last decision, bitmaps cannot be composited */
268 return FALSE;
271 static VOID HIDDCompositorRedrawBitmap(struct HIDDCompositorData * compdata,
272 OOP_Object * bm, WORD x, WORD y, WORD width, WORD height)
274 struct StackBitMapNode * n = NULL;
276 /* Check if compositedbitmap is being displayed right now */
277 if (compdata->screenbitmap != compdata->compositedbitmap)
278 return;
280 /* Check if passed bitmap is in stack, ignore if not */
281 if ((n = HIDDCompositorIsBitMapOnStack(compdata, bm)) == NULL)
282 return;
284 if (!n->isscreenvisible)
285 return;
287 if (compdata->compositedbitmap)
289 IPTR leftedge, topedge;
290 struct _Rectangle srcrect;
291 struct _Rectangle srcindstrect;
292 struct _Rectangle dstandvisrect;
294 OOP_GetAttr(bm, aHidd_BitMap_LeftEdge, &leftedge);
295 OOP_GetAttr(bm, aHidd_BitMap_TopEdge, &topedge);
297 /* Rectangle in source bitmap coord system */
298 srcrect.MinX = x;
299 srcrect.MinY = y;
300 srcrect.MaxX = x + width - 1;
301 srcrect.MaxY = y + height - 1;
303 /* Source bitmap rectangle in destination (screen) coord system */
304 srcindstrect.MinX = srcrect.MinX + leftedge;
305 srcindstrect.MaxX = srcrect.MaxX + leftedge;
306 srcindstrect.MinY = srcrect.MinY + topedge;
307 srcindstrect.MaxY = srcrect.MaxY + topedge;
309 /* Find intersection of bitmap visible screen rect and srcindst rect */
310 if (AndRectRect(&srcindstrect, &n->screenvisiblerect, &dstandvisrect))
312 /* Intersection is valid. Blit. */
314 HIDD_Gfx_CopyBox(
315 compdata->gfx,
317 /* Transform back to source bitmap coord system */
318 dstandvisrect.MinX - leftedge, dstandvisrect.MinY - topedge,
319 compdata->compositedbitmap,
320 dstandvisrect.MinX, dstandvisrect.MinY,
321 dstandvisrect.MaxX - dstandvisrect.MinX + 1,
322 dstandvisrect.MaxY - dstandvisrect.MinY + 1,
323 compdata->gc);
328 static VOID HIDDCompositorRedrawVisibleScreen(struct HIDDCompositorData * compdata)
330 struct StackBitMapNode * n = NULL;
331 ULONG lastscreenvisibleline = compdata->screenrect.MaxY;
333 /* Calculations are performed regardless if compositedbitmap is beeing show.
334 Gfx operations are only performed if compositedbitmap is beeing show */
336 /* Recalculate visible rects per screen */
337 HIDDCompositorRecalculateVisibleRects(compdata);
339 /* Refresh all bitmaps on stack */
340 ForeachNode(&compdata->bitmapstack, n)
342 if (n->isscreenvisible)
344 IPTR width, height;
345 OOP_GetAttr(n->bm, aHidd_BitMap_Width, &width);
346 OOP_GetAttr(n->bm, aHidd_BitMap_Height, &height);
348 HIDDCompositorRedrawBitmap(compdata, n->bm, 0, 0, width, height);
349 if (lastscreenvisibleline > n->screenvisiblerect.MinY)
350 lastscreenvisibleline = n->screenvisiblerect.MinY;
354 /* Clean up area revealed by drag */
355 /* TODO: Find all areas which might have been releaved, not only top -
356 This will happen when there are bitmaps of different sizes composited */
357 if ((compdata->screenbitmap == compdata->compositedbitmap) && (lastscreenvisibleline > 1))
359 HIDD_BM_FillRect(compdata->compositedbitmap,
360 compdata->gc, 0, 0, compdata->screenrect.MaxX, lastscreenvisibleline - 1);
366 There are several cases that needs to be handled in this code. They are documented
367 below. Please read it before making changes.
368 etb = existing topbitmap
369 ntb = new top bitmap
370 sb = screen bitmap
371 cb = composited bitmap
372 fs = covers full screen
373 nfs = not covers full screen
374 mA = mode "A"
375 mB = mode "B"
376 disp() = dispose
377 new() = new
379 The resulting mode is always that of screen bitmap as set in "effect" column.
380 The composited bitmap always matches the resulting screen mode or is NULL.
382 | exiting screen situation | change | effect |
383 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - SAME MODE |
384 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mA | sb==ntb, cb==NULL |
385 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
386 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
387 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb, cb!=NULL |
388 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
389 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - SAME MODE |
390 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
391 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==ntb, cb!=NULL |
392 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - SAME MODE |
393 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
394 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mA | sb==cb, cb!=NULL |
397 | USE CASE: SWITCHING BETWEEN FULL SCREEN SCREENS - DIFFERENT MODES |
398 | etb->fs, mA, sb==etb, cb==NULL | ntb->fs, mB | sb==ntb, cb==NULL |
399 | etb->fs, mA, sb==etb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
400 | USE CASE: SWITCHING BETWEEN FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
401 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mB | new(cb), sb==cb, cb!=NULL |
402 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
403 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND FULL SCREEN SCREENS - DIFFERENT MODES |
404 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
405 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mB | disp(cb), sb==ntb, cb==NULL |
406 | USE CASE: SWITCHING BETWEEN NOT FULL SCREEN AND NOT FULL SCREEN SCREENS - DIFFERENT MODES |
407 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
408 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->nfs, mB | disp(cb), new(cb), sb==cb, cb!=NULL |
411 | USE CASE: DRAGGING SCREEN DOWN |
412 | etb->fs, mA, sb==etb, cb==NULL | ntb->nfs, mA | new(cb), sb==cb |
413 | etb->fs, mA, sb==etb, cb!=NULL | ntb->nfs, mA | sb==cb |
414 | USE CASE: DRAGGING SCREEN UP |
415 | etb->nfs, mA, sb==cb, cb!=NULL | ntb->fs, mA | sb==etb |
416 | etb->nfs, mA, sb==cb, cb==NULL | NOT POSSIBLE |
418 Resulting rules (order matters):
420 (a) if ((cb!=NULL) && (etb->mode!=ntb->mode)) {dispose(cb), cb=NULL}
421 (b) if ((ntb->nfs) && (cb==NULL)) new(cb)
422 (c) if (ntb->nsf) sb=cb
423 (d) if (ntb->fs) sb=ntb
425 Additional rule:
426 (e) if (oldsb!=sb) modeswitch(sb)
429 static VOID HIDDCompositorToggleCompositing(struct HIDDCompositorData * compdata)
431 /* If the topbitmap covers the complete screen, show it instead of
432 compositedbitmap. This removes the need for copying
433 screen bitmap -> composited bitmap. Not copying improves performance */
434 IPTR topedge;
435 OOP_Object * oldscreenbitmap = compdata->screenbitmap;
436 OOP_Object * oldcompositedbitmap = NULL;
438 OOP_GetAttr(compdata->topbitmap, aHidd_BitMap_TopEdge, &topedge);
440 /* (a) */
441 if ((compdata->compositedbitmap) && (compdata->modeschanged))
443 oldcompositedbitmap = compdata->compositedbitmap;
444 compdata->compositedbitmap = NULL;
448 /* This condition is enough as compositor allows only dragging screen down
449 and not up/left/right */
450 if ((LONG)topedge > (LONG)0) /* Explicitly cast to get signed comparison */
452 /* (b) */
453 if (compdata->compositedbitmap == NULL)
455 struct TagItem bmtags[5];
457 /* Create a new bitmap that will be used for compositor */
458 bmtags[0].ti_Tag = aHidd_BitMap_Width; bmtags[0].ti_Data = compdata->screenrect.MaxX + 1;
459 bmtags[1].ti_Tag = aHidd_BitMap_Height; bmtags[1].ti_Data = compdata->screenrect.MaxY + 1;
460 bmtags[2].ti_Tag = aHidd_BitMap_Displayable; bmtags[2].ti_Data = TRUE;
461 bmtags[3].ti_Tag = aHidd_BitMap_ModeID; bmtags[3].ti_Data = compdata->screenmodeid;
462 bmtags[4].ti_Tag = TAG_DONE; bmtags[4].ti_Data = TAG_DONE;
464 compdata->compositedbitmap = HIDD_Gfx_CreateObject(compdata->gfx, SD(OOP_OCLASS(compdata->gfx))->basebm, bmtags);
467 /* (c) */
468 if (oldscreenbitmap != compdata->compositedbitmap)
470 compdata->screenbitmap = compdata->compositedbitmap;
472 /* Redraw bitmap stack - compensate for changes that happened while
473 compositor was not active */
474 HIDDCompositorRedrawVisibleScreen(compdata);
477 else
479 /* (d) */
480 compdata->screenbitmap = compdata->topbitmap;
483 D(bug("[Compositor] Toggle te %d, oldscr 0x%x, top 0x%x, comp 0x%x, scr 0x%x\n",
484 topedge, oldscreenbitmap, compdata->topbitmap, compdata->compositedbitmap,
485 compdata->screenbitmap));
487 /* If the screenbitmap changed, show the new screenbitmap */
488 /* (e) */
489 if (oldscreenbitmap != compdata->screenbitmap)
490 HIDDNouveauSwitchToVideoMode(compdata->screenbitmap);
492 /* (a) - disposing of oldcompositorbitmap needs to happen after mode switch
493 since it could have been the current screenbitmap */
494 if (oldcompositedbitmap)
495 OOP_DisposeObject(oldcompositedbitmap);
497 /* Handled */
498 compdata->modeschanged = FALSE;
501 static VOID HIDDCompositorPurgeBitMapStack(struct HIDDCompositorData * compdata)
503 struct StackBitMapNode * curr, * next;
505 ForeachNodeSafe(&compdata->bitmapstack, curr, next)
507 Remove((struct Node *)curr);
508 FreeMem(curr, sizeof(struct StackBitMapNode));
511 NEWLIST(&compdata->bitmapstack);
517 /* PUBLIC METHODS */
518 OOP_Object *METHOD(Compositor, Root, New)
520 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
522 if(o)
524 struct HIDDCompositorData * compdata = OOP_INST_DATA(cl, o);
526 struct OOP_ABDescr attrbases[] =
528 { IID_Hidd_PixFmt, &compdata->pixFmtAttrBase },
529 { IID_Hidd_Sync, &compdata->syncAttrBase },
530 { IID_Hidd_BitMap, &compdata->bitMapAttrBase },
531 { IID_Hidd_GC, &compdata->gcAttrBase },
532 { IID_Hidd_Compositor, &compdata->compositorAttrBase },
533 { NULL, NULL }
536 NEWLIST(&compdata->bitmapstack);
537 compdata->compositedbitmap = NULL;
538 compdata->topbitmap = NULL;
539 compdata->screenbitmap = NULL;
540 compdata->screenmodeid = vHidd_ModeID_Invalid;
541 compdata->modeschanged = FALSE;
542 InitSemaphore(&compdata->semaphore);
544 /* Obtain Attr bases - make this class self-contained */
545 if (OOP_ObtainAttrBases(attrbases))
547 compdata->gfx = (OOP_Object *)GetTagData(aHidd_Compositor_GfxHidd, 0, msg->attrList);
549 if (compdata->gfx != NULL)
551 /* Create GC object that will be used for drawing operations */
552 compdata->gc = HIDD_Gfx_CreateObject(compdata->gfx, SD(cl)->basegc, NULL);
556 if ((compdata->gfx == NULL) || (compdata->gc == NULL))
558 /* Creation failed */
559 OOP_MethodID disposemid;
560 disposemid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
561 OOP_CoerceMethod(cl, o, (OOP_Msg)&disposemid);
562 o = NULL;
566 return o;
569 VOID METHOD(Compositor, Hidd_Compositor, BitMapStackChanged)
571 struct HIDD_ViewPortData * vpdata;
572 struct HIDDCompositorData * compdata = OOP_INST_DATA(cl, o);
573 struct StackBitMapNode * n = NULL;
575 D(bug("[Compositor] BitMapStackChanged, topbitmap: 0x%x\n",
576 msg->data->Bitmap));
578 LOCK_COMPOSITOR_WRITE
580 /* Free all items which are already on the list */
581 HIDDCompositorPurgeBitMapStack(compdata);
584 if (!msg->data)
586 UNLOCK_COMPOSITOR
587 return; /* TODO: BLANK SCREEN */
590 /* Switch mode if needed */
591 if (!HIDDCompositorTopBitMapChanged(compdata, msg->data->Bitmap))
593 /* Something bad happened. Yes, bitmap stack is already erased - that's ok */
594 D(bug("[Compositor] Failed to change top bitmap\n"));
595 UNLOCK_COMPOSITOR
596 return;
599 /* Copy bitmaps pointers to our stack */
600 for (vpdata = msg->data; vpdata; vpdata = vpdata->Next)
602 D(bug("Compositor] Testing bitmap: %x\n", vpdata->Bitmap));
603 /* Check if the passed bitmap can be composited together with screen
604 bitmap */
605 if (HIDDCompositorCanCompositeWithScreenBitMap(compdata, vpdata->Bitmap))
607 n = AllocMem(sizeof(struct StackBitMapNode), MEMF_ANY | MEMF_CLEAR);
609 n->bm = vpdata->Bitmap;
610 n->isscreenvisible = FALSE;
611 n->displayedwidth = compdata->screenrect.MaxX + 1;
612 n->displayedheight = compdata->screenrect.MaxY + 1;
613 AddTail(&compdata->bitmapstack, (struct Node *)n);
617 /* Validate bitmap offsets - they might not match the compositor rules taking
618 new displayedwidth/displayedheight values */
619 ForeachNode(&compdata->bitmapstack, n)
621 LONG newxoffset, newyoffset;
622 IPTR val;
623 OOP_GetAttr(n->bm, aHidd_BitMap_TopEdge, &val);newyoffset = (LONG)val;
624 OOP_GetAttr(n->bm, aHidd_BitMap_LeftEdge, &val);newxoffset = (LONG)val;
626 HIDDCompositorValidateBitMapPositionChange(compdata, n->bm,
627 &newxoffset, &newyoffset);
629 /* Override offsets without checks present in bitmap Set method */
630 HIDDNouveauSetOffsets(n->bm, newxoffset, newyoffset);
633 /* Toogle compositor based on screen positions */
634 HIDDCompositorToggleCompositing(compdata);
636 /* Redraw bitmap stack - compensate for change of visible rects
637 resulting from new top bitmap */
638 HIDDCompositorRedrawVisibleScreen(compdata);
640 UNLOCK_COMPOSITOR
643 VOID METHOD(Compositor, Hidd_Compositor, BitMapRectChanged)
645 struct HIDDCompositorData * compdata = OOP_INST_DATA(cl, o);
647 LOCK_COMPOSITOR_READ
649 HIDDCompositorRedrawBitmap(compdata, msg->bm, msg->x, msg->y, msg->width, msg->height);
651 UNLOCK_COMPOSITOR
654 VOID METHOD(Compositor, Hidd_Compositor, BitMapPositionChanged)
656 struct HIDDCompositorData * compdata = OOP_INST_DATA(cl, o);
658 LOCK_COMPOSITOR_WRITE
660 /* Check is passed bitmap is in stack, ignore if not */
661 if (HIDDCompositorIsBitMapOnStack(compdata, msg->bm) != NULL)
663 /* If top bitmap position has changed, possibly toggle compositor */
664 if (compdata->topbitmap == msg->bm)
665 HIDDCompositorToggleCompositing(compdata);
667 /* If compositor is not active and top bitmap has changed, execute scroll */
668 if ((compdata->screenbitmap == compdata->topbitmap)
669 && (compdata->topbitmap == msg->bm))
672 HIDDNouveauSwitchToVideoMode(compdata->screenbitmap);
674 else
676 /* Redraw bitmap stack - compensate change of visible rects resulting
677 from move of bitmap */
678 HIDDCompositorRedrawVisibleScreen(compdata);
682 UNLOCK_COMPOSITOR
685 VOID METHOD(Compositor, Hidd_Compositor, ValidateBitMapPositionChange)
687 struct HIDDCompositorData * compdata = OOP_INST_DATA(cl, o);
689 LOCK_COMPOSITOR_READ
691 HIDDCompositorValidateBitMapPositionChange(compdata, msg->bm,
692 msg->newxoffset, msg->newyoffset);
694 UNLOCK_COMPOSITOR