src/video/bwindow/SDL_sysvideo.cc
author Sam Lantinga <slouken@libsdl.org>
Tue, 17 Mar 2009 03:58:53 +0000
branchSDL-1.2
changeset 4164 7a4c511c980a
parent 4159 a1b03ba2fcd0
child 4287 0620847bf1a8
permissions -rw-r--r--
Date: Fri, 6 Mar 2009 12:41:17 -0800
From: scott mc
Subject: Re: [SDL] patch for building on haiku

Ok. I've combined the various Haiku patches for the SDL-1.2 branch
into one .diff file
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@4159
     3
    Copyright (C) 1997-2009 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@1403
    22
#include "SDL_config.h"
slouken@0
    23
slouken@0
    24
/* BWindow based framebuffer implementation */
slouken@0
    25
slouken@0
    26
#include <unistd.h>
slouken@0
    27
slouken@0
    28
#include "SDL_BWin.h"
slouken@0
    29
#include "SDL_timer.h"
slouken@0
    30
slouken@0
    31
extern "C" {
slouken@0
    32
slouken@1361
    33
#include "../SDL_sysvideo.h"
slouken@1361
    34
#include "../../events/SDL_events_c.h"
slouken@1367
    35
#include "SDL_sysevents_c.h"
slouken@0
    36
#include "SDL_sysmouse_c.h"
slouken@0
    37
#include "SDL_syswm_c.h"
slouken@0
    38
#include "SDL_lowvideo.h"
slouken@1361
    39
#include "../SDL_yuvfuncs.h"
slouken@756
    40
#include "SDL_sysyuv.h"
slouken@1361
    41
#include "../blank_cursor.h"
slouken@0
    42
slouken@0
    43
#define BEOS_HIDDEN_SIZE	32	/* starting hidden window size */
slouken@0
    44
slouken@0
    45
/* Initialization/Query functions */
slouken@0
    46
static int BE_VideoInit(_THIS, SDL_PixelFormat *vformat);
slouken@0
    47
static SDL_Rect **BE_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
slouken@0
    48
static SDL_Surface *BE_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
slouken@0
    49
static void BE_UpdateMouse(_THIS);
slouken@0
    50
static int BE_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
slouken@0
    51
static void BE_VideoQuit(_THIS);
slouken@0
    52
slouken@0
    53
/* Hardware surface functions */
slouken@0
    54
static int BE_AllocHWSurface(_THIS, SDL_Surface *surface);
slouken@0
    55
static int BE_LockHWSurface(_THIS, SDL_Surface *surface);
slouken@0
    56
static void BE_UnlockHWSurface(_THIS, SDL_Surface *surface);
slouken@0
    57
static void BE_FreeHWSurface(_THIS, SDL_Surface *surface);
slouken@0
    58
slouken@0
    59
static int BE_ToggleFullScreen(_THIS, int fullscreen);
slouken@4164
    60
SDL_Overlay *BE_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display);
slouken@0
    61
slouken@0
    62
/* OpenGL functions */
slouken@1361
    63
#if SDL_VIDEO_OPENGL
slouken@906
    64
static int BE_GL_LoadLibrary(_THIS, const char *path);
slouken@906
    65
static void* BE_GL_GetProcAddress(_THIS, const char *proc);
slouken@906
    66
static int BE_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value);
slouken@906
    67
static int BE_GL_MakeCurrent(_THIS);
slouken@0
    68
static void BE_GL_SwapBuffers(_THIS);
slouken@0
    69
#endif
slouken@0
    70
slouken@0
    71
/* FB driver bootstrap functions */
slouken@0
    72
slouken@0
    73
static int BE_Available(void)
slouken@0
    74
{
slouken@0
    75
	return(1);
slouken@0
    76
}
slouken@0
    77
slouken@0
    78
static void BE_DeleteDevice(SDL_VideoDevice *device)
slouken@0
    79
{
slouken@1336
    80
	SDL_free(device->hidden);
slouken@1336
    81
	SDL_free(device);
slouken@0
    82
}
slouken@0
    83
slouken@0
    84
static SDL_VideoDevice *BE_CreateDevice(int devindex)
slouken@0
    85
{
slouken@0
    86
	SDL_VideoDevice *device;
slouken@0
    87
slouken@0
    88
	/* Initialize all variables that we clean on shutdown */
slouken@1336
    89
	device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
slouken@0
    90
	if ( device ) {
slouken@1336
    91
		SDL_memset(device, 0, (sizeof *device));
slouken@0
    92
		device->hidden = (struct SDL_PrivateVideoData *)
slouken@1336
    93
				SDL_malloc((sizeof *device->hidden));
slouken@0
    94
	}
slouken@0
    95
	if ( (device == NULL) || (device->hidden == NULL) ) {
slouken@0
    96
		SDL_OutOfMemory();
slouken@0
    97
		if ( device ) {
slouken@1336
    98
			SDL_free(device);
slouken@0
    99
		}
slouken@0
   100
		return(0);
slouken@0
   101
	}
slouken@1336
   102
	SDL_memset(device->hidden, 0, (sizeof *device->hidden));
slouken@0
   103
slouken@0
   104
	/* Set the function pointers */
slouken@906
   105
	/* Initialization/Query functions */
slouken@0
   106
	device->VideoInit = BE_VideoInit;
slouken@0
   107
	device->ListModes = BE_ListModes;
slouken@0
   108
	device->SetVideoMode = BE_SetVideoMode;
slouken@906
   109
	device->ToggleFullScreen = BE_ToggleFullScreen;
slouken@0
   110
	device->UpdateMouse = BE_UpdateMouse;
slouken@906
   111
	device->CreateYUVOverlay = BE_CreateYUVOverlay;
slouken@0
   112
	device->SetColors = BE_SetColors;
slouken@0
   113
	device->UpdateRects = NULL;
slouken@0
   114
	device->VideoQuit = BE_VideoQuit;
slouken@906
   115
	/* Hardware acceleration functions */
slouken@0
   116
	device->AllocHWSurface = BE_AllocHWSurface;
slouken@0
   117
	device->CheckHWBlit = NULL;
slouken@0
   118
	device->FillHWRect = NULL;
slouken@0
   119
	device->SetHWColorKey = NULL;
slouken@0
   120
	device->SetHWAlpha = NULL;
slouken@0
   121
	device->LockHWSurface = BE_LockHWSurface;
slouken@0
   122
	device->UnlockHWSurface = BE_UnlockHWSurface;
slouken@0
   123
	device->FlipHWSurface = NULL;
slouken@0
   124
	device->FreeHWSurface = BE_FreeHWSurface;
slouken@906
   125
	/* Gamma support */
slouken@1361
   126
#if SDL_VIDEO_OPENGL
slouken@906
   127
	/* OpenGL support */
slouken@906
   128
	device->GL_LoadLibrary = BE_GL_LoadLibrary;
slouken@906
   129
	device->GL_GetProcAddress = BE_GL_GetProcAddress;
slouken@906
   130
	device->GL_GetAttribute = BE_GL_GetAttribute;
slouken@906
   131
	device->GL_MakeCurrent = BE_GL_MakeCurrent;
slouken@0
   132
	device->GL_SwapBuffers = BE_GL_SwapBuffers;
slouken@0
   133
#endif
slouken@906
   134
	/* Window manager functions */
slouken@906
   135
	device->SetCaption = BE_SetWMCaption;
slouken@0
   136
	device->SetIcon = NULL;
slouken@906
   137
	device->IconifyWindow = BE_IconifyWindow;
slouken@3878
   138
	device->GrabInput = BE_GrabInput;
slouken@906
   139
	device->GetWMInfo = BE_GetWMInfo;
slouken@906
   140
	/* Cursor manager functions */
slouken@0
   141
	device->FreeWMCursor = BE_FreeWMCursor;
slouken@0
   142
	device->CreateWMCursor = BE_CreateWMCursor;
slouken@0
   143
	device->ShowWMCursor = BE_ShowWMCursor;
slouken@0
   144
	device->WarpWMCursor = BE_WarpWMCursor;
slouken@906
   145
	device->MoveWMCursor = NULL;
slouken@3878
   146
	device->CheckMouseMode = BE_CheckMouseMode;
slouken@906
   147
	/* Event manager functions */
slouken@0
   148
	device->InitOSKeymap = BE_InitOSKeymap;
slouken@0
   149
	device->PumpEvents = BE_PumpEvents;
slouken@0
   150
slouken@0
   151
	device->free = BE_DeleteDevice;
slouken@0
   152
slouken@0
   153
	/* Set the driver flags */
slouken@0
   154
	device->handles_any_size = 1;
slouken@0
   155
	
slouken@0
   156
	return device;
slouken@0
   157
}
slouken@0
   158
slouken@0
   159
VideoBootStrap BWINDOW_bootstrap = {
slouken@0
   160
	"bwindow", "BDirectWindow graphics",
slouken@0
   161
	BE_Available, BE_CreateDevice
slouken@0
   162
};
slouken@0
   163
slouken@0
   164
static inline int ColorSpaceToBitsPerPixel(uint32 colorspace)
slouken@0
   165
{
slouken@0
   166
	int bitsperpixel;
slouken@0
   167
slouken@0
   168
	bitsperpixel = 0;
slouken@0
   169
	switch (colorspace) {
slouken@0
   170
	    case B_CMAP8:
slouken@0
   171
		bitsperpixel = 8;
slouken@0
   172
		break;
slouken@0
   173
	    case B_RGB15:
slouken@0
   174
	    case B_RGBA15:
slouken@0
   175
	    case B_RGB15_BIG:
slouken@0
   176
	    case B_RGBA15_BIG:
slouken@0
   177
		bitsperpixel = 15;
slouken@0
   178
		break;
slouken@0
   179
	    case B_RGB16:
slouken@0
   180
	    case B_RGB16_BIG:
slouken@0
   181
		bitsperpixel = 16;
slouken@0
   182
		break;
slouken@0
   183
	    case B_RGB32:
slouken@0
   184
	    case B_RGBA32:
slouken@0
   185
	    case B_RGB32_BIG:
slouken@0
   186
	    case B_RGBA32_BIG:
slouken@0
   187
		bitsperpixel = 32;
slouken@0
   188
		break;
slouken@0
   189
	    default:
slouken@0
   190
		break;
slouken@0
   191
	}
slouken@0
   192
	return(bitsperpixel);
slouken@0
   193
}
slouken@0
   194
slouken@0
   195
/* Function to sort the display_list in bscreen */
slouken@0
   196
static int CompareModes(const void *A, const void *B)
slouken@0
   197
{
slouken@0
   198
	const display_mode *a = (display_mode *)A;
slouken@0
   199
	const display_mode *b = (display_mode *)B;
slouken@0
   200
slouken@0
   201
	if ( a->space == b->space ) {
slouken@0
   202
		return((b->virtual_width*b->virtual_height)-
slouken@0
   203
		       (a->virtual_width*a->virtual_height));
slouken@0
   204
	} else {
slouken@0
   205
		return(ColorSpaceToBitsPerPixel(b->space)-
slouken@0
   206
		       ColorSpaceToBitsPerPixel(a->space));
slouken@0
   207
	}
slouken@0
   208
}
slouken@0
   209
slouken@0
   210
/* Yes, this isn't the fastest it could be, but it works nicely */
slouken@0
   211
static int BE_AddMode(_THIS, int index, unsigned int w, unsigned int h)
slouken@0
   212
{
slouken@0
   213
	SDL_Rect *mode;
slouken@0
   214
	int i;
slouken@0
   215
	int next_mode;
slouken@0
   216
slouken@0
   217
	/* Check to see if we already have this mode */
slouken@0
   218
	if ( SDL_nummodes[index] > 0 ) {
slouken@0
   219
		for ( i=SDL_nummodes[index]-1; i >= 0; --i ) {
slouken@0
   220
			mode = SDL_modelist[index][i];
slouken@0
   221
			if ( (mode->w == w) && (mode->h == h) ) {
slouken@0
   222
#ifdef BWINDOW_DEBUG
slouken@0
   223
				fprintf(stderr, "We already have mode %dx%d at %d bytes per pixel\n", w, h, index+1);
slouken@0
   224
#endif
slouken@0
   225
				return(0);
slouken@0
   226
			}
slouken@0
   227
		}
slouken@0
   228
	}
slouken@0
   229
slouken@0
   230
	/* Set up the new video mode rectangle */
slouken@1336
   231
	mode = (SDL_Rect *)SDL_malloc(sizeof *mode);
slouken@0
   232
	if ( mode == NULL ) {
slouken@0
   233
		SDL_OutOfMemory();
slouken@0
   234
		return(-1);
slouken@0
   235
	}
slouken@0
   236
	mode->x = 0;
slouken@0
   237
	mode->y = 0;
slouken@0
   238
	mode->w = w;
slouken@0
   239
	mode->h = h;
slouken@0
   240
#ifdef BWINDOW_DEBUG
slouken@0
   241
	fprintf(stderr, "Adding mode %dx%d at %d bytes per pixel\n", w, h, index+1);
slouken@0
   242
#endif
slouken@0
   243
slouken@0
   244
	/* Allocate the new list of modes, and fill in the new mode */
slouken@0
   245
	next_mode = SDL_nummodes[index];
slouken@0
   246
	SDL_modelist[index] = (SDL_Rect **)
slouken@1336
   247
	       SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));
slouken@0
   248
	if ( SDL_modelist[index] == NULL ) {
slouken@0
   249
		SDL_OutOfMemory();
slouken@0
   250
		SDL_nummodes[index] = 0;
slouken@1336
   251
		SDL_free(mode);
slouken@0
   252
		return(-1);
slouken@0
   253
	}
slouken@0
   254
	SDL_modelist[index][next_mode] = mode;
slouken@0
   255
	SDL_modelist[index][next_mode+1] = NULL;
slouken@0
   256
	SDL_nummodes[index]++;
slouken@0
   257
slouken@0
   258
	return(0);
slouken@0
   259
}
slouken@0
   260
slouken@0
   261
int BE_VideoInit(_THIS, SDL_PixelFormat *vformat)
slouken@0
   262
{
slouken@0
   263
	display_mode *modes;
slouken@0
   264
	uint32 i, nmodes;
slouken@0
   265
	int bpp;
slouken@0
   266
	BRect bounds;
slouken@0
   267
slouken@0
   268
	/* Initialize the Be Application for appserver interaction */
slouken@0
   269
	if ( SDL_InitBeApp() < 0 ) {
slouken@0
   270
		return(-1);
slouken@0
   271
	}
slouken@0
   272
slouken@0
   273
	/* It is important that this be created after SDL_InitBeApp() */
slouken@0
   274
	BScreen bscreen;
slouken@0
   275
slouken@0
   276
	/* Save the current display mode */
slouken@0
   277
	bscreen.GetMode(&saved_mode);
slouken@1545
   278
	_this->info.current_w = saved_mode.virtual_width;
slouken@1545
   279
	_this->info.current_h = saved_mode.virtual_height;
slouken@0
   280
slouken@0
   281
	/* Determine the screen depth */
slouken@0
   282
	vformat->BitsPerPixel = ColorSpaceToBitsPerPixel(bscreen.ColorSpace());
slouken@0
   283
	if ( vformat->BitsPerPixel == 0 ) {
slouken@0
   284
		SDL_SetError("Unknown BScreen colorspace: 0x%x",
slouken@0
   285
						bscreen.ColorSpace());
slouken@0
   286
		return(-1);
slouken@0
   287
	}
slouken@0
   288
slouken@0
   289
	/* Get the video modes we can switch to in fullscreen mode */
slouken@0
   290
	bscreen.GetModeList(&modes, &nmodes);
slouken@1338
   291
	SDL_qsort(modes, nmodes, sizeof *modes, CompareModes);
slouken@0
   292
	for ( i=0; i<nmodes; ++i ) {
slouken@0
   293
		bpp = ColorSpaceToBitsPerPixel(modes[i].space);
slouken@0
   294
		//if ( bpp != 0 ) { // There are bugs in changing colorspace
slouken@0
   295
		if ( modes[i].space == saved_mode.space ) {
slouken@0
   296
			BE_AddMode(_this, ((bpp+7)/8)-1,
slouken@0
   297
				modes[i].virtual_width,
slouken@0
   298
				modes[i].virtual_height);
slouken@0
   299
		}
slouken@0
   300
	}
slouken@0
   301
slouken@0
   302
	/* Create the window and view */
slouken@0
   303
	bounds.top = 0; bounds.left = 0;
slouken@0
   304
	bounds.right = BEOS_HIDDEN_SIZE;
slouken@0
   305
	bounds.bottom = BEOS_HIDDEN_SIZE;
slouken@0
   306
	SDL_Win = new SDL_BWin(bounds);
slouken@0
   307
slouken@1361
   308
#if SDL_VIDEO_OPENGL
slouken@906
   309
	/* testgl application doesn't load library, just tries to load symbols */
slouken@906
   310
	/* is it correct? if so we have to load library here */
slouken@906
   311
	BE_GL_LoadLibrary(_this, NULL);
slouken@906
   312
#endif
slouken@906
   313
slouken@0
   314
	/* Create the clear cursor */
slouken@0
   315
	SDL_BlankCursor = BE_CreateWMCursor(_this, blank_cdata, blank_cmask,
slouken@0
   316
			BLANK_CWIDTH, BLANK_CHEIGHT, BLANK_CHOTX, BLANK_CHOTY);
slouken@0
   317
slouken@0
   318
	/* Fill in some window manager capabilities */
slouken@0
   319
	_this->info.wm_available = 1;
slouken@0
   320
slouken@0
   321
	/* We're done! */
slouken@0
   322
	return(0);
slouken@0
   323
}
slouken@0
   324
slouken@0
   325
/* We support any dimension at our bit-depth */
slouken@0
   326
SDL_Rect **BE_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
slouken@0
   327
{
slouken@0
   328
	SDL_Rect **modes;
slouken@0
   329
slouken@0
   330
	modes = ((SDL_Rect **)0);
slouken@0
   331
	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
slouken@0
   332
		modes = SDL_modelist[((format->BitsPerPixel+7)/8)-1];
slouken@0
   333
	} else {
slouken@0
   334
		if ( format->BitsPerPixel ==
slouken@0
   335
			_this->screen->format->BitsPerPixel ) {
slouken@0
   336
			modes = ((SDL_Rect **)-1);
slouken@0
   337
		}
slouken@0
   338
	}
slouken@0
   339
	return(modes);
slouken@0
   340
}
slouken@0
   341
slouken@0
   342
/* Various screen update functions available */
slouken@0
   343
static void BE_NormalUpdate(_THIS, int numrects, SDL_Rect *rects);
slouken@0
   344
slouken@0
   345
slouken@0
   346
/* Find the closest display mode for fullscreen */
slouken@0
   347
static bool BE_FindClosestFSMode(_THIS, int width, int height, int bpp,
slouken@0
   348
					 display_mode *mode)
slouken@0
   349
{
slouken@0
   350
	BScreen bscreen;
slouken@0
   351
	uint32 i, nmodes;
slouken@0
   352
	SDL_Rect **modes;
slouken@0
   353
	display_mode *dmodes;
slouken@756
   354
	display_mode current;
slouken@756
   355
	float current_refresh;
slouken@756
   356
	bscreen.GetMode(&current);
slouken@756
   357
	current_refresh = (1000 * current.timing.pixel_clock) / 
slouken@756
   358
	                  (current.timing.h_total * current.timing.v_total);
slouken@0
   359
slouken@0
   360
	modes = SDL_modelist[((bpp+7)/8)-1];
slouken@0
   361
	for ( i=0; modes[i] && (modes[i]->w > width) &&
slouken@0
   362
		      (modes[i]->h > height); ++i ) {
slouken@0
   363
		/* still looking */
slouken@0
   364
	}
slouken@0
   365
	if ( ! modes[i] || (modes[i]->w < width) || (modes[i]->h < width) ) {
slouken@0
   366
		--i;	/* We went too far */
slouken@0
   367
	}
slouken@3878
   368
slouken@4012
   369
	width = modes[i]->w;
slouken@4012
   370
	height = modes[i]->h;      
slouken@3878
   371
slouken@0
   372
	bscreen.GetModeList(&dmodes, &nmodes);
slouken@0
   373
	for ( i = 0; i < nmodes; ++i ) {
slouken@0
   374
		if ( (bpp == ColorSpaceToBitsPerPixel(dmodes[i].space)) &&
slouken@0
   375
		     (width == dmodes[i].virtual_width) &&
slouken@0
   376
		     (height == dmodes[i].virtual_height) ) {
slouken@0
   377
			break;
slouken@0
   378
		}
slouken@0
   379
	}
slouken@0
   380
	if ( i != nmodes ) {
slouken@0
   381
		*mode = dmodes[i];
slouken@756
   382
		if ((mode->virtual_width <= current.virtual_width) &&
slouken@756
   383
		    (mode->virtual_height <= current.virtual_height)) {
slouken@756
   384
			float new_refresh = (1000 * mode->timing.pixel_clock) /
slouken@756
   385
			                    (mode->timing.h_total * mode->timing.v_total);
slouken@756
   386
			if (new_refresh < current_refresh) {
slouken@756
   387
				mode->timing.pixel_clock = (uint32)((mode->timing.h_total * mode->timing.v_total)
slouken@756
   388
				                                    * current_refresh / 1000);
slouken@756
   389
			}
slouken@756
   390
		}
slouken@0
   391
		return true;
slouken@0
   392
	} else {
slouken@0
   393
		return false;
slouken@0
   394
	}	
slouken@0
   395
}
slouken@0
   396
slouken@114
   397
static int BE_SetFullScreen(_THIS, SDL_Surface *screen, int fullscreen)
slouken@0
   398
{
slouken@114
   399
	int was_fullscreen;
slouken@114
   400
	bool needs_unlock;
slouken@0
   401
	BScreen bscreen;
slouken@0
   402
	BRect bounds;
slouken@0
   403
	display_mode mode;
slouken@0
   404
	int width, height, bpp;
slouken@0
   405
slouken@114
   406
	/* Set the fullscreen mode */
slouken@114
   407
	was_fullscreen = SDL_Win->IsFullScreen();
slouken@0
   408
	SDL_Win->SetFullScreen(fullscreen);
slouken@114
   409
	fullscreen = SDL_Win->IsFullScreen();
slouken@0
   410
slouken@114
   411
	width = screen->w;
slouken@114
   412
	height = screen->h;
slouken@0
   413
slouken@0
   414
	/* Set the appropriate video mode */
slouken@0
   415
	if ( fullscreen ) {
slouken@114
   416
		bpp = screen->format->BitsPerPixel;
slouken@0
   417
		bscreen.GetMode(&mode);
slouken@0
   418
		if ( (bpp != ColorSpaceToBitsPerPixel(mode.space)) ||
slouken@0
   419
		     (width != mode.virtual_width) ||
slouken@0
   420
		     (height != mode.virtual_height)) {
slouken@0
   421
			if(BE_FindClosestFSMode(_this, width, height, bpp, &mode)) {
slouken@0
   422
				bscreen.SetMode(&mode);
slouken@0
   423
				/* This simply stops the next resize event from being
slouken@0
   424
				 * sent to the SDL handler.
slouken@0
   425
				 */
slouken@0
   426
				SDL_Win->InhibitResize();
slouken@0
   427
			} else {
slouken@114
   428
				fullscreen = 0;
slouken@114
   429
				SDL_Win->SetFullScreen(fullscreen);
slouken@0
   430
			}
slouken@0
   431
		}
slouken@114
   432
	}
slouken@206
   433
	if ( was_fullscreen && ! fullscreen ) {
slouken@0
   434
		bscreen.SetMode(&saved_mode);
slouken@0
   435
	}
slouken@114
   436
slouken@0
   437
	if ( SDL_Win->Lock() ) {
slouken@3878
   438
		int cx, cy;
slouken@0
   439
		if ( SDL_Win->Shown() ) {
slouken@0
   440
			needs_unlock = 1;
slouken@0
   441
			SDL_Win->Hide();
slouken@0
   442
		} else {
slouken@0
   443
			needs_unlock = 0;
slouken@0
   444
		}
slouken@114
   445
		/* This resizes the window and view area, but inhibits resizing
slouken@114
   446
		 * of the BBitmap due to the InhibitResize call above. Thus the
slouken@114
   447
		 * bitmap (pixel data) never changes.
slouken@0
   448
		 */
slouken@0
   449
		SDL_Win->ResizeTo(width, height);
slouken@0
   450
		bounds = bscreen.Frame();
slouken@114
   451
		/* Calculate offsets - used either to center window
slouken@114
   452
		 * (windowed mode) or to set drawing offsets (fullscreen mode)
slouken@0
   453
		 */
slouken@3878
   454
		cx = (bounds.IntegerWidth() - width)/2;
slouken@3878
   455
		cy = (bounds.IntegerHeight() - height)/2;
slouken@3878
   456
slouken@4012
   457
		if ( fullscreen ) {
slouken@4012
   458
			/* Set offset for drawing */
slouken@4012
   459
			SDL_Win->SetXYOffset(cx, cy);
slouken@4012
   460
		} else {
slouken@4012
   461
			SDL_Win->SetXYOffset(0, 0);
slouken@4012
   462
		}
slouken@114
   463
		if ( ! needs_unlock || was_fullscreen ) {
slouken@114
   464
			/* Center the window the first time */
slouken@3878
   465
			SDL_Win->MoveTo(cx, cy);
slouken@114
   466
		}
slouken@0
   467
		SDL_Win->Show();
slouken@0
   468
		
slouken@0
   469
		/* Unlock the window manually after the first Show() */
slouken@114
   470
		if ( needs_unlock ) {
slouken@114
   471
			SDL_Win->Unlock();
slouken@114
   472
		}
slouken@114
   473
	}
slouken@114
   474
slouken@114
   475
	/* Set the fullscreen flag in the screen surface */
slouken@114
   476
	if ( fullscreen ) {
slouken@114
   477
		screen->flags |= SDL_FULLSCREEN;
slouken@114
   478
	} else {
slouken@114
   479
		screen->flags &= ~SDL_FULLSCREEN; 
slouken@0
   480
	}
slouken@0
   481
	return(1);
slouken@0
   482
}
slouken@0
   483
slouken@114
   484
static int BE_ToggleFullScreen(_THIS, int fullscreen)
slouken@114
   485
{
slouken@114
   486
	return BE_SetFullScreen(_this, _this->screen, fullscreen);
slouken@114
   487
}
slouken@114
   488
slouken@0
   489
/* FIXME: check return values and cleanup here */
slouken@0
   490
SDL_Surface *BE_SetVideoMode(_THIS, SDL_Surface *current,
slouken@0
   491
				int width, int height, int bpp, Uint32 flags)
slouken@0
   492
{
slouken@0
   493
	BScreen bscreen;
slouken@0
   494
	BBitmap *bbitmap;
slouken@0
   495
	BRect bounds;
slouken@906
   496
	Uint32 gl_flags = 0;
slouken@0
   497
slouken@906
   498
	/* Only RGB works on r5 currently */
slouken@906
   499
	gl_flags = BGL_RGB;
slouken@906
   500
	if (_this->gl_config.double_buffer)
slouken@906
   501
		gl_flags |= BGL_DOUBLE;
slouken@906
   502
	else
slouken@906
   503
		gl_flags |= BGL_SINGLE;
slouken@906
   504
	if (_this->gl_config.alpha_size > 0 || bpp == 32)
slouken@906
   505
		gl_flags |= BGL_ALPHA;
slouken@906
   506
	if (_this->gl_config.depth_size > 0)
slouken@906
   507
		gl_flags |= BGL_DEPTH;
slouken@906
   508
	if (_this->gl_config.stencil_size > 0)
slouken@906
   509
		gl_flags |= BGL_STENCIL;
slouken@906
   510
	if (_this->gl_config.accum_red_size > 0
slouken@906
   511
		|| _this->gl_config.accum_green_size > 0
slouken@906
   512
		|| _this->gl_config.accum_blue_size > 0
slouken@906
   513
		|| _this->gl_config.accum_alpha_size > 0)
slouken@906
   514
		gl_flags |= BGL_ACCUM;
slouken@906
   515
slouken@906
   516
	/* Create the view for this window, using found flags */
slouken@906
   517
	if ( SDL_Win->CreateView(flags, gl_flags) < 0 ) {
slouken@0
   518
		return(NULL);
slouken@0
   519
	}
slouken@0
   520
slouken@0
   521
	current->flags = 0;		/* Clear flags */
slouken@0
   522
	current->w = width;
slouken@0
   523
	current->h = height;
slouken@0
   524
	SDL_Win->SetType(B_TITLED_WINDOW);
slouken@0
   525
	if ( flags & SDL_NOFRAME ) {
slouken@0
   526
		current->flags |= SDL_NOFRAME;
slouken@0
   527
		SDL_Win->SetLook(B_NO_BORDER_WINDOW_LOOK);
slouken@0
   528
	} else {
slouken@0
   529
		if ( (flags & SDL_RESIZABLE) && !(flags & SDL_OPENGL) )  {
slouken@0
   530
			current->flags |= SDL_RESIZABLE;
slouken@0
   531
			/* We don't want opaque resizing (TM). :-) */
slouken@0
   532
			SDL_Win->SetFlags(B_OUTLINE_RESIZE);
slouken@0
   533
		} else {
slouken@0
   534
			SDL_Win->SetFlags(B_NOT_RESIZABLE|B_NOT_ZOOMABLE);
slouken@0
   535
		}
slouken@0
   536
	}
slouken@0
   537
slouken@0
   538
	if ( flags & SDL_OPENGL ) {
slouken@0
   539
		current->flags |= SDL_OPENGL;
slouken@0
   540
		current->pitch = 0;
slouken@0
   541
		current->pixels = NULL;
slouken@906
   542
		_this->UpdateRects = NULL;
slouken@0
   543
	} else {
slouken@0
   544
		/* Create the BBitmap framebuffer */
slouken@0
   545
		bounds.top = 0; bounds.left = 0;
slouken@0
   546
		bounds.right = width-1;
slouken@0
   547
		bounds.bottom = height-1;
slouken@0
   548
		bbitmap = new BBitmap(bounds, bscreen.ColorSpace());
slouken@0
   549
		if ( ! bbitmap->IsValid() ) {
slouken@0
   550
			SDL_SetError("Couldn't create screen bitmap");
slouken@0
   551
			delete bbitmap;
slouken@0
   552
			return(NULL);
slouken@0
   553
		}
slouken@0
   554
		current->pitch = bbitmap->BytesPerRow();
slouken@0
   555
		current->pixels = (void *)bbitmap->Bits();
slouken@0
   556
		SDL_Win->SetBitmap(bbitmap);
slouken@0
   557
		_this->UpdateRects = BE_NormalUpdate;
slouken@0
   558
	}
slouken@0
   559
slouken@114
   560
	/* Set the correct fullscreen mode */
slouken@114
   561
	BE_SetFullScreen(_this, current, flags & SDL_FULLSCREEN ? 1 : 0);
slouken@0
   562
slouken@0
   563
	/* We're done */
slouken@0
   564
	return(current);
slouken@0
   565
}
slouken@0
   566
slouken@0
   567
/* Update the current mouse state and position */
slouken@0
   568
void BE_UpdateMouse(_THIS)
slouken@0
   569
{
slouken@0
   570
	BPoint point;
slouken@0
   571
	uint32 buttons;
slouken@0
   572
slouken@0
   573
	if ( SDL_Win->Lock() ) {
slouken@0
   574
		/* Get new input state, if still active */
slouken@0
   575
		if ( SDL_Win->IsActive() ) {
slouken@0
   576
			(SDL_Win->View())->GetMouse(&point, &buttons, true);
slouken@0
   577
		} else {
slouken@0
   578
			point.x = -1;
slouken@0
   579
			point.y = -1;
slouken@0
   580
		}
slouken@0
   581
		SDL_Win->Unlock();
slouken@0
   582
slouken@0
   583
		if ( (point.x >= 0) && (point.x < SDL_VideoSurface->w) &&
slouken@0
   584
		     (point.y >= 0) && (point.y < SDL_VideoSurface->h) ) {
slouken@0
   585
			SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
slouken@0
   586
			SDL_PrivateMouseMotion(0, 0,
slouken@0
   587
					(Sint16)point.x, (Sint16)point.y);
slouken@0
   588
		} else {
slouken@0
   589
			SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
slouken@0
   590
		}
slouken@0
   591
	}
slouken@0
   592
}
slouken@0
   593
slouken@0
   594
/* We don't actually allow hardware surfaces other than the main one */
slouken@0
   595
static int BE_AllocHWSurface(_THIS, SDL_Surface *surface)
slouken@0
   596
{
slouken@0
   597
	return(-1);
slouken@0
   598
}
slouken@0
   599
static void BE_FreeHWSurface(_THIS, SDL_Surface *surface)
slouken@0
   600
{
slouken@0
   601
	return;
slouken@0
   602
}
slouken@0
   603
static int BE_LockHWSurface(_THIS, SDL_Surface *surface)
slouken@0
   604
{
slouken@0
   605
	return(0);
slouken@0
   606
}
slouken@0
   607
static void BE_UnlockHWSurface(_THIS, SDL_Surface *surface)
slouken@0
   608
{
slouken@0
   609
	return;
slouken@0
   610
}
slouken@0
   611
slouken@0
   612
static void BE_NormalUpdate(_THIS, int numrects, SDL_Rect *rects)
slouken@0
   613
{
slouken@0
   614
	if ( SDL_Win->BeginDraw() ) {
slouken@0
   615
		int i;
slouken@0
   616
slouken@0
   617
		for ( i=0; i<numrects; ++i ) {
slouken@0
   618
			BRect rect;
slouken@0
   619
slouken@0
   620
			rect.top = rects[i].y;
slouken@0
   621
			rect.left = rects[i].x;
slouken@0
   622
			rect.bottom = rect.top+rects[i].h-1;
slouken@0
   623
			rect.right = rect.left+rects[i].w-1;
slouken@0
   624
			SDL_Win->DrawAsync(rect);
slouken@0
   625
		}
slouken@0
   626
		SDL_Win->EndDraw();
slouken@0
   627
	}
slouken@0
   628
}
slouken@0
   629
slouken@1361
   630
#if SDL_VIDEO_OPENGL
slouken@906
   631
/* Passing a NULL path means load pointers from the application */
slouken@906
   632
int BE_GL_LoadLibrary(_THIS, const char *path)
slouken@906
   633
{
slouken@906
   634
	if (path == NULL) {
slouken@906
   635
		if (_this->gl_config.dll_handle == NULL) {
slouken@906
   636
			image_info info;
slouken@906
   637
			int32 cookie = 0;
slouken@906
   638
			while (get_next_image_info(0,&cookie,&info) == B_OK) {
slouken@906
   639
				void *location = NULL;
slouken@4164
   640
#ifdef __HAIKU__
slouken@4164
   641
				if (get_image_symbol(info.id,"glBegin",B_SYMBOL_TYPE_ANY,&location) == B_OK) { // This is how it actually works in Haiku
slouken@4164
   642
#else
slouken@4164
   643
				if (get_image_symbol((image_id)cookie,"glBegin",B_SYMBOL_TYPE_ANY,&location) == B_OK) { // I don't know if that *did* work in BeOS
slouken@4164
   644
#endif
slouken@4164
   645
					_this->gl_config.dll_handle = (void*)info.id;
slouken@906
   646
					_this->gl_config.driver_loaded = 1;
slouken@1572
   647
					SDL_strlcpy(_this->gl_config.driver_path, "libGL.so", SDL_arraysize(_this->gl_config.driver_path));
slouken@906
   648
				}
slouken@906
   649
			}
slouken@906
   650
		}
slouken@906
   651
	} else {
slouken@906
   652
		/*
slouken@906
   653
			FIXME None of BeOS libGL.so implementations have exported functions 
slouken@906
   654
			to load BGLView, which should be reloaded from new lib.
slouken@906
   655
			So for now just "load" linked libGL.so :(
slouken@906
   656
		*/
slouken@906
   657
		if (_this->gl_config.dll_handle == NULL) {
slouken@906
   658
			return BE_GL_LoadLibrary(_this, NULL);
slouken@906
   659
		}
slouken@906
   660
slouken@906
   661
		/* Unload old first */
slouken@906
   662
		/*if (_this->gl_config.dll_handle != NULL) {*/
slouken@906
   663
			/* Do not try to unload application itself (if LoadLibrary was called before with NULL ;) */
slouken@906
   664
		/*	image_info info;
slouken@906
   665
			if (get_image_info((image_id)_this->gl_config.dll_handle, &info) == B_OK) {
slouken@906
   666
				if (info.type != B_APP_IMAGE) {
slouken@906
   667
					unload_add_on((image_id)_this->gl_config.dll_handle);
slouken@906
   668
				}
slouken@906
   669
			}
slouken@906
   670
			
slouken@906
   671
		}
slouken@906
   672
slouken@906
   673
		if ((_this->gl_config.dll_handle = (void*)load_add_on(path)) != (void*)B_ERROR) {
slouken@906
   674
			_this->gl_config.driver_loaded = 1;
slouken@1572
   675
			SDL_strlcpy(_this->gl_config.driver_path, path, SDL_arraysize(_this->gl_config.driver_path));
slouken@906
   676
		}*/
slouken@906
   677
	}
slouken@906
   678
slouken@906
   679
	if (_this->gl_config.dll_handle != NULL) {
slouken@906
   680
		return 0;
slouken@906
   681
	} else {
slouken@906
   682
		_this->gl_config.dll_handle = NULL;
slouken@906
   683
		_this->gl_config.driver_loaded = 0;
slouken@1572
   684
		*_this->gl_config.driver_path = '\0';
slouken@906
   685
		return -1;
slouken@906
   686
	}
slouken@906
   687
}
slouken@906
   688
slouken@906
   689
void* BE_GL_GetProcAddress(_THIS, const char *proc)
slouken@906
   690
{
slouken@906
   691
	if (_this->gl_config.dll_handle != NULL) {
slouken@906
   692
		void *location = NULL;
slouken@906
   693
		status_t err;
slouken@906
   694
		if ((err = get_image_symbol((image_id)_this->gl_config.dll_handle, proc, B_SYMBOL_TYPE_ANY, &location)) == B_OK) {
slouken@906
   695
			return location;
slouken@906
   696
		} else {
slouken@906
   697
			SDL_SetError("Couldn't find OpenGL symbol");
slouken@906
   698
			return NULL;
slouken@906
   699
		}
slouken@906
   700
	} else {
slouken@906
   701
		SDL_SetError("OpenGL library not loaded");
slouken@906
   702
		return NULL;
slouken@906
   703
	}
slouken@906
   704
}
slouken@906
   705
slouken@906
   706
int BE_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value)
slouken@906
   707
{
slouken@906
   708
	/*
slouken@906
   709
		FIXME? Right now BE_GL_GetAttribute shouldn't be called between glBegin() and glEnd() - it doesn't use "cached" values
slouken@906
   710
	*/
slouken@906
   711
	switch (attrib)
slouken@906
   712
    {
slouken@906
   713
		case SDL_GL_RED_SIZE:
slouken@906
   714
			glGetIntegerv(GL_RED_BITS, (GLint*)value);
slouken@906
   715
			break;
slouken@906
   716
		case SDL_GL_GREEN_SIZE:
slouken@906
   717
			glGetIntegerv(GL_GREEN_BITS, (GLint*)value);
slouken@906
   718
			break;
slouken@906
   719
		case SDL_GL_BLUE_SIZE:
slouken@906
   720
			glGetIntegerv(GL_BLUE_BITS, (GLint*)value);
slouken@906
   721
			break;
slouken@906
   722
		case SDL_GL_ALPHA_SIZE:
slouken@906
   723
			glGetIntegerv(GL_ALPHA_BITS, (GLint*)value);
slouken@906
   724
			break;
slouken@906
   725
		case SDL_GL_DOUBLEBUFFER:
slouken@906
   726
			glGetBooleanv(GL_DOUBLEBUFFER, (GLboolean*)value);
slouken@906
   727
			break;
slouken@906
   728
		case SDL_GL_BUFFER_SIZE:
slouken@906
   729
			int v;
slouken@906
   730
			glGetIntegerv(GL_RED_BITS, (GLint*)&v);
slouken@906
   731
			*value = v;
slouken@906
   732
			glGetIntegerv(GL_GREEN_BITS, (GLint*)&v);
slouken@906
   733
			*value += v;
slouken@906
   734
			glGetIntegerv(GL_BLUE_BITS, (GLint*)&v);
slouken@906
   735
			*value += v;
slouken@906
   736
			glGetIntegerv(GL_ALPHA_BITS, (GLint*)&v);
slouken@906
   737
			*value += v;
slouken@906
   738
			break;
slouken@906
   739
		case SDL_GL_DEPTH_SIZE:
slouken@906
   740
			glGetIntegerv(GL_DEPTH_BITS, (GLint*)value); /* Mesa creates 16 only? r5 always 32 */
slouken@906
   741
			break;
slouken@906
   742
		case SDL_GL_STENCIL_SIZE:
slouken@906
   743
			glGetIntegerv(GL_STENCIL_BITS, (GLint*)value);
slouken@906
   744
			break;
slouken@906
   745
		case SDL_GL_ACCUM_RED_SIZE:
slouken@906
   746
			glGetIntegerv(GL_ACCUM_RED_BITS, (GLint*)value);
slouken@906
   747
			break;
slouken@906
   748
		case SDL_GL_ACCUM_GREEN_SIZE:
slouken@906
   749
			glGetIntegerv(GL_ACCUM_GREEN_BITS, (GLint*)value);
slouken@906
   750
			break;
slouken@906
   751
		case SDL_GL_ACCUM_BLUE_SIZE:
slouken@906
   752
			glGetIntegerv(GL_ACCUM_BLUE_BITS, (GLint*)value);
slouken@906
   753
			break;
slouken@906
   754
		case SDL_GL_ACCUM_ALPHA_SIZE:
slouken@906
   755
			glGetIntegerv(GL_ACCUM_ALPHA_BITS, (GLint*)value);
slouken@906
   756
			break;
slouken@906
   757
		case SDL_GL_STEREO:
slouken@906
   758
		case SDL_GL_MULTISAMPLEBUFFERS:
slouken@906
   759
		case SDL_GL_MULTISAMPLESAMPLES:
slouken@906
   760
		default:
slouken@906
   761
			*value=0;
slouken@906
   762
			return(-1);
slouken@906
   763
	}
slouken@906
   764
	return 0;
slouken@906
   765
}
slouken@906
   766
slouken@906
   767
int BE_GL_MakeCurrent(_THIS)
slouken@906
   768
{
slouken@906
   769
	/* FIXME: should we glview->unlock and then glview->lock()? */
slouken@906
   770
	return 0;
slouken@906
   771
}
slouken@906
   772
slouken@0
   773
void BE_GL_SwapBuffers(_THIS)
slouken@0
   774
{
slouken@0
   775
	SDL_Win->SwapBuffers();
slouken@0
   776
}
slouken@0
   777
#endif
slouken@0
   778
slouken@0
   779
/* Is the system palette settable? */
slouken@0
   780
int BE_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
slouken@0
   781
{
slouken@0
   782
	int i;
slouken@0
   783
	SDL_Palette *palette;
slouken@0
   784
	const color_map *cmap = BScreen().ColorMap();
slouken@0
   785
slouken@0
   786
	/* Get the screen colormap */
slouken@0
   787
	palette = _this->screen->format->palette;
slouken@0
   788
	for ( i=0; i<256; ++i ) {
slouken@0
   789
		palette->colors[i].r = cmap->color_list[i].red;
slouken@0
   790
		palette->colors[i].g = cmap->color_list[i].green;
slouken@0
   791
		palette->colors[i].b = cmap->color_list[i].blue;
slouken@0
   792
	}
slouken@0
   793
	return(0);
slouken@0
   794
}
slouken@0
   795
slouken@0
   796
void BE_VideoQuit(_THIS)
slouken@0
   797
{
slouken@0
   798
	int i, j;
slouken@0
   799
slouken@906
   800
	SDL_Win->Quit();
slouken@906
   801
	SDL_Win = NULL;
slouken@906
   802
slouken@0
   803
	if ( SDL_BlankCursor != NULL ) {
slouken@0
   804
		BE_FreeWMCursor(_this, SDL_BlankCursor);
slouken@0
   805
		SDL_BlankCursor = NULL;
slouken@0
   806
	}
slouken@0
   807
	for ( i=0; i<NUM_MODELISTS; ++i ) {
slouken@0
   808
		if ( SDL_modelist[i] ) {
slouken@0
   809
			for ( j=0; SDL_modelist[i][j]; ++j ) {
slouken@1336
   810
				SDL_free(SDL_modelist[i][j]);
slouken@0
   811
			}
slouken@1336
   812
			SDL_free(SDL_modelist[i]);
slouken@0
   813
			SDL_modelist[i] = NULL;
slouken@0
   814
		}
slouken@0
   815
	}
slouken@0
   816
	/* Restore the original video mode */
slouken@0
   817
	if ( _this->screen ) {
slouken@0
   818
		if ( (_this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
slouken@0
   819
			BScreen bscreen;
slouken@0
   820
			bscreen.SetMode(&saved_mode);
slouken@0
   821
		}
slouken@0
   822
		_this->screen->pixels = NULL;
slouken@0
   823
	}
slouken@906
   824
slouken@1361
   825
#if SDL_VIDEO_OPENGL
slouken@906
   826
	if (_this->gl_config.dll_handle != NULL)
slouken@906
   827
		unload_add_on((image_id)_this->gl_config.dll_handle);
slouken@906
   828
#endif
slouken@906
   829
slouken@0
   830
	SDL_QuitBeApp();
slouken@0
   831
}
slouken@0
   832
slouken@0
   833
}; /* Extern C */