src/video/bwindow/SDL_bmodes.cc
author Nathan Heisey <nathanheisey@gmail.com>
Fri, 22 Jul 2011 12:39:53 +0000
changeset 5922 efd1498efdff
parent 5921 4cec9ba57dfb
child 5923 460ce3fb104c
permissions -rw-r--r--
Drawing code works, but it flashes
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@5921
    46
	return rint(10 * float(mode.timing.pixel_clock * 1000)
nathanheisey@5921
    47
		/ float(mode.timing.h_total * mode.timing.v_total)) / 10.0;
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@5921
    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@5921
   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
	printf("Quit Modes\n");
nathanheisey@5921
   149
	
nathanheisey@5921
   150
	BScreen screen;
nathanheisey@5921
   151
	display_mode *savedMode = _GetBeApp()->GetPrevMode();
nathanheisey@5921
   152
	screen.SetMode(savedMode);
nathanheisey@5921
   153
	return 0;
nathanheisey@5921
   154
}
nathanheisey@5921
   155
nathanheisey@5921
   156
nathanheisey@5921
   157
int BE_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect) {
nathanheisey@5921
   158
	BScreen bscreen;
nathanheisey@5921
   159
	BRect rc = bscreen.Frame();
nathanheisey@5921
   160
	rect->x = (int)rc.left;
nathanheisey@5921
   161
	rect->y = (int)rc.top;
nathanheisey@5921
   162
	rect->w = (int)rc.Width() + 1;
nathanheisey@5921
   163
	rect->h = (int)rc.Height() + 1;
nathanheisey@5921
   164
	return 0;
nathanheisey@5921
   165
}
nathanheisey@5921
   166
nathanheisey@5921
   167
void BE_GetDisplayModes(_THIS, SDL_VideoDisplay *display) {
nathanheisey@5921
   168
	printf("Get Display Modes\n");
nathanheisey@5921
   169
	/* Get the current screen */
nathanheisey@5921
   170
	BScreen bscreen;
nathanheisey@5921
   171
	
nathanheisey@5921
   172
	/* Iterate through all of the modes */
nathanheisey@5921
   173
	SDL_DisplayMode mode;
nathanheisey@5921
   174
	display_mode this_bmode;
nathanheisey@5921
   175
	display_mode *bmodes;
nathanheisey@5921
   176
	uint32 count, i;
nathanheisey@5921
   177
	
nathanheisey@5921
   178
	/* Get graphics-hardware supported modes */
nathanheisey@5921
   179
	bscreen.GetModeList(&bmodes, &count);
nathanheisey@5921
   180
	bscreen.GetMode(&this_bmode);
nathanheisey@5921
   181
	
nathanheisey@5921
   182
	for(i = 0; i < count; ++i) {
nathanheisey@5921
   183
		//FIXME: Apparently there are errors with colorspace changes
nathanheisey@5921
   184
		if (bmodes[i].space == this_bmode.space) {
nathanheisey@5921
   185
			BE_BDisplayModeToSdlDisplayMode(&bmodes[i], &mode);
nathanheisey@5921
   186
			SDL_AddDisplayMode(display, &mode);
nathanheisey@5918
   187
		}
nathanheisey@5918
   188
	}
nathanheisey@5921
   189
	free(bmodes);
nathanheisey@5921
   190
}
nathanheisey@5918
   191
nathanheisey@5921
   192
int BE_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode){
nathanheisey@5921
   193
	printf("Set Display Modes\n");
nathanheisey@5921
   194
	/* Get the current screen */
nathanheisey@5921
   195
	BScreen bscreen;
nathanheisey@5921
   196
	
nathanheisey@5921
   197
	/* Set the mode using the driver data */
nathanheisey@5921
   198
	display_mode *bmode = (display_mode*)mode->driverdata;
nathanheisey@5921
   199
	if(bscreen.SetMode(bmode) == B_OK) {
nathanheisey@5921
   200
		return 0;	/* No error */
nathanheisey@5918
   201
	}
nathanheisey@5921
   202
	
nathanheisey@5921
   203
	return -1;
nathanheisey@5921
   204
}
nathanheisey@5921
   205
nathanheisey@5922
   206
nathanheisey@5922
   207
nathanheisey@5922
   208
int BE_CreateWindowFramebuffer(_THIS, SDL_Window * window,
nathanheisey@5922
   209
                                       Uint32 * format,
nathanheisey@5922
   210
                                       void ** pixels, int *pitch) {
nathanheisey@5922
   211
	SDL_BWin *bwin = _ToBeWin(window);
nathanheisey@5922
   212
	BScreen bscreen;
nathanheisey@5922
   213
	if(!bscreen.IsValid()) {
nathanheisey@5922
   214
		return -1;
nathanheisey@5922
   215
	}
nathanheisey@5922
   216
	
nathanheisey@5922
   217
	while(!bwin->Connected()) { snooze(1600); }
nathanheisey@5922
   218
nathanheisey@5922
   219
	/* Make sure we have exclusive access to frame buffer data */
nathanheisey@5922
   220
	bwin->LockBuffer();
nathanheisey@5922
   221
nathanheisey@5922
   222
	/* format */
nathanheisey@5922
   223
	display_mode bmode;
nathanheisey@5922
   224
	bscreen.GetMode(&bmode);
nathanheisey@5922
   225
	int32 bpp = ColorSpaceToBitsPerPixel(bmode.space);
nathanheisey@5922
   226
	*format = BppToSDLPxFormat(bpp);
nathanheisey@5922
   227
nathanheisey@5922
   228
	/* pitch = width of screen, in bytes */
nathanheisey@5922
   229
	*pitch = bpp * bwin->GetFbWidth() / 8;
nathanheisey@5922
   230
nathanheisey@5922
   231
	/* Create a copy of the pixel buffer */
nathanheisey@5922
   232
	printf("SDL_bmodes.cc: 230; fbh: %i, pitch: %i; (x,y) = (%i, %i)\n", bwin->GetFbHeight(), (*pitch), bwin->GetFbX(), bwin->GetFbY());
nathanheisey@5922
   233
	*pixels = SDL_calloc((*pitch) * bwin->GetFbHeight() * bpp / 8, sizeof(uint8));
nathanheisey@5922
   234
nathanheisey@5922
   235
	bwin->UnlockBuffer();
nathanheisey@5922
   236
	return 0;
nathanheisey@5922
   237
}
nathanheisey@5922
   238
nathanheisey@5922
   239
nathanheisey@5922
   240
nathanheisey@5922
   241
int BE_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
nathanheisey@5922
   242
                                      SDL_Rect * rects, int numrects) {
nathanheisey@5922
   243
	SDL_BWin *bwin = _ToBeWin(window);
nathanheisey@5922
   244
	BScreen bscreen;
nathanheisey@5922
   245
	if(!bscreen.IsValid()) {
nathanheisey@5922
   246
		return -1;
nathanheisey@5922
   247
	}
nathanheisey@5922
   248
nathanheisey@5922
   249
	if(bwin->ConnectionEnabled() && bwin->Connected()) {
nathanheisey@5922
   250
		bwin->LockBuffer();
nathanheisey@5922
   251
		int32 windowPitch = window->surface->pitch;
nathanheisey@5922
   252
		int32 bufferPitch = bwin->GetRowBytes();
nathanheisey@5922
   253
		uint8 *windowpx;
nathanheisey@5922
   254
		uint8 *bufferpx;
nathanheisey@5922
   255
nathanheisey@5922
   256
		int32 bpp = window->surface->format->BitsPerPixel;
nathanheisey@5922
   257
		uint8 *windowBaseAddress = (uint8*)window->surface->pixels;
nathanheisey@5922
   258
		int32 windowSub = bwin->GetFbX() * bpp / 8 +
nathanheisey@5922
   259
						  bwin->GetFbY() * windowPitch;
nathanheisey@5922
   260
		clipping_rect *clips = bwin->GetClips();
nathanheisey@5922
   261
		int32 numClips = bwin->GetNumClips();
nathanheisey@5922
   262
		int i, y;
nathanheisey@5922
   263
nathanheisey@5922
   264
		/* Blit each clipping rectangle */
nathanheisey@5922
   265
		bscreen.WaitForRetrace();
nathanheisey@5922
   266
		for(i = 0; i < numClips; ++i) {
nathanheisey@5922
   267
			/* Get addresses of the start of each clipping rectangle */
nathanheisey@5922
   268
			int32 width = clips[i].right - clips[i].left + 1;
nathanheisey@5922
   269
			int32 height = clips[i].bottom - clips[i].top + 1;
nathanheisey@5922
   270
			bufferpx = bwin->GetBufferPx() + 
nathanheisey@5922
   271
				clips[i].top * bufferPitch + clips[i].left * bpp / 8;
nathanheisey@5922
   272
			windowpx = windowBaseAddress + 
nathanheisey@5922
   273
				clips[i].top * windowPitch + clips[i].left * bpp / 8
nathanheisey@5922
   274
				- windowSub;
nathanheisey@5922
   275
nathanheisey@5922
   276
			/* Copy each row of pixels from the window buffer into the frame
nathanheisey@5922
   277
			   buffer */
nathanheisey@5922
   278
			for(y = 0; y < height; ++y)
nathanheisey@5922
   279
			{
nathanheisey@5922
   280
				memcpy(bufferpx, windowpx, width * bpp / 8);
nathanheisey@5922
   281
				bufferpx += bufferPitch;
nathanheisey@5922
   282
				windowpx += windowPitch;
nathanheisey@5922
   283
			}
nathanheisey@5922
   284
		}
nathanheisey@5922
   285
		bwin->UnlockBuffer();
nathanheisey@5922
   286
	}
nathanheisey@5922
   287
	return 0;
nathanheisey@5922
   288
}
nathanheisey@5922
   289
nathanheisey@5922
   290
void BE_DestroyWindowFramebuffer(_THIS, SDL_Window * window) {
nathanheisey@5922
   291
	/* FIXME: FINISH! */
nathanheisey@5922
   292
	printf("ERROR: Attempted to destroy the window frame buffer\n");
nathanheisey@5922
   293
}
nathanheisey@5922
   294
nathanheisey@5921
   295
#ifdef __cplusplus
nathanheisey@5921
   296
}
nathanheisey@5918
   297
#endif