2 * sdl.hidd - SDL graphics/sound/keyboard for AROS hosted
3 * Copyright (c) 2007 Robert Norris. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the same terms as AROS itself.
9 #define __OOP_NOATTRBASES__
11 #include <aros/symbolsets.h>
13 #include <hidd/hidd.h>
14 #include <hidd/graphics.h>
15 #include <utility/tagitem.h>
18 #include <proto/alib.h>
19 #include <proto/exec.h>
20 #include <proto/oop.h>
21 #include <proto/utility.h>
23 #include "sdl_intern.h"
25 #include LC_LIBDEFS_FILE
28 #include <aros/debug.h>
30 static OOP_AttrBase HiddPixFmtAttrBase
;
31 static OOP_AttrBase HiddBitMapAttrBase
;
32 static OOP_AttrBase HiddSyncAttrBase
;
33 static OOP_AttrBase HiddGfxAttrBase
;
34 static OOP_AttrBase HiddSDLBitMapAttrBase
;
36 static struct OOP_ABDescr attrbases
[] = {
37 { IID_Hidd_PixFmt
, &HiddPixFmtAttrBase
},
38 { IID_Hidd_BitMap
, &HiddBitMapAttrBase
},
39 { IID_Hidd_Sync
, &HiddSyncAttrBase
},
40 { IID_Hidd_Gfx
, &HiddGfxAttrBase
},
41 { IID_Hidd_SDLBitMap
, &HiddSDLBitMapAttrBase
},
45 static int sdl_gfxclass_init(LIBBASETYPEPTR LIBBASE
) {
46 D(bug("[sdl] sdl_gfxclass_init\n"));
48 return OOP_ObtainAttrBases(attrbases
);
51 static int sdl_gfxclass_expunge(LIBBASETYPEPTR LIBBASE
) {
52 D(bug("[sdl] sdl_gfxclass_expunge\n"));
54 OOP_ReleaseAttrBases(attrbases
);
58 ADD2INITLIB(sdl_gfxclass_init
, 0)
59 ADD2EXPUNGELIB(sdl_gfxclass_expunge
, 0)
61 #define SDLGfxBase ((LIBBASETYPEPTR) cl->UserData)
63 static const SDL_Rect mode_1600_1200
= { .w
= 1600, .h
= 1200 };
64 static const SDL_Rect mode_1280_1024
= { .w
= 1280, .h
= 1024 };
65 static const SDL_Rect mode_1280_960
= { .w
= 1280, .h
= 960 };
66 static const SDL_Rect mode_1152_864
= { .w
= 1152, .h
= 864 };
67 static const SDL_Rect mode_1024_768
= { .w
= 1024, .h
= 768 };
68 static const SDL_Rect mode_800_600
= { .w
= 800, .h
= 600 };
70 static const SDL_Rect
*default_modes
[] = {
80 OOP_Object
*SDLGfx__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
) {
81 const SDL_VideoInfo
*info
;
82 const SDL_PixelFormat
*pixfmt
;
83 char driver
[128] = "";
86 struct TagItem
*pftags
;
89 struct TagItem
**synctags
, *modetags
, *msgtags
;
91 struct pRoot_New supermsg
;
93 S(SDL_VideoDriverName
, driver
, sizeof(driver
));
94 info
= S(SDL_GetVideoInfo
);
97 kprintf("sdlgfx: using %s driver\n", driver
);
99 D(bug("[sdl] window manager: %savailable\n", info
->wm_available
? "" : "not "));
100 D(bug("[sdl] hardware surfaces: %savailable\n", info
->hw_available
? "" : "not "));
102 LIBBASE
->use_hwsurface
= info
->hw_available
? TRUE
: FALSE
;
103 surftype
= LIBBASE
->use_hwsurface
? SDL_HWSURFACE
: SDL_SWSURFACE
;
105 D(bug("[sdl] colour model: %s\n", pixfmt
->palette
== NULL
? "truecolour" : "palette"));
106 if (pixfmt
->palette
== NULL
) {
107 D(bug("[sdl] colour mask: alpha=0x%08x red=0x%08x green=0x%08x blue=0x%08x\n", pixfmt
->Amask
, pixfmt
->Rmask
, pixfmt
->Gmask
, pixfmt
->Bmask
, pixfmt
->Amask
));
108 D(bug("[sdl] colour shift: alpha=%d red=%d green=%d blue=%d\n", pixfmt
->Ashift
, pixfmt
->Rshift
, pixfmt
->Gshift
, pixfmt
->Bshift
, pixfmt
->Ashift
));
111 if (pixfmt
->palette
!= NULL
) {
112 /* XXX deal with palette (CLUT) modes */
116 /* select an appropriate AROS pixel format based on the SDL format */
117 int stdpixfmt
= vHidd_StdPixFmt_Unknown
;
118 int alpha_shift
, red_shift
, green_shift
, blue_shift
;
120 if (pixfmt
->BitsPerPixel
== 32) {
121 if (pixfmt
->Amask
== 0x000000ff && pixfmt
->Rmask
== 0x0000ff00 &&
122 pixfmt
->Gmask
== 0x00ff0000 && pixfmt
->Bmask
== 0xff000000) {
123 stdpixfmt
= vHidd_StdPixFmt_ARGB32
;
130 else if (pixfmt
->Amask
== 0xff000000 && pixfmt
->Rmask
== 0x00ff0000 &&
131 pixfmt
->Gmask
== 0x0000ff00 && pixfmt
->Bmask
== 0x000000ff) {
132 stdpixfmt
= vHidd_StdPixFmt_BGRA32
;
139 else if (pixfmt
->Amask
== 0xff000000 && pixfmt
->Rmask
== 0x000000ff &&
140 pixfmt
->Gmask
== 0x0000ff00 && pixfmt
->Bmask
== 0x00ff0000) {
141 stdpixfmt
= vHidd_StdPixFmt_RGBA32
;
148 else if (pixfmt
->Amask
== 0x000000ff && pixfmt
->Rmask
== 0xff000000 &&
149 pixfmt
->Gmask
== 0x00ff0000 && pixfmt
->Bmask
== 0x0000ff00) {
150 stdpixfmt
= vHidd_StdPixFmt_ABGR32
;
157 else if (pixfmt
->Amask
== 0x00000000 && pixfmt
->Rmask
== 0x0000ff00 &&
158 pixfmt
->Gmask
== 0x00ff0000 && pixfmt
->Bmask
== 0xff000000) {
159 stdpixfmt
= vHidd_StdPixFmt_0RGB32
;
166 else if (pixfmt
->Amask
== 0x00000000 && pixfmt
->Rmask
== 0x00ff0000 &&
167 pixfmt
->Gmask
== 0x0000ff00 && pixfmt
->Bmask
== 0x000000ff) {
168 stdpixfmt
= vHidd_StdPixFmt_BGR032
;
175 else if (pixfmt
->Amask
== 0x00000000 && pixfmt
->Rmask
== 0x000000ff &&
176 pixfmt
->Gmask
== 0x0000ff00 && pixfmt
->Bmask
== 0x00ff0000) {
177 stdpixfmt
= vHidd_StdPixFmt_RGB032
;
184 else if (pixfmt
->Amask
== 0x00000000 && pixfmt
->Rmask
== 0xff000000 &&
185 pixfmt
->Gmask
== 0x00ff0000 && pixfmt
->Bmask
== 0x0000ff00) {
186 stdpixfmt
= vHidd_StdPixFmt_0BGR32
;
194 else if (pixfmt
->BitsPerPixel
== 24) {
196 vHidd_StdPixFmt_RGB24
197 vHidd_StdPixFmt_BGR24
201 else if (pixfmt
->BitsPerPixel
== 16) {
203 vHidd_StdPixFmt_RGB16
204 vHidd_StdPixFmt_RGB16_LE
205 vHidd_StdPixFmt_BGR16
206 vHidd_StdPixFmt_BGR16_LE
210 else if (pixfmt
->BitsPerPixel
== 15) {
212 vHidd_StdPixFmt_RGB15,
213 vHidd_StdPixFmt_RGB15_LE,
214 vHidd_StdPixFmt_BGR15,
215 vHidd_StdPixFmt_BGR15_LE,
219 if (stdpixfmt
== vHidd_StdPixFmt_Unknown
) {
220 stdpixfmt
= vHidd_StdPixFmt_Native
;
221 alpha_shift
= pixfmt
->Ashift
;
222 red_shift
= pixfmt
->Rshift
;
223 green_shift
= pixfmt
->Gshift
;
224 blue_shift
= pixfmt
->Bshift
;
227 D(bug("[sdl] selected pixel format %d\n", stdpixfmt
));
230 aHidd_PixFmt_ColorModel
, vHidd_ColorModel_TrueColor
,
231 aHidd_PixFmt_RedShift
, red_shift
,
232 aHidd_PixFmt_GreenShift
, green_shift
,
233 aHidd_PixFmt_BlueShift
, blue_shift
,
234 aHidd_PixFmt_AlphaShift
, alpha_shift
,
235 aHidd_PixFmt_RedMask
, pixfmt
->Rmask
,
236 aHidd_PixFmt_GreenMask
, pixfmt
->Gmask
,
237 aHidd_PixFmt_BlueMask
, pixfmt
->Bmask
,
238 aHidd_PixFmt_AlphaMask
, pixfmt
->Amask
,
239 aHidd_PixFmt_Depth
, pixfmt
->BitsPerPixel
,
240 aHidd_PixFmt_BitsPerPixel
, pixfmt
->BitsPerPixel
,
241 aHidd_PixFmt_BytesPerPixel
, pixfmt
->BytesPerPixel
,
242 aHidd_PixFmt_StdPixFmt
, stdpixfmt
,
243 aHidd_PixFmt_BitMapType
, vHidd_BitMapType_Chunky
247 LIBBASE
->use_fullscreen
= CFG_WANT_FULLSCREEN
? TRUE
: FALSE
;
249 modes
= S(SDL_ListModes
, NULL
, surftype
| LIBBASE
->use_fullscreen
? SDL_FULLSCREEN
: 0);
251 D(bug("[sdl] available modes:"));
257 if (modes
== (SDL_Rect
**) -1) {
258 D(bug(" (default)"));
259 modes
= default_modes
;
261 for (nmodes
= 0; modes
[nmodes
] != NULL
&& modes
[nmodes
]->w
!= 0; nmodes
++)
262 D(bug(" %dx%d", modes
[nmodes
]->w
, modes
[nmodes
]->h
));
266 D(bug("[sdl] building %d mode sync items\n", nmodes
));
268 tagpool
= CreatePool(MEMF_CLEAR
, 1024, 128);
270 synctags
= AllocPooled(tagpool
, sizeof(struct TagItem
*) * (nmodes
+1));
272 for (i
= 0; i
< nmodes
; i
++) {
273 /* remove modes larger than the current screen res */
274 if (modes
[i
]->w
> info
->current_w
|| modes
[i
]->h
> info
->current_h
) {
279 desc
= AllocPooled(tagpool
, 16);
280 __sprintf(desc
, "SDL:%dx%d", modes
[i
]->w
, modes
[i
]->h
);
282 synctags
[i
] = AllocPooled(tagpool
, sizeof(struct TagItem
) * 4);
283 synctags
[i
][0].ti_Tag
= aHidd_Sync_HDisp
; synctags
[i
][0].ti_Data
= modes
[i
]->w
;
284 synctags
[i
][1].ti_Tag
= aHidd_Sync_VDisp
; synctags
[i
][1].ti_Data
= modes
[i
]->h
;
285 synctags
[i
][2].ti_Tag
= aHidd_Sync_Description
; synctags
[i
][2].ti_Data
= (IPTR
) desc
;
286 synctags
[i
][3].ti_Tag
= TAG_DONE
;
289 modetags
= AllocPooled(tagpool
, sizeof(struct TagItem
) * (nmodes
+9));
291 modetags
[0].ti_Tag
= aHidd_Gfx_PixFmtTags
; modetags
[0].ti_Data
= (IPTR
) pftags
;
292 modetags
[1].ti_Tag
= aHidd_Sync_PixelClock
; modetags
[1].ti_Data
= 100000000;
293 modetags
[2].ti_Tag
= aHidd_Sync_LeftMargin
; modetags
[2].ti_Data
= 0;
294 modetags
[3].ti_Tag
= aHidd_Sync_RightMargin
; modetags
[3].ti_Data
= 0;
295 modetags
[4].ti_Tag
= aHidd_Sync_UpperMargin
; modetags
[4].ti_Data
= 0;
296 modetags
[5].ti_Tag
= aHidd_Sync_LowerMargin
; modetags
[5].ti_Data
= 0;
297 modetags
[6].ti_Tag
= aHidd_Sync_HSyncLength
; modetags
[6].ti_Data
= 0;
298 modetags
[7].ti_Tag
= aHidd_Sync_VSyncLength
; modetags
[7].ti_Data
= 0;
300 for (i
= 0; i
< nmodes
; i
++) {
301 if (synctags
[i
] == NULL
) {
302 modetags
[8+i
].ti_Tag
= TAG_IGNORE
;
306 modetags
[8+i
].ti_Tag
= aHidd_Gfx_SyncTags
;
307 modetags
[8+i
].ti_Data
= (IPTR
) synctags
[i
];
310 modetags
[8+i
].ti_Tag
= TAG_DONE
;
313 aHidd_Gfx_ModeTags
, (IPTR
) modetags
,
314 TAG_MORE
, (IPTR
) msg
->attrList
317 supermsg
.mID
= msg
->mID
;
318 supermsg
.attrList
= msgtags
;
320 D(bug("[sdl] hidd tags built, calling supermethod\n"));
322 o
= (OOP_Object
*) OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) &supermsg
);
327 D(bug("[sdl] supermethod failed, bailing out\n"));
331 return (OOP_Object
*) o
;
334 VOID
SDLGfx__Root__Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
) {
337 D(bug("[sdl] SDLGfx::Dispose\n"));
339 s
= S(SDL_GetVideoSurface
);
341 D(bug("[sdl] freeing existing video surface\n"));
342 SV(SDL_FreeSurface
, s
);
345 OOP_DoSuperMethod(cl
, o
, msg
);
350 OOP_Object
*SDLGfx__Hidd_Gfx__NewBitMap(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_NewBitMap
*msg
) {
351 OOP_Object
*bmclass
= NULL
, *friend, *gfxhidd
;
354 HIDDT_StdPixFmt stdpixfmt
;
355 struct TagItem
*msgtags
;
356 struct pHidd_Gfx_NewBitMap supermsg
;
358 D(bug("[sdl] SDLGfx::NewBitMap\n"));
360 if (GetTagData(aHidd_BitMap_FrameBuffer
, FALSE
, msg
->attrList
)) {
361 D(bug("[sdl] framebuffer bitmap, we can handle it\n"));
362 bmclass
= LIBBASE
->bmclass
;
365 else if (GetTagData(aHidd_BitMap_Displayable
, FALSE
, msg
->attrList
)) {
366 D(bug("[sdl] displayable bitmap, we can handle it\n"));
367 bmclass
= LIBBASE
->bmclass
;
370 else if ((HIDDT_ModeID
) GetTagData(aHidd_BitMap_ModeID
, vHidd_ModeID_Invalid
, msg
->attrList
) != vHidd_ModeID_Invalid
) {
371 D(bug("[sdl] bitmap with valid mode, we can handle it\n"));
372 bmclass
= LIBBASE
->bmclass
;
375 else if ((HIDDT_StdPixFmt
) GetTagData(aHidd_BitMap_StdPixFmt
, vHidd_StdPixFmt_Unknown
, msg
->attrList
) == vHidd_StdPixFmt_Unknown
) {
376 friend = (OOP_Object
*) GetTagData(aHidd_BitMap_Friend
, NULL
, msg
->attrList
);
377 if (friend != NULL
) {
378 OOP_GetAttr(friend, aHidd_BitMap_GfxHidd
, (APTR
) &gfxhidd
);
380 D(bug("[sdl] bitmap with unknown pixel format and sdl friend bitmap, we can handle it\n"));
381 bmclass
= LIBBASE
->bmclass
;
388 aHidd_BitMap_ClassPtr
, (IPTR
) LIBBASE
->bmclass
,
389 TAG_MORE
, (IPTR
) msg
->attrList
393 msgtags
= msg
->attrList
;
395 supermsg
.mID
= msg
->mID
;
396 supermsg
.attrList
= msgtags
;
398 o
= (OOP_Object
*) OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) &supermsg
);
403 VOID
SDLGfx__Hidd_Gfx__CopyBox(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CopyBox
*msg
) {
404 struct SDL_Surface
*src
, *dest
;
405 struct SDL_Rect srect
, drect
;
408 D(bug("[sdl] SDLGfx::CopyBox\n"));
410 OOP_GetAttr(msg
->src
, aHidd_SDLBitMap_Surface
, &src
);
411 OOP_GetAttr(msg
->dest
, aHidd_SDLBitMap_Surface
, &dest
);
413 if (src
== NULL
|| dest
== NULL
) {
414 D(bug("[sdl] missing a surface: src is 0x%08x, dest is 0x%08x. letting the superclass deal with it\n", src
, dest
));
416 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
423 srect
.w
= msg
->width
;
424 srect
.h
= msg
->height
;
426 drect
.x
= msg
->destX
;
427 drect
.y
= msg
->destY
;
429 D(bug("[sdl] blitting %dx%d rect from src 0x%08x [%d,%d] to dest 0x%08x [%d,%d]\n", msg
->width
, msg
->height
, src
, msg
->srcX
, msg
->srcY
, dest
, msg
->destX
, msg
->destY
));
431 S(SDL_BlitSurface
, src
, &srect
, dest
, &drect
);
433 OOP_GetAttr(msg
->dest
, aHidd_SDLBitMap_IsOnScreen
, &is_onscreen
);
435 D(bug("[sdl] refreshing onscreen surface 0x%08x\n", dest
));
437 SV(SDL_UpdateRect
, dest
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
);