Beispiel #1
0
 VideoWrapper::VideoWrapper(SDL_Window *window, osg::ref_ptr<osgViewer::Viewer> viewer)
     : mWindow(window)
     , mViewer(viewer)
     , mGamma(1.f)
     , mContrast(1.f)
     , mHasSetGammaContrast(false)
 {
     SDL_GetWindowGammaRamp(mWindow, mOldSystemGammaRamp, &mOldSystemGammaRamp[256], &mOldSystemGammaRamp[512]);
 }
Beispiel #2
0
/**
 * TODO documentation
 */
bool GLimp_GetGammaRamp( size_t stride, unsigned short *psize, unsigned short *ramp )
{
	unsigned short ramp256[3 * 256];

	if( stride < 256 ) {
		// SDL only supports gamma ramps with 256 mappings per channel
		return false;
	}

	if( SDL_GetWindowGammaRamp( glw_state.sdl_window, ramp256, ramp256 + 256, ramp256 + ( 256 << 1 ) ) != -1 ) {
		*psize = 256;
		memcpy( ramp, ramp256, 256 * sizeof( *ramp ) );
		memcpy( ramp + stride, ramp256 + 256, 256 * sizeof( *ramp ) );
		memcpy( ramp + 2 * stride, ramp256 + 2 * 256, 256 * sizeof( *ramp ) );
	}
	return false;
}
Beispiel #3
0
void VID_StartupGamma( void )
{
	// Device supports gamma anyway, but cannot do anything with it.
	fs_offset_t	gamma_size;
	byte	*savedGamma;
	size_t	gammaTypeSize = sizeof(glState.stateRamp);

	// init gamma ramp
	Q_memset( glState.stateRamp, 0, gammaTypeSize);

#if defined(XASH_SDL)
	glConfig.deviceSupportsGamma = !SDL_GetWindowGammaRamp( host.hWnd, NULL, NULL, NULL);
#endif

	if( !glConfig.deviceSupportsGamma )
	{
		// force to set cvar
		Cvar_FullSet( "gl_ignorehwgamma", "1", CVAR_GLCONFIG );
		MsgDev( D_ERROR, "VID_StartupGamma: hardware gamma unsupported\n");
	}

	if( gl_ignorehwgamma->integer )
	{
		glConfig.deviceSupportsGamma = false;	// even if supported!
		BuildGammaTable( vid_gamma->value, vid_texgamma->value );
		MsgDev( D_NOTE, "VID_StartupGamma: software gamma initialized\n" );
		return;
	}

	// share this extension so engine can grab them
	GL_SetExtension( GL_HARDWARE_GAMMA_CONTROL, glConfig.deviceSupportsGamma );

	savedGamma = FS_LoadFile( "gamma.dat", &gamma_size, false );

	if( !savedGamma || gamma_size != (fs_offset_t)gammaTypeSize)
	{
		// saved gamma not found or corrupted file
		FS_WriteFile( "gamma.dat", glState.stateRamp, gammaTypeSize);
		MsgDev( D_NOTE, "VID_StartupGamma: gamma.dat initialized\n" );
		if( savedGamma ) Mem_Free( savedGamma );
	}
	else
	{
		GL_BuildGammaTable();

		// validate base gamma
		if( !Q_memcmp( savedGamma, glState.stateRamp, gammaTypeSize))
		{
			// all ok, previous gamma is valid
			MsgDev( D_NOTE, "VID_StartupGamma: validate screen gamma - ok\n" );
		}
		else if( !Q_memcmp( glState.gammaRamp, glState.stateRamp, gammaTypeSize))
		{
			// screen gamma is equal to render gamma (probably previous instance crashed)
			// run additional check to make sure for it
			if( Q_memcmp( savedGamma, glState.stateRamp, gammaTypeSize))
			{
				// yes, current gamma it's totally wrong, restore it from gamma.dat
				MsgDev( D_NOTE, "VID_StartupGamma: restore original gamma after crash\n" );
				Q_memcpy( glState.stateRamp, savedGamma, gammaTypeSize);
			}
			else
			{
				// oops, savedGamma == glState.stateRamp == glState.gammaRamp
				// probably r_gamma set as default
				MsgDev( D_NOTE, "VID_StartupGamma: validate screen gamma - disabled\n" ); 
			}
		}
		else if( !Q_memcmp( glState.gammaRamp, savedGamma, gammaTypeSize))
		{
			// saved gamma is equal render gamma, probably gamma.dat wroted after crash
			// run additional check to make sure it
			if( Q_memcmp( savedGamma, glState.stateRamp, gammaTypeSize))
			{
				// yes, saved gamma it's totally wrong, get origianl gamma from screen
				MsgDev( D_NOTE, "VID_StartupGamma: merge gamma.dat after crash\n" );
				FS_WriteFile( "gamma.dat", glState.stateRamp, gammaTypeSize);
			}
			else
			{
				// oops, savedGamma == glState.stateRamp == glState.gammaRamp
				// probably r_gamma set as default
				MsgDev( D_NOTE, "VID_StartupGamma: validate screen gamma - disabled\n" ); 
			}
		}
		else
		{
			// current gamma unset by other application, so we can restore it here
			MsgDev( D_NOTE, "VID_StartupGamma: restore original gamma after crash\n" );
			Q_memcpy( glState.stateRamp, savedGamma, gammaTypeSize);
		}

		Mem_Free( savedGamma );
	}

	vid_gamma->modified = true;
}
int opengl_init_display_device()
{
	int bpp = gr_screen.bits_per_pixel;

	Assertion((bpp == 16) || (bpp == 32), "Invalid bits-per-pixel value %d!", bpp);

	// screen format
	switch (bpp) {
		case 16: {
			Gr_red.bits = 5;
			Gr_red.shift = 11;
			Gr_red.scale = 8;
			Gr_red.mask = 0xF800;

			Gr_green.bits = 6;
			Gr_green.shift = 5;
			Gr_green.scale = 4;
			Gr_green.mask = 0x7E0;

			Gr_blue.bits = 5;
			Gr_blue.shift = 0;
			Gr_blue.scale = 8;
			Gr_blue.mask = 0x1F;

			break;
		}

		case 32: {
			Gr_red.bits = 8;
			Gr_red.shift = 16;
			Gr_red.scale = 1;
			Gr_red.mask = 0xff0000;

			Gr_green.bits = 8;
			Gr_green.shift = 8;
			Gr_green.scale = 1;
			Gr_green.mask = 0x00ff00;

			Gr_blue.bits = 8;
			Gr_blue.shift = 0;
			Gr_blue.scale = 1;
			Gr_blue.mask = 0x0000ff;

			Gr_alpha.bits = 8;
			Gr_alpha.shift = 24;
			Gr_alpha.mask = 0xff000000;
			Gr_alpha.scale = 1;

			break;
		}
	}

	// texture format
	Gr_t_red.bits = 5;
	Gr_t_red.mask = 0x7c00;
	Gr_t_red.shift = 10;
	Gr_t_red.scale = 8;

	Gr_t_green.bits = 5;
	Gr_t_green.mask = 0x03e0;
	Gr_t_green.shift = 5;
	Gr_t_green.scale = 8;

	Gr_t_blue.bits = 5;
	Gr_t_blue.mask = 0x001f;
	Gr_t_blue.shift = 0;
	Gr_t_blue.scale = 8;

	Gr_t_alpha.bits = 1;
	Gr_t_alpha.mask = 0x8000;
	Gr_t_alpha.scale = 255;
	Gr_t_alpha.shift = 15;

	// alpha-texture format
	Gr_ta_red.bits = 4;
	Gr_ta_red.mask = 0x0f00;
	Gr_ta_red.shift = 8;
	Gr_ta_red.scale = 17;

	Gr_ta_green.bits = 4;
	Gr_ta_green.mask = 0x00f0;
	Gr_ta_green.shift = 4;
	Gr_ta_green.scale = 17;

	Gr_ta_blue.bits = 4;
	Gr_ta_blue.mask = 0x000f;
	Gr_ta_blue.shift = 0;
	Gr_ta_blue.scale = 17;

	Gr_ta_alpha.bits = 4;
	Gr_ta_alpha.mask = 0xf000;
	Gr_ta_alpha.shift = 12;
	Gr_ta_alpha.scale = 17;

	// allocate storage for original gamma settings
	if ( !Cmdline_no_set_gamma && (GL_original_gamma_ramp == NULL) ) {
		GL_original_gamma_ramp = (ushort*) vm_malloc( 3 * 256 * sizeof(ushort), memory::quiet_alloc);

		if (GL_original_gamma_ramp == NULL) {
			mprintf(("  Unable to allocate memory for gamma ramp!  Disabling...\n"));
			Cmdline_no_set_gamma = 1;
		} else {
			// assume identity ramp by default, to be overwritten by true ramp later
			for (ushort x = 0; x < 256; x++) {
				GL_original_gamma_ramp[x] = GL_original_gamma_ramp[x + 256] = GL_original_gamma_ramp[x + 512] = (x << 8) | x;
			}
		}
	}

	os::ViewPortProperties attrs;
	attrs.enable_opengl = true;

	attrs.gl_attributes.major_version = MIN_REQUIRED_GL_VERSION / 10;
	attrs.gl_attributes.minor_version = MIN_REQUIRED_GL_VERSION % 10;

#ifndef NDEBUG
	attrs.gl_attributes.flags.set(os::OpenGLContextFlags::Debug);
#endif

	attrs.gl_attributes.profile = os::OpenGLProfile::Core;

	attrs.display = os_config_read_uint("Video", "Display", 0);
	attrs.width = (uint32_t) gr_screen.max_w;
	attrs.height = (uint32_t) gr_screen.max_h;

	attrs.title = Osreg_title;

	if (!Cmdline_window && ! Cmdline_fullscreen_window) {
		attrs.flags.set(os::ViewPortFlags::Fullscreen);
	} else if (Cmdline_fullscreen_window) {
		attrs.flags.set(os::ViewPortFlags::Borderless);
	}

	auto viewport = gr_opengl_create_viewport(attrs);
	if (!viewport) {
		return 1;
	}

	const int gl_versions[] = { 45, 44, 43, 42, 41, 40, 33, 32 };

	// find the latest and greatest OpenGL context
	for (auto ver : gl_versions)
	{
		auto gl_attrs = attrs.gl_attributes;
		gl_attrs.major_version = ver / 10;
		gl_attrs.minor_version = ver % 10;

		GL_context = graphic_operations->createOpenGLContext(viewport.get(), gl_attrs);

		if (GL_context != nullptr)
		{
			break;
		}
	}

	if (GL_context == nullptr) {
		return 1;
	}

	auto port = os::addViewport(std::move(viewport));
	os::setMainViewPort(port);

	// We can't use gr_use_viewport because that tries to use OpenGL which hasn't been initialized yet
	graphic_operations->makeOpenGLContextCurrent(port, GL_context.get());
	current_viewport = port;

	if (GL_original_gamma_ramp != NULL && os::getSDLMainWindow() != nullptr) {
		SDL_GetWindowGammaRamp( os::getSDLMainWindow(), GL_original_gamma_ramp, (GL_original_gamma_ramp+256),
								(GL_original_gamma_ramp+512) );
	}

	return 0;
}
int SDLHardwareRenderDevice::createContextInternal() {
	bool settings_changed = (fullscreen != settings->fullscreen ||
			                 hwsurface != settings->hwsurface ||
							 vsync != settings->vsync ||
							 texture_filter != settings->texture_filter ||
							 ignore_texture_filter != eset->resolutions.ignore_texture_filter);

	Uint32 w_flags = 0;
	Uint32 r_flags = 0;
	int window_w = settings->screen_w;
	int window_h = settings->screen_h;

	if (settings->fullscreen) {
		w_flags = w_flags | SDL_WINDOW_FULLSCREEN_DESKTOP;

		// make the window the same size as the desktop resolution
		SDL_DisplayMode desktop;
		if (SDL_GetDesktopDisplayMode(0, &desktop) == 0) {
			window_w = desktop.w;
			window_h = desktop.h;
		}
	}
	else if (fullscreen && is_initialized) {
		// if the game was previously in fullscreen, resize the window when returning to windowed mode
		window_w = eset->resolutions.min_screen_w;
		window_h = eset->resolutions.min_screen_h;
		w_flags = w_flags | SDL_WINDOW_SHOWN;
	}
	else {
		w_flags = w_flags | SDL_WINDOW_SHOWN;
	}

	w_flags = w_flags | SDL_WINDOW_RESIZABLE;

	if (settings->hwsurface) {
		r_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
	}
	else {
		r_flags = SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE;
		settings->vsync = false; // can't have software mode & vsync at the same time
	}
	if (settings->vsync) r_flags = r_flags | SDL_RENDERER_PRESENTVSYNC;

	if (settings_changed || !is_initialized) {
		destroyContext();

		window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_w, window_h, w_flags);
		if (window) {
			renderer = SDL_CreateRenderer(window, -1, r_flags);
			if (renderer) {
				if (settings->texture_filter && !eset->resolutions.ignore_texture_filter)
					SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
				else
					SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");

				windowResize();
			}

			SDL_SetWindowMinimumSize(window, eset->resolutions.min_screen_w, eset->resolutions.min_screen_h);
			// setting minimum size might move the window, so set position again
			SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
		}

		if (window && renderer) {
			if (!is_initialized) {
				// save the system gamma levels if we just created the window
				SDL_GetWindowGammaRamp(window, gamma_r, gamma_g, gamma_b);
				Utils::logInfo("RenderDevice: Window size is %dx%d", settings->screen_w, settings->screen_h);
			}

			fullscreen = settings->fullscreen;
			hwsurface = settings->hwsurface;
			vsync = settings->vsync;
			texture_filter = settings->texture_filter;
			ignore_texture_filter = eset->resolutions.ignore_texture_filter;
			is_initialized = true;

			Utils::logInfo("RenderDevice: Fullscreen=%d, Hardware surfaces=%d, Vsync=%d, Texture Filter=%d", fullscreen, hwsurface, vsync, texture_filter);

#if SDL_VERSION_ATLEAST(2, 0, 4)
			SDL_GetDisplayDPI(0, &ddpi, 0, 0);
			Utils::logInfo("RenderDevice: Display DPI is %f", ddpi);
#else
			Utils::logError("RenderDevice: The SDL version used to compile Flare does not support SDL_GetDisplayDPI(). The virtual_dpi setting will be ignored.");
#endif
		}
	}

	if (is_initialized) {
		// update minimum window size if it has changed
		if (min_screen.x != eset->resolutions.min_screen_w || min_screen.y != eset->resolutions.min_screen_h) {
			min_screen.x = eset->resolutions.min_screen_w;
			min_screen.y = eset->resolutions.min_screen_h;
			SDL_SetWindowMinimumSize(window, eset->resolutions.min_screen_w, eset->resolutions.min_screen_h);
			SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
		}

		windowResize();

		// update title bar text and icon
		updateTitleBar();

		// load persistent resources
		delete icons;
		icons = new IconManager();
		delete curs;
		curs = new CursorManager();

		if (settings->change_gamma)
			setGamma(settings->gamma);
		else {
			resetGamma();
			settings->change_gamma = false;
			settings->gamma = 1.0;
		}
	}

	return (is_initialized ? 0 : -1);
}
int SDLHardwareRenderDevice::createContext(bool allow_fallback) {
	bool settings_changed = (fullscreen != FULLSCREEN || hwsurface != HWSURFACE || vsync != VSYNC || texture_filter != TEXTURE_FILTER);

	Uint32 w_flags = 0;
	Uint32 r_flags = 0;
	int window_w = SCREEN_W;
	int window_h = SCREEN_H;

	if (FULLSCREEN) {
		w_flags = w_flags | SDL_WINDOW_FULLSCREEN_DESKTOP;

		// make the window the same size as the desktop resolution
		SDL_DisplayMode desktop;
		if (SDL_GetDesktopDisplayMode(0, &desktop) == 0) {
			window_w = desktop.w;
			window_h = desktop.h;
		}
	}
	else if (fullscreen && is_initialized) {
		// if the game was previously in fullscreen, resize the window when returning to windowed mode
		window_w = MIN_SCREEN_W;
		window_h = MIN_SCREEN_H;
		w_flags = w_flags | SDL_WINDOW_SHOWN;
	}
	else {
		w_flags = w_flags | SDL_WINDOW_SHOWN;
	}

	w_flags = w_flags | SDL_WINDOW_RESIZABLE;

	if (HWSURFACE) {
		r_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
	}
	else {
		r_flags = SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE;
		VSYNC = false; // can't have software mode & vsync at the same time
	}
	if (VSYNC) r_flags = r_flags | SDL_RENDERER_PRESENTVSYNC;

	if (settings_changed || !is_initialized) {
		destroyContext();

		window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_w, window_h, w_flags);
		if (window) {
			renderer = SDL_CreateRenderer(window, -1, r_flags);
			if (renderer) {
				if (TEXTURE_FILTER && !IGNORE_TEXTURE_FILTER)
					SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
				else
					SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");

				windowResize();
			}

			SDL_SetWindowMinimumSize(window, MIN_SCREEN_W, MIN_SCREEN_H);
			// setting minimum size might move the window, so set position again
			SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
		}

		bool window_created = window != NULL && renderer != NULL;

		if (!window_created) {
			if (allow_fallback) {
				// try previous setting first
				FULLSCREEN = fullscreen;
				HWSURFACE = hwsurface;
				VSYNC = vsync;
				TEXTURE_FILTER = texture_filter;
				if (createContext(false) == -1) {
					// last resort, try turning everything off
					FULLSCREEN = false;
					HWSURFACE = false;
					VSYNC = false;
					TEXTURE_FILTER = false;
					int last_resort = createContext(false);
					if (last_resort == -1 && !is_initialized) {
						// If this is the first attempt and it failed we are not
						// getting anywhere.
						logError("SDLHardwareRenderDevice: createContext() failed: %s", SDL_GetError());
						logErrorDialog("SDLHardwareRenderDevice: createContext() failed: %s", SDL_GetError());
						Exit(1);
					}
					return last_resort;
				}
				else {
					return 0;
				}
			}
		}
		else {
			if (!is_initialized) {
				// save the system gamma levels if we just created the window
				SDL_GetWindowGammaRamp(window, gamma_r, gamma_g, gamma_b);
				logInfo("RenderDevice: Window size is %dx%d", SCREEN_W, SCREEN_H);
			}

			fullscreen = FULLSCREEN;
			hwsurface = HWSURFACE;
			vsync = VSYNC;
			texture_filter = TEXTURE_FILTER;
			is_initialized = true;

			logInfo("RenderDevice: Fullscreen=%d, Hardward surfaces=%d, Vsync=%d, Texture Filter=%d", fullscreen, hwsurface, vsync, texture_filter);
		}
	}

	if (is_initialized) {
		// update minimum window size if it has changed
		if (min_screen.x != MIN_SCREEN_W || min_screen.y != MIN_SCREEN_H) {
			min_screen.x = MIN_SCREEN_W;
			min_screen.y = MIN_SCREEN_H;
			SDL_SetWindowMinimumSize(window, MIN_SCREEN_W, MIN_SCREEN_H);
			SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
		}

		windowResize();

		// update title bar text and icon
		updateTitleBar();

		// load persistent resources
		delete icons;
		icons = new IconManager();
		delete curs;
		curs = new CursorManager();

		if (CHANGE_GAMMA)
			setGamma(GAMMA);
		else {
			resetGamma();
			CHANGE_GAMMA = false;
			GAMMA = 1.0;
		}
	}

	return (is_initialized ? 0 : -1);
}
/*	Get gamma level.
	Based on the Darkplaces implementation.
*/
void Window_GetGamma(unsigned short *usRamp, int iRampSize)
{
	if (!SDL_GetWindowGammaRamp(sMainWindow, usRamp, usRamp + iRampSize, usRamp + iRampSize * 2))
		Con_Warning("Failed to get gamma level!\n%s", SDL_GetError());
}