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