SDL_bmodes.cc (8243B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../../SDL_internal.h" 22 23#if SDL_VIDEO_DRIVER_HAIKU 24 25#include <AppKit.h> 26#include <InterfaceKit.h> 27#include "SDL_bmodes.h" 28#include "SDL_BWin.h" 29 30#if SDL_VIDEO_OPENGL 31#include "SDL_bopengl.h" 32#endif 33 34#include "../../main/haiku/SDL_BApp.h" 35 36#ifdef __cplusplus 37extern "C" { 38#endif 39 40 41#define WRAP_BMODE 1 /* FIXME: Some debate as to whether this is necessary */ 42 43#if WRAP_BMODE 44/* This wrapper is here so that the driverdata can be freed without freeing 45 the display_mode structure */ 46typedef struct SDL_DisplayModeData { 47 display_mode *bmode; 48}; 49#endif 50 51static SDL_INLINE SDL_BWin *_ToBeWin(SDL_Window *window) { 52 return ((SDL_BWin*)(window->driverdata)); 53} 54 55static SDL_INLINE SDL_BApp *_GetBeApp() { 56 return ((SDL_BApp*)be_app); 57} 58 59static SDL_INLINE display_mode * _ExtractBMode(SDL_DisplayMode *mode) { 60#if WRAP_BMODE 61 return ((SDL_DisplayModeData*)mode->driverdata)->bmode; 62#else 63 return (display_mode*)(mode->driverdata); 64#endif 65} 66 67/* Copied from haiku/trunk/src/preferences/screen/ScreenMode.cpp */ 68static float get_refresh_rate(display_mode &mode) { 69 return float(mode.timing.pixel_clock * 1000) 70 / float(mode.timing.h_total * mode.timing.v_total); 71} 72 73 74#if 0 75/* TODO: 76 * This is a useful debugging tool. Uncomment and insert into code as needed. 77 */ 78void _SpoutModeData(display_mode *bmode) { 79 printf("BMode:\n"); 80 printf("\tw,h = (%i,%i)\n", bmode->virtual_width, bmode->virtual_height); 81 printf("\th,v = (%i,%i)\n", bmode->h_display_start, 82 bmode->v_display_start); 83 if(bmode->flags) { 84 printf("\tFlags:\n"); 85 if(bmode->flags & B_SCROLL) { 86 printf("\t\tB_SCROLL\n"); 87 } 88 if(bmode->flags & B_8_BIT_DAC) { 89 printf("\t\tB_8_BIT_DAC\n"); 90 } 91 if(bmode->flags & B_HARDWARE_CURSOR) { 92 printf("\t\tB_HARDWARE_CURSOR\n"); 93 } 94 if(bmode->flags & B_PARALLEL_ACCESS) { 95 printf("\t\tB_PARALLEL_ACCESS\n"); 96 } 97 if(bmode->flags & B_DPMS) { 98 printf("\t\tB_DPMS\n"); 99 } 100 if(bmode->flags & B_IO_FB_NA) { 101 printf("\t\tB_IO_FB_NA\n"); 102 } 103 } 104 printf("\tTiming:\n"); 105 printf("\t\tpx clock: %i\n", bmode->timing.pixel_clock); 106 printf("\t\th - display: %i sync start: %i sync end: %i total: %i\n", 107 bmode->timing.h_display, bmode->timing.h_sync_start, 108 bmode->timing.h_sync_end, bmode->timing.h_total); 109 printf("\t\tv - display: %i sync start: %i sync end: %i total: %i\n", 110 bmode->timing.v_display, bmode->timing.v_sync_start, 111 bmode->timing.v_sync_end, bmode->timing.v_total); 112 if(bmode->timing.flags) { 113 printf("\t\tFlags:\n"); 114 if(bmode->timing.flags & B_BLANK_PEDESTAL) { 115 printf("\t\t\tB_BLANK_PEDESTAL\n"); 116 } 117 if(bmode->timing.flags & B_TIMING_INTERLACED) { 118 printf("\t\t\tB_TIMING_INTERLACED\n"); 119 } 120 if(bmode->timing.flags & B_POSITIVE_HSYNC) { 121 printf("\t\t\tB_POSITIVE_HSYNC\n"); 122 } 123 if(bmode->timing.flags & B_POSITIVE_VSYNC) { 124 printf("\t\t\tB_POSITIVE_VSYNC\n"); 125 } 126 if(bmode->timing.flags & B_SYNC_ON_GREEN) { 127 printf("\t\t\tB_SYNC_ON_GREEN\n"); 128 } 129 } 130} 131#endif 132 133 134 135int32 BE_ColorSpaceToBitsPerPixel(uint32 colorspace) 136{ 137 int bitsperpixel; 138 139 bitsperpixel = 0; 140 switch (colorspace) { 141 case B_CMAP8: 142 bitsperpixel = 8; 143 break; 144 case B_RGB15: 145 case B_RGBA15: 146 case B_RGB15_BIG: 147 case B_RGBA15_BIG: 148 bitsperpixel = 15; 149 break; 150 case B_RGB16: 151 case B_RGB16_BIG: 152 bitsperpixel = 16; 153 break; 154 case B_RGB32: 155 case B_RGBA32: 156 case B_RGB32_BIG: 157 case B_RGBA32_BIG: 158 bitsperpixel = 32; 159 break; 160 default: 161 break; 162 } 163 return(bitsperpixel); 164} 165 166int32 BE_BPPToSDLPxFormat(int32 bpp) { 167 /* Translation taken from SDL_windowsmodes.c */ 168 switch (bpp) { 169 case 32: 170 return SDL_PIXELFORMAT_RGB888; 171 break; 172 case 24: /* May not be supported by Haiku */ 173 return SDL_PIXELFORMAT_RGB24; 174 break; 175 case 16: 176 return SDL_PIXELFORMAT_RGB565; 177 break; 178 case 15: 179 return SDL_PIXELFORMAT_RGB555; 180 break; 181 case 8: 182 return SDL_PIXELFORMAT_INDEX8; 183 break; 184 case 4: /* May not be supported by Haiku */ 185 return SDL_PIXELFORMAT_INDEX4LSB; 186 break; 187 } 188 189 /* May never get here, but safer and needed to shut up compiler */ 190 SDL_SetError("Invalid bpp value"); 191 return 0; 192} 193 194static void _BDisplayModeToSdlDisplayMode(display_mode *bmode, 195 SDL_DisplayMode *mode) { 196 mode->w = bmode->virtual_width; 197 mode->h = bmode->virtual_height; 198 mode->refresh_rate = (int)get_refresh_rate(*bmode); 199 200#if WRAP_BMODE 201 SDL_DisplayModeData *data = (SDL_DisplayModeData*)SDL_calloc(1, 202 sizeof(SDL_DisplayModeData)); 203 data->bmode = bmode; 204 205 mode->driverdata = data; 206 207#else 208 209 mode->driverdata = bmode; 210#endif 211 212 /* Set the format */ 213 int32 bpp = BE_ColorSpaceToBitsPerPixel(bmode->space); 214 mode->format = BE_BPPToSDLPxFormat(bpp); 215} 216 217/* Later, there may be more than one monitor available */ 218static void _AddDisplay(BScreen *screen) { 219 SDL_VideoDisplay display; 220 SDL_DisplayMode *mode = (SDL_DisplayMode*)SDL_calloc(1, 221 sizeof(SDL_DisplayMode)); 222 display_mode *bmode = (display_mode*)SDL_calloc(1, sizeof(display_mode)); 223 screen->GetMode(bmode); 224 225 _BDisplayModeToSdlDisplayMode(bmode, mode); 226 227 SDL_zero(display); 228 display.desktop_mode = *mode; 229 display.current_mode = *mode; 230 231 SDL_AddVideoDisplay(&display); 232} 233 234/* 235 * Functions called by SDL 236 */ 237 238int BE_InitModes(_THIS) { 239 BScreen screen; 240 241 /* TODO: When Haiku supports multiple display screens, call 242 _AddDisplayScreen() for each of them. */ 243 _AddDisplay(&screen); 244 return 0; 245} 246 247int BE_QuitModes(_THIS) { 248 /* FIXME: Nothing really needs to be done here at the moment? */ 249 return 0; 250} 251 252 253int BE_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect) { 254 BScreen bscreen; 255 BRect rc = bscreen.Frame(); 256 rect->x = (int)rc.left; 257 rect->y = (int)rc.top; 258 rect->w = (int)rc.Width() + 1; 259 rect->h = (int)rc.Height() + 1; 260 return 0; 261} 262 263void BE_GetDisplayModes(_THIS, SDL_VideoDisplay *display) { 264 /* Get the current screen */ 265 BScreen bscreen; 266 267 /* Iterate through all of the modes */ 268 SDL_DisplayMode mode; 269 display_mode this_bmode; 270 display_mode *bmodes; 271 uint32 count, i; 272 273 /* Get graphics-hardware supported modes */ 274 bscreen.GetModeList(&bmodes, &count); 275 bscreen.GetMode(&this_bmode); 276 277 for(i = 0; i < count; ++i) { 278 // FIXME: Apparently there are errors with colorspace changes 279 if (bmodes[i].space == this_bmode.space) { 280 _BDisplayModeToSdlDisplayMode(&bmodes[i], &mode); 281 SDL_AddDisplayMode(display, &mode); 282 } 283 } 284 free(bmodes); 285} 286 287 288int BE_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode){ 289 /* Get the current screen */ 290 BScreen bscreen; 291 if(!bscreen.IsValid()) { 292 printf(__FILE__": %d - ERROR: BAD SCREEN\n", __LINE__); 293 } 294 295 /* Set the mode using the driver data */ 296 display_mode *bmode = _ExtractBMode(mode); 297 298 299 /* FIXME: Is the first option always going to be the right one? */ 300 uint32 c = 0, i; 301 display_mode *bmode_list; 302 bscreen.GetModeList(&bmode_list, &c); 303 for(i = 0; i < c; ++i) { 304 if( bmode_list[i].space == bmode->space && 305 bmode_list[i].virtual_width == bmode->virtual_width && 306 bmode_list[i].virtual_height == bmode->virtual_height ) { 307 bmode = &bmode_list[i]; 308 break; 309 } 310 } 311 312 if(bscreen.SetMode(bmode) != B_OK) { 313 return SDL_SetError("Bad video mode\n"); 314 } 315 316 free(bmode_list); 317 318#if SDL_VIDEO_OPENGL 319 /* FIXME: Is there some way to reboot the OpenGL context? This doesn't 320 help */ 321// BE_GL_RebootContexts(_this); 322#endif 323 324 return 0; 325} 326 327#ifdef __cplusplus 328} 329#endif 330 331#endif /* SDL_VIDEO_DRIVER_HAIKU */