2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Class for LCD Display.
9 #include <proto/exec.h>
10 #include <proto/utility.h>
11 #include <proto/oop.h>
14 #include <exec/alerts.h>
15 #include <exec/memory.h>
17 #include <hidd/hidd.h>
18 #include <hidd/graphics.h>
20 #include <aros/system.h>
21 #include <aros/asmcall.h>
23 #include <hardware/custom.h>
25 #include <devices/inputevent.h>
28 #include "displayclass.h"
32 #include <aros/debug.h>
35 /* Some attrbases needed as global vars.
36 These are write-once read-many */
38 /* Don't initialize them with "= 0", otherwise they end up in the DATA segment! */
41 static OOP_AttrBase HiddBitMapAttrBase
;
42 static OOP_AttrBase HiddPixFmtAttrBase
;
43 static OOP_AttrBase HiddGfxAttrBase
;
44 static OOP_AttrBase HiddSyncAttrBase
;
45 static OOP_AttrBase HiddDisplayAB
;
46 static OOP_AttrBase HiddDisplayBitMapAB
;
49 static struct OOP_ABDescr attrbases
[] =
51 { IID_Hidd_BitMap
, &HiddBitMapAttrBase
},
52 { IID_Hidd_DisplayBitMap
, &HiddDisplayBitMapAB
},
53 { IID_Hidd_Displaygfx
, &HiddDisplayAB
},
54 // { IID_Hidd_PixFmt, &HiddPixFmtAttrBase },
55 { IID_Hidd_Sync
, &HiddSyncAttrBase
},
56 { IID_Hidd_Gfx
, &HiddGfxAttrBase
},
64 int i
; //dummy!!!!!!!!!
67 /* Default graphics modes */
69 struct DisplayModeDesc
70 DisplayDefMode
[NUM_MODES
]={
71 {"160x160x1 @ 60Hz", // h: 31.5 kHz v: 60Hz
78 /* Default mouse shape */
82 06,02,00,00,00,00,00,00,00,00,00,
83 01,06,02,02,00,00,00,00,00,00,00,
84 00,01,06,06,02,02,00,00,00,00,00,
85 00,01,06,06,06,06,02,02,00,00,00,
86 00,00,01,06,06,06,06,06,02,02,00,
87 00,00,01,06,06,06,06,06,06,06,00,
88 00,00,00,01,06,06,06,02,00,00,00,
89 00,00,00,01,06,06,01,06,02,00,00,
90 00,00,00,00,01,06,00,01,06,02,00,
91 00,00,00,00,01,06,00,00,01,06,02,
92 00,00,00,00,00,00,00,00,00,01,06
95 /*********************
97 *********************/
99 #define NUM_SYNC_TAGS 10
100 #define SET_SYNC_TAG(taglist, idx, tag, val) \
101 taglist[idx].ti_Tag = aHidd_Sync_ ## tag; \
102 taglist[idx].ti_Data = val
104 static OOP_Object
*gfxhidd_newbitmap(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_NewBitMap
*msg
);
106 VOID
init_sync_tags(struct TagItem
*tags
, struct DisplayModeDesc
*md
, OOP_Class
* cl
)
109 ULONG clock
= (md
->clock
== 1) ? 28322000 : 25175000;
110 SET_SYNC_TAG(tags
, 0, PixelClock
, clock
);
111 SET_SYNC_TAG(tags
, 1, HDisp
, md
->HDisplay
);
112 SET_SYNC_TAG(tags
, 2, VDisp
, md
->VDisplay
);
113 SET_SYNC_TAG(tags
, 3, HSyncStart
, md
->HSyncStart
);
114 SET_SYNC_TAG(tags
, 4, HSyncEnd
, md
->HSyncEnd
);
115 SET_SYNC_TAG(tags
, 5, HTotal
, md
->HTotal
);
116 SET_SYNC_TAG(tags
, 6, VSyncStart
, md
->VSyncStart
);
117 SET_SYNC_TAG(tags
, 7, VSyncEnd
, md
->VSyncEnd
);
118 SET_SYNC_TAG(tags
, 8, VTotal
, md
->VTotal
);
119 tags
[9].ti_Tag
= TAG_DONE
;
123 static OOP_Object
*gfx_new(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
126 struct TagItem pftags
[] = {
127 { aHidd_PixFmt_RedShift
, 0 }, /* 0 */
128 { aHidd_PixFmt_GreenShift
, 0 }, /* 1 */
129 { aHidd_PixFmt_BlueShift
, 0 }, /* 2 */
130 { aHidd_PixFmt_AlphaShift
, 0 }, /* 3 */
131 { aHidd_PixFmt_RedMask
, 0 }, /* 4 */
132 { aHidd_PixFmt_GreenMask
, 0 }, /* 5 */
133 { aHidd_PixFmt_BlueMask
, 0 }, /* 6 */
134 { aHidd_PixFmt_AlphaMask
, 0 }, /* 7 */
135 { aHidd_PixFmt_ColorModel
, 0 }, /* 8 */
136 { aHidd_PixFmt_Depth
, 0 }, /* 9 */
137 { aHidd_PixFmt_BytesPerPixel
, 0 }, /* 10 */
138 { aHidd_PixFmt_BitsPerPixel
, 0 }, /* 11 */
139 { aHidd_PixFmt_StdPixFmt
, 0 }, /* 12 */
140 { aHidd_PixFmt_CLUTShift
, 0 }, /* 13 */
141 { aHidd_PixFmt_CLUTMask
, 0x01 }, /* 14 */
142 { aHidd_PixFmt_BitMapType
, 0 }, /* 15 */
145 struct TagItem sync_160_160
[NUM_SYNC_TAGS
];
147 struct TagItem modetags
[] = {
148 { aHidd_Gfx_PixFmtTags
, (IPTR
)pftags
},
149 { aHidd_Gfx_SyncTags
, (IPTR
)sync_160_160
},
153 struct TagItem mytags
[] = {
154 { aHidd_Gfx_ModeTags
, (IPTR
)modetags
},
157 struct pRoot_New mymsg
;
160 /* Init the pixel format */
161 pftags
[0].ti_Data
= 0;
162 pftags
[1].ti_Data
= 0;
163 pftags
[2].ti_Data
= 0;
164 pftags
[3].ti_Data
= 0;
166 pftags
[4].ti_Data
= 0x00003f;
167 pftags
[5].ti_Data
= 0x003f00;
168 pftags
[6].ti_Data
= 0x3f0000;
169 pftags
[7].ti_Data
= 0;
171 pftags
[8].ti_Data
= vHidd_ColorModel_Palette
;
172 pftags
[9].ti_Data
= 1;
173 pftags
[10].ti_Data
= 1;
174 pftags
[11].ti_Data
= 1;
175 pftags
[12].ti_Data
= vHidd_StdPixFmt_Native
;
177 #warning Is this true in all cases ?
178 pftags
[15].ti_Data
= vHidd_BitMapType_Planar
;
181 /* First init the sync tags */
182 init_sync_tags(sync_160_160
, &DisplayDefMode
[0], cl
);
184 /* init mytags. We use TAG_MORE to attach our own tags before we send them
186 mytags
[1].ti_Tag
= TAG_MORE
;
187 mytags
[1].ti_Data
= (IPTR
)msg
->attrList
;
189 /* Init mymsg. We have to use our own message struct because
190 one should not alter the one passed to this method.
191 message structs passed to a method are allways read-only.
192 (The user who called us might want to reuse the same msg struct
193 for several calls, but that will break if som method changes the
196 mymsg
.mID
= msg
->mID
; /* We got New() method and we are sending
197 the same method to the superclass */
198 mymsg
.attrList
= mytags
;
203 EnterFunc(bug("DisplayGfx::New()\n"));
205 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
209 D(bug("Got object from super\n"));
212 XSD(cl
)->displayhidd
= o
;
214 ReturnPtr("DisplayGfx::New", OOP_Object
*, o
);
217 ReturnPtr("DisplayGfx::New", OOP_Object
*, NULL
);
220 static VOID
gfx_dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
222 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
226 static VOID
gfx_get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
231 if (IS_GFX_ATTR(msg
->attrID
, idx
)) {
234 case aoHidd_Gfx_SupportsHWCursor
:
235 *msg
->storage
= (IPTR
)TRUE
;
238 case aoHidd_Gfx_IsWindowed
:
239 *msg
->storage
= (IPTR
)TRUE
;
246 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
251 /********** GfxHidd::NewBitMap() ****************************/
252 static OOP_Object
*gfxhidd_newbitmap(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_NewBitMap
*msg
)
255 BOOL displayable
, framebuffer
;
256 struct display_data
*data
;
257 OOP_Class
*classptr
= NULL
;
258 struct TagItem mytags
[2];
259 struct pHidd_Gfx_NewBitMap mymsg
;
261 EnterFunc(bug("DisplayGfx::NewBitMap()\n"));
263 data
= OOP_INST_DATA(cl
, o
);
267 /* Displayable bitmap ? */
269 displayable
= GetTagData(aHidd_BitMap_Displayable
, FALSE
, msg
->attrList
);
270 framebuffer
= GetTagData(aHidd_BitMap_FrameBuffer
, FALSE
, msg
->attrList
);
274 /* If the user asks for a framebuffer map we must ALLWAYS supply a class */
275 classptr
= XSD(cl
)->onbmclass
;
277 } else if (displayable
) {
278 classptr
= XSD(cl
)->offbmclass
;
282 For the non-displayable case we can either supply a class ourselves
283 if we can optimize a certain type of non-displayable bitmaps. Or we
284 can let the superclass create on for us.
286 The attributes that might come from the user deciding the bitmap
288 - aHidd_BitMap_ModeID: a modeid. create a nondisplayable
289 bitmap with the size and pixelformat of a gfxmode.
290 - aHidd_BitMap_StdPixFmt: a standard pixelformat as described in
292 - aHidd_BitMap_Friend: if this is supplied and none of the two above
293 are supplied, then the pixel format of the created bitmap
294 will be the same as the one of the friend bitmap.
296 These tags are listed in prioritized order, so if
297 the user supplied a ModeID tag, then you should not care about StdPixFmt
298 or Friend. If there is no ModeID, but a StdPixFmt tag supplied,
299 then you should not care about Friend because you have to
300 create the correct pixelformat. And as said above, if only Friend
301 is supplied, you can create a bitmap with same pixelformat as Frien
305 modeid
= (HIDDT_ModeID
)GetTagData(aHidd_BitMap_ModeID
, vHidd_ModeID_Invalid
, msg
->attrList
);
307 if (vHidd_ModeID_Invalid
!= modeid
) {
308 /* User supplied a valid modeid. We can use our offscreen class */
309 classptr
= XSD(cl
)->offbmclass
;
311 /* We may create an offscreen bitmap if the user supplied a friend
312 bitmap. But we need to check that he did not supplied a StdPixFmt
314 HIDDT_StdPixFmt stdpf
;
315 stdpf
= (HIDDT_StdPixFmt
)GetTagData(aHidd_BitMap_StdPixFmt
, vHidd_StdPixFmt_Unknown
, msg
->attrList
);
316 if (vHidd_StdPixFmt_Unknown
== stdpf
) {
317 /* No std pixfmt supplied */
320 /* Did the user supply a friend bitmap ? */
321 friend = (OOP_Object
*)GetTagData(aHidd_BitMap_Friend
, 0, msg
->attrList
);
322 if (NULL
!= friend) {
323 OOP_Object
* gfxhidd
;
324 /* User supplied friend bitmap. Is the friend bitmap a
325 Display Gfx hidd bitmap ? */
326 OOP_GetAttr(friend, aHidd_BitMap_GfxHidd
, (IPTR
*)&gfxhidd
);
328 /* Friend was Display hidd bitmap. Now we can supply our own class */
329 classptr
= XSD(cl
)->offbmclass
;
336 /* Do we supply our own class ? */
337 if (NULL
!= classptr
) {
338 /* Yes. We must let the superclass not that we do this. This is
339 done through adding a tag in the frot of the taglist */
340 mytags
[0].ti_Tag
= aHidd_BitMap_ClassPtr
;
342 mytags
[0].ti_Data
= (IPTR
)classptr
;
343 mytags
[1].ti_Tag
= TAG_MORE
;
344 mytags
[1].ti_Data
= (IPTR
)msg
->attrList
;
346 /* Like in Gfx::New() we init a new message struct */
347 mymsg
.mID
= msg
->mID
;
348 mymsg
.attrList
= mytags
;
350 /* Pass the new message to the superclass */
354 ReturnPtr("DisplayGfx::NewBitMap", OOP_Object
*, (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
));
357 /********* GfxHidd::CopyBox() ***************************/
359 static VOID
gfxhidd_copybox(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CopyBox
*msg
)
362 unsigned char *src
= 0, *dest
= 0;
363 struct Box box
= {0, 0, 0, 0};
365 mode
= GC_DRMD(msg
->gc
);
367 EnterFunc(bug("DisplayGfx.BitMap::CopyBox( %d,%d to %d,%d of dim %d,%d) mode=0x%x\n",
368 msg
->srcX
, msg
->srcY
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
, mode
));
371 #warning Potential source for error: HiddDisplayBitMapAB define.
372 OOP_GetAttr(msg
->src
, aHidd_DisplayBitMap_Drawable
, (IPTR
*)&src
);
373 OOP_GetAttr(msg
->dest
, aHidd_DisplayBitMap_Drawable
, (IPTR
*)&dest
);
376 ((mode
!= vHidd_GC_DrawMode_Copy
) &&
377 (mode
!= vHidd_GC_DrawMode_And
) &&
378 (mode
!= vHidd_GC_DrawMode_Xor
) &&
379 (mode
!= vHidd_GC_DrawMode_Clear
) &&
380 (mode
!= vHidd_GC_DrawMode_Invert
)))
382 /* The source and/or destination object is no Display bitmap, onscreen nor offscreen.
383 Or drawmode is not one of those we accelerate. Let the superclass do the
384 copying in a more general way
386 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
392 struct bitmap_data
*data
= OOP_INST_DATA(OOP_OCLASS(msg
->src
), msg
->src
);
393 struct bitmap_data
*ddata
= OOP_INST_DATA(OOP_OCLASS(msg
->dest
), msg
->dest
);
394 int i
, width
, phase
, j
;
397 // start of Source data
398 unsigned char *s_start
= data
->VideoData
+
399 msg
->srcX
+ (msg
->srcY
* data
->width
);
400 // adder for each line
401 ULONG s_add
= data
->width
- msg
->width
;
402 ULONG cnt
= msg
->height
;
404 unsigned char *d_start
= ddata
->VideoData
+
405 msg
->destX
+ (msg
->destY
* ddata
->width
);
406 ULONG d_add
= ddata
->width
- msg
->width
;
410 if ((msg
->srcY
> msg
->destY
) ||
411 ((msg
->srcY
== msg
->destY
) && (msg
->srcX
>= msg
->destX
)) ||
412 (mode
== vHidd_GC_DrawMode_Clear
) ||
413 (mode
== vHidd_GC_DrawMode_Invert
))
419 s_start
+= (cnt
- 1) * data
->width
+ width
;
420 d_start
+= (cnt
- 1) * ddata
->width
+ width
;
426 case vHidd_GC_DrawMode_Copy
/* 0x03 */:
434 *d_start
++ = *s_start
++;
447 *--d_start
= *--s_start
;
455 case vHidd_GC_DrawMode_And
/* 0x01 */:
463 *d_start
++ &= *s_start
++;
476 *--d_start
&= *--s_start
;
485 case vHidd_GC_DrawMode_Xor
/* 0x06 */:
493 *d_start
++ ^= *s_start
++;
506 *--d_start
^= *--s_start
;
514 case vHidd_GC_DrawMode_Clear
/* 0x00 */:
515 D(bug("Clearing!\n"));
516 if ((phase
= ((long)d_start
& 3L)))
519 if (phase
> width
) phase
= width
;
533 *((unsigned long*)d_start
) = 0;
545 case vHidd_GC_DrawMode_Invert
/* 0x0a */:
546 if ((phase
= ((long)d_start
& 3L)))
549 if (phase
> width
) phase
= width
;
559 *d_start
= ~*d_start
;
564 *((unsigned long*)d_start
) = ~*((unsigned long*)d_start
);
570 *d_start
= ~*d_start
;
584 box
.x2
= box
.x1
+ msg
->width
;
585 box
.y2
= box
.y1
+ msg
->height
;
587 ObtainSemaphore(&XSD(cl
)->HW_acc
);
589 DisplayRefreshArea(ddata
, 1, &box
);
591 ReleaseSemaphore(&XSD(cl
)->HW_acc
);
596 ReturnVoid("DisplayGfx.BitMap::CopyBox");
599 /* stuff added by stegerg */
601 /********** GfxHidd::SetCursorShape() ****************************/
603 static BOOL
gfxhidd_setcursorshape(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorShape
*msg
)
605 /* hmm ... moHidd_Gfx_SetCursorShape seems to have a HIDD bitmap in msg->shape, while
606 the old (obsolete?) native moHidd_Gfx_SetMouseShape seems to expect a simple
607 chunky array. So don't do anything for now (it would have to be done similiar as
608 in config/hidd/fakegfxhidd.c I guess */
613 /********** GfxHidd::SetCursorPos() ****************************/
615 static BOOL
gfxhidd_setcursorpos(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorPos
*msg
)
617 struct Box box
= {0, 0, 0, 0};
620 ObtainSemaphore(&XSD(cl
)->HW_acc
);
622 if (XSD(cl
)->visible
)
623 DisplayRefreshArea(XSD(cl
)->visible
, 1, &box
);
626 ReleaseSemaphore(&XSD(cl
)->HW_acc
);
631 /********** GfxHidd::SetCursorVisible() ****************************/
633 static VOID
gfxhidd_setcursorvisible(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorVisible
*msg
)
636 ObtainSemaphore(&XSD(cl
)->HW_acc
);
637 ReleaseSemaphore(&XSD(cl
)->HW_acc
);
640 /* end of stuff added by stegerg */
645 /******************** init_displayclass() *********************************/
647 #define NUM_ROOT_METHODS 3
648 #define NUM_Display_METHODS 5
650 OOP_Class
*init_displayclass (struct display_staticdata
*xsd
)
652 OOP_Class
*cl
= NULL
;
654 struct OOP_MethodDescr root_descr
[NUM_ROOT_METHODS
+ 1] =
656 {(IPTR (*)())gfx_new
, moRoot_New
},
657 {(IPTR (*)())gfx_dispose
, moRoot_Dispose
},
658 {(IPTR (*)())gfx_get
, moRoot_Get
},
662 struct OOP_MethodDescr displayhidd_descr
[NUM_Display_METHODS
+ 1] =
664 {(IPTR (*)())gfxhidd_newbitmap
, moHidd_Gfx_NewBitMap
},
665 {(IPTR (*)())gfxhidd_copybox
, moHidd_Gfx_CopyBox
},
667 {(IPTR (*)())gfxhidd_setcursorshape
, moHidd_Gfx_SetCursorShape
},
668 {(IPTR (*)())gfxhidd_setcursorpos
, moHidd_Gfx_SetCursorPos
},
669 {(IPTR (*)())gfxhidd_setcursorvisible
, moHidd_Gfx_SetCursorVisible
},
675 struct OOP_InterfaceDescr ifdescr
[] =
677 {root_descr
, IID_Root
, NUM_ROOT_METHODS
},
678 {displayhidd_descr
, IID_Hidd_Gfx
, NUM_Display_METHODS
},
682 OOP_AttrBase MetaAttrBase
= OOP_ObtainAttrBase(IID_Meta
);
684 struct TagItem tags
[] =
686 { aMeta_SuperID
, (IPTR
)CLID_Hidd_Gfx
},
687 { aMeta_InterfaceDescr
, (IPTR
)ifdescr
},
688 { aMeta_InstSize
, (IPTR
)sizeof (struct display_data
) },
689 { aMeta_ID
, (IPTR
)CLID_Hidd_Displaygfx
},
693 EnterFunc(bug("VgaHiddClass init\n"));
697 cl
= OOP_NewObject(NULL
, CLID_HiddMeta
, tags
);
700 cl
->UserData
= (APTR
)xsd
;
701 xsd
->displayclass
= cl
;
703 __IHidd_BitMap
= OOP_ObtainAttrBase(IID_Hidd_BitMap
);
704 __IHidd_DisplayBitMap
= OOP_ObtainAttrBase(IID_Hidd_DisplayBitMap
);
705 __IHidd_DisplayGfx
= OOP_ObtainAttrBase(IID_Hidd_Displaygfx
);
706 __IHidd_Sync
= OOP_ObtainAttrBase(IID_Hidd_Sync
);
707 __IHidd_Gfx
= OOP_ObtainAttrBase(IID_Hidd_Gfx
);
710 if (OOP_ObtainAttrBases(attrbases
))
712 if (__IHidd_BitMap
&&
713 __IHidd_DisplayBitMap
&&
714 __IHidd_DisplayGfx
&&
719 D(bug("VgaHiddClass ok\n"));
725 free_displayclass(xsd
);
729 /* Don't need this anymore */
730 OOP_ReleaseAttrBase(IID_Meta
);
732 ReturnPtr("init_displayclass", OOP_Class
*, cl
);
735 /*************** free_displayclass() **********************************/
736 VOID
free_displayclass(struct display_staticdata
*xsd
)
738 EnterFunc(bug("free_displayclass(xsd=%p)\n", xsd
));
742 OOP_RemoveClass(xsd
->displayclass
);
744 if(xsd
->displayclass
) OOP_DisposeObject((OOP_Object
*) xsd
->displayclass
);
745 xsd
->displayclass
= NULL
;
749 OOP_ReleaseAttrBases(attrbases
);
752 ReturnVoid("free_displayclass");