only bring in as many sdl things as are strictly necessary
[tangerine.git] / arch / all-hosted / hidd / sdl / gfxclass.c
blob89404c906d8b4b8b66fde82bd7a77e859943fe0b
1 /*
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.
7 */
9 #define __OOP_NOATTRBASES__
11 #include <aros/symbolsets.h>
13 #include <hidd/hidd.h>
14 #include <hidd/graphics.h>
15 #include <utility/tagitem.h>
16 #include <oop/oop.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
27 #define DEBUG 0
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 },
42 { NULL, NULL }
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);
55 return TRUE;
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[] = {
71 &mode_1600_1200,
72 &mode_1280_1024,
73 &mode_1280_960,
74 &mode_1152_864,
75 &mode_1024_768,
76 &mode_800_600,
77 NULL
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] = "";
84 Uint32 surftype;
85 SDL_Rect **modes;
86 struct TagItem *pftags;
87 int nmodes, i;
88 APTR tagpool;
89 struct TagItem **synctags, *modetags, *msgtags;
90 char *desc;
91 struct pRoot_New supermsg;
93 S(SDL_VideoDriverName, driver, sizeof(driver));
94 info = S(SDL_GetVideoInfo);
95 pixfmt = info->vfmt;
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 */
115 else {
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;
124 alpha_shift = 24;
125 red_shift = 16;
126 green_shift = 8;
127 blue_shift = 0;
130 else if (pixfmt->Amask == 0xff000000 && pixfmt->Rmask == 0x00ff0000 &&
131 pixfmt->Gmask == 0x0000ff00 && pixfmt->Bmask == 0x000000ff) {
132 stdpixfmt = vHidd_StdPixFmt_BGRA32;
133 alpha_shift = 0;
134 red_shift = 8;
135 green_shift = 16;
136 blue_shift = 24;
139 else if (pixfmt->Amask == 0xff000000 && pixfmt->Rmask == 0x000000ff &&
140 pixfmt->Gmask == 0x0000ff00 && pixfmt->Bmask == 0x00ff0000) {
141 stdpixfmt = vHidd_StdPixFmt_RGBA32;
142 alpha_shift = 0;
143 red_shift = 24;
144 green_shift = 16;
145 blue_shift = 8;
148 else if (pixfmt->Amask == 0x000000ff && pixfmt->Rmask == 0xff000000 &&
149 pixfmt->Gmask == 0x00ff0000 && pixfmt->Bmask == 0x0000ff00) {
150 stdpixfmt = vHidd_StdPixFmt_ABGR32;
151 alpha_shift = 24;
152 red_shift = 0;
153 green_shift = 8;
154 blue_shift = 16;
157 else if (pixfmt->Amask == 0x00000000 && pixfmt->Rmask == 0x0000ff00 &&
158 pixfmt->Gmask == 0x00ff0000 && pixfmt->Bmask == 0xff000000) {
159 stdpixfmt = vHidd_StdPixFmt_0RGB32;
160 alpha_shift = 0;
161 red_shift = 16;
162 green_shift = 8;
163 blue_shift = 0;
166 else if (pixfmt->Amask == 0x00000000 && pixfmt->Rmask == 0x00ff0000 &&
167 pixfmt->Gmask == 0x0000ff00 && pixfmt->Bmask == 0x000000ff) {
168 stdpixfmt = vHidd_StdPixFmt_BGR032;
169 alpha_shift = 0;
170 red_shift = 8;
171 green_shift = 16;
172 blue_shift = 24;
175 else if (pixfmt->Amask == 0x00000000 && pixfmt->Rmask == 0x000000ff &&
176 pixfmt->Gmask == 0x0000ff00 && pixfmt->Bmask == 0x00ff0000) {
177 stdpixfmt = vHidd_StdPixFmt_RGB032;
178 alpha_shift = 0;
179 red_shift = 24;
180 green_shift = 16;
181 blue_shift = 8;
184 else if (pixfmt->Amask == 0x00000000 && pixfmt->Rmask == 0xff000000 &&
185 pixfmt->Gmask == 0x00ff0000 && pixfmt->Bmask == 0x0000ff00) {
186 stdpixfmt = vHidd_StdPixFmt_0BGR32;
187 alpha_shift = 0;
188 red_shift = 0;
189 green_shift = 8;
190 blue_shift = 16;
194 else if (pixfmt->BitsPerPixel == 24) {
195 /* XXX implement
196 vHidd_StdPixFmt_RGB24
197 vHidd_StdPixFmt_BGR24
201 else if (pixfmt->BitsPerPixel == 16) {
202 /* XXX implement
203 vHidd_StdPixFmt_RGB16
204 vHidd_StdPixFmt_RGB16_LE
205 vHidd_StdPixFmt_BGR16
206 vHidd_StdPixFmt_BGR16_LE
210 else if (pixfmt->BitsPerPixel == 15) {
211 /* XXX implement
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));
229 pftags = TAGLIST(
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:"));
252 if (modes == NULL) {
253 D(bug(" none\n"));
254 nmodes = 0;
256 else {
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));
263 D(bug("\n"));
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) {
275 synctags[i] = NULL;
276 continue;
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;
303 continue;
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;
312 msgtags = TAGLIST(
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);
324 DeletePool(tagpool);
326 if (o == NULL) {
327 D(bug("[sdl] supermethod failed, bailing out\n"));
328 return NULL;
331 return (OOP_Object *) o;
334 VOID SDLGfx__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg) {
335 SDL_Surface *s;
337 D(bug("[sdl] SDLGfx::Dispose\n"));
339 s = S(SDL_GetVideoSurface);
340 if (s != NULL) {
341 D(bug("[sdl] freeing existing video surface\n"));
342 SV(SDL_FreeSurface, s);
345 OOP_DoSuperMethod(cl, o, msg);
347 return;
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;
352 BOOL displayable;
353 HIDDT_ModeID modeid;
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);
379 if (gfxhidd == o) {
380 D(bug("[sdl] bitmap with unknown pixel format and sdl friend bitmap, we can handle it\n"));
381 bmclass = LIBBASE->bmclass;
386 if (bmclass != NULL)
387 msgtags = TAGLIST(
388 aHidd_BitMap_ClassPtr, (IPTR) LIBBASE->bmclass,
389 TAG_MORE, (IPTR) msg->attrList
392 else
393 msgtags = msg->attrList;
395 supermsg.mID = msg->mID;
396 supermsg.attrList = msgtags;
398 o = (OOP_Object *) OOP_DoSuperMethod(cl, o, (OOP_Msg) &supermsg);
400 return o;
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;
406 BOOL is_onscreen;
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);
418 return;
421 srect.x = msg->srcX;
422 srect.y = msg->srcY;
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);
434 if (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);
440 return;