cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_bmodes.cc (8243B)


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