make the linux-ppc packags be in synch with other platforms
[tangerine.git] / arch / all-linux / hidd / gfxclass.c
blob6cc9ca2f3a24c253b9c632fad94423a230cdf615
1 /*
2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Linux fbdev gfx HIDD for AROS.
6 Lang: English.
7 */
9 #define __OOP_NOATTRBASES__
11 #include <stddef.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <sys/mman.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/fcntl.h>
20 #include <sys/signal.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <sys/ioctl.h>
25 #include <proto/exec.h>
26 #include <proto/oop.h>
27 #include <proto/utility.h>
28 #include <oop/oop.h>
30 #include <hidd/hidd.h>
31 #include <hidd/graphics.h>
33 #include <aros/symbolsets.h>
35 #include "linux_intern.h"
36 #include "bitmap.h"
38 #include LC_LIBDEFS_FILE
40 #define DEBUG 0
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 },
57 { NULL , NULL }
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 */
90 { TAG_DONE , 0 }
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 */
106 { TAG_DONE , 0 }
109 struct TagItem modetags[] =
111 { aHidd_Gfx_PixFmtTags , (IPTR)pftags },
112 { aHidd_Gfx_SyncTags , (IPTR)synctags },
113 { TAG_DONE , 0 }
116 struct TagItem mytags[] =
118 { aHidd_Gfx_ModeTags, (IPTR)modetags },
119 { TAG_MORE , 0 }
122 struct pRoot_New mymsg;
125 /* Do GfxHidd initalization here */
126 if (setup_linuxfb(LSD(cl)))
128 /* Register gfxmodes */
129 HIDDT_PixelFormat *pf;
131 pf = &LSD(cl)->pf;
133 /* Set the pixfmt */
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;
148 else
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"
173 , LSD(cl)->vsi.xres
174 , LSD(cl)->vsi.yres
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);
202 if (NULL != o)
204 /* OOP_MethodID dispose_mid;
205 struct gfx_data *data = OOP_INST_DATA(cl, o);
207 */ return o;
210 cleanup_linuxfb(LSD(cl));
213 return NULL;
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);
223 return;
226 /********** FBGfx::NewBitMap() ****************************/
227 OOP_Object *LinuxFB__Hidd_Gfx__NewBitMap(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_NewBitMap *msg)
230 BOOL displayable;
231 BOOL framebuffer;
233 struct TagItem tags[2];
234 struct pHidd_Gfx_NewBitMap p;
235 HIDDT_ModeID modeid;
236 HIDDT_StdPixFmt stdpf;
237 OOP_Object *friend;
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;
256 p.mID = msg->mID;
257 p.attrList = tags;
259 msg = &p;
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;
268 ULONG mode;
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;
276 if (!dest || !src ||
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);
284 return;
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);
292 switch(mode)
294 case vHidd_GC_DrawMode_Copy:
295 switch(data->bytesperpix)
297 case 1:
298 HIDD_BM_CopyMemBox8(msg->dest,
299 data->VideoData,
300 msg->srcX,
301 msg->srcY,
302 ddata->VideoData,
303 msg->destX,
304 msg->destY,
305 msg->width,
306 msg->height,
307 data->bytesperline,
308 ddata->bytesperline);
309 break;
311 case 2:
312 HIDD_BM_CopyMemBox16(msg->dest,
313 data->VideoData,
314 msg->srcX,
315 msg->srcY,
316 ddata->VideoData,
317 msg->destX,
318 msg->destY,
319 msg->width,
320 msg->height,
321 data->bytesperline,
322 ddata->bytesperline);
323 break;
326 case 3:
327 HIDD_BM_CopyMemBox24(msg->dest,
328 data->VideoData,
329 msg->srcX,
330 msg->srcY,
331 ddata->VideoData,
332 msg->destX,
333 msg->destY,
334 msg->width,
335 msg->height,
336 data->bytesperline,
337 ddata->bytesperline);
338 break;
340 case 4:
341 HIDD_BM_CopyMemBox32(msg->dest,
342 data->VideoData,
343 msg->srcX,
344 msg->srcY,
345 ddata->VideoData,
346 msg->destX,
347 msg->destY,
348 msg->width,
349 msg->height,
350 data->bytesperline,
351 ddata->bytesperline);
352 break;
354 } /* switch(data->bytesperpix) */
355 break;
357 } /* switch(mode) */
359 #if BUFFERED_VRAM
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));
366 #endif
368 } /**/
372 /******* FBGfx::Set() ********************************************/
373 VOID LinuxFB__Root__Get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
375 ULONG idx;
377 if (IS_GFX_ATTR(msg->attrID, idx))
379 switch (idx)
381 case aoHidd_Gfx_IsWindowed:
382 *msg->storage = (IPTR)FALSE;
383 break;
385 default:
386 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
387 break;
390 else
392 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
395 return;
398 #undef LSD
399 #define LSD(cl) fsd
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);
415 return TRUE;
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 */
436 else
438 if (-1 == ioctl(fsd->fbdev, FBIOGET_FSCREENINFO, &fsd->fsi))
440 kprintf("!!! COULD NOT GET FIXED SCREEN INFO: %s !!!\n", strerror(errno));
442 else
444 if (-1 == ioctl(fsd->fbdev, FBIOGET_VSCREENINFO, &fsd->vsi))
446 kprintf("!!! COULD NOT GET FIXED SCREEN INFO: %s !!!\n", strerror(errno));
448 else
450 if (!get_pixfmt(&fsd->pf, fsd))
452 kprintf("!!! COULD NOT GET PIXEL FORMAT !!!\n");
454 else
456 /* Memorymap the framebuffer using mmap() */
457 fsd->baseaddr = mmap(NULL, fsd->fsi.smem_len
458 , PROT_READ | PROT_WRITE
459 , MAP_SHARED
460 , fsd->fbdev
463 if (MAP_FAILED == fsd->baseaddr)
465 kprintf("!!! COULD NOT MAP FRAMEBUFFER MEM: %s !!!\n", strerror(errno));
467 else
469 success = TRUE;
476 if (!success)
478 cleanup_linuxfb(fsd);
481 return success;
484 VOID cleanup_linuxfb(struct linux_staticdata *fsd)
487 if (NULL != fsd->baseaddr)
489 munmap(fsd->baseaddr, fsd->fsi.smem_len);
492 if (0 != fsd->fbdev)
494 close(fsd->fbdev);
498 static HIDDT_Pixel bitfield2mask(struct fb_bitfield *bf)
500 #if 0
501 return ((1L << (bf->offset)) - 1) - ((1L << (bf->offset - bf->length)) - 1);
502 #else
503 return ((1L << bf->length) - 1) << bf->offset;
504 #endif
508 static ULONG bitfield2shift(struct fb_bitfield *bf)
510 int shift;
512 shift = 32 - (bf->offset + bf->length);
513 if (shift == 32)
514 shift = 0;
516 return shift;
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;
529 BOOL success = TRUE;
531 fsi = &fsd->fsi;
532 vsi = &fsd->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);
544 switch (fsi->visual)
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);
559 break;
561 case FB_VISUAL_PSEUDOCOLOR:
562 pf->clut_shift = 0;
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);
576 break;
578 case FB_VISUAL_STATIC_PSEUDOCOLOR:
579 pf->clut_shift = 0;
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);
593 break;
595 case FB_VISUAL_MONO01:
596 case FB_VISUAL_MONO10:
597 kprintf("!!! FB: UNHANDLED GRAPHTYPE :%d !!!\n", fsi->visual);
598 success = FALSE;
599 break;
601 default:
602 kprintf("!!! FB: UNKNOWN GRAPHTYPE :%d !!!\n", fsi->visual);
603 success = FALSE;
604 break;
607 switch (fsi->type)
609 case FB_TYPE_PACKED_PIXELS:
610 SET_PF_BITMAPTYPE(pf, vHidd_BitMapType_Chunky);
611 break;
612 case FB_TYPE_PLANES:
613 SET_PF_BITMAPTYPE(pf, vHidd_BitMapType_Planar);
614 break;
615 case FB_TYPE_INTERLEAVED_PLANES:
616 SET_PF_BITMAPTYPE(pf, vHidd_BitMapType_InterleavedPlanar);
617 break;
619 default:
620 kprintf("!!! UNSUPPORTED FRAMEBUFFER TYPE: %d !!!\n", fsi->type);
621 success = FALSE;
622 break;
625 return success;
628 #if BUFFERED_VRAM
629 void fbRefreshArea(struct BitmapData *data, LONG x1, LONG y1, LONG x2, LONG y2)
631 UBYTE *src, *dst;
632 ULONG srcmod, dstmod;
633 LONG x, y, w, h;
635 x1 *= data->bytesperpix;
636 x2 *= data->bytesperpix; x2 += data->bytesperpix - 1;
638 x1 &= ~3;
639 x2 = (x2 & ~3) + 3;
640 w = (x2 - x1) + 1;
641 h = (y2 - y1) + 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;
654 dst += 4; src += 4;
656 src += srcmod;
657 dst += dstmod;
661 #endif