Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / monitors / IntelGMA / compositingclass.c
blob38ec1ba815315228bb40596485cf8912930b9adb
1 /*
2 Copyright © 2010-2015, 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 compositing 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 #define DEBUG 0
18 #include <aros/debug.h>
19 #include <proto/exec.h>
20 #include <proto/oop.h>
21 #include <proto/utility.h>
23 /* Non generic part */
24 #include "intelG45_intern.h"
25 /* Non generic part */
27 #include "compositing_intern.h"
29 #define MAX(a,b) a > b ? a : b
30 #define MIN(a,b) a < b ? a : b
32 static BOOL AndRectRect(struct _Rectangle * rect1, struct _Rectangle * rect2,
33 struct _Rectangle * intersect)
35 intersect->MinX = MAX(rect1->MinX, rect2->MinX);
36 intersect->MinY = MAX(rect1->MinY, rect2->MinY);
37 intersect->MaxX = MIN(rect1->MaxX, rect2->MaxX);
38 intersect->MaxY = MIN(rect1->MaxY, rect2->MaxY);
40 if ((intersect->MinX > intersect->MaxX) ||
41 (intersect->MinY > intersect->MaxY))
42 return FALSE;
43 else
44 return TRUE;
47 static struct StackBitMapNode * HIDDCompositingIsBitMapOnStack(struct HIDDCompositingData * compdata, OOP_Object * bm)
49 struct StackBitMapNode * n = NULL;
51 ForeachNode(&compdata->bitmapstack, n)
53 if (n->bm == bm)
54 return n;
57 return NULL;
60 static struct StackBitMapNode * HIDDCompositingCanUseFramebuffer(struct HIDDCompositingData * compdata)
62 struct StackBitMapNode * n = NULL;
63 struct StackBitMapNode * frn = NULL;
65 ForeachNode(&compdata->bitmapstack, n)
67 if( n->isscreenvisible )
69 if( n->screenvisiblerect.MinX <= 0 &&
70 n->screenvisiblerect.MinY <= 0 &&
71 n->screenvisiblerect.MaxX >= compdata->screenrect.MaxX &&
72 n->screenvisiblerect.MaxY >= compdata->screenrect.MaxY )
74 frn = n;
76 else return NULL;
79 D(bug("[Compositing] HIDDCompositingCanUseFramebuffer bm %x\n",frn->bm));
80 return frn;
83 static VOID HIDDCompositingRecalculateVisibleRects(struct HIDDCompositingData * compdata)
85 ULONG lastscreenvisibleline = compdata->screenrect.MaxY + 1;
86 struct StackBitMapNode * n = NULL;
88 ForeachNode(&compdata->bitmapstack, n)
90 /* Stack bitmap bounding boxes equal screen bounding box taking into
91 account topedge */
92 IPTR topedge;
93 struct _Rectangle tmprect;
95 OOP_GetAttr(n->bm, aHidd_BitMap_TopEdge, &topedge);
96 /* Copy screen rect */
97 tmprect = compdata->screenrect;
98 /* Set bottom and top values */
99 tmprect.MinY = topedge;
100 tmprect.MaxY = lastscreenvisibleline - 1;
101 /* Intersect both to make sure values are withint screen limit */
102 if (AndRectRect(&tmprect, &compdata->screenrect, &n->screenvisiblerect))
104 lastscreenvisibleline = n->screenvisiblerect.MinY;
105 n->isscreenvisible = TRUE;
107 else
108 n->isscreenvisible = FALSE;
110 D(bug("[Compositing] Bitmap %x, visible %d, (%d, %d) , (%d, %d)\n",
111 n->bm, n->isscreenvisible,
112 n->screenvisiblerect.MinX, n->screenvisiblerect.MinY,
113 n->screenvisiblerect.MaxX, n->screenvisiblerect.MaxY));
119 static VOID HIDDCompositingRecalculateDisplayedWidthHeight(struct HIDDCompositingData * compdata)
121 struct StackBitMapNode * n = NULL;
122 IPTR displayedwidth, displayedheight;
124 OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Width, &displayedwidth);
125 OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Height, &displayedheight);
127 ForeachNode(&compdata->bitmapstack, n)
129 n->displayedwidth = displayedwidth;
130 n->displayedheight = displayedheight;
134 static BOOL HIDDCompositingTopBitMapChanged(struct HIDDCompositingData * compdata, OOP_Object * bm)
137 Desctiption:
138 a) take incomming top bitmap
139 b) read its mode and sizes,
140 c) create a mirroring bitmap that fits the mode
141 d) switch mode (driver dependandant)
143 OOP_Object * sync = NULL;
144 OOP_Object * pf = NULL;
145 OOP_Object * fbbitmap = NULL;
146 IPTR modeid, hdisp, vdisp, e, depth;
147 struct TagItem bmtags[5];
149 OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, &e);
151 /* Sanity check */
152 if (compdata->gfx != (OOP_Object *)e)
154 /* Provided top bitmap is not using the same driver as compositing. Fail. */
155 D(bug("[Compositing] GfxHidd different than one used by compositing\n"));
156 return FALSE;
159 /* Read display mode properties */
160 OOP_GetAttr(bm, aHidd_BitMap_ModeID, &modeid);
161 if (modeid == vHidd_ModeID_Invalid)
163 D(bug("[Compositing] Invalid ModeID\n"));
164 return FALSE;
167 /* If the mode is already visible do nothing */
168 if (modeid == compdata->screenmodeid)
169 return TRUE;
171 /* Get width and height of mode */
172 struct pHidd_Gfx_GetMode __getmodemsg =
174 modeID: modeid,
175 syncPtr: &sync,
176 pixFmtPtr: &pf,
177 }, *getmodemsg = &__getmodemsg;
179 getmodemsg->mID = OOP_GetMethodID(IID_Hidd_Gfx, moHidd_Gfx_GetMode);
180 OOP_DoMethod(compdata->gfx, (OOP_Msg)getmodemsg);
182 OOP_GetAttr(sync, aHidd_Sync_HDisp, &hdisp);
183 OOP_GetAttr(sync, aHidd_Sync_VDisp, &vdisp);
184 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
186 /* Create a new bitmap that will be used for framebuffer */
187 bmtags[0].ti_Tag = aHidd_BitMap_Width; bmtags[0].ti_Data = hdisp;
188 bmtags[1].ti_Tag = aHidd_BitMap_Height; bmtags[1].ti_Data = vdisp;
189 bmtags[2].ti_Tag = aHidd_BitMap_Displayable; bmtags[2].ti_Data = TRUE;
190 bmtags[3].ti_Tag = aHidd_BitMap_ModeID; bmtags[3].ti_Data = modeid;
191 bmtags[4].ti_Tag = TAG_DONE; bmtags[4].ti_Data = TAG_DONE;
193 fbbitmap = HIDD_Gfx_CreateObject(compdata->gfx, SD(OOP_OCLASS(compdata->gfx))->basebm, bmtags);
194 if (fbbitmap)
196 BOOL ret = HIDD_INTELG45_SwitchToVideoMode(fbbitmap);
197 if (ret)
200 struct TagItem gctags[] =
202 { aHidd_GC_Foreground, (HIDDT_Pixel)0x99999999 },
203 { TAG_DONE, TAG_DONE }
207 /* Dispose the previous screenbitmap */
208 if (compdata->screenbitmap)
209 OOP_DisposeObject(compdata->screenbitmap);
211 /* Store bitmap/mode information */
212 compdata->screenmodeid = modeid;
213 compdata->screenbitmap = fbbitmap;
214 compdata->screenrect.MinX = 0;
215 compdata->screenrect.MinY = 0;
216 compdata->screenrect.MaxX = hdisp - 1;
217 compdata->screenrect.MaxY = vdisp - 1;
218 compdata->directbitmap = NULL;
220 /* Get gray foregound */
221 if (depth < 24) gctags[0].ti_Data = (HIDDT_Pixel)0x9492;
222 OOP_SetAttrs(compdata->gc, gctags);
224 return TRUE;
226 else
228 /* Dispose fbbitmap */
229 OOP_DisposeObject(fbbitmap);
230 return FALSE;
234 return FALSE;
237 static BOOL HIDDCompositingCanCompositeWithScreenBitMap(struct HIDDCompositingData * compdata, OOP_Object * bm)
239 OOP_Object * screenbm = compdata->screenbitmap;
240 IPTR screenbmwidth, screenbmheight, screenbmstdpixfmt;
241 IPTR bmgfx, bmmodeid, bmwidth, bmheight, bmstdpixfmt;
242 IPTR pf;
244 /* HINT: both bitmaps can have different classes */
245 OOP_GetAttr(screenbm, aHidd_BitMap_Width, &screenbmwidth);
246 OOP_GetAttr(screenbm, aHidd_BitMap_Height, &screenbmheight);
247 OOP_GetAttr(screenbm, aHidd_BitMap_PixFmt, &pf);
248 OOP_GetAttr((OOP_Object*)pf, aHidd_PixFmt_StdPixFmt, &screenbmstdpixfmt);
250 OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, &bmgfx);
251 OOP_GetAttr(bm, aHidd_BitMap_ModeID, &bmmodeid);
252 OOP_GetAttr(bm, aHidd_BitMap_Width, &bmwidth);
253 OOP_GetAttr(bm, aHidd_BitMap_Height, &bmheight);
254 OOP_GetAttr(bm, aHidd_BitMap_PixFmt, &pf);
255 OOP_GetAttr((OOP_Object*)pf, aHidd_PixFmt_StdPixFmt, &bmstdpixfmt);
257 /* If bm uses different instances of gfx hidd than screenbm(=composing), they cannot be composited */
258 if (compdata->gfx != (OOP_Object *)bmgfx)
259 return FALSE;
261 /* If bitmaps have the same modeid, they can be composited */
262 if (compdata->screenmodeid == bmmodeid)
263 return TRUE;
265 /* If bitmaps have different pixel formats, they cannot be composited */
266 /* actually they can, if hw conversion is supported. */
267 if ( ( screenbmstdpixfmt != bmstdpixfmt ) && !copybox3d_supported() )
268 return FALSE;
270 return TRUE;
273 static VOID HIDDCompositingRedrawBitmap(struct HIDDCompositingData * compdata,
274 OOP_Object * bm, WORD x, WORD y, WORD width, WORD height, BOOL clean)
276 struct StackBitMapNode * n = NULL;
278 /* Check if passed bitmap is in stack, ignore if not */
279 if ((n = HIDDCompositingIsBitMapOnStack(compdata, bm)) == NULL)
280 return;
282 if (!n->isscreenvisible)
283 return;
285 if (compdata->screenbitmap)
287 IPTR leftedge, topedge;
288 struct _Rectangle srcrect;
289 struct _Rectangle srcindstrect;
290 struct _Rectangle dstandvisrect;
292 OOP_GetAttr(bm, aHidd_BitMap_LeftEdge, &leftedge);
293 OOP_GetAttr(bm, aHidd_BitMap_TopEdge, &topedge);
295 /* Rectangle in source bitmap coord system */
296 srcrect.MinX = x;
297 srcrect.MinY = y;
298 srcrect.MaxX = x + width - 1;
299 srcrect.MaxY = y + height - 1;
301 /* Source bitmap rectangle in destination (screen) coord system */
302 srcindstrect.MinX = srcrect.MinX + leftedge;
303 srcindstrect.MaxX = srcrect.MaxX + leftedge;
304 srcindstrect.MinY = srcrect.MinY + topedge;
305 srcindstrect.MaxY = srcrect.MaxY + topedge;
307 /* Find intersection of bitmap visible screen rect and srcindst rect */
308 if (AndRectRect(&srcindstrect, &n->screenvisiblerect, &dstandvisrect))
310 /* Intersection is valid. Blit. */
312 HIDD_Gfx_CopyBox(
313 compdata->gfx,
315 /* Transform back to source bitmap coord system */
316 dstandvisrect.MinX - leftedge, dstandvisrect.MinY - topedge,
317 compdata->screenbitmap,
318 dstandvisrect.MinX, dstandvisrect.MinY,
319 dstandvisrect.MaxX - dstandvisrect.MinX + 1,
320 dstandvisrect.MaxY - dstandvisrect.MinY + 1,
321 compdata->gc);
323 if( clean && dstandvisrect.MaxX+1 < n->screenvisiblerect.MaxX )
325 /* Clean right side.*/
326 D(bug("[Compositing] clean right %d,%d-%d,%d\n",dstandvisrect.MaxX+1, dstandvisrect.MinY,
327 n->screenvisiblerect.MaxX, dstandvisrect.MaxY));
328 HIDD_BM_FillRect(compdata->screenbitmap, compdata->gc,
329 dstandvisrect.MaxX+1, dstandvisrect.MinY-1,
330 n->screenvisiblerect.MaxX, dstandvisrect.MaxY);
333 if( clean && dstandvisrect.MaxY+1 < n->screenvisiblerect.MaxY )
335 /* Clean bottom.*/
336 D(bug("[Compositing] clean bottom %d,%d-%d,%d\n",
337 dstandvisrect.MinX, dstandvisrect.MaxY+1,
338 n->screenvisiblerect.MaxX, n->screenvisiblerect.MaxY));
339 HIDD_BM_FillRect(compdata->screenbitmap, compdata->gc,
340 dstandvisrect.MinX, dstandvisrect.MaxY+1,
341 n->screenvisiblerect.MaxX, n->screenvisiblerect.MaxY);
348 static VOID HIDDCompositingRedrawVisibleScreen(struct HIDDCompositingData * compdata)
350 struct StackBitMapNode * n = NULL;
351 ULONG lastscreenvisibleline = compdata->screenrect.MaxY;
353 /* Recalculate visible rects per screen */
354 HIDDCompositingRecalculateVisibleRects(compdata);
356 /* use direct framebuffer if it is possible */
357 struct StackBitMapNode *fbn;
358 if( ( fbn = HIDDCompositingCanUseFramebuffer(compdata) ) )
360 if( HIDD_INTELG45_SetFramebuffer( fbn->bm ) ){
361 D(bug("[Compositing] directbitmap used, bitmap %x\n",fbn->bm););
362 compdata->directbitmap = fbn->bm;
365 else
367 if( compdata->directbitmap ){
368 compdata->directbitmap = NULL;
369 D(bug("[Compositing] directbitmap not used, set screenbitmap %x\n",compdata->screenbitmap););
370 HIDD_INTELG45_SetFramebuffer( compdata->screenbitmap );
374 /* Refresh all bitmaps on stack */
375 ForeachNode(&compdata->bitmapstack, n)
377 if (n->isscreenvisible)
379 IPTR width, height;
381 OOP_GetAttr(n->bm, aHidd_BitMap_Width, &width);
382 OOP_GetAttr(n->bm, aHidd_BitMap_Height, &height);
384 HIDDCompositingRedrawBitmap(compdata, n->bm, 0, 0, width, height, TRUE);
385 if (lastscreenvisibleline > n->screenvisiblerect.MinY)
386 lastscreenvisibleline = n->screenvisiblerect.MinY;
390 /* Clean up area revealed by drag */
391 /* TODO: Find all areas which might have been releaved, not only top -
392 This will happen when there are bitmaps of different sizes composited */
393 if (lastscreenvisibleline > 0)
395 IPTR viswidth;
397 OOP_GetAttr(compdata->screenbitmap, aHidd_BitMap_Width, &viswidth);
398 D(bug("[Compositing] Clean upper area %d,%d-%d,%d\n",0, 0, viswidth - 1, lastscreenvisibleline - 1));
399 HIDD_BM_FillRect(compdata->screenbitmap,
400 compdata->gc, 0, 0, viswidth - 1, lastscreenvisibleline - 1);
404 static VOID HIDDCompositingPurgeBitMapStack(struct HIDDCompositingData * compdata)
406 struct StackBitMapNode * curr, * next;
408 ForeachNodeSafe(&compdata->bitmapstack, curr, next)
410 Remove((struct Node *)curr);
411 FreeMem(curr, sizeof(struct StackBitMapNode));
414 NEWLIST(&compdata->bitmapstack);
420 /* PUBLIC METHODS */
421 OOP_Object *METHOD(Compositing, Root, New)
423 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
424 D(bug("[Compositing] New\n"));
425 if(o)
427 struct HIDDCompositingData * compdata = OOP_INST_DATA(cl, o);
429 NEWLIST(&compdata->bitmapstack);
430 compdata->screenbitmap = NULL;
431 compdata->directbitmap = NULL;
432 compdata->screenmodeid = vHidd_ModeID_Invalid;
433 InitSemaphore(&compdata->semaphore);
435 compdata->gfx = (OOP_Object *)GetTagData(aHidd_Compositing_GfxHidd, 0, msg->attrList);
437 if (compdata->gfx != NULL)
439 /* Create GC object that will be used for drawing operations */
440 compdata->gc = HIDD_Gfx_CreateObject(compdata->gfx, SD(cl)->basegc, NULL);
443 if ((compdata->gfx == NULL) || (compdata->gc == NULL))
445 /* Creation failed */
446 OOP_MethodID disposemid;
447 disposemid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
448 OOP_CoerceMethod(cl, o, (OOP_Msg)&disposemid);
449 o = NULL;
453 return o;
456 VOID METHOD(Compositing, Hidd_Compositing, BitMapStackChanged)
458 struct HIDD_ViewPortData * vpdata;
459 struct HIDDCompositingData * compdata = OOP_INST_DATA(cl, o);
461 D(bug("[Compositing] BitMapStackChanged\n"));
463 LOCK_COMPOSITING_WRITE
465 /* Free all items which are already on the list */
466 HIDDCompositingPurgeBitMapStack(compdata);
469 if (!msg->data)
471 UNLOCK_COMPOSITING
472 return; /* TODO: BLANK SCREEN */
475 /* Switch mode if needed */
476 if (!HIDDCompositingTopBitMapChanged(compdata, msg->data->Bitmap))
478 /* Something bad happened. Yes, bitmap stack is already erased - that's ok */
479 D(bug("[Compositing] Failed to change top bitmap\n"));
480 UNLOCK_COMPOSITING
481 return;
484 /* Copy bitmaps pointers to our stack */
485 for (vpdata = msg->data; vpdata; vpdata = vpdata->Next)
487 /* Check if the passed bitmap can be composited together with screen
488 bitmap */
489 if (HIDDCompositingCanCompositeWithScreenBitMap(compdata, vpdata->Bitmap))
491 struct StackBitMapNode * n = AllocMem(sizeof(struct StackBitMapNode), MEMF_ANY | MEMF_CLEAR);
492 n->bm = vpdata->Bitmap;
493 n->isscreenvisible = FALSE;
494 n->displayedwidth = 0;
495 n->displayedheight = 0;
496 AddTail(&compdata->bitmapstack, (struct Node *)n);
500 /* Set displayedwidth/displayedheight on all screen bitmaps */
501 HIDDCompositingRecalculateDisplayedWidthHeight(compdata);
503 /* Redraw bitmap stack */
504 HIDDCompositingRedrawVisibleScreen(compdata);
506 UNLOCK_COMPOSITING
509 VOID METHOD(Compositing, Hidd_Compositing, BitMapRectChanged)
511 struct HIDDCompositingData * compdata = OOP_INST_DATA(cl, o);
512 //D(bug("[Compositing] BitMapRectChanged\n"));
513 if( ! compdata->directbitmap ){
514 LOCK_COMPOSITING_READ
515 HIDDCompositingRedrawBitmap(compdata, msg->bm, msg->x, msg->y, msg->width, msg->height, FALSE);
516 UNLOCK_COMPOSITING
520 VOID METHOD(Compositing, Hidd_Compositing, BitMapPositionChanged)
522 struct HIDDCompositingData * compdata = OOP_INST_DATA(cl, o);
523 D(bug("[Compositing] BitMapPositionChanged\n"));
524 LOCK_COMPOSITING_READ
526 /* Check is passed bitmap is in stack, ignore if not */
527 if (HIDDCompositingIsBitMapOnStack(compdata, msg->bm) != NULL)
529 /* Redraw bitmap stack */
530 HIDDCompositingRedrawVisibleScreen(compdata);
533 UNLOCK_COMPOSITING
536 VOID METHOD(Compositing, Hidd_Compositing, ValidateBitMapPositionChange)
538 struct HIDDCompositingData * compdata = OOP_INST_DATA(cl, o);
539 struct StackBitMapNode * n = NULL;
540 D(bug("[Compositing] ValidateBitMapPositionChange %d,%d\n",
541 *msg->newxoffset,*msg->newyoffset));
543 LOCK_COMPOSITING_READ
545 /* Check if passed bitmap is in stack, ignore if not */
546 if ((n = HIDDCompositingIsBitMapOnStack(compdata, msg->bm)) != NULL)
548 IPTR width, height;
549 LONG limit;
551 OOP_GetAttr(msg->bm, aHidd_BitMap_Width, &width);
552 OOP_GetAttr(msg->bm, aHidd_BitMap_Height, &height);
554 /* Check x position */
555 limit = n->displayedwidth < width ? n->displayedwidth - width : 0;
556 if (*(msg->newxoffset) > 0)
557 *(msg->newxoffset) = 0;
559 if (*(msg->newxoffset) < limit)
560 *(msg->newxoffset) = limit;
562 /* Check y position */
563 limit = n->displayedheight < height ? n->displayedheight - height : 0;
564 if (*(msg->newyoffset) > n->displayedheight - 15) /* Limit for drag */
565 *(msg->newyoffset) = n->displayedheight - 15;
567 if (*(msg->newyoffset) < limit) /* Limit for scroll */
568 *(msg->newyoffset) = limit;
571 UNLOCK_COMPOSITING
575 static const struct OOP_MethodDescr Compositing_Root_descr[] =
577 {(OOP_MethodFunc)Compositing__Root__New, moRoot_New},
578 {NULL, 0}
580 #define NUM_Compositing_Root_METHODS 1
582 static const struct OOP_MethodDescr Compositing_Hidd_Compositing_descr[] =
584 {(OOP_MethodFunc)Compositing__Hidd_Compositing__BitMapStackChanged, moHidd_Compositing_BitMapStackChanged},
585 {(OOP_MethodFunc)Compositing__Hidd_Compositing__BitMapRectChanged, moHidd_Compositing_BitMapRectChanged},
586 {(OOP_MethodFunc)Compositing__Hidd_Compositing__BitMapPositionChanged, moHidd_Compositing_BitMapPositionChanged},
587 {(OOP_MethodFunc)Compositing__Hidd_Compositing__ValidateBitMapPositionChange, moHidd_Compositing_ValidateBitMapPositionChange},
588 {NULL, 0}
590 #define NUM_Compositing_Hidd_Compositing_METHODS 4
592 const struct OOP_InterfaceDescr Compositing_ifdescr[] =
594 {Compositing_Root_descr, IID_Root, NUM_Compositing_Root_METHODS},
595 {Compositing_Hidd_Compositing_descr, IID_Hidd_Compositing, NUM_Compositing_Hidd_Compositing_METHODS},
596 {NULL, NULL}