Added a test for MUIA_Listview_SelectChange.
[AROS.git] / arch / all-hosted / hidd / sdl / gfxclass.c
blob7b3ec90746017e782df20086d1f1d09c991f90dd
1 /*
2 * sdl.hidd - SDL graphics/sound/keyboard for AROS hosted
3 * Copyright (c) 2007 Robert Norris. All rights reserved.
4 * Copyright (c) 2010-2015 The AROS Development Team. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the same terms as AROS itself.
8 */
10 #include <hidd/hidd.h>
11 #include <hidd/graphics.h>
12 #include <utility/tagitem.h>
13 #include <oop/oop.h>
15 #include <proto/alib.h>
16 #include <proto/exec.h>
17 #include <proto/oop.h>
18 #include <proto/utility.h>
20 #ifdef __THROW
21 #undef __THROW
22 #endif
23 #ifdef __CONCAT
24 #undef __CONCAT
25 #endif
27 #include "sdl_intern.h"
29 #define DEBUG 0
30 #include <aros/debug.h>
32 #define LIBBASE (&xsd)
34 static const SDL_Rect mode_1600_1200 = { .w = 1600, .h = 1200 };
35 static const SDL_Rect mode_1280_1024 = { .w = 1280, .h = 1024 };
36 static const SDL_Rect mode_1280_960 = { .w = 1280, .h = 960 };
37 static const SDL_Rect mode_1152_864 = { .w = 1152, .h = 864 };
38 static const SDL_Rect mode_1024_768 = { .w = 1024, .h = 768 };
39 static const SDL_Rect mode_800_600 = { .w = 800, .h = 600 };
41 static const SDL_Rect *default_modes[] = {
42 &mode_1600_1200,
43 &mode_1280_1024,
44 &mode_1280_960,
45 &mode_1152_864,
46 &mode_1024_768,
47 &mode_800_600,
48 NULL
51 OOP_Object *SDLGfx__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg) {
52 const SDL_VideoInfo *info;
53 const SDL_PixelFormat *pixfmt;
54 #if DEBUG
55 char driver[128] = "";
56 #endif
57 Uint32 surftype;
58 const SDL_Rect **modes;
59 struct TagItem *pftags = NULL;
60 int nmodes, i;
61 APTR tagpool;
62 struct TagItem **synctags, *modetags, *msgtags;
63 struct pRoot_New supermsg;
65 #if DEBUG
66 S(SDL_VideoDriverName, driver, sizeof(driver));
67 kprintf("sdlgfx: using %s driver\n", driver);
68 #endif
69 info = SP(SDL_GetVideoInfo);
70 pixfmt = info->vfmt;
71 D(bug("[sdl] window manager: %savailable\n", info->wm_available ? "" : "not "));
72 D(bug("[sdl] hardware surfaces: %savailable\n", info->hw_available ? "" : "not "));
74 LIBBASE->use_hwsurface = info->hw_available ? TRUE : FALSE;
75 surftype = LIBBASE->use_hwsurface ? SDL_HWSURFACE : SDL_SWSURFACE;
77 D(bug("[sdl] colour model: %s\n", pixfmt->palette == NULL ? "truecolour" : "palette"));
78 if (pixfmt->palette == NULL) {
79 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));
80 D(bug("[sdl] colour shift: alpha=%d red=%d green=%d blue=%d\n", pixfmt->Ashift, pixfmt->Rshift, pixfmt->Gshift, pixfmt->Bshift, pixfmt->Ashift));
83 if (pixfmt->palette != NULL) {
84 /* XXX deal with palette (CLUT) modes */
87 else {
88 /* select an appropriate AROS pixel format based on the SDL format */
89 int stdpixfmt = vHidd_StdPixFmt_Unknown;
90 int alpha_shift, red_shift, green_shift, blue_shift;
92 if (pixfmt->BitsPerPixel == 32) {
93 if (pixfmt->Amask == 0x000000ff && pixfmt->Rmask == 0x0000ff00 &&
94 pixfmt->Gmask == 0x00ff0000 && pixfmt->Bmask == 0xff000000) {
95 stdpixfmt = vHidd_StdPixFmt_ARGB32;
96 alpha_shift = 24;
97 red_shift = 16;
98 green_shift = 8;
99 blue_shift = 0;
102 else if (pixfmt->Amask == 0xff000000 && pixfmt->Rmask == 0x00ff0000 &&
103 pixfmt->Gmask == 0x0000ff00 && pixfmt->Bmask == 0x000000ff) {
104 stdpixfmt = vHidd_StdPixFmt_BGRA32;
105 alpha_shift = 0;
106 red_shift = 8;
107 green_shift = 16;
108 blue_shift = 24;
111 else if (pixfmt->Amask == 0xff000000 && pixfmt->Rmask == 0x000000ff &&
112 pixfmt->Gmask == 0x0000ff00 && pixfmt->Bmask == 0x00ff0000) {
113 stdpixfmt = vHidd_StdPixFmt_RGBA32;
114 alpha_shift = 0;
115 red_shift = 24;
116 green_shift = 16;
117 blue_shift = 8;
120 else if (pixfmt->Amask == 0x000000ff && pixfmt->Rmask == 0xff000000 &&
121 pixfmt->Gmask == 0x00ff0000 && pixfmt->Bmask == 0x0000ff00) {
122 stdpixfmt = vHidd_StdPixFmt_ABGR32;
123 alpha_shift = 24;
124 red_shift = 0;
125 green_shift = 8;
126 blue_shift = 16;
129 else if (pixfmt->Amask == 0x00000000 && pixfmt->Rmask == 0x0000ff00 &&
130 pixfmt->Gmask == 0x00ff0000 && pixfmt->Bmask == 0xff000000) {
131 stdpixfmt = vHidd_StdPixFmt_0RGB32;
132 alpha_shift = 0;
133 red_shift = 16;
134 green_shift = 8;
135 blue_shift = 0;
138 else if (pixfmt->Amask == 0x00000000 && pixfmt->Rmask == 0x00ff0000 &&
139 pixfmt->Gmask == 0x0000ff00 && pixfmt->Bmask == 0x000000ff) {
140 stdpixfmt = vHidd_StdPixFmt_BGR032;
141 alpha_shift = 0;
142 red_shift = 8;
143 green_shift = 16;
144 blue_shift = 24;
147 else if (pixfmt->Amask == 0x00000000 && pixfmt->Rmask == 0x000000ff &&
148 pixfmt->Gmask == 0x0000ff00 && pixfmt->Bmask == 0x00ff0000) {
149 stdpixfmt = vHidd_StdPixFmt_RGB032;
150 alpha_shift = 0;
151 red_shift = 24;
152 green_shift = 16;
153 blue_shift = 8;
156 else if (pixfmt->Amask == 0x00000000 && pixfmt->Rmask == 0xff000000 &&
157 pixfmt->Gmask == 0x00ff0000 && pixfmt->Bmask == 0x0000ff00) {
158 stdpixfmt = vHidd_StdPixFmt_0BGR32;
159 alpha_shift = 0;
160 red_shift = 0;
161 green_shift = 8;
162 blue_shift = 16;
166 else if (pixfmt->BitsPerPixel == 24) {
167 /* XXX implement
168 vHidd_StdPixFmt_RGB24
169 vHidd_StdPixFmt_BGR24
173 else if (pixfmt->BitsPerPixel == 16) {
174 /* XXX implement
175 vHidd_StdPixFmt_RGB16
176 vHidd_StdPixFmt_RGB16_LE
177 vHidd_StdPixFmt_BGR16
178 vHidd_StdPixFmt_BGR16_LE
182 else if (pixfmt->BitsPerPixel == 15) {
183 /* XXX implement
184 vHidd_StdPixFmt_RGB15,
185 vHidd_StdPixFmt_RGB15_LE,
186 vHidd_StdPixFmt_BGR15,
187 vHidd_StdPixFmt_BGR15_LE,
191 if (stdpixfmt == vHidd_StdPixFmt_Unknown) {
192 stdpixfmt = vHidd_StdPixFmt_Native;
193 alpha_shift = pixfmt->Ashift;
194 red_shift = pixfmt->Rshift;
195 green_shift = pixfmt->Gshift;
196 blue_shift = pixfmt->Bshift;
199 D(bug("[sdl] selected pixel format %d\n", stdpixfmt));
201 pftags = TAGLIST(
202 aHidd_PixFmt_ColorModel, vHidd_ColorModel_TrueColor,
203 aHidd_PixFmt_RedShift, red_shift,
204 aHidd_PixFmt_GreenShift, green_shift,
205 aHidd_PixFmt_BlueShift, blue_shift,
206 aHidd_PixFmt_AlphaShift, alpha_shift,
207 aHidd_PixFmt_RedMask, pixfmt->Rmask,
208 aHidd_PixFmt_GreenMask, pixfmt->Gmask,
209 aHidd_PixFmt_BlueMask, pixfmt->Bmask,
210 aHidd_PixFmt_AlphaMask, pixfmt->Amask,
211 aHidd_PixFmt_Depth, pixfmt->BitsPerPixel,
212 aHidd_PixFmt_BitsPerPixel, pixfmt->BitsPerPixel,
213 aHidd_PixFmt_BytesPerPixel, pixfmt->BytesPerPixel,
214 aHidd_PixFmt_StdPixFmt, stdpixfmt,
215 aHidd_PixFmt_BitMapType, vHidd_BitMapType_Chunky
219 modes = SP(SDL_ListModes, NULL, surftype | LIBBASE->use_fullscreen ? SDL_FULLSCREEN : 0);
220 D(bug("[sdl] available modes:"));
221 if (modes == NULL) {
222 D(bug(" none\n"));
223 nmodes = 0;
225 else {
226 if (modes == (const SDL_Rect **) -1) {
227 D(bug(" (default)"));
228 modes = default_modes;
230 for (nmodes = 0; modes[nmodes] != NULL && modes[nmodes]->w != 0; nmodes++)
231 D(bug(" %dx%d", modes[nmodes]->w, modes[nmodes]->h));
232 D(bug("\n"));
235 D(bug("[sdl] building %d mode sync items\n", nmodes));
237 tagpool = CreatePool(MEMF_CLEAR, 1024, 128);
239 synctags = AllocPooled(tagpool, sizeof(struct TagItem *) * (nmodes+1));
241 for (i = 0; i < nmodes; i++) {
242 /* remove modes larger than the current screen res */
243 if (modes[i]->w > info->current_w || modes[i]->h > info->current_h) {
244 synctags[i] = NULL;
245 continue;
248 synctags[i] = AllocPooled(tagpool, sizeof(struct TagItem) * 4);
249 synctags[i][0].ti_Tag = aHidd_Sync_HDisp; synctags[i][0].ti_Data = modes[i]->w;
250 synctags[i][1].ti_Tag = aHidd_Sync_VDisp; synctags[i][1].ti_Data = modes[i]->h;
251 synctags[i][2].ti_Tag = aHidd_Sync_Description; synctags[i][2].ti_Data = (IPTR)"SDL:%hx%v";
252 synctags[i][3].ti_Tag = TAG_DONE;
255 modetags = AllocPooled(tagpool, sizeof(struct TagItem) * (nmodes+2));
257 modetags[0].ti_Tag = aHidd_Gfx_PixFmtTags; modetags[0].ti_Data = (IPTR) pftags;
259 for (i = 0; i < nmodes; i++) {
260 if (synctags[i] == NULL) {
261 modetags[1+i].ti_Tag = TAG_IGNORE;
262 continue;
265 modetags[1+i].ti_Tag = aHidd_Gfx_SyncTags;
266 modetags[1+i].ti_Data = (IPTR) synctags[i];
269 modetags[1+i].ti_Tag = TAG_DONE;
271 msgtags = TAGLIST(
272 aHidd_Gfx_ModeTags, (IPTR)modetags,
273 aHidd_Name , (IPTR)"sdl.monitor",
274 aHidd_HardwareName, (IPTR)"Simple DirectMedia Layer",
275 aHidd_ProducerName, (IPTR)"SDL development team (http://libsdl.org/credits.php)",
276 TAG_MORE , (IPTR)msg->attrList
279 supermsg.mID = msg->mID;
280 supermsg.attrList = msgtags;
282 D(bug("[sdl] hidd tags built, calling supermethod\n"));
284 o = (OOP_Object *) OOP_DoSuperMethod(cl, o, (OOP_Msg) &supermsg);
286 DeletePool(tagpool);
288 if (o == NULL) {
289 D(bug("[sdl] supermethod failed, bailing out\n"));
290 return NULL;
293 return (OOP_Object *) o;
296 VOID SDLGfx__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg) {
297 SDL_Surface *s;
299 D(bug("[sdl] SDLGfx::Dispose\n"));
301 s = SP(SDL_GetVideoSurface);
302 if (s != NULL) {
303 D(bug("[sdl] freeing existing video surface\n"));
304 SV(SDL_FreeSurface, s);
307 OOP_DoSuperMethod(cl, o, msg);
309 return;
312 VOID SDLGfx__Root__Get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
314 ULONG idx;
316 if (IS_GFX_ATTR(msg->attrID, idx))
318 switch (idx)
320 case aoHidd_Gfx_IsWindowed:
321 *msg->storage = TRUE;
322 return;
324 case aoHidd_Gfx_DriverName:
325 *msg->storage = (IPTR)"SDL";
326 return;
329 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
332 VOID SDLGfx__Root__Set(OOP_Class *cl, OOP_Object *obj, struct pRoot_Set *msg)
334 struct TagItem *tag, *tstate;
335 ULONG idx;
337 tstate = msg->attrList;
338 while((tag = NextTagItem(&tstate)))
340 if (IS_GFX_ATTR(tag->ti_Tag, idx)) {
341 switch(idx)
343 case aoHidd_Gfx_ActiveCallBack:
344 xsd.cb = (void *)tag->ti_Data;
345 break;
347 case aoHidd_Gfx_ActiveCallBackData:
348 xsd.cbdata = (void *)tag->ti_Data;
349 break;
353 OOP_DoSuperMethod(cl, obj, (OOP_Msg)msg);
356 OOP_Object *SDLGfx__Hidd_Gfx__CreateObject(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CreateObject *msg) {
357 OOP_Object *object = NULL;
359 if (msg->cl == LIBBASE->basebm)
361 struct TagItem *msgtags;
362 struct pHidd_Gfx_CreateObject supermsg;
363 struct gfxdata *data = OOP_INST_DATA(cl, o);
365 D(bug("[sdl] SDLGfx::CreateObject, UtilityBase is 0x%p\n", UtilityBase));
367 if (GetTagData(aHidd_BitMap_ModeID, vHidd_ModeID_Invalid, msg->attrList) != vHidd_ModeID_Invalid) {
368 D(bug("[sdl] bitmap with valid mode, we can handle it\n"));
370 msgtags = TAGLIST(
371 aHidd_BitMap_ClassPtr, (IPTR) LIBBASE->bmclass,
372 TAG_MORE, (IPTR) msg->attrList
374 D(bug("[sdl] ClassPtr is 0x%p\n", LIBBASE->bmclass));
375 } else
376 msgtags = msg->attrList;
378 supermsg.mID = msg->mID;
379 supermsg.cl = msg->cl;
380 supermsg.attrList = msgtags;
382 D(bug("[sdl] Calling DoSuperMethod()\n"));
383 object = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) &supermsg);
385 if (GetTagData(aHidd_BitMap_FrameBuffer, FALSE, msg->attrList))
386 data->framebuffer = object;
388 D(bug("[sdl] Created bitmap 0x%p\n", object));
390 else
391 object = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
393 return object;
396 VOID SDLGfx__Hidd_Gfx__CopyBox(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CopyBox *msg) {
397 struct SDL_Surface *src = NULL;
398 struct SDL_Surface *dest = NULL;
399 struct SDL_Rect srect, drect;
401 D(bug("[sdl] SDLGfx::CopyBox\n"));
403 OOP_GetAttr(msg->src, aHidd_SDLBitMap_Surface, (IPTR *)&src);
404 OOP_GetAttr(msg->dest, aHidd_SDLBitMap_Surface, (IPTR *)&dest);
406 if (src == NULL || dest == NULL) {
407 D(bug("[sdl] missing a surface: src is 0x%08x, dest is 0x%08x. letting the superclass deal with it\n", src, dest));
409 OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
411 return;
414 srect.x = msg->srcX;
415 srect.y = msg->srcY;
416 srect.w = msg->width;
417 srect.h = msg->height;
419 drect.x = msg->destX;
420 drect.y = msg->destY;
422 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));
424 S(SDL_BlitSurface, src, &srect, dest, &drect);
426 return;
429 OOP_Object *SDLGfx__Hidd_Gfx__Show(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Show *msg)
431 struct gfxdata *data = OOP_INST_DATA(cl, o);
432 struct pHidd_Gfx_Show mymsg = {msg->mID, msg->bitMap, 0};
433 IPTR width, height;
435 /* Resetting SDL onscreen surface will destroy its old contents.
436 Copy back old bitmap data if there's one and if asked to do so */
437 if (data->shownbm && (msg->flags & fHidd_Gfx_Show_CopyBack)) {
438 OOP_Object *colmap;
439 IPTR numentries, i;
441 OOP_GetAttr(data->framebuffer, aHidd_BitMap_Width, &width);
442 OOP_GetAttr(data->framebuffer, aHidd_BitMap_Height, &height);
444 OOP_GetAttr(data->framebuffer, aHidd_BitMap_ColorMap, (IPTR *)&colmap);
445 OOP_GetAttr(colmap, aHidd_ColorMap_NumEntries, &numentries);
447 /* We need also to copy colormap (palette) */
448 for (i = 0; i < numentries; i ++) {
449 HIDDT_Color col;
451 HIDD_CM_GetColor(colmap, i, &col);
452 HIDD_BM_SetColors(data->shownbm, &col, i, 1);
455 /* Our CopyBox() happily ignores the GC, so set it to NULL and don't bother */
456 HIDD_Gfx_CopyBox(o, data->framebuffer, 0, 0, data->shownbm, 0, 0, width, height, NULL);
459 /* Set up new onscreen surface if there's a new bitmap to show.
460 This will change resolution */
461 if (msg->bitMap) {
462 HIDDT_ModeID modeid = vHidd_ModeID_Invalid;
463 IPTR depth;
464 OOP_Object *sync, *pixfmt;
465 SDL_Surface *s;
466 struct TagItem bmtags[] = {
467 {aHidd_SDLBitMap_Surface, 0},
468 {aHidd_BitMap_Width , 0},
469 {aHidd_BitMap_Height , 0},
470 {aHidd_BitMap_PixFmt , 0},
471 {TAG_DONE , 0}
474 /* Ask ModeID from our bitmap */
475 OOP_GetAttr(msg->bitMap, aHidd_BitMap_ModeID, &modeid);
476 if (modeid == vHidd_ModeID_Invalid)
477 return NULL;
479 HIDD_Gfx_GetMode(o, modeid, &sync, &pixfmt);
480 OOP_GetAttr(sync, aHidd_Sync_HDisp, &width);
481 OOP_GetAttr(sync, aHidd_Sync_VDisp, &height);
482 OOP_GetAttr(pixfmt, aHidd_PixFmt_Depth, &depth);
484 /* Set up new onscreen surface */
485 s = SP(SDL_SetVideoMode, width, height, depth,
486 (LIBBASE->use_hwsurface ? SDL_HWSURFACE | SDL_HWPALETTE : SDL_SWSURFACE) |
487 (LIBBASE->use_fullscreen ? SDL_FULLSCREEN : 0) |
488 SDL_ANYFORMAT);
489 if (!s)
490 return NULL;
492 /* Tell new parameters to the framebuffer object */
493 bmtags[0].ti_Data = (IPTR)s;
494 bmtags[1].ti_Data = width;
495 bmtags[2].ti_Data = height;
496 bmtags[3].ti_Data = (IPTR)pixfmt;
497 OOP_SetAttrs(data->framebuffer, bmtags);
500 data->shownbm = msg->bitMap;
502 /* Framebuffer contents has been destroyed, so call superclass without fHidd_Gfx_Show_CopyBack */
503 return (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)&mymsg);
506 static struct OOP_MethodDescr SDLGfx_Root_descr[] = {
507 {(OOP_MethodFunc)SDLGfx__Root__New , moRoot_New },
508 {(OOP_MethodFunc)SDLGfx__Root__Dispose, moRoot_Dispose},
509 {(OOP_MethodFunc)SDLGfx__Root__Get , moRoot_Get },
510 {(OOP_MethodFunc)SDLGfx__Root__Set , moRoot_Set },
511 {NULL , 0 }
513 #define NUM_SDLGfx_Root_METHODS 4
515 static struct OOP_MethodDescr SDLGfx_Hidd_Gfx_descr[] = {
516 {(OOP_MethodFunc)SDLGfx__Hidd_Gfx__CreateObject, moHidd_Gfx_CreateObject},
517 {(OOP_MethodFunc)SDLGfx__Hidd_Gfx__Show, moHidd_Gfx_Show},
518 {(OOP_MethodFunc)SDLGfx__Hidd_Gfx__CopyBox, moHidd_Gfx_CopyBox},
519 {NULL, 0}
521 #define NUM_SDLGfx_Hidd_Gfx_METHODS 3
523 struct OOP_InterfaceDescr SDLGfx_ifdescr[] = {
524 {SDLGfx_Root_descr , IID_Root , NUM_SDLGfx_Root_METHODS },
525 {SDLGfx_Hidd_Gfx_descr, IID_Hidd_Gfx, NUM_SDLGfx_Hidd_Gfx_METHODS},
526 {NULL , NULL }