src/video/haiku/SDL_bmodes.cc
author Sam Lantinga <slouken@libsdl.org>
Fri, 09 Dec 2016 01:47:43 -0800
changeset 10690 23a825f341e6
parent 9998 f67cf37e9cd4
child 10737 3406a0f8b041
permissions -rw-r--r--
Fixed bug 3513 - SDL_GL_SwapWindow does not return error status

Return an error code from SDL_GL_SwapWindow(), like the other SDL APIs.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2016 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
    37 extern "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 */
    46 typedef struct SDL_DisplayModeData {
    47 	display_mode *bmode;
    48 };
    49 #endif
    50 
    51 static SDL_INLINE SDL_BWin *_ToBeWin(SDL_Window *window) {
    52 	return ((SDL_BWin*)(window->driverdata));
    53 }
    54 
    55 static SDL_INLINE SDL_BApp *_GetBeApp() {
    56 	return ((SDL_BApp*)be_app);
    57 }
    58 
    59 static 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 */
    68 static 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  */
    78 void _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 
   135 int32 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 
   166 int32 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 
   194 static 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 */
   218 static 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 
   238 int 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 
   247 int BE_QuitModes(_THIS) {
   248 	/* FIXME: Nothing really needs to be done here at the moment? */
   249 	return 0;
   250 }
   251 
   252 
   253 int 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 
   263 void 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 
   288 int 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 */
   332 
   333 /* vi: set ts=4 sw=4 expandtab: */