src/video/bwindow/SDL_bmodes.cc
author Nathan Heisey <nathanheisey@gmail.com>
Mon, 25 Jul 2011 16:46:55 +0000
changeset 5925 262ce29aabf6
parent 5924 5fb68068019d
child 5926 d9d57de9fb4e
permissions -rw-r--r--
Variable name/debugging output changes
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2011 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 
    22 
    23 
    24 #include <AppKit.h>
    25 #include <InterfaceKit.h>
    26 #include "SDL_bmodes.h"
    27 #include "SDL_BWin.h"
    28 
    29 #include "../../main/beos/SDL_BApp.h"
    30 
    31 #ifdef __cplusplus
    32 extern "C" {
    33 #endif
    34 
    35 static inline SDL_BWin *_ToBeWin(SDL_Window *window) {
    36 	return ((SDL_BWin*)(window->driverdata));
    37 }
    38 
    39 static inline SDL_BApp *_GetBeApp() {
    40 	return ((SDL_BApp*)be_app);
    41 }
    42 
    43 
    44 /* Copied from haiku/trunk/src/preferences/screen/ScreenMode.cpp */
    45 static float get_refresh_rate(display_mode &mode) {
    46 	return float(mode.timing.pixel_clock * 1000)
    47 		/ float(mode.timing.h_total * mode.timing.v_total);
    48 }
    49 
    50 static inline int ColorSpaceToBitsPerPixel(uint32 colorspace)
    51 {
    52 	int bitsperpixel;
    53 
    54 	bitsperpixel = 0;
    55 	switch (colorspace) {
    56 	    case B_CMAP8:
    57 		bitsperpixel = 8;
    58 		break;
    59 	    case B_RGB15:
    60 	    case B_RGBA15:
    61 	    case B_RGB15_BIG:
    62 	    case B_RGBA15_BIG:
    63 		bitsperpixel = 15;
    64 		break;
    65 	    case B_RGB16:
    66 	    case B_RGB16_BIG:
    67 		bitsperpixel = 16;
    68 		break;
    69 	    case B_RGB32:
    70 	    case B_RGBA32:
    71 	    case B_RGB32_BIG:
    72 	    case B_RGBA32_BIG:
    73 		bitsperpixel = 32;
    74 		break;
    75 	    default:
    76 		break;
    77 	}
    78 	return(bitsperpixel);
    79 }
    80 
    81 static inline int32 BPPToSDLPxFormat(int32 bpp) {
    82 	/* Translation taken from SDL_windowsmodes.c */
    83 	switch (bpp) {
    84 	case 32:
    85 		return SDL_PIXELFORMAT_RGB888;
    86 		break;
    87 	case 24:	/* May not be supported by Haiku */
    88 		return SDL_PIXELFORMAT_RGB24;
    89 		break;
    90 	case 16:
    91 		return SDL_PIXELFORMAT_RGB565;
    92 		break;
    93 	case 15:
    94 		return SDL_PIXELFORMAT_RGB555;
    95 		break;
    96 	case 8:
    97 		return SDL_PIXELFORMAT_INDEX8;
    98 		break;
    99 	case 4:		/* May not be supported by Haiku */
   100 		return SDL_PIXELFORMAT_INDEX4LSB;
   101 		break;
   102 	}
   103 }
   104 
   105 static inline void BE_BDisplayModeToSdlDisplayMode(display_mode *bmode,
   106 		SDL_DisplayMode *mode) {
   107 	mode->w = bmode->virtual_width;
   108 	mode->h = bmode->virtual_height;
   109 	mode->refresh_rate = (int)get_refresh_rate(*bmode);
   110 	mode->driverdata = bmode;	/* This makes setting display
   111 									   modes easier */
   112 
   113 	/* Set the format */
   114 	int32 bpp = ColorSpaceToBitsPerPixel(bmode->space);
   115 	mode->format = BPPToSDLPxFormat(bpp);
   116 }
   117 
   118 /* Later, there may be more than one monitor available */
   119 void BE_AddDisplay(BScreen *screen) {
   120 	SDL_VideoDisplay display;
   121 	SDL_DisplayMode *mode = (SDL_DisplayMode*)SDL_calloc(1, sizeof(SDL_DisplayMode));
   122 	display_mode bmode;
   123 	screen->GetMode(&bmode);
   124 
   125 	BE_BDisplayModeToSdlDisplayMode(&bmode, mode);
   126 	
   127 	SDL_zero(display);
   128 	display.desktop_mode = *mode;
   129 	display.current_mode = *mode;
   130 	SDL_AddVideoDisplay(&display);
   131 }
   132 
   133 int BE_InitModes(_THIS) {
   134 	BScreen screen;
   135 	
   136 	/* Save the current display mode */
   137 	display_mode *prevMode;
   138 	screen.GetMode(prevMode);
   139 	_GetBeApp()->SetPrevMode(prevMode);
   140 
   141 	/* Only one possible video display right now */
   142 	BE_AddDisplay(&screen);
   143 }
   144 
   145 int BE_QuitModes(_THIS) {
   146 	printf(__FILE__": %d; Begin quit\n", __LINE__);
   147 	/* Restore the previous video mode */
   148 	BScreen screen;
   149 	display_mode *savedMode = _GetBeApp()->GetPrevMode();
   150 	screen.SetMode(savedMode);
   151 	return 0;
   152 }
   153 
   154 
   155 int BE_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect) {
   156 	BScreen bscreen;
   157 	BRect rc = bscreen.Frame();
   158 	rect->x = (int)rc.left;
   159 	rect->y = (int)rc.top;
   160 	rect->w = (int)rc.Width() + 1;
   161 	rect->h = (int)rc.Height() + 1;
   162 	return 0;
   163 }
   164 
   165 void BE_GetDisplayModes(_THIS, SDL_VideoDisplay *display) {
   166 	/* Get the current screen */
   167 	BScreen bscreen;
   168 
   169 	/* Iterate through all of the modes */
   170 	SDL_DisplayMode mode;
   171 	display_mode this_bmode;
   172 	display_mode *bmodes;
   173 	uint32 count, i;
   174 	
   175 	/* Get graphics-hardware supported modes */
   176 	bscreen.GetModeList(&bmodes, &count);
   177 	bscreen.GetMode(&this_bmode);
   178 	
   179 	for(i = 0; i < count; ++i) {
   180 		//FIXME: Apparently there are errors with colorspace changes
   181 		if (bmodes[i].space == this_bmode.space) {
   182 			BE_BDisplayModeToSdlDisplayMode(&bmodes[i], &mode);
   183 			SDL_AddDisplayMode(display, &mode);
   184 		}
   185 	}
   186 	free(bmodes);
   187 }
   188 
   189 int BE_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode){
   190 	/* Get the current screen */
   191 	BScreen bscreen;
   192 	
   193 	/* Set the mode using the driver data */
   194 	display_mode *bmode = (display_mode*)mode->driverdata;
   195 	if(bscreen.SetMode(bmode) == B_OK) {
   196 		return 0;	/* No error */
   197 	}
   198 	
   199 	return -1;
   200 }
   201 
   202 
   203 
   204 int BE_CreateWindowFramebuffer(_THIS, SDL_Window * window,
   205                                        Uint32 * format,
   206                                        void ** pixels, int *pitch) {
   207 	SDL_BWin *bwin = _ToBeWin(window);
   208 	BScreen bscreen;
   209 	if(!bscreen.IsValid()) {
   210 		return -1;
   211 	}
   212 	
   213 	while(!bwin->Connected()) { snooze(10); }
   214 
   215 	/* Make sure we have exclusive access to frame buffer data */
   216 	bwin->LockBuffer();
   217 
   218 	/* format */
   219 	display_mode bmode;
   220 	bscreen.GetMode(&bmode);
   221 	int32 bpp = ColorSpaceToBitsPerPixel(bmode.space);
   222 	*format = BPPToSDLPxFormat(bpp);
   223 
   224 	/* pitch = width of screen, in bytes */
   225 	*pitch = bwin->GetFbWidth() * bwin->GetBytesPerPx();
   226 
   227 	/* Create a copy of the pixel buffer if it doesn't recycle */
   228 	*pixels = bwin->GetWindowFramebuffer();
   229 	if( bwin->CanTrashWindowBuffer() || (*pixels) == NULL) {
   230 		if( (*pixels) != NULL ) {
   231 			SDL_free(*pixels);
   232 		}
   233 		*pixels = SDL_calloc((*pitch) * bwin->GetFbHeight() * 
   234 			bwin->GetBytesPerPx(), sizeof(uint8));
   235 		bwin->SetWindowFramebuffer((uint8*)(*pixels));
   236 	}
   237 
   238 	bwin->UnlockBuffer();
   239 	return 0;
   240 }
   241 
   242 
   243 
   244 int BE_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
   245                                       SDL_Rect * rects, int numrects) {
   246 	SDL_BWin *bwin = _ToBeWin(window);
   247 	BScreen bscreen;
   248 	if(!bscreen.IsValid()) {
   249 		return -1;
   250 	}
   251 
   252 	if(bwin->ConnectionEnabled() && bwin->Connected()) {
   253 		bwin->LockBuffer();
   254 		int32 windowPitch = window->surface->pitch;
   255 		int32 bufferPitch = bwin->GetRowBytes();
   256 		uint8 *windowpx;
   257 		uint8 *bufferpx;
   258 
   259 		int32 BPP = bwin->GetBytesPerPx();
   260 		uint8 *windowBaseAddress = (uint8*)window->surface->pixels;
   261 		int32 windowSub = bwin->GetFbX() * BPP +
   262 						  bwin->GetFbY() * windowPitch;
   263 		clipping_rect *clips = bwin->GetClips();
   264 		int32 numClips = bwin->GetNumClips();
   265 		int i, y;
   266 
   267 		/* Blit each clipping rectangle */
   268 		bscreen.WaitForRetrace();
   269 		for(i = 0; i < numClips; ++i) {
   270 			clipping_rect rc = clips[i];
   271 			/* Get addresses of the start of each clipping rectangle */
   272 			int32 width = clips[i].right - clips[i].left + 1;
   273 			int32 height = clips[i].bottom - clips[i].top + 1;
   274 			bufferpx = bwin->GetBufferPx() + 
   275 				clips[i].top * bufferPitch + clips[i].left * BPP;
   276 			windowpx = windowBaseAddress + 
   277 				clips[i].top * windowPitch + clips[i].left * BPP - windowSub;
   278 
   279 			/* Copy each row of pixels from the window buffer into the frame
   280 			   buffer */
   281 			for(y = 0; y < height; ++y)
   282 			{
   283 				memcpy(bufferpx, windowpx, width * BPP);
   284 				bufferpx += bufferPitch;
   285 				windowpx += windowPitch;
   286 			}
   287 		}
   288 		bwin->UnlockBuffer();
   289 	}
   290 	return 0;
   291 }
   292 
   293 void BE_DestroyWindowFramebuffer(_THIS, SDL_Window * window) {
   294 	SDL_BWin *bwin = _ToBeWin(window);
   295 	
   296 	bwin->LockBuffer();
   297 	
   298 	/* Free and clear the window buffer */
   299 	uint8* winBuffer = bwin->GetWindowFramebuffer();
   300 	SDL_free(winBuffer);
   301 	bwin->SetWindowFramebuffer(NULL);
   302 	bwin->UnlockBuffer();
   303 }
   304 
   305 #ifdef __cplusplus
   306 }
   307 #endif