changeset 18170:37c6cc37533d draft

(svn r22999) -Codechange: Allow changing the blitter during the running game.
author michi_cc <michi_cc@openttd.org>
date Tue, 04 Oct 2011 21:35:40 +0000
parents c0dd5603dfd4
children 00edd5060cd9
files src/video/allegro_v.cpp src/video/allegro_v.h src/video/cocoa/cocoa_v.h src/video/cocoa/cocoa_v.mm src/video/cocoa/fullscreen.mm src/video/cocoa/wnd_quartz.mm src/video/cocoa/wnd_quickdraw.mm src/video/sdl_v.cpp src/video/sdl_v.h src/video/video_driver.hpp src/video/win32_v.cpp src/video/win32_v.h
diffstat 12 files changed, 97 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/src/video/allegro_v.cpp
+++ b/src/video/allegro_v.cpp
@@ -555,4 +555,9 @@
 #endif
 }
 
+bool VideoDriver_Allegro::AfterBlitterChange()
+{
+	return CreateMainSurface(_screen.width, _screen.height);
+}
+
 #endif /* WITH_ALLEGRO */
--- a/src/video/allegro_v.h
+++ b/src/video/allegro_v.h
@@ -28,6 +28,9 @@
 	/* virtual */ bool ChangeResolution(int w, int h);
 
 	/* virtual */ bool ToggleFullscreen(bool fullscreen);
+
+	/* virtual */ bool AfterBlitterChange();
+
 	/* virtual */ const char *GetName() const { return "allegro"; }
 };
 
--- a/src/video/cocoa/cocoa_v.h
+++ b/src/video/cocoa/cocoa_v.h
@@ -47,6 +47,11 @@
 	 */
 	/* virtual */ bool ToggleFullscreen(bool fullscreen);
 
+	/** Callback invoked after the blitter was changed.
+	 * @return True if no error.
+	 */
+	/* virtual */ bool AfterBlitterChange();
+
 	/** Return driver name
 	 * @return driver name
 	 */
@@ -123,7 +128,7 @@
 	 * @param h New window height
 	 * @return Whether change was successful
 	 */
-	virtual bool ChangeResolution(int w, int h) = 0;
+	virtual bool ChangeResolution(int w, int h, int bpp) = 0;
 
 	/** Are we in fullscreen mode
 	 * @return whether fullscreen mode is currently used
--- a/src/video/cocoa/cocoa_v.mm
+++ b/src/video/cocoa/cocoa_v.mm
@@ -400,7 +400,7 @@
 {
 	assert(_cocoa_subdriver != NULL);
 
-	bool ret = _cocoa_subdriver->ChangeResolution(w, h);
+	bool ret = _cocoa_subdriver->ChangeResolution(w, h, BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth());
 
 	QZ_GameSizeChanged();
 	QZ_UpdateVideoModes();
@@ -444,6 +444,16 @@
 }
 
 /**
+ * Callback invoked after the blitter was changed.
+ *
+ * @return True if no error.
+ */
+bool VideoDriver_Cocoa::AfterBlitterChange()
+{
+	return this->ChangeResolution(_screen.width, _screen.height);
+}
+
+/**
  * Catch asserts prior to initialization of the videodriver.
  *
  * @param title Window title.
--- a/src/video/cocoa/fullscreen.mm
+++ b/src/video/cocoa/fullscreen.mm
@@ -250,7 +250,7 @@
 	}
 
 
-	bool SetVideoMode(int w, int h)
+	bool SetVideoMode(int w, int h, int bpp)
 	{
 		/* Define this variables at the top (against coding style) because
 		 * otherwise GCC 4.2 barfs at the goto's jumping over variable initialization. */
@@ -266,14 +266,14 @@
 
 		/* See if requested mode exists */
 		boolean_t exact_match;
-		this->cur_mode = CGDisplayBestModeForParameters(this->display_id, this->device_depth, w, h, &exact_match);
+		this->cur_mode = CGDisplayBestModeForParameters(this->display_id, bpp, w, h, &exact_match);
 
 		/* If the mode wasn't an exact match, check if it has the right bpp, and update width and height */
 		if (!exact_match) {
-			int bpp;
+			int act_bpp;
 			CFNumberRef number = (const __CFNumber*) CFDictionaryGetValue(this->cur_mode, kCGDisplayBitsPerPixel);
-			CFNumberGetValue(number, kCFNumberSInt32Type, &bpp);
-			if (bpp != this->device_depth) {
+			CFNumberGetValue(number, kCFNumberSInt32Type, &act_bpp);
+			if (act_bpp != bpp) {
 				DEBUG(driver, 0, "Failed to find display resolution");
 				goto ERR_NO_MATCH;
 			}
@@ -323,6 +323,7 @@
 
 		this->device_width  = CGDisplayPixelsWide(this->display_id);
 		this->device_height = CGDisplayPixelsHigh(this->display_id);
+		this->device_depth  = bpp;
 
 		/* Setup double-buffer emulation */
 		this->pixel_buffer = malloc(this->device_width * this->device_height * this->device_depth / 8);
@@ -418,22 +419,18 @@
 	}
 
 public:
-	FullscreenSubdriver(int bpp)
+	FullscreenSubdriver()
 	{
-		if (bpp != 8 && bpp != 32) {
-			error("Cocoa: This video driver only supports 8 and 32 bpp blitters.");
-		}
-
 		/* Initialize the video settings; this data persists between mode switches */
 		this->display_id = kCGDirectMainDisplay;
 		this->save_mode  = CGDisplayCurrentMode(this->display_id);
 
-		if (bpp == 8) this->palette = CGPaletteCreateDefaultColorPalette();
+		this->palette = CGPaletteCreateDefaultColorPalette();
 
 		this->device_width  = CGDisplayPixelsWide(this->display_id);
 		this->device_height = CGDisplayPixelsHigh(this->display_id);
-		this->device_depth  = bpp;
-		this->pixel_buffer   = NULL;
+		this->device_depth  = 0;
+		this->pixel_buffer  = NULL;
 
 		this->num_dirty_rects = MAX_DIRTY_RECTS;
 	}
@@ -512,14 +509,16 @@
 		return QZ_ListModes(modes, max_modes, this->display_id, this->device_depth);
 	}
 
-	virtual bool ChangeResolution(int w, int h)
+	virtual bool ChangeResolution(int w, int h, int bpp)
 	{
 		int old_width  = this->device_width;
 		int old_height = this->device_height;
+		int old_bpp    = this->device_depth;
 
-		if (SetVideoMode(w, h)) return true;
+		if (bpp != 8 && bpp != 32) error("Cocoa: This video driver only supports 8 and 32 bpp blitters.");
 
-		if (old_width != 0 && old_height != 0) SetVideoMode(old_width, old_height);
+		if (SetVideoMode(w, h, bpp)) return true;
+		if (old_width != 0 && old_height != 0) SetVideoMode(old_width, old_height, old_bpp);
 
 		return false;
 	}
@@ -583,9 +582,9 @@
 		return NULL;
 	}
 
-	FullscreenSubdriver *ret = new FullscreenSubdriver(bpp);
+	FullscreenSubdriver *ret = new FullscreenSubdriver();
 
-	if (!ret->ChangeResolution(width, height)) {
+	if (!ret->ChangeResolution(width, height, bpp)) {
 		delete ret;
 		return NULL;
 	}
--- a/src/video/cocoa/wnd_quartz.mm
+++ b/src/video/cocoa/wnd_quartz.mm
@@ -63,10 +63,10 @@
 	void BlitIndexedToView32(int left, int top, int right, int bottom);
 
 	virtual void GetDeviceInfo();
-	virtual bool SetVideoMode(int width, int height);
+	virtual bool SetVideoMode(int width, int height, int bpp);
 
 public:
-	WindowQuartzSubdriver(int bpp);
+	WindowQuartzSubdriver();
 	virtual ~WindowQuartzSubdriver();
 
 	virtual void Draw(bool force_update);
@@ -75,7 +75,7 @@
 
 	virtual uint ListModes(OTTD_Point *modes, uint max_modes);
 
-	virtual bool ChangeResolution(int w, int h);
+	virtual bool ChangeResolution(int w, int h, int bpp);
 
 	virtual bool IsFullscreen() { return false; }
 	virtual bool ToggleFullscreen(); /* Full screen mode on OSX 10.7 */
@@ -248,7 +248,7 @@
 #endif
 }
 
-bool WindowQuartzSubdriver::SetVideoMode(int width, int height)
+bool WindowQuartzSubdriver::SetVideoMode(int width, int height, int bpp)
 {
 	this->setup = true;
 	this->GetDeviceInfo();
@@ -337,6 +337,7 @@
 
 	this->window_width = width;
 	this->window_height = height;
+	this->buffer_depth = bpp;
 
 	[ this->window center ];
 
@@ -381,11 +382,11 @@
 }
 
 
-WindowQuartzSubdriver::WindowQuartzSubdriver(int bpp)
+WindowQuartzSubdriver::WindowQuartzSubdriver()
 {
 	this->window_width  = 0;
 	this->window_height = 0;
-	this->buffer_depth  = bpp;
+	this->buffer_depth  = 0;
 	this->window_buffer  = NULL;
 	this->pixel_buffer  = NULL;
 	this->active        = false;
@@ -481,13 +482,14 @@
 	return QZ_ListModes(modes, max_modes, kCGDirectMainDisplay, this->buffer_depth);
 }
 
-bool WindowQuartzSubdriver::ChangeResolution(int w, int h)
+bool WindowQuartzSubdriver::ChangeResolution(int w, int h, int bpp)
 {
 	int old_width  = this->window_width;
 	int old_height = this->window_height;
+	int old_bpp    = this->buffer_depth;
 
-	if (this->SetVideoMode(w, h)) return true;
-	if (old_width != 0 && old_height != 0) this->SetVideoMode(old_width, old_height);
+	if (this->SetVideoMode(w, h, bpp)) return true;
+	if (old_width != 0 && old_height != 0) this->SetVideoMode(old_width, old_height, old_bpp);
 
 	return false;
 }
@@ -599,9 +601,9 @@
 		return NULL;
 	}
 
-	WindowQuartzSubdriver *ret = new WindowQuartzSubdriver(bpp);
+	WindowQuartzSubdriver *ret = new WindowQuartzSubdriver();
 
-	if (!ret->ChangeResolution(width, height)) {
+	if (!ret->ChangeResolution(width, height, bpp)) {
 		delete ret;
 		return NULL;
 	}
--- a/src/video/cocoa/wnd_quickdraw.mm
+++ b/src/video/cocoa/wnd_quickdraw.mm
@@ -81,10 +81,10 @@
 	void DrawResizeIcon();
 
 	virtual void GetDeviceInfo();
-	virtual bool SetVideoMode(int width, int height);
+	virtual bool SetVideoMode(int width, int height, int bpp);
 
 public:
-	WindowQuickdrawSubdriver(int bpp);
+	WindowQuickdrawSubdriver();
 	virtual ~WindowQuickdrawSubdriver();
 
 	virtual void Draw(bool force_update);
@@ -93,7 +93,7 @@
 
 	virtual uint ListModes(OTTD_Point *modes, uint max_modes);
 
-	virtual bool ChangeResolution(int w, int h);
+	virtual bool ChangeResolution(int w, int h, int bpp);
 
 	virtual bool IsFullscreen() { return false; }
 
@@ -152,12 +152,12 @@
 		kCFNumberSInt32Type, &this->device_height);
 }
 
-bool WindowQuickdrawSubdriver::SetVideoMode(int width, int height)
+bool WindowQuickdrawSubdriver::SetVideoMode(int width, int height, int bpp)
 {
 	this->setup = true;
 	this->GetDeviceInfo();
 
-	if (this->buffer_depth > this->device_depth) {
+	if (bpp > this->device_depth) {
 		DEBUG(driver, 0, "Cannot use a blitter with a higer screen depth than the display when running in windowed mode.");
 		this->setup = false;
 		return false;
@@ -217,6 +217,7 @@
 	/* Update again */
 	this->window_width = width;
 	this->window_height = height;
+	this->buffer_depth = bpp;
 
 	[ this->window center ];
 
@@ -335,11 +336,11 @@
 }
 
 
-WindowQuickdrawSubdriver::WindowQuickdrawSubdriver(int bpp)
+WindowQuickdrawSubdriver::WindowQuickdrawSubdriver()
 {
 	this->window_width  = 0;
 	this->window_height = 0;
-	this->buffer_depth  = bpp;
+	this->buffer_depth  = 0;
 	this->pixel_buffer  = NULL;
 	this->active        = false;
 	this->setup         = false;
@@ -440,14 +441,15 @@
 	return QZ_ListModes(modes, max_modes, kCGDirectMainDisplay, this->buffer_depth);
 }
 
-bool WindowQuickdrawSubdriver::ChangeResolution(int w, int h)
+bool WindowQuickdrawSubdriver::ChangeResolution(int w, int h, int bpp)
 {
 	int old_width  = this->window_width;
 	int old_height = this->window_height;
+	int old_bpp    = this->buffer_depth;
 
-	if (this->SetVideoMode(w, h)) return true;
+	if (this->SetVideoMode(w, h, bpp)) return true;
 
-	if (old_width != 0 && old_height != 0) this->SetVideoMode(old_width, old_height);
+	if (old_width != 0 && old_height != 0) this->SetVideoMode(old_width, old_height, old_bpp);
 
 	return false;
 }
@@ -544,9 +546,9 @@
 		return NULL;
 	}
 
-	ret = new WindowQuickdrawSubdriver(bpp);
+	ret = new WindowQuickdrawSubdriver();
 
-	if (!ret->ChangeResolution(width, height)) {
+	if (!ret->ChangeResolution(width, height, bpp)) {
 		delete ret;
 		return NULL;
 	}
--- a/src/video/sdl_v.cpp
+++ b/src/video/sdl_v.cpp
@@ -635,4 +635,9 @@
 	return true;
 }
 
+bool VideoDriver_SDL::AfterBlitterChange()
+{
+	return this->ChangeResolution(_screen.width, _screen.height)
+}
+
 #endif /* WITH_SDL */
--- a/src/video/sdl_v.h
+++ b/src/video/sdl_v.h
@@ -28,6 +28,9 @@
 	/* virtual */ bool ChangeResolution(int w, int h);
 
 	/* virtual */ bool ToggleFullscreen(bool fullscreen);
+
+	/* virtual */ bool AfterBlitterChange();
+
 	/* virtual */ const char *GetName() const { return "sdl"; }
 };
 
--- a/src/video/video_driver.hpp
+++ b/src/video/video_driver.hpp
@@ -48,6 +48,15 @@
 	virtual bool ToggleFullscreen(bool fullscreen) = 0;
 
 	/**
+	 * Callback invoked after the blitter was changed.
+	 * @return True if no error.
+	 */
+	virtual bool AfterBlitterChange()
+	{
+		return true;
+	}
+
+	/**
 	 * Whether the driver has a graphical user interface with the end user.
 	 * Or in other words, whether we should spawn a thread for world generation
 	 * and NewGRF scanning so the graphical updates can keep coming. Otherwise
--- a/src/video/win32_v.cpp
+++ b/src/video/win32_v.cpp
@@ -149,7 +149,7 @@
 	return key;
 }
 
-static bool AllocateDibSection(int w, int h);
+static bool AllocateDibSection(int w, int h, bool force = false);
 
 static void ClientSizeChanged(int w, int h)
 {
@@ -690,7 +690,7 @@
 	}
 }
 
-static bool AllocateDibSection(int w, int h)
+static bool AllocateDibSection(int w, int h, bool force)
 {
 	BITMAPINFO *bi;
 	HDC dc;
@@ -701,7 +701,7 @@
 
 	if (bpp == 0) usererror("Can't use a blitter that blits 0 bpp for normal visuals");
 
-	if (w == _screen.width && h == _screen.height) return false;
+	if (!force && w == _screen.width && h == _screen.height) return false;
 
 	_screen.width = w;
 	_screen.pitch = (bpp == 8) ? Align(w, 4) : w;
@@ -927,3 +927,8 @@
 {
 	return this->MakeWindow(full_screen);
 }
+
+bool VideoDriver_Win32::AfterBlitterChange()
+{
+	return AllocateDibSection(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen);
+}
--- a/src/video/win32_v.h
+++ b/src/video/win32_v.h
@@ -28,6 +28,9 @@
 	/* virtual */ bool ChangeResolution(int w, int h);
 
 	/* virtual */ bool ToggleFullscreen(bool fullscreen);
+
+	/* virtual */ bool AfterBlitterChange();
+
 	/* virtual */ const char *GetName() const { return "win32"; }
 
 	bool MakeWindow(bool full_screen);