2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
5 Desc: Class for VGA and compatible cards.
10 #include <aros/debug.h>
12 #define __OOP_NOATTRBASES__
14 #include <aros/asmcall.h>
15 #include <proto/exec.h>
16 #include <proto/utility.h>
17 #include <proto/oop.h>
20 #include <exec/alerts.h>
21 #include <exec/memory.h>
23 #include <hidd/hidd.h>
26 #include <aros/symbolsets.h>
28 #include <hardware/custom.h>
30 #include <devices/inputevent.h>
33 #include LC_LIBDEFS_FILE
35 static AROS_INTH1(ResetHandler
, struct VGAGfx_staticdata
*, xsd
)
39 struct VGAGfxBitMapData
*data
= NULL
;
41 /* On my machine this fills the screen with colorful vertical stripes
42 instead of blanking. So for now we use software method.
47 data
= OOP_INST_DATA(xsd
->bmclass
, xsd
->visible
);
51 struct Box box
= {0, 0, data
->width
- 1, data
->height
- 1};
53 vgaEraseArea(data
, &box
);
61 /* Default graphics modes */
64 vgaDefMode
[NUM_MODES
]={
65 {"640x480x4 @ 60Hz", // h: 31.5 kHz v: 60Hz
71 ,{"768x576x4 @ 54Hz", // h: 32.5 kHz v: 54Hz
76 {"800x600x4 @ 52Hz", // h: 31.5 kHz v: 52Hz
79 800,826,838,900,0, // 900
80 600,601,603,617} // 617
84 /*********************
86 *********************/
88 #define NUM_SYNC_TAGS 11
89 #define SET_SYNC_TAG(taglist, idx, tag, val) \
90 taglist[idx].ti_Tag = aHidd_Sync_ ## tag; \
91 taglist[idx].ti_Data = val
93 VOID
synctags_init(OOP_Class
*cl
, struct TagItem
*tags
, struct vgaModeDesc
*md
, STRPTR name
)
95 ULONG clock
= (md
->clock
== 1) ? 28322000 : 25175000;
97 SET_SYNC_TAG(tags
, 0, PixelClock
, clock
);
98 SET_SYNC_TAG(tags
, 1, HDisp
, md
->HDisplay
);
99 SET_SYNC_TAG(tags
, 2, VDisp
, md
->VDisplay
);
100 SET_SYNC_TAG(tags
, 3, HSyncStart
, md
->HSyncStart
);
101 SET_SYNC_TAG(tags
, 4, HSyncEnd
, md
->HSyncEnd
);
102 SET_SYNC_TAG(tags
, 5, HTotal
, md
->HTotal
);
103 SET_SYNC_TAG(tags
, 6, VSyncStart
, md
->VSyncStart
);
104 SET_SYNC_TAG(tags
, 7, VSyncEnd
, md
->VSyncEnd
);
105 SET_SYNC_TAG(tags
, 8, VTotal
, md
->VTotal
);
106 SET_SYNC_TAG(tags
, 9, Description
, (IPTR
)name
);
107 tags
[10].ti_Tag
= TAG_DONE
;
110 #define init_sync_tags(tags, md, name) synctags_init(cl, tags, md, name)
112 OOP_Object
*VGAGfx__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
114 struct TagItem pftags
[] = {
115 { aHidd_PixFmt_RedShift
, 0 }, /* 0 */
116 { aHidd_PixFmt_GreenShift
, 0 }, /* 1 */
117 { aHidd_PixFmt_BlueShift
, 0 }, /* 2 */
118 { aHidd_PixFmt_AlphaShift
, 0 }, /* 3 */
119 { aHidd_PixFmt_RedMask
, 0x000000FC }, /* 4 */
120 { aHidd_PixFmt_GreenMask
, 0x0000FC00 }, /* 5 */
121 { aHidd_PixFmt_BlueMask
, 0x00FC0000 }, /* 6 */
122 { aHidd_PixFmt_AlphaMask
, 0x00000000 }, /* 7 */
123 { aHidd_PixFmt_ColorModel
, vHidd_ColorModel_Palette
}, /* 8 */
124 { aHidd_PixFmt_Depth
, 4 }, /* 9 */
125 { aHidd_PixFmt_BytesPerPixel
, 1 }, /* 10 */
126 { aHidd_PixFmt_BitsPerPixel
, 4 }, /* 11 */
127 { aHidd_PixFmt_StdPixFmt
, vHidd_StdPixFmt_LUT8
}, /* 12 */
128 { aHidd_PixFmt_CLUTShift
, 0 }, /* 13 */
129 { aHidd_PixFmt_CLUTMask
, 0x0f }, /* 14 */
130 { aHidd_PixFmt_BitMapType
, vHidd_BitMapType_Chunky
}, /* 15 */
134 struct TagItem sync_640_480
[NUM_SYNC_TAGS
];
136 struct TagItem sync_758_576
[NUM_SYNC_TAGS
];
137 struct TagItem sync_800_600
[NUM_SYNC_TAGS
];
140 struct TagItem modetags
[] = {
141 { aHidd_Sync_HMax
, 16384 },
142 { aHidd_Sync_VMax
, 16384 },
143 { aHidd_Gfx_PixFmtTags
, (IPTR
)pftags
},
144 { aHidd_Gfx_SyncTags
, (IPTR
)sync_640_480
},
146 { aHidd_Gfx_SyncTags
, (IPTR
)sync_758_576
},
147 { aHidd_Gfx_SyncTags
, (IPTR
)sync_800_600
},
152 struct TagItem mytags
[] = {
153 { aHidd_Gfx_ModeTags
, (IPTR
)modetags
},
154 { aHidd_Name
, (IPTR
)"vgagfx.hidd" },
155 { aHidd_HardwareName
, (IPTR
)"VGA Compatible Controller" },
156 { aHidd_ProducerName
, (IPTR
)"IBM" },
157 { TAG_MORE
, (IPTR
)msg
->attrList
}
159 struct pRoot_New mymsg
;
161 /* Do not allow to create more than one object */
162 if (XSD(cl
)->vgahidd
)
165 /* First init the sync tags */
166 init_sync_tags(sync_640_480
, &vgaDefMode
[0], "VGA:640x480");
168 init_sync_tags(sync_758_576
, &vgaDefMode
[1], "VGA:758x576");
169 init_sync_tags(sync_800_600
, &vgaDefMode
[2], "VGA:800x600");
172 /* Init mymsg. We have to use our own message struct because
173 one should not alter the one passed to this method.
174 message structs passed to a method are always read-only.
175 (The user who called us might want to reuse the same msg struct
176 for several calls, but that will break if some method changes the
179 mymsg
.mID
= msg
->mID
; /* We got New() method and we are sending
180 the same method to the superclass */
181 mymsg
.attrList
= mytags
;
184 EnterFunc(bug("VGAGfx::New()\n"));
186 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
187 XSD(cl
)->vgahidd
= o
;
189 struct VGAGfxDriverData
*data
= OOP_INST_DATA(cl
, o
);
191 data
->ResetInterrupt
.is_Node
.ln_Name
= cl
->ClassNode
.ln_Name
;
192 data
->ResetInterrupt
.is_Code
= (VOID_FUNC
)ResetHandler
;
193 data
->ResetInterrupt
.is_Data
= XSD(cl
);
194 AddResetCallback(&data
->ResetInterrupt
);
196 ReturnPtr("VGAGfx::New", OOP_Object
*, o
);
199 VOID
VGAGfx__Root__Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
201 struct VGAGfxDriverData
*data
= OOP_INST_DATA(cl
, o
);
203 RemResetCallback(&data
->ResetInterrupt
);
204 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
205 XSD(cl
)->vgahidd
= NULL
;
208 VOID
VGAGfx__Root__Get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
212 if (IS_GFX_ATTR(msg
->attrID
, idx
)) {
214 case aoHidd_Gfx_SupportsHWCursor
:
215 case aoHidd_Gfx_NoFrameBuffer
:
216 *msg
->storage
= (IPTR
)TRUE
;
223 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
228 /********** GfxHidd::CreateObject() ****************************/
229 OOP_Object
*VGAGfx__Hidd_Gfx__CreateObject(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CreateObject
*msg
)
231 OOP_Object
*object
= NULL
;
233 EnterFunc(bug("VGAGfx::CreateObject()\n"));
235 if (msg
->cl
== XSD(cl
)->basebm
)
237 struct TagItem mytags
[] =
239 { TAG_IGNORE
, TAG_IGNORE
}, /* Placeholder for aHidd_BitMap_ClassPtr */
240 { TAG_MORE
, (IPTR
)msg
->attrList
}
243 struct pHidd_Gfx_CreateObject mymsg
;
246 modeid
= (HIDDT_ModeID
)GetTagData(aHidd_BitMap_ModeID
, vHidd_ModeID_Invalid
, msg
->attrList
);
247 if (vHidd_ModeID_Invalid
!= modeid
) {
248 /* User supplied a valid modeid. We can use our class */
249 mytags
[0].ti_Tag
= aHidd_BitMap_ClassPtr
;
250 mytags
[0].ti_Data
= (IPTR
)XSD(cl
)->bmclass
;
252 /* Like in Gfx::New() we init a new message struct */
253 mymsg
.mID
= msg
->mID
;
255 mymsg
.attrList
= mytags
;
257 object
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)&mymsg
);
260 object
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
262 ReturnPtr("VGAGfx::CreateObject", OOP_Object
*, object
);
265 /********* GfxHidd::Show() ***************************/
267 OOP_Object
*VGAGfx__Hidd_Gfx__Show(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_Show
*msg
)
269 /* We currently use class static data instead of
270 object data. In addition we directly access
271 bitmap's private data. This is horribly wrong
272 and needs further refactoring */
273 struct VGAGfx_staticdata
*data
= XSD(cl
);
276 D(bug("[VGAGfx] Show(0x%p)\n", msg
->bitMap
));
277 ObtainSemaphore(&data
->sema
);
279 /* Remove old bitmap from the screen */
281 IPTR tags
[] = {aHidd_BitMap_Visible
, FALSE
, TAG_DONE
};
283 D(bug("[VGAGfx] Old displayed bitmap: 0x%p\n", data
->visible
));
284 OOP_SetAttrs(data
->visible
, (struct TagItem
*)tags
);
288 /* If we have a bitmap to show, set it as visible */
289 IPTR tags
[] = {aHidd_BitMap_Visible
, TRUE
, TAG_DONE
};
293 OOP_GetAttr(msg
->bitMap
, aHidd_BitMap_PixFmt
, (IPTR
*)&pixfmt
);
294 OOP_GetAttr(pixfmt
, aHidd_PixFmt_Depth
, &depth
);
295 /* TODO: this should be brought in from SpriteBase of the colormap */
296 data
->mouseBase
= (depth
> 4) ? 16 : (1 << depth
) - 8;
298 OOP_SetAttrs(msg
->bitMap
, (struct TagItem
*)tags
);
299 data
->visible
= msg
->bitMap
;
301 /* Otherwise simply clear the framebuffer */
306 ObtainSemaphore(&data
->HW_acc
);
307 /* We use old visible bitmap pointer here since this bitmap
308 contains data about the current video mode */
309 vgaEraseArea(OOP_INST_DATA(data
->bmclass
, data
->visible
), &box
);
311 ReleaseSemaphore(&data
->HW_acc
);
313 data
->visible
= NULL
;
315 D(bug("[VGAGfx] New displayed bitmap: 0x%p\n", data
->visible
));
316 D(bug("[VGAGfx] Mouse pointer base color: %u\n", data
->mouseBase
));
318 ReleaseSemaphore(&data
->sema
);
322 /********* GfxHidd::CopyBox() ***************************/
324 VOID
VGAGfx__Hidd_Gfx__CopyBox(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CopyBox
*msg
)
327 unsigned char *src
= 0, *dest
= 0;
329 mode
= GC_DRMD(msg
->gc
);
331 EnterFunc(bug("VGAGfx.BitMap::CopyBox (%d,%d) to (%d,%d) of dim %d,%d\n",
332 msg
->srcX
, msg
->srcY
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
));
333 D(bug("[VGAGfx] Src: 0x%p, dest: 0x%p\n", msg
->src
, msg
->dest
));
334 OOP_GetAttr(msg
->src
, aHidd_VGABitMap_Drawable
, (IPTR
*)&src
);
335 OOP_GetAttr(msg
->dest
, aHidd_VGABitMap_Drawable
, (IPTR
*)&dest
);
338 ((mode
!= vHidd_GC_DrawMode_Copy
) &&
339 (mode
!= vHidd_GC_DrawMode_And
) &&
340 (mode
!= vHidd_GC_DrawMode_Xor
) &&
341 (mode
!= vHidd_GC_DrawMode_Clear
) &&
342 (mode
!= vHidd_GC_DrawMode_Invert
)))
344 /* The source and/or destination object is no VGA bitmap, onscreen nor offscreen.
345 Or drawmode is not one of those we accelerate. Let the superclass do the
346 copying in a more general way
348 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
354 struct VGAGfxBitMapData
*data
= OOP_INST_DATA(OOP_OCLASS(msg
->src
), msg
->src
);
355 struct VGAGfxBitMapData
*ddata
= OOP_INST_DATA(OOP_OCLASS(msg
->dest
), msg
->dest
);
356 int i
, width
, phase
, j
;
359 // start of Source data
360 unsigned char *s_start
= data
->VideoData
+
361 msg
->srcX
+ (msg
->srcY
* data
->bpr
);
362 // adder for each line
363 ULONG s_add
= data
->bpr
- msg
->width
;
364 ULONG cnt
= msg
->height
;
366 unsigned char *d_start
= ddata
->VideoData
+
367 msg
->destX
+ (msg
->destY
* ddata
->bpr
);
368 ULONG d_add
= ddata
->bpr
- msg
->width
;
372 if ((msg
->srcY
> msg
->destY
) || ((msg
->srcY
== msg
->destY
) && (msg
->srcX
>= msg
->destX
)))
374 if ((phase
= ((IPTR
)s_start
& 3L)))
377 if (phase
> width
) phase
= width
;
384 s_start
+= (cnt
- 1) * data
->bpr
+ width
;
385 d_start
+= (cnt
- 1) * ddata
->bpr
+ width
;
387 phase
= ((IPTR
)s_start
& 3L);
388 if (phase
> width
) phase
= width
;
396 case vHidd_GC_DrawMode_Copy
:
397 HIDD_BM_CopyMemBox8(msg
->dest
,
410 case vHidd_GC_DrawMode_And
:
419 *d_start
++ &= *s_start
++;
423 *((ULONG
*)d_start
) &= *((ULONG
*)s_start
);
430 *d_start
++ &= *s_start
++;
444 *--d_start
&= *--s_start
;
450 *((ULONG
*)d_start
) &= *((ULONG
*)s_start
);
455 *--d_start
&= *--s_start
;
464 case vHidd_GC_DrawMode_Xor
:
473 *d_start
++ ^= *s_start
++;
477 *((ULONG
*)d_start
) ^= *((ULONG
*)s_start
);
484 *d_start
++ ^= *s_start
++;
498 *--d_start
^= *--s_start
;
504 *((ULONG
*)d_start
) ^= *((ULONG
*)s_start
);
509 *--d_start
^= *--s_start
;
517 case vHidd_GC_DrawMode_Clear
:
530 *((ULONG
*)d_start
) = 0;
554 *((ULONG
*)d_start
) = 0;
566 case vHidd_GC_DrawMode_Invert
:
575 *d_start
= ~*d_start
;
580 *((ULONG
*)d_start
) = ~*((ULONG
*)d_start
);
586 *d_start
= ~*d_start
;
600 *d_start
= ~*d_start
;
606 *((ULONG
*)d_start
) = ~*((ULONG
*)d_start
);
611 *d_start
= ~*d_start
;
622 ReturnVoid("VGAGfx.BitMap::CopyBox");
625 /********** GfxHidd::SetCursorShape() ****************************/
627 BOOL
VGAGfx__Hidd_Gfx__SetCursorShape(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorShape
*msg
)
629 struct VGAGfx_staticdata
*data
= XSD(cl
);
630 IPTR curs_width
, curs_height
;
631 UBYTE
*new_curs_pixels
;
633 OOP_GetAttr(msg
->shape
, aHidd_BitMap_Width
, &curs_width
);
634 OOP_GetAttr(msg
->shape
, aHidd_BitMap_Height
, &curs_height
);
636 new_curs_pixels
= AllocMem(curs_width
* curs_height
, MEMF_ANY
);
637 if (!new_curs_pixels
)
640 HIDD_BM_GetImage(msg
->shape
, new_curs_pixels
, curs_width
, 0, 0, curs_width
, curs_height
, vHidd_StdPixFmt_LUT8
);
642 ObtainSemaphore(&data
->HW_acc
);
644 if (data
->mouseShape
)
645 FreeMem(data
->mouseShape
, data
->mouseW
* data
->mouseH
);
647 data
->mouseW
= curs_width
;
648 data
->mouseH
= curs_height
;
649 data
->mouseShape
= new_curs_pixels
;
652 ReleaseSemaphore(&data
->HW_acc
);
656 /********** GfxHidd::SetCursorPos() ****************************/
658 BOOL
VGAGfx__Hidd_Gfx__SetCursorPos(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorPos
*msg
)
660 ObtainSemaphore(&XSD(cl
)->HW_acc
);
662 erase_mouse(XSD(cl
));
664 XSD(cl
)->mouseX
= (short)msg
->x
;
665 XSD(cl
)->mouseY
= (short)msg
->y
;
667 if (XSD(cl
)->visible
)
669 struct VGAGfxBitMapData
*bm_data
=
670 OOP_INST_DATA(XSD(cl
)->bmclass
, XSD(cl
)->visible
);
672 if (XSD(cl
)->mouseX
< 0) XSD(cl
)->mouseX
= 0;
673 if (XSD(cl
)->mouseY
< 0) XSD(cl
)->mouseY
= 0;
674 if (XSD(cl
)->mouseX
>= bm_data
->width
) XSD(cl
)->mouseX
=
676 if (XSD(cl
)->mouseY
>= bm_data
->height
) XSD(cl
)->mouseY
=
682 ReleaseSemaphore(&XSD(cl
)->HW_acc
);
687 /********** GfxHidd::SetCursorVisible() ****************************/
689 VOID
VGAGfx__Hidd_Gfx__SetCursorVisible(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorVisible
*msg
)
691 XSD(cl
)->mouseVisible
= msg
->visible
;
693 ObtainSemaphore(&XSD(cl
)->HW_acc
);
694 erase_mouse(XSD(cl
));
696 ReleaseSemaphore(&XSD(cl
)->HW_acc
);
699 /* end of stuff added by stegerg */
700 /*******************************************************************/
702 void draw_mouse(struct VGAGfx_staticdata
*xsd
)
705 unsigned char *ptr
, *data
;
706 int x
, y
, width
, fg
, x_i
, y_i
;
708 if (!xsd
->mouseShape
)
711 if (xsd
->mouseVisible
)
715 struct VGAGfxBitMapData
*bm_data
=
716 OOP_INST_DATA(xsd
->bmclass
, xsd
->visible
);
718 /* Get display width */
719 width
= bm_data
->disp_width
;
721 /* And pointer data */
722 data
= xsd
->mouseShape
;
724 ObtainSemaphore(&xsd
->HW_acc
);
731 for (y_i
= 0, y
= xsd
->mouseY
; y_i
< xsd
->mouseH
; y_i
++, y
++)
733 for (x_i
= 0, x
= xsd
->mouseX
; x_i
< xsd
->mouseW
; x_i
++, x
++)
735 ptr
= (char *)(IPTR
)(0xa0000 + (x
+ (y
* width
)) / 8);
736 pix
= 0x8000 >> (x
% 8);
740 if (fg
&& (x
< width
))
742 fg
+= xsd
->mouseBase
;
744 outw(0x3ce,(fg
<< 8));
746 *ptr
|= 1; // This or'ed value isn't important
751 ReleaseSemaphore(&xsd
->HW_acc
);
756 void erase_mouse(struct VGAGfx_staticdata
*data
)
759 struct Box box
= {0, 0, 0, 0};
761 box
.x1
= data
->mouseX
;
762 box
.y1
= data
->mouseY
;
763 box
.x2
= box
.x1
+ data
->mouseW
;
764 box
.y2
= box
.y1
+ data
->mouseH
;
766 vgaRefreshArea(OOP_INST_DATA(data
->bmclass
, data
->visible
), &box
);