2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
5 Desc: Linux fbdev gfx HIDD for AROS.
9 #define __OOP_NOATTRBASES__
16 #include <sys/types.h>
18 #include <sys/fcntl.h>
20 #include <sys/signal.h>
23 #include <sys/ioctl.h>
25 #include <proto/exec.h>
26 #include <proto/oop.h>
27 #include <proto/utility.h>
30 #include <hidd/hidd.h>
31 #include <hidd/graphics.h>
33 #include <aros/symbolsets.h>
35 #include "linux_intern.h"
38 #include LC_LIBDEFS_FILE
41 #include <aros/debug.h>
43 /* Some attrbases needed as global vars.
44 These are write-once read-many */
46 static OOP_AttrBase HiddBitMapAttrBase
;
47 static OOP_AttrBase HiddSyncAttrBase
;
48 static OOP_AttrBase HiddGfxAttrBase
;
49 static OOP_AttrBase HiddPixFmtAttrBase
;
51 static struct OOP_ABDescr attrbases
[] =
53 { IID_Hidd_BitMap
, &HiddBitMapAttrBase
},
54 { IID_Hidd_Sync
, &HiddSyncAttrBase
},
55 { IID_Hidd_Gfx
, &HiddGfxAttrBase
},
56 { IID_Hidd_PixFmt
, &HiddPixFmtAttrBase
},
60 static BOOL
setup_linuxfb(struct linux_staticdata
*fsd
);
61 static VOID
cleanup_linuxfb(struct linux_staticdata
*fsd
);
62 static BOOL
get_pixfmt(HIDDT_PixelFormat
*pf
, struct linux_staticdata
*fsd
);
64 /***************** FBGfx::New() ***********************/
68 OOP_Object
*LinuxFB__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
70 UBYTE sync_description
[32];
72 struct TagItem pftags
[] =
74 { aHidd_PixFmt_RedShift
, 0 }, /* 0 */
75 { aHidd_PixFmt_GreenShift
, 0 }, /* 1 */
76 { aHidd_PixFmt_BlueShift
, 0 }, /* 2 */
77 { aHidd_PixFmt_AlphaShift
, 0 }, /* 3 */
78 { aHidd_PixFmt_RedMask
, 0 }, /* 4 */
79 { aHidd_PixFmt_GreenMask
, 0 }, /* 5 */
80 { aHidd_PixFmt_BlueMask
, 0 }, /* 6 */
81 { aHidd_PixFmt_AlphaMask
, 0 }, /* 7 */
82 { aHidd_PixFmt_ColorModel
, 0 }, /* 8 */
83 { aHidd_PixFmt_Depth
, 0 }, /* 9 */
84 { aHidd_PixFmt_BytesPerPixel
, 0 }, /* 10 */
85 { aHidd_PixFmt_BitsPerPixel
, 0 }, /* 11 */
86 { aHidd_PixFmt_StdPixFmt
, 0 }, /* 12 */
87 { aHidd_PixFmt_CLUTShift
, 0 }, /* 13 */
88 { aHidd_PixFmt_CLUTMask
, 0 }, /* 14 */
89 { aHidd_PixFmt_BitMapType
, 0 }, /* 15 */
94 struct TagItem synctags
[] =
96 { aHidd_Sync_PixelTime
, 0 }, /* 0 */
97 { aHidd_Sync_HDisp
, 0 }, /* 1 */
98 { aHidd_Sync_VDisp
, 0 }, /* 2 */
99 { aHidd_Sync_LeftMargin
, 0 }, /* 3 */
100 { aHidd_Sync_RightMargin
, 0 }, /* 4 */
101 { aHidd_Sync_HSyncLength
, 0 }, /* 5 */
102 { aHidd_Sync_UpperMargin
, 0 }, /* 6 */
103 { aHidd_Sync_LowerMargin
, 0 }, /* 7 */
104 { aHidd_Sync_VSyncLength
, 0 }, /* 8 */
105 { aHidd_Sync_Description
, 0 }, /* 9 */
109 struct TagItem modetags
[] =
111 { aHidd_Gfx_PixFmtTags
, (IPTR
)pftags
},
112 { aHidd_Gfx_SyncTags
, (IPTR
)synctags
},
116 struct TagItem mytags
[] =
118 { aHidd_Gfx_ModeTags
, (IPTR
)modetags
},
122 struct pRoot_New mymsg
;
125 /* Do GfxHidd initalization here */
126 if (setup_linuxfb(LSD(cl
)))
128 /* Register gfxmodes */
129 HIDDT_PixelFormat
*pf
;
134 if (vHidd_ColorModel_TrueColor
== HIDD_PF_COLMODEL(pf
))
137 pftags
[0].ti_Data
= pf
->red_shift
;
138 pftags
[1].ti_Data
= pf
->green_shift
;
139 pftags
[2].ti_Data
= pf
->blue_shift
;
140 pftags
[3].ti_Data
= pf
->alpha_shift
;
142 pftags
[4].ti_Data
= pf
->red_mask
;
143 pftags
[5].ti_Data
= pf
->green_mask
;
144 pftags
[6].ti_Data
= pf
->blue_mask
;
145 pftags
[7].ti_Data
= pf
->alpha_mask
;
150 #warning "Check this"
151 /* stegerg: apps when using GetDisplayInfoData(DTA_DISP) even on 8 bit palettized
152 screens expect DisplayInfo->redbits/greenbits/bluebits to have
153 correct values (they are calculated based on the red/green/blue masks)
154 which reflect the "size" of the palette (16M, 4096, 262144) */
156 pftags
[4].ti_Data
= pf
->red_mask
;
157 pftags
[5].ti_Data
= pf
->green_mask
;
158 pftags
[6].ti_Data
= pf
->blue_mask
;
160 pftags
[13].ti_Data
= pf
->clut_shift
;
161 pftags
[14].ti_Data
= pf
->clut_mask
;
164 pftags
[8].ti_Data
= HIDD_PF_COLMODEL(pf
);
165 pftags
[9].ti_Data
= pf
->depth
;
166 pftags
[10].ti_Data
= pf
->bytes_per_pixel
;
167 pftags
[11].ti_Data
= pf
->size
;
168 pftags
[12].ti_Data
= vHidd_StdPixFmt_Native
;
169 pftags
[15].ti_Data
= (IPTR
)HIDD_PF_BITMAPTYPE(pf
);
172 kprintf("FB: Width: %d, height: %d, line length=%d\n"
175 , LSD(cl
)->fsi
.line_length
177 kprintf("FB; mask: (%p, %p, %p, %p), shift: (%d, %d, %d, %d)\n"
178 , pf
->red_mask
, pf
->green_mask
, pf
->blue_mask
, pf
->alpha_mask
179 , pf
->red_shift
, pf
->green_shift
, pf
->blue_shift
, pf
->alpha_shift
182 /* Set the gfxmode info */
183 synctags
[0].ti_Data
= LSD(cl
)->vsi
.pixclock
;
184 synctags
[1].ti_Data
= LSD(cl
)->vsi
.xres
;
185 synctags
[2].ti_Data
= LSD(cl
)->vsi
.yres
;
186 synctags
[3].ti_Data
= LSD(cl
)->vsi
.left_margin
;
187 synctags
[4].ti_Data
= LSD(cl
)->vsi
.right_margin
;
188 synctags
[5].ti_Data
= LSD(cl
)->vsi
.hsync_len
;
189 synctags
[6].ti_Data
= LSD(cl
)->vsi
.upper_margin
;
190 synctags
[7].ti_Data
= LSD(cl
)->vsi
.lower_margin
;
191 synctags
[8].ti_Data
= LSD(cl
)->vsi
.vsync_len
;
192 synctags
[9].ti_Data
= (IPTR
)sync_description
;
194 snprintf(sync_description
, sizeof(sync_description
), "FBDev:%dx%d",
195 LSD(cl
)->vsi
.xres
, LSD(cl
)->vsi
.yres
);
197 mytags
[1].ti_Data
= (IPTR
)msg
->attrList
;
198 mymsg
.mID
= msg
->mID
;
199 mymsg
.attrList
= mytags
;
201 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)&mymsg
);
204 /* OOP_MethodID dispose_mid;
205 struct gfx_data *data = OOP_INST_DATA(cl, o);
210 cleanup_linuxfb(LSD(cl
));
216 /********** FBGfx::Dispose() ******************************/
217 VOID
LinuxFB__Root__Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
219 cleanup_linuxfb(LSD(cl
));
221 OOP_DoSuperMethod(cl
, o
, msg
);
226 /********** FBGfx::NewBitMap() ****************************/
227 OOP_Object
*LinuxFB__Hidd_Gfx__NewBitMap(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_NewBitMap
*msg
)
233 struct TagItem tags
[2];
234 struct pHidd_Gfx_NewBitMap p
;
236 HIDDT_StdPixFmt stdpf
;
238 OOP_Object
*gfxhidd
= NULL
;
240 displayable
= GetTagData(aHidd_BitMap_Displayable
, FALSE
, msg
->attrList
);
241 framebuffer
= GetTagData(aHidd_BitMap_FrameBuffer
, FALSE
, msg
->attrList
);
242 modeid
= (HIDDT_ModeID
)GetTagData(aHidd_BitMap_ModeID
, vHidd_ModeID_Invalid
, msg
->attrList
);
243 stdpf
= (HIDDT_StdPixFmt
)GetTagData(aHidd_BitMap_StdPixFmt
, vHidd_StdPixFmt_Unknown
, msg
->attrList
);
244 friend = (OOP_Object
*)GetTagData(aHidd_BitMap_Friend
, 0, msg
->attrList
);
245 if (friend) OOP_GetAttr(friend, aHidd_BitMap_GfxHidd
, (IPTR
*)&gfxhidd
);
247 if ((framebuffer
|| displayable
|| (modeid
!= vHidd_ModeID_Invalid
)) ||
248 ((stdpf
== vHidd_StdPixFmt_Unknown
) && friend && (gfxhidd
== o
)))
250 tags
[0].ti_Tag
= aHidd_BitMap_ClassPtr
;
251 tags
[0].ti_Data
= (IPTR
)LSD(cl
)->bmclass
;
253 tags
[1].ti_Tag
= TAG_MORE
;
254 tags
[1].ti_Data
= (IPTR
)msg
->attrList
;
262 return (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
265 VOID
LinuxFB__Hidd_Gfx__CopyBox(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CopyBox
*msg
)
267 BOOL src
= FALSE
, dest
= FALSE
;
270 mode
= GC_DRMD(msg
->gc
);
272 if (OOP_OCLASS(msg
->src
) == LSD(cl
)->bmclass
) src
= TRUE
;
273 if (OOP_OCLASS(msg
->dest
) == LSD(cl
)->bmclass
) dest
= TRUE
;
277 ((mode
!= vHidd_GC_DrawMode_Copy
)))
279 /* The source and/or destination object is no linuxgfx bitmap, onscreen nor offscreen.
280 Or drawmode is not one of those we accelerate. Let the superclass do the
281 copying in a more general way
283 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
289 struct BitmapData
*data
= OOP_INST_DATA(OOP_OCLASS(msg
->src
), msg
->src
);
290 struct BitmapData
*ddata
= OOP_INST_DATA(OOP_OCLASS(msg
->dest
), msg
->dest
);
294 case vHidd_GC_DrawMode_Copy
:
295 switch(data
->bytesperpix
)
298 HIDD_BM_CopyMemBox8(msg
->dest
,
308 ddata
->bytesperline
);
312 HIDD_BM_CopyMemBox16(msg
->dest
,
322 ddata
->bytesperline
);
327 HIDD_BM_CopyMemBox24(msg
->dest
,
337 ddata
->bytesperline
);
341 HIDD_BM_CopyMemBox32(msg
->dest
,
351 ddata
->bytesperline
);
354 } /* switch(data->bytesperpix) */
360 if (ddata
->RealVideoData
)
362 LOCK_FRAMEBUFFER(LSD(cl
));
363 fbRefreshArea(ddata
, msg
->destX
, msg
->destY
, msg
->destX
+ msg
->width
- 1, msg
->destY
+ msg
->height
- 1);
364 UNLOCK_FRAMEBUFFER(LSD(cl
));
372 /******* FBGfx::Set() ********************************************/
373 VOID
LinuxFB__Root__Get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
377 if (IS_GFX_ATTR(msg
->attrID
, idx
))
381 case aoHidd_Gfx_IsWindowed
:
382 *msg
->storage
= (IPTR
)FALSE
;
386 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
392 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
401 /******************** init_gfxclass() *********************************/
403 static int Init_GfxClass(LIBBASETYPEPTR LIBBASE
)
405 return OOP_ObtainAttrBases(attrbases
);
411 /*************** free_gfxclass() **********************************/
412 static int Expunge_GfxClass(LIBBASETYPEPTR LIBBASE
)
414 OOP_ReleaseAttrBases(attrbases
);
418 ADD2INITLIB(Init_GfxClass
, 0)
419 ADD2EXPUNGELIB(Expunge_GfxClass
, 0)
424 #define FBDEVNAME "/dev/fb0"
427 BOOL
setup_linuxfb(struct linux_staticdata
*fsd
)
429 BOOL success
= FALSE
;
430 fsd
->fbdev
= open(FBDEVNAME
, O_RDWR
);
431 if (-1 == fsd
->fbdev
)
433 kprintf("!!! COULD NOT OPEN FB DEV: %s !!!\n", strerror(errno
));
434 /* Get info on the framebuffer */
438 if (-1 == ioctl(fsd
->fbdev
, FBIOGET_FSCREENINFO
, &fsd
->fsi
))
440 kprintf("!!! COULD NOT GET FIXED SCREEN INFO: %s !!!\n", strerror(errno
));
444 if (-1 == ioctl(fsd
->fbdev
, FBIOGET_VSCREENINFO
, &fsd
->vsi
))
446 kprintf("!!! COULD NOT GET FIXED SCREEN INFO: %s !!!\n", strerror(errno
));
450 if (!get_pixfmt(&fsd
->pf
, fsd
))
452 kprintf("!!! COULD NOT GET PIXEL FORMAT !!!\n");
456 /* Memorymap the framebuffer using mmap() */
457 fsd
->baseaddr
= mmap(NULL
, fsd
->fsi
.smem_len
458 , PROT_READ
| PROT_WRITE
463 if (MAP_FAILED
== fsd
->baseaddr
)
465 kprintf("!!! COULD NOT MAP FRAMEBUFFER MEM: %s !!!\n", strerror(errno
));
478 cleanup_linuxfb(fsd
);
484 VOID
cleanup_linuxfb(struct linux_staticdata
*fsd
)
487 if (NULL
!= fsd
->baseaddr
)
489 munmap(fsd
->baseaddr
, fsd
->fsi
.smem_len
);
498 static HIDDT_Pixel
bitfield2mask(struct fb_bitfield
*bf
)
501 return ((1L << (bf
->offset
)) - 1) - ((1L << (bf
->offset
- bf
->length
)) - 1);
503 return ((1L << bf
->length
) - 1) << bf
->offset
;
508 static ULONG
bitfield2shift(struct fb_bitfield
*bf
)
512 shift
= 32 - (bf
->offset
+ bf
->length
);
519 static void print_bitfield(const char *color
, struct fb_bitfield
*bf
, struct linux_staticdata
*fsd
)
521 kprintf("FB: Bitfield %s: %d, %d, %d\n"
522 , color
, bf
->offset
, bf
->length
, bf
->msb_right
);
524 static BOOL
get_pixfmt(HIDDT_PixelFormat
*pf
, struct linux_staticdata
*fsd
)
526 struct fb_fix_screeninfo
*fsi
;
527 struct fb_var_screeninfo
*vsi
;
534 pf
->depth
= pf
->size
= vsi
->bits_per_pixel
;
535 pf
->stdpixfmt
= vHidd_StdPixFmt_Native
;
536 pf
->bytes_per_pixel
= ((pf
->size
- 1) / 8) + 1;
539 print_bitfield("red", &vsi
->red
, fsd
);
540 print_bitfield("green", &vsi
->green
, fsd
);
541 print_bitfield("blue", &vsi
->blue
, fsd
);
542 print_bitfield("transp", &vsi
->transp
, fsd
);
546 case FB_VISUAL_TRUECOLOR
:
547 case FB_VISUAL_DIRECTCOLOR
:
548 pf
->red_mask
= bitfield2mask(&vsi
->red
);
549 pf
->green_mask
= bitfield2mask(&vsi
->green
);
550 pf
->blue_mask
= bitfield2mask(&vsi
->blue
);
551 pf
->alpha_mask
= bitfield2mask(&vsi
->transp
);
553 pf
->red_shift
= bitfield2shift(&vsi
->red
);
554 pf
->green_shift
= bitfield2shift(&vsi
->green
);
555 pf
->blue_shift
= bitfield2shift(&vsi
->blue
);
556 pf
->alpha_shift
= bitfield2shift(&vsi
->transp
);
558 SET_PF_COLMODEL(pf
, vHidd_ColorModel_TrueColor
);
561 case FB_VISUAL_PSEUDOCOLOR
:
563 pf
->clut_mask
= 0xFF;
565 #warning "also pseudocolor pixelformats need red/green/blue masks now. Is the calc. correct here!?"
566 /* stegerg: apps when using GetDisplayInfoData(DTA_DISP) even on 8 bit palettized
567 screens expect DisplayInfo->redbits/greenbits/bluebits to have
568 correct values (they are calculated based on the red/green/blue masks)
569 which reflect the "size" of the palette (16M, 4096, 262144) */
571 pf
->red_mask
= bitfield2mask(&vsi
->red
);
572 pf
->green_mask
= bitfield2mask(&vsi
->green
);
573 pf
->blue_mask
= bitfield2mask(&vsi
->blue
);
575 SET_PF_COLMODEL(pf
, vHidd_ColorModel_Palette
);
578 case FB_VISUAL_STATIC_PSEUDOCOLOR
:
580 pf
->clut_mask
= 0xFF;
582 #warning "also pseudocolor pixelformats need red/green/blue masks now. Is the calc. correct here!?"
583 /* stegerg: apps when using GetDisplayInfoData(DTA_DISP) even on 8 bit palettized
584 screens expect DisplayInfo->redbits/greenbits/bluebits to have
585 correct values (they are calculated based on the red/green/blue masks)
586 which reflect the "size" of the palette (16M, 4096, 262144) */
588 pf
->red_mask
= bitfield2mask(&vsi
->red
);
589 pf
->green_mask
= bitfield2mask(&vsi
->green
);
590 pf
->blue_mask
= bitfield2mask(&vsi
->blue
);
592 SET_PF_COLMODEL(pf
, vHidd_ColorModel_StaticPalette
);
595 case FB_VISUAL_MONO01
:
596 case FB_VISUAL_MONO10
:
597 kprintf("!!! FB: UNHANDLED GRAPHTYPE :%d !!!\n", fsi
->visual
);
602 kprintf("!!! FB: UNKNOWN GRAPHTYPE :%d !!!\n", fsi
->visual
);
609 case FB_TYPE_PACKED_PIXELS
:
610 SET_PF_BITMAPTYPE(pf
, vHidd_BitMapType_Chunky
);
613 SET_PF_BITMAPTYPE(pf
, vHidd_BitMapType_Planar
);
615 case FB_TYPE_INTERLEAVED_PLANES
:
616 SET_PF_BITMAPTYPE(pf
, vHidd_BitMapType_InterleavedPlanar
);
620 kprintf("!!! UNSUPPORTED FRAMEBUFFER TYPE: %d !!!\n", fsi
->type
);
629 void fbRefreshArea(struct BitmapData
*data
, LONG x1
, LONG y1
, LONG x2
, LONG y2
)
632 ULONG srcmod
, dstmod
;
635 x1
*= data
->bytesperpix
;
636 x2
*= data
->bytesperpix
; x2
+= data
->bytesperpix
- 1;
643 srcmod
= (data
->bytesperline
- w
);
644 dstmod
= (data
->realbytesperline
- w
);
646 src
= data
->VideoData
+ y1
* data
->bytesperline
+ x1
;
647 dst
= data
->RealVideoData
+ y1
* data
->realbytesperline
+ x1
;
649 for(y
= 0; y
< h
; y
++)
651 for(x
= 0; x
< w
/ 4; x
++)
653 *(ULONG
*)dst
= *(ULONG
*)src
;