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/exec.h>
19 #include <proto/oop.h>
20 #include <proto/utility.h>
22 #include "sdl_intern.h"
24 #include LC_LIBDEFS_FILE
27 #include <aros/debug.h>
29 static OOP_AttrBase HiddPixFmtAttrBase
;
30 static OOP_AttrBase HiddBitMapAttrBase
;
31 static OOP_AttrBase HiddSyncAttrBase
;
32 static OOP_AttrBase HiddGfxAttrBase
;
33 static OOP_AttrBase HiddSDLBitMapAttrBase
;
35 static struct OOP_ABDescr attrbases
[] = {
36 { IID_Hidd_PixFmt
, &HiddPixFmtAttrBase
},
37 { IID_Hidd_BitMap
, &HiddBitMapAttrBase
},
38 { IID_Hidd_Sync
, &HiddSyncAttrBase
},
39 { IID_Hidd_Gfx
, &HiddGfxAttrBase
},
40 { IID_Hidd_SDLBitMap
, &HiddSDLBitMapAttrBase
},
44 static int sdl_gfxclass_init(LIBBASETYPEPTR LIBBASE
) {
45 D(bug("[sdl] sdl_gfxclass_init\n"));
47 return OOP_ObtainAttrBases(attrbases
);
50 static int sdl_gfxclass_expunge(LIBBASETYPEPTR LIBBASE
) {
51 D(bug("[sdl] sdl_gfxclass_expunge\n"));
53 OOP_ReleaseAttrBases(attrbases
);
57 ADD2INITLIB(sdl_gfxclass_init
, 0)
58 ADD2EXPUNGELIB(sdl_gfxclass_expunge
, 0)
60 #define SDLGfxBase ((LIBBASETYPEPTR) cl->UserData)
62 static const SDL_Rect mode_1600_1200
= { .w
= 1600, .h
= 1200 };
63 static const SDL_Rect mode_1280_1024
= { .w
= 1280, .h
= 1024 };
64 static const SDL_Rect mode_1280_960
= { .w
= 1280, .h
= 960 };
65 static const SDL_Rect mode_1152_864
= { .w
= 1152, .h
= 864 };
66 static const SDL_Rect mode_1024_768
= { .w
= 1024, .h
= 768 };
67 static const SDL_Rect mode_800_600
= { .w
= 800, .h
= 600 };
69 static const SDL_Rect
*default_modes
[] = {
79 OOP_Object
*SDLGfx__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
) {
80 const SDL_VideoInfo
*info
;
81 const SDL_PixelFormat
*pixfmt
;
82 char driver
[128] = "";
85 struct TagItem
*pftags
;
88 struct TagItem
**synctags
, *modetags
, *msgtags
;
90 struct pRoot_New supermsg
;
92 S(SDL_VideoDriverName
, driver
, sizeof(driver
));
93 info
= S(SDL_GetVideoInfo
);
96 kprintf("sdlgfx: using %s driver\n", driver
);
98 D(bug("[sdl] window manager: %savailable\n", info
->wm_available
? "" : "not "));
99 D(bug("[sdl] hardware surfaces: %savailable\n", info
->hw_available
? "" : "not "));
101 LIBBASE
->use_hwsurface
= info
->hw_available
? TRUE
: FALSE
;
102 surftype
= LIBBASE
->use_hwsurface
? SDL_HWSURFACE
: SDL_SWSURFACE
;
104 D(bug("[sdl] colour model: %s\n", pixfmt
->palette
== NULL
? "truecolour" : "palette"));
105 if (pixfmt
->palette
== NULL
) {
106 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
));
107 D(bug("[sdl] colour shift: alpha=%d red=%d green=%d blue=%d\n", pixfmt
->Ashift
, pixfmt
->Rshift
, pixfmt
->Gshift
, pixfmt
->Bshift
, pixfmt
->Ashift
));
110 if (pixfmt
->palette
!= NULL
) {
111 /* XXX deal with palette (CLUT) modes */
115 /* select an appropriate AROS pixel format based on the SDL format */
116 int stdpixfmt
= vHidd_StdPixFmt_Unknown
;
117 int alpha_shift
, red_shift
, green_shift
, blue_shift
;
119 if (pixfmt
->BitsPerPixel
== 32) {
120 if (pixfmt
->Amask
== 0x000000ff && pixfmt
->Rmask
== 0x0000ff00 &&
121 pixfmt
->Gmask
== 0x00ff0000 && pixfmt
->Bmask
== 0xff000000) {
122 stdpixfmt
= vHidd_StdPixFmt_ARGB32
;
129 else if (pixfmt
->Amask
== 0xff000000 && pixfmt
->Rmask
== 0x00ff0000 &&
130 pixfmt
->Gmask
== 0x0000ff00 && pixfmt
->Bmask
== 0x000000ff) {
131 stdpixfmt
= vHidd_StdPixFmt_BGRA32
;
138 else if (pixfmt
->Amask
== 0xff000000 && pixfmt
->Rmask
== 0x000000ff &&
139 pixfmt
->Gmask
== 0x0000ff00 && pixfmt
->Bmask
== 0x00ff0000) {
140 stdpixfmt
= vHidd_StdPixFmt_RGBA32
;
147 else if (pixfmt
->Amask
== 0x000000ff && pixfmt
->Rmask
== 0xff000000 &&
148 pixfmt
->Gmask
== 0x00ff0000 && pixfmt
->Bmask
== 0x0000ff00) {
149 stdpixfmt
= vHidd_StdPixFmt_ABGR32
;
156 else if (pixfmt
->Amask
== 0x00000000 && pixfmt
->Rmask
== 0x0000ff00 &&
157 pixfmt
->Gmask
== 0x00ff0000 && pixfmt
->Bmask
== 0xff000000) {
158 stdpixfmt
= vHidd_StdPixFmt_0RGB32
;
165 else if (pixfmt
->Amask
== 0x00000000 && pixfmt
->Rmask
== 0x00ff0000 &&
166 pixfmt
->Gmask
== 0x0000ff00 && pixfmt
->Bmask
== 0x000000ff) {
167 stdpixfmt
= vHidd_StdPixFmt_BGR032
;
174 else if (pixfmt
->Amask
== 0x00000000 && pixfmt
->Rmask
== 0x000000ff &&
175 pixfmt
->Gmask
== 0x0000ff00 && pixfmt
->Bmask
== 0x00ff0000) {
176 stdpixfmt
= vHidd_StdPixFmt_RGB032
;
183 else if (pixfmt
->Amask
== 0x00000000 && pixfmt
->Rmask
== 0xff000000 &&
184 pixfmt
->Gmask
== 0x00ff0000 && pixfmt
->Bmask
== 0x0000ff00) {
185 stdpixfmt
= vHidd_StdPixFmt_0BGR32
;
193 else if (pixfmt
->BitsPerPixel
== 24) {
195 vHidd_StdPixFmt_RGB24
196 vHidd_StdPixFmt_BGR24
200 else if (pixfmt
->BitsPerPixel
== 16) {
202 vHidd_StdPixFmt_RGB16
203 vHidd_StdPixFmt_RGB16_LE
204 vHidd_StdPixFmt_BGR16
205 vHidd_StdPixFmt_BGR16_LE
209 else if (pixfmt
->BitsPerPixel
== 15) {
211 vHidd_StdPixFmt_RGB15,
212 vHidd_StdPixFmt_RGB15_LE,
213 vHidd_StdPixFmt_BGR15,
214 vHidd_StdPixFmt_BGR15_LE,
218 if (stdpixfmt
== vHidd_StdPixFmt_Unknown
) {
219 stdpixfmt
= vHidd_StdPixFmt_Native
;
220 alpha_shift
= pixfmt
->Ashift
;
221 red_shift
= pixfmt
->Rshift
;
222 green_shift
= pixfmt
->Gshift
;
223 blue_shift
= pixfmt
->Bshift
;
226 D(bug("[sdl] selected pixel format %d\n", stdpixfmt
));
229 aHidd_PixFmt_ColorModel
, vHidd_ColorModel_TrueColor
,
230 aHidd_PixFmt_RedShift
, red_shift
,
231 aHidd_PixFmt_GreenShift
, green_shift
,
232 aHidd_PixFmt_BlueShift
, blue_shift
,
233 aHidd_PixFmt_AlphaShift
, alpha_shift
,
234 aHidd_PixFmt_RedMask
, pixfmt
->Rmask
,
235 aHidd_PixFmt_GreenMask
, pixfmt
->Gmask
,
236 aHidd_PixFmt_BlueMask
, pixfmt
->Bmask
,
237 aHidd_PixFmt_AlphaMask
, pixfmt
->Amask
,
238 aHidd_PixFmt_Depth
, pixfmt
->BitsPerPixel
,
239 aHidd_PixFmt_BitsPerPixel
, pixfmt
->BitsPerPixel
,
240 aHidd_PixFmt_BytesPerPixel
, pixfmt
->BytesPerPixel
,
241 aHidd_PixFmt_StdPixFmt
, stdpixfmt
,
242 aHidd_PixFmt_BitMapType
, vHidd_BitMapType_Chunky
246 LIBBASE
->use_fullscreen
= CFG_WANT_FULLSCREEN
? TRUE
: FALSE
;
248 modes
= S(SDL_ListModes
, NULL
, surftype
| LIBBASE
->use_fullscreen
? SDL_FULLSCREEN
: 0);
250 D(bug("[sdl] available modes:"));
256 if (modes
== (SDL_Rect
**) -1) {
257 D(bug(" (default)"));
258 modes
= default_modes
;
260 for (nmodes
= 0; modes
[nmodes
] != NULL
&& modes
[nmodes
]->w
!= 0; nmodes
++)
261 D(bug(" %dx%d", modes
[nmodes
]->w
, modes
[nmodes
]->h
));
265 D(bug("[sdl] building %d mode sync items\n", nmodes
));
267 tagpool
= CreatePool(MEMF_CLEAR
, 1024, 128);
269 synctags
= AllocPooled(tagpool
, sizeof(struct TagItem
*) * (nmodes
+1));
271 for (i
= 0; i
< nmodes
; i
++) {
272 /* remove modes larger than the current screen res */
273 if (modes
[i
]->w
> info
->current_w
|| modes
[i
]->h
> info
->current_h
) {
278 desc
= AllocPooled(tagpool
, 16);
279 sprintf(desc
, "SDL:%dx%d", modes
[i
]->w
, modes
[i
]->h
);
281 synctags
[i
] = AllocPooled(tagpool
, sizeof(struct TagItem
) * 4);
282 synctags
[i
][0].ti_Tag
= aHidd_Sync_HDisp
; synctags
[i
][0].ti_Data
= modes
[i
]->w
;
283 synctags
[i
][1].ti_Tag
= aHidd_Sync_VDisp
; synctags
[i
][1].ti_Data
= modes
[i
]->h
;
284 synctags
[i
][2].ti_Tag
= aHidd_Sync_Description
; synctags
[i
][2].ti_Data
= (IPTR
) desc
;
285 synctags
[i
][3].ti_Tag
= TAG_DONE
;
288 modetags
= AllocPooled(tagpool
, sizeof(struct TagItem
) * (nmodes
+9));
290 modetags
[0].ti_Tag
= aHidd_Gfx_PixFmtTags
; modetags
[0].ti_Data
= (IPTR
) pftags
;
291 modetags
[1].ti_Tag
= aHidd_Sync_PixelClock
; modetags
[1].ti_Data
= 100000000;
292 modetags
[2].ti_Tag
= aHidd_Sync_LeftMargin
; modetags
[2].ti_Data
= 0;
293 modetags
[3].ti_Tag
= aHidd_Sync_RightMargin
; modetags
[3].ti_Data
= 0;
294 modetags
[4].ti_Tag
= aHidd_Sync_UpperMargin
; modetags
[4].ti_Data
= 0;
295 modetags
[5].ti_Tag
= aHidd_Sync_LowerMargin
; modetags
[5].ti_Data
= 0;
296 modetags
[6].ti_Tag
= aHidd_Sync_HSyncLength
; modetags
[6].ti_Data
= 0;
297 modetags
[7].ti_Tag
= aHidd_Sync_VSyncLength
; modetags
[7].ti_Data
= 0;
299 for (i
= 0; i
< nmodes
; i
++) {
300 if (synctags
[i
] == NULL
) {
301 modetags
[8+i
].ti_Tag
= TAG_IGNORE
;
305 modetags
[8+i
].ti_Tag
= aHidd_Gfx_SyncTags
;
306 modetags
[8+i
].ti_Data
= (IPTR
) synctags
[i
];
309 modetags
[8+i
].ti_Tag
= TAG_DONE
;
312 aHidd_Gfx_ModeTags
, (IPTR
) modetags
,
313 TAG_MORE
, (IPTR
) msg
->attrList
316 supermsg
.mID
= msg
->mID
;
317 supermsg
.attrList
= msgtags
;
319 D(bug("[sdl] hidd tags built, calling supermethod\n"));
321 o
= (OOP_Object
*) OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) &supermsg
);
326 D(bug("[sdl] supermethod failed, bailing out\n"));
330 return (OOP_Object
*) o
;
333 VOID
SDLGfx__Root__Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
) {
336 D(bug("[sdl] SDLGfx::Dispose\n"));
338 s
= S(SDL_GetVideoSurface
);
340 D(bug("[sdl] freeing existing video surface\n"));
341 SV(SDL_FreeSurface
, s
);
344 OOP_DoSuperMethod(cl
, o
, msg
);
349 OOP_Object
*SDLGfx__Hidd_Gfx__NewBitMap(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_NewBitMap
*msg
) {
350 OOP_Object
*bmclass
= NULL
, *friend, *gfxhidd
;
353 HIDDT_StdPixFmt stdpixfmt
;
354 struct TagItem
*msgtags
;
355 struct pHidd_Gfx_NewBitMap supermsg
;
357 D(bug("[sdl] SDLGfx::NewBitMap\n"));
359 if (GetTagData(aHidd_BitMap_FrameBuffer
, FALSE
, msg
->attrList
)) {
360 D(bug("[sdl] framebuffer bitmap, we can handle it\n"));
361 bmclass
= LIBBASE
->bmclass
;
364 else if (GetTagData(aHidd_BitMap_Displayable
, FALSE
, msg
->attrList
)) {
365 D(bug("[sdl] displayable bitmap, we can handle it\n"));
366 bmclass
= LIBBASE
->bmclass
;
369 else if ((HIDDT_ModeID
) GetTagData(aHidd_BitMap_ModeID
, vHidd_ModeID_Invalid
, msg
->attrList
) != vHidd_ModeID_Invalid
) {
370 D(bug("[sdl] bitmap with valid mode, we can handle it\n"));
371 bmclass
= LIBBASE
->bmclass
;
374 else if ((HIDDT_StdPixFmt
) GetTagData(aHidd_BitMap_StdPixFmt
, vHidd_StdPixFmt_Unknown
, msg
->attrList
) == vHidd_StdPixFmt_Unknown
) {
375 friend = (OOP_Object
*) GetTagData(aHidd_BitMap_Friend
, NULL
, msg
->attrList
);
376 if (friend != NULL
) {
377 OOP_GetAttr(friend, aHidd_BitMap_GfxHidd
, (APTR
) &gfxhidd
);
379 D(bug("[sdl] bitmap with unknown pixel format and sdl friend bitmap, we can handle it\n"));
380 bmclass
= LIBBASE
->bmclass
;
387 aHidd_BitMap_ClassPtr
, (IPTR
) LIBBASE
->bmclass
,
388 TAG_MORE
, (IPTR
) msg
->attrList
392 msgtags
= msg
->attrList
;
394 supermsg
.mID
= msg
->mID
;
395 supermsg
.attrList
= msgtags
;
397 o
= (OOP_Object
*) OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) &supermsg
);
402 VOID
SDLGfx__Hidd_Gfx__CopyBox(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CopyBox
*msg
) {
403 struct SDL_Surface
*src
, *dest
;
404 struct SDL_Rect srect
, drect
;
407 D(bug("[sdl] SDLGfx::CopyBox\n"));
409 OOP_GetAttr(msg
->src
, aHidd_SDLBitMap_Surface
, &src
);
410 OOP_GetAttr(msg
->dest
, aHidd_SDLBitMap_Surface
, &dest
);
412 if (src
== NULL
|| dest
== NULL
) {
413 D(bug("[sdl] missing a surface: src is 0x%08x, dest is 0x%08x. letting the superclass deal with it\n", src
, dest
));
415 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
422 srect
.w
= msg
->width
;
423 srect
.h
= msg
->height
;
425 drect
.x
= msg
->destX
;
426 drect
.y
= msg
->destY
;
428 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
));
430 S(SDL_BlitSurface
, src
, &srect
, dest
, &drect
);
432 OOP_GetAttr(msg
->dest
, aHidd_SDLBitMap_IsOnScreen
, &is_onscreen
);
434 D(bug("[sdl] refreshing onscreen surface 0x%08x\n", dest
));
436 SV(SDL_UpdateRect
, dest
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
);