2 Copyright 1995-2015, The AROS Development Team. All rights reserved.
5 Desc: GDI gfx HIDD for AROS.
9 #define __OOP_NOATTRBASES__
11 #include <exec/libraries.h>
12 #include <exec/rawfmt.h>
13 #include <exec/types.h>
14 #include <exec/resident.h>
15 #include <exec/memory.h>
16 #include <graphics/displayinfo.h>
17 #include <aros/libcall.h>
18 #include <proto/alib.h>
19 #include <proto/exec.h>
20 #include <proto/kernel.h>
21 #include <proto/oop.h>
22 #include <proto/utility.h>
25 #include <hidd/hidd.h>
26 #include <hidd/graphics.h>
28 #include <aros/symbolsets.h>
33 #include LC_LIBDEFS_FILE
37 #include <aros/debug.h>
41 #define PRINT_POINTER(image, xsize, xmax, ymax) \
42 bug("[GDIGfx] Pointer data:\n"); \
44 ULONG *pix = (ULONG *)image; \
47 for (y = 0; y < ymax; y++) { \
48 for (x = 0; x < xmax; x++) \
49 bug("0x%08X ", pix[x]); \
56 #define PRINT_POINTER(image, xsize, xmax, ymax)
59 /****************************************************************************************/
61 /* Some attrbases needed as global vars.
62 These are write-once read-many */
64 static OOP_AttrBase HiddBitMapAttrBase
;
65 static OOP_AttrBase HiddGDIBitMapAB
;
66 static OOP_AttrBase HiddSyncAttrBase
;
67 static OOP_AttrBase HiddPixFmtAttrBase
;
68 static OOP_AttrBase HiddGfxAttrBase
;
69 OOP_AttrBase HiddAttrBase
;
71 static struct OOP_ABDescr attrbases
[] =
73 { IID_Hidd_BitMap
, &HiddBitMapAttrBase
},
74 { IID_Hidd_GDIBitMap
, &HiddGDIBitMapAB
},
75 { IID_Hidd_Sync
, &HiddSyncAttrBase
},
76 { IID_Hidd_PixFmt
, &HiddPixFmtAttrBase
},
77 { IID_Hidd_Gfx
, &HiddGfxAttrBase
},
78 { IID_Hidd
, &HiddAttrBase
},
82 static void GfxIntHandler(struct gdi_staticdata
*xsd
, void *unused
)
84 struct gfx_data
*active
;
86 /* Process ShowDone IRQ */
87 if (xsd
->ctl
->ShowDone
)
89 xsd
->ctl
->ShowDone
= FALSE
;
91 Signal(xsd
->showtask
, SIGF_BLIT
);
94 /* Process display window activation */
95 active
= xsd
->ctl
->Active
;
98 xsd
->ctl
->Active
= NULL
;
99 D(bug("Activated display data 0x%p\n", active
));
101 active
->cb(active
->cbdata
, NULL
);
105 /****************************************************************************************/
107 OOP_Object
*GDICl__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
109 struct TagItem pftags
[] =
111 /* Shifts are non-obviously calculated from the MSB, not from the LSB.
112 I. e. color value is placed in the most significant byte of the ULONG
113 before shifting (cc000000, not 000000cc) */
114 { aHidd_PixFmt_RedShift
, 24 },
115 { aHidd_PixFmt_GreenShift
, 16 },
116 { aHidd_PixFmt_BlueShift
, 8 },
117 { aHidd_PixFmt_AlphaShift
, 0 },
118 { aHidd_PixFmt_RedMask
, 0x000000FF },
119 { aHidd_PixFmt_GreenMask
, 0x0000FF00 },
120 { aHidd_PixFmt_BlueMask
, 0x00FF0000 },
121 { aHidd_PixFmt_AlphaMask
, 0x00000000 },
122 /* Windows effectively hides from us all details of
123 color management and everything looks like if the
124 display mode is always truecolor */
125 { aHidd_PixFmt_ColorModel
, vHidd_ColorModel_TrueColor
},
126 { aHidd_PixFmt_Depth
, 24 },
127 { aHidd_PixFmt_BytesPerPixel
, 4 },
128 { aHidd_PixFmt_BitsPerPixel
, 24 },
129 { aHidd_PixFmt_StdPixFmt
, vHidd_StdPixFmt_Native
},
130 { aHidd_PixFmt_BitMapType
, vHidd_BitMapType_Chunky
},
134 struct TagItem tags_160_160
[] =
136 { aHidd_Sync_HDisp
, 160 },
137 { aHidd_Sync_VDisp
, 160 },
141 struct TagItem tags_240_320
[] =
143 { aHidd_Sync_HDisp
, 240 },
144 { aHidd_Sync_VDisp
, 320 },
148 struct TagItem tags_320_240
[] =
150 { aHidd_Sync_HDisp
, 320 },
151 { aHidd_Sync_VDisp
, 240 },
155 struct TagItem tags_512_384
[] =
157 { aHidd_Sync_HDisp
, 512 },
158 { aHidd_Sync_VDisp
, 384 },
162 struct TagItem tags_640_480
[] =
164 { aHidd_Sync_HDisp
, 640 },
165 { aHidd_Sync_VDisp
, 480 },
169 struct TagItem tags_800_600
[] =
171 { aHidd_Sync_HDisp
, 800 },
172 { aHidd_Sync_VDisp
, 600 },
176 struct TagItem tags_1024_768
[] =
178 { aHidd_Sync_HDisp
, 1024 },
179 { aHidd_Sync_VDisp
, 768 },
183 struct TagItem tags_1152_864
[] =
185 { aHidd_Sync_HDisp
, 1152 },
186 { aHidd_Sync_VDisp
, 864 },
190 struct TagItem tags_1280_800
[] =
192 { aHidd_Sync_HDisp
, 1280 },
193 { aHidd_Sync_VDisp
, 800 },
197 struct TagItem tags_1280_960
[] =
199 { aHidd_Sync_HDisp
, 1280 },
200 { aHidd_Sync_VDisp
, 960 },
204 struct TagItem tags_1280_1024
[] =
206 { aHidd_Sync_HDisp
, 1280 },
207 { aHidd_Sync_VDisp
, 1024 },
211 struct TagItem tags_1600_1200
[] =
213 { aHidd_Sync_HDisp
, 1600 },
214 { aHidd_Sync_VDisp
, 1200 },
218 struct TagItem mode_tags
[] =
220 { aHidd_Gfx_PixFmtTags
, (IPTR
)pftags
},
222 /* Default values for the sync attributes */
223 { aHidd_Sync_PixelClock
, 0 },
224 { aHidd_Sync_HTotal
, 0 },
225 { aHidd_Sync_VTotal
, 0 },
226 { aHidd_Sync_HMin
, 112 }, /* In fact these can be even smaller, and */
227 { aHidd_Sync_VMin
, 112 }, /* maximum can be even bigger... */
228 { aHidd_Sync_HMax
, 16384 },
229 { aHidd_Sync_VMax
, 16384 },
230 /* Formatting stands for:
234 { aHidd_Sync_Description
, (IPTR
)"Windows %b: %hx%v"},
235 { aHidd_Sync_BoardNumber
, XSD(cl
)->displaynum
},
237 /* The different syncmodes. The default attribute values above
238 will be applied to each of these. Note that
239 you can alter the defaults between the tags below
241 { aHidd_Gfx_SyncTags
, (IPTR
)tags_160_160
},
242 { aHidd_Gfx_SyncTags
, (IPTR
)tags_240_320
},
243 { aHidd_Gfx_SyncTags
, (IPTR
)tags_320_240
},
244 { aHidd_Gfx_SyncTags
, (IPTR
)tags_512_384
},
245 { aHidd_Gfx_SyncTags
, (IPTR
)tags_640_480
},
246 { aHidd_Gfx_SyncTags
, (IPTR
)tags_800_600
},
247 { aHidd_Gfx_SyncTags
, (IPTR
)tags_1024_768
},
248 { aHidd_Gfx_SyncTags
, (IPTR
)tags_1152_864
},
249 { aHidd_Gfx_SyncTags
, (IPTR
)tags_1280_800
},
250 { aHidd_Gfx_SyncTags
, (IPTR
)tags_1280_960
},
251 { aHidd_Gfx_SyncTags
, (IPTR
)tags_1280_1024
},
252 { aHidd_Gfx_SyncTags
, (IPTR
)tags_1600_1200
},
257 struct TagItem mytags
[] =
259 { aHidd_Gfx_ModeTags
, (IPTR
)mode_tags
},
260 { aHidd_Name
, (IPTR
)name
},
261 { aHidd_HardwareName
, (IPTR
)"Windows GDI" },
262 { aHidd_ProducerName
, (IPTR
)"Microsoft corporation"},
263 { TAG_MORE
, (IPTR
)msg
->attrList
}
265 struct pRoot_New mymsg
= { msg
->mID
, mytags
};
267 ULONG vfreq
, htotal
, vtotal
;
269 EnterFunc(bug("GDIGfx::New()\n"));
273 /* TODO: If we replace "DISPLAY" with something else here,
274 we get a possibility to select on which monitor to work.
275 Perhaps we should have some kind of preferences for this. */
276 display
= GDICALL(CreateDC
, "DISPLAY", NULL
, NULL
, NULL
);
279 ReturnPtr("GDIGfx::New()", OOP_Object
*, NULL
);
282 /* Fill in sync data */
283 vfreq
= GDICALL(GetDeviceCaps
, display
, VREFRESH
);
284 htotal
= GDICALL(GetDeviceCaps
, display
, HORZRES
);
285 vtotal
= GDICALL(GetDeviceCaps
, display
, VERTRES
);
289 D(bug("[GDI] Display size is %u x %u, Vertical refresh rate is %d Hz\n", htotal
, vtotal
, vfreq
));
290 /* Sometimes Windows may refuse to provide us with the valid refresh rate.
291 In this case it returns either 0 or 1 (which means "hardware default").
292 Perhaps we should assume two standard VGA clocks for 0 and 1 ? */
294 mode_tags
[1].ti_Data
= vfreq
* htotal
* vtotal
;
295 mode_tags
[2].ti_Data
= htotal
;
296 mode_tags
[3].ti_Data
= vtotal
;
298 NewRawDoFmt("gdi%lu.monitor", (VOID_FUNC
)RAWFMTFUNC_STRING
, name
, XSD(cl
)->displaynum
);
300 /* Register gfxmodes */
301 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)&mymsg
);
304 struct gfx_data
*data
= OOP_INST_DATA(cl
, o
);
306 D(bug("GDIGfx::New(): Got object from super\n"));
307 data
->display
= display
;
308 NewList((struct List
*)&data
->bitmaps
);
309 XSD(cl
)->displaynum
++;
311 ReturnPtr("GDIGfx::New", OOP_Object
*, o
);
314 /********** GfxHidd::Dispose() ******************************/
315 VOID
GDICl__Root__Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
317 struct gfx_data
*data
;
319 EnterFunc(bug("GDIGfx::Dispose(o=%p)\n", o
));
321 data
= OOP_INST_DATA(cl
, o
);
325 NATIVECALL(GDI_PutMsg
, data
->fbwin
, WM_CLOSE
, 0, 0);
327 USERCALL(DestroyIcon
, data
->cursor
);
329 GDICALL(DeleteDC
, data
->display
);
331 D(bug("GDIGfx::Dispose: calling super\n"));
332 OOP_DoSuperMethod(cl
, o
, msg
);
334 ReturnVoid("GDIGfx::Dispose");
337 /****************************************************************************************/
339 OOP_Object
*GDICl__Hidd_Gfx__CreateObject(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CreateObject
*msg
)
341 OOP_Object
*object
= NULL
;
343 if (msg
->cl
== XSD(cl
)->basebm
)
346 struct pHidd_Gfx_CreateObject p
;
347 HIDDT_StdPixFmt stdpf
;
349 struct gfx_data
*data
;
350 struct TagItem tags
[] =
352 { aHidd_GDIBitMap_SysDisplay
, 0UL }, /* 0 */
353 { TAG_IGNORE
, 0UL }, /* 1 */
354 { TAG_IGNORE
, 32 }, /* 2 */
355 { TAG_MORE
, 0UL } /* 3 */
358 EnterFunc(bug("GDIGfx::CreateObject()\n"));
359 data
= OOP_INST_DATA(cl
, o
);
361 tags
[0].ti_Data
= (IPTR
)data
->display
;
362 tags
[1].ti_Data
= (IPTR
)XSD(cl
)->bmclass
;
363 tags
[3].ti_Data
= (IPTR
)msg
->attrList
;
365 /* Create a GDI bitmap if we have a valid ModeID.
367 Also GDI bitmap can be created if there's no explicit
368 pixelformat specification and a friend bitmap is supplied,
369 which is a GDI bitmap. This is handled in the
372 Some day when AROS learns to deal with several display drivers at once, this check may go
373 away completely. This should really be handled by graphics.library. We do it here only because
374 display bitmap classes are currently private and only drivers themselves know about them.
376 modeid
= (HIDDT_ModeID
)GetTagData(aHidd_BitMap_ModeID
, vHidd_ModeID_Invalid
, msg
->attrList
);
377 stdpf
= (HIDDT_StdPixFmt
)GetTagData(aHidd_BitMap_StdPixFmt
, vHidd_StdPixFmt_Unknown
, msg
->attrList
);
379 if (modeid
!= vHidd_ModeID_Invalid
) {
380 tags
[1].ti_Tag
= aHidd_BitMap_ClassPtr
;
381 D(bug("[GDI] ModeID: 0x%08lX, ClassPtr: 0x%p\n", modeid
, tags
[1].ti_Data
));
383 /* longword-align planar bitmaps. This is needed for BlitColorExpansion() to work properly. */
384 if (stdpf
== vHidd_StdPixFmt_Plane
)
385 tags
[2].ti_Tag
= aHidd_BitMap_Align
;
391 object
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)&p
);
394 object
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
396 ReturnPtr("GDIGfx::CreateObject", OOP_Object
*, object
);
399 /****************************************************************************************/
401 VOID
GDICl__Root__Get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
405 if (IS_GFX_ATTR(msg
->attrID
, idx
))
409 case aoHidd_Gfx_IsWindowed
:
410 case aoHidd_Gfx_SupportsHWCursor
:
411 case aoHidd_Gfx_NoFrameBuffer
:
412 *msg
->storage
= TRUE
;
415 case aoHidd_Gfx_HWSpriteTypes
:
416 *msg
->storage
= vHidd_SpriteType_DirectColor
;
419 case aoHidd_Gfx_DriverName
:
420 *msg
->storage
= (IPTR
)"GDI";
424 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
427 /****************************************************************************************/
429 VOID
GDICl__Root__Set(OOP_Class
*cl
, OOP_Object
*obj
, struct pRoot_Set
*msg
)
431 struct gfx_data
*data
= OOP_INST_DATA(cl
, obj
);
432 struct TagItem
*tag
, *tstate
;
435 tstate
= msg
->attrList
;
436 while((tag
= NextTagItem(&tstate
)))
438 if (IS_GFX_ATTR(tag
->ti_Tag
, idx
)) {
441 case aoHidd_Gfx_ActiveCallBack
:
442 data
->cb
= (void *)tag
->ti_Data
;
445 case aoHidd_Gfx_ActiveCallBackData
:
446 data
->cbdata
= (APTR
)tag
->ti_Data
;
451 OOP_DoSuperMethod(cl
, obj
, (OOP_Msg
)msg
);
454 /****************************************************************************************/
456 static void AddToList(struct MinList
*list
, OOP_Object
*bitmap
)
458 OOP_Class
*bmclass
= OOP_OCLASS(bitmap
);
459 struct bitmap_data
*bmdata
= OOP_INST_DATA(bmclass
, bitmap
);
461 D(bug("[GDI] Will display bitmap data 0x%p, window 0x%p\n", bmdata
, bmdata
->window
));
462 if (bmdata
->node
.mln_Pred
) {
463 D(bug("[GDI] This bitmap is already on display\n"));
464 Remove((struct Node
*)bmdata
);
466 AddTail((struct List
*)list
, (struct Node
*)bmdata
);
469 static void ShowList(struct gdi_staticdata
*xsd
, struct gfx_data
*data
, struct MinList
*list
)
471 struct bitmap_data
*bmdata
;
473 /* If something left in displayed bitmaps list, close it */
474 for (bmdata
= (struct bitmap_data
*)data
->bitmaps
.mlh_Head
;
475 bmdata
->node
.mln_Succ
; bmdata
= (struct bitmap_data
*)bmdata
->node
.mln_Succ
) {
476 D(bug("[GDI] Hiding bitmap data 0x%p, window 0x%p\n", bmdata
, bmdata
->window
));
477 if (bmdata
->window
) {
478 NATIVECALL(GDI_PutMsg
, bmdata
->window
, WM_CLOSE
, 0, 0);
479 bmdata
->window
= NULL
;
481 /* This indicates that the bitmap is not in the list any more */
482 bmdata
->node
.mln_Pred
= NULL
;
485 /* Transfer the contents of our temporary list into display list */
486 data
->bitmaps
.mlh_Head
= list
->mlh_Head
;
487 data
->bitmaps
.mlh_Head
->mln_Pred
= (struct MinNode
*)&data
->bitmaps
.mlh_Head
;
488 data
->bitmaps
.mlh_TailPred
= list
->mlh_TailPred
;
489 data
->bitmaps
.mlh_TailPred
->mln_Succ
= (struct MinNode
*)&data
->bitmaps
.mlh_Tail
;
491 /* Own our virtual hardware. We are in Forbid() state and i hope it's enough */
492 xsd
->showtask
= FindTask(NULL
);
493 SetSignal(0, SIGF_BLIT
);
495 /* This will show display list and sort bitmaps in correct Z-order.
496 Windows must be created by control thread in order to be owned
498 NATIVECALL(GDI_PutMsg
, data
->fbwin
, NOTY_SHOW
, (IPTR
)data
, 0);
501 /* Disown virtual hardware */
502 xsd
->showtask
= NULL
;
505 ULONG
GDICl__Hidd_Gfx__ShowViewPorts(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_ShowViewPorts
*msg
)
507 struct gfx_data
*data
= OOP_INST_DATA(cl
, o
);
508 struct HIDD_ViewPortData
*vpdata
;
509 struct MinList new_bitmaps
;
513 NewList((struct List
*)&new_bitmaps
);
515 /* Traverse through bitmaps chain and move them from old displayed list to the new temporary one */
516 for (vpdata
= msg
->Data
; vpdata
; vpdata
= vpdata
->Next
)
517 AddToList(&new_bitmaps
, vpdata
->Bitmap
);
518 ShowList(XSD(cl
), data
, &new_bitmaps
);
522 /* We always return TRUE in order to indicate that we support this method.
523 LoadView() has no return code, so we have no rights for error too. */
527 /****************************************************************************************/
529 /* This method is needed for software mouse sprite emulation so that we can test it on
532 OOP_Object
*GDICl__Hidd_Gfx__Show(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_Show
*msg
)
534 struct gfx_data
*data
= OOP_INST_DATA(cl
, o
);
535 struct MinList new_bitmaps
;
539 NewList((struct List
*)&new_bitmaps
);
542 AddToList(&new_bitmaps
, msg
->bitMap
);
543 ShowList(XSD(cl
), data
, &new_bitmaps
);
550 /****************************************************************************************/
552 extern ULONG Copy_DrawModeTable
[];
554 VOID
GDICl__Hidd_Gfx__CopyBox(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CopyBox
*msg
)
556 APTR src
= NULL
, dest
= NULL
;
558 IPTR xoffset
, yoffset
;
560 EnterFunc(bug("[GDI] hidd.gfx.wingdi::CopyBox(0x%p(%lu, %lu, %lu, %lu) -> 0x%p(%lu, %lu)\n", msg
->src
, msg
->srcX
, msg
->srcY
, msg
->width
, msg
->height
,
561 msg
->dest
, msg
->destX
, msg
->destY
));
563 OOP_GetAttr(msg
->src
, aHidd_GDIBitMap_DeviceContext
, (IPTR
*)&src
);
564 OOP_GetAttr(msg
->dest
, aHidd_GDIBitMap_DeviceContext
, (IPTR
*)&dest
);
565 OOP_GetAttr(msg
->dest
, aHidd_BitMap_LeftEdge
, &xoffset
);
566 OOP_GetAttr(msg
->dest
, aHidd_BitMap_TopEdge
, &yoffset
);
568 if (NULL
== dest
|| NULL
== src
)
570 D(bug("[GDI] Process by superclass\n"));
571 /* The destination object is not a GDI bitmap.
572 Let the superclass do the copying in a more general way
574 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
579 drmd
= GC_DRMD(msg
->gc
);
581 GDICALL(BitBlt
, dest
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
, src
, msg
->srcX
, msg
->srcY
, Copy_DrawModeTable
[drmd
]);
586 /****************************************************************************************/
588 BOOL
GDICl__Hidd_Gfx__SetCursorShape(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorShape
*msg
)
590 struct gfx_data
*data
= OOP_INST_DATA(cl
, o
);
592 OOP_Object
*colormap
;
597 APTR buf_bm
, mask_bm
;
600 OOP_GetAttr(msg
->shape
, aHidd_BitMap_Width
, &width
);
601 OOP_GetAttr(msg
->shape
, aHidd_BitMap_Height
, &height
);
602 OOP_GetAttr(msg
->shape
, aHidd_BitMap_PixFmt
, (APTR
)&pfmt
);
603 OOP_GetAttr(pfmt
, aHidd_PixFmt_Depth
, &depth
);
604 OOP_GetAttr(msg
->shape
, aHidd_BitMap_ColorMap
, (APTR
)&colormap
);
606 bufsize
= width
* height
* 4;
607 buf
= AllocMem(bufsize
, MEMF_ANY
);
609 mask
= AllocMem(bufsize
, MEMF_ANY
);
614 HIDD_BM_GetImage(msg
->shape
, (UBYTE
*)buf
, width
* 4, 0, 0, width
, height
, vHidd_StdPixFmt_ARGB32_Native
);
615 PRINT_POINTER(buf
, width
, 8, 8);
616 /* Construct the mask from alpha channel data. The mask will be used on pre-XP systems or
617 on LUT screens. Of course there'll be no alpha blending there. */
618 for (i
= 0; i
< width
* height
; i
++)
619 mask
[i
] = (buf
[i
] & 0xFF000000) ? 0 : 0xFFFFFFFF;
623 bm
.bmHeight
= height
;
624 bm
.bmWidthBytes
= width
* 4;
629 buf_bm
= GDICALL(CreateBitmapIndirect
, &bm
);
632 mask_bm
= GDICALL(CreateBitmapIndirect
, &bm
);
636 -msg
->xoffset
, -msg
->yoffset
,
639 cursor
= USERCALL(CreateIconIndirect
, &curs
);
641 APTR old_cursor
= data
->cursor
;
643 D(bug("[GDI] Created cursor 0x%p, old cursor 0x%p\n", cursor
, old_cursor
));
644 data
->cursor
= cursor
;
645 USERCALL(SetCursor
, cursor
);
647 USERCALL(DestroyIcon
, old_cursor
);
649 GDICALL(DeleteObject
, mask_bm
);
651 GDICALL(DeleteObject
, buf_bm
);
654 FreeMem(mask
, bufsize
);
656 FreeMem(buf
, bufsize
);
658 return cursor
? TRUE
: FALSE
;
661 /****************************************************************************************/
663 /* This is simple - all modes have the same properties */
664 static struct HIDD_ModeProperties mode_props
= {
667 COMPF_ABOVE
|COMPF_BELOW
|COMPF_LEFT
|COMPF_RIGHT
670 ULONG
GDICl__Hidd_Gfx__ModeProperties(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_ModeProperties
*msg
)
672 ULONG len
= msg
->propsLen
;
674 if (len
> sizeof(mode_props
))
675 len
= sizeof(mode_props
);
676 CopyMem(&mode_props
, msg
->props
, len
);
681 /****************************************************************************************/
683 static int gdigfx_init(LIBBASETYPEPTR LIBBASE
)
685 InitSemaphore(&LIBBASE
->xsd
.sema
);
686 LIBBASE
->xsd
.displaynum
= 1;
688 if (OOP_ObtainAttrBases(attrbases
)) {
689 D(bug("[GDI] Starting up GDI controller\n"));
692 LIBBASE
->xsd
.ctl
= NATIVECALL(GDI_Init
);
695 if (LIBBASE
->xsd
.ctl
) {
696 LIBBASE
->xsd
.gfx_int
= KrnAddIRQHandler(LIBBASE
->xsd
.ctl
->GfxIrq
, GfxIntHandler
, &LIBBASE
->xsd
, NULL
);
697 if (LIBBASE
->xsd
.gfx_int
)
704 /****************************************************************************************/
706 static int gdigfx_expunge(LIBBASETYPEPTR LIBBASE
)
708 if (LIBBASE
->xsd
.gfx_int
)
709 KrnRemIRQHandler(LIBBASE
->xsd
.gfx_int
);
711 if (LIBBASE
->xsd
.ctl
) {
713 NATIVECALL(GDI_Shutdown
, LIBBASE
->xsd
.ctl
);
716 OOP_ReleaseAttrBases(attrbases
);
721 /****************************************************************************************/
723 ADD2INITLIB(gdigfx_init
, 0);
724 ADD2EXPUNGELIB(gdigfx_expunge
, 0);