From 88b4ab52ad9e58bd6ee8bcb10ab3f88613ea7817 Mon Sep 17 00:00:00 2001
From: Randy Heit <rheit@zdoom.fake>
Date: Wed, 2 Dec 2009 05:49:45 +0000
Subject: [PATCH] - For windowed and pixel doubled modes, use a chain of two
 TempRenderTextures and   swap between them each frame. The one that's not the
 TempRenderTexture is used   as the FrontCopySurface without the need for a
 copy operation. This removes the   performance penalty the previous commit
 introduced for these modes.

SVN r2014 (trunk)
---
 src/win32/fb_d3d9.cpp      | 61 ++++++++++++++++++++++++++------------
 src/win32/fb_d3d9_wipe.cpp | 16 +++++-----
 src/win32/win32iface.h     |  4 ++-
 3 files changed, 53 insertions(+), 28 deletions(-)

diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp
index 9c34db2bd..561891e29 100644
--- a/src/win32/fb_d3d9.cpp
+++ b/src/win32/fb_d3d9.cpp
@@ -247,6 +247,8 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
 	IndexBuffer = NULL;
 	FBTexture = NULL;
 	TempRenderTexture = NULL;
+	RenderTexture[0] = NULL;
+	RenderTexture[1] = NULL;
 	InitialWipeScreen = NULL;
 	ScreenshotTexture = NULL;
 	ScreenshotSurface = NULL;
@@ -277,6 +279,8 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
 	Packs = NULL;
 	PixelDoubling = 0;
 	SkipAt = -1;
+	CurrRenderTexture = 0;
+	RenderTextureToggle = 0;
 
 	Gamma = 1.0;
 	FlashColor0 = 0;
@@ -624,15 +628,9 @@ void D3DFB::ReleaseResources ()
 void D3DFB::ReleaseDefaultPoolItems()
 {
 	SAFE_RELEASE( FBTexture );
-	if (FinalWipeScreen != NULL)
-	{
-		if (FinalWipeScreen != TempRenderTexture)
-		{
-			FinalWipeScreen->Release();
-		}
-		FinalWipeScreen = NULL;
-	}
-	SAFE_RELEASE( TempRenderTexture );
+	SAFE_RELEASE( FinalWipeScreen );
+	SAFE_RELEASE( RenderTexture[0] );
+	SAFE_RELEASE( RenderTexture[1] );
 	SAFE_RELEASE( InitialWipeScreen );
 	SAFE_RELEASE( VertexBuffer );
 	SAFE_RELEASE( IndexBuffer );
@@ -772,24 +770,42 @@ bool D3DFB::CreateFBTexture ()
 		FBWidth = Width;
 		FBHeight = Height;
 	}
-	if (FAILED(D3DDevice->CreateTexture(FBWidth, FBHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &TempRenderTexture, NULL)))
+	RenderTextureToggle = 0;
+	RenderTexture[0] = NULL;
+	RenderTexture[1] = NULL;
+	if (FAILED(D3DDevice->CreateTexture(FBWidth, FBHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &RenderTexture[0], NULL)))
 	{
-		TempRenderTexture = NULL;
+		return false;
+	}
+	if (Windowed || PixelDoubling)
+	{
+		// Windowed or pixel doubling: Create another render texture so we can flip between them.
+		RenderTextureToggle = 1;
+		if (FAILED(D3DDevice->CreateTexture(FBWidth, FBHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &RenderTexture[1], NULL)))
+		{
+			return false;
+		}
 	}
 	else
 	{
-		// Initialize the TempRenderTexture to black.
+		// Fullscreen and not pixel doubling: Create a render target to have the back buffer copied to.
+		if (FAILED(D3DDevice->CreateRenderTarget(Width, Height, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &FrontCopySurface, NULL)))
+		{
+			return false;
+		}
+	}
+	// Initialize the TempRenderTextures to black.
+	for (int i = 0; i <= RenderTextureToggle; ++i)
+	{
 		IDirect3DSurface9 *surf;
-		if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &surf)))
+		if (SUCCEEDED(RenderTexture[i]->GetSurfaceLevel(0, &surf)))
 		{
 			D3DDevice->ColorFill(surf, NULL, D3DCOLOR_XRGB(0,0,0));
 			surf->Release();
 		}
 	}
-	if (FAILED(D3DDevice->CreateRenderTarget(Width, Height, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &FrontCopySurface, NULL)))
-	{
-		return false;
-	}
+	TempRenderTexture = RenderTexture[0];
+	CurrRenderTexture = 0;
 	return true;
 }
 
@@ -1179,6 +1195,13 @@ void D3DFB::Flip()
 	}
 	D3DDevice->Present(NULL, NULL, NULL, NULL);
 	InScene = false;
+
+	if (RenderTextureToggle)
+	{
+		// Flip the TempRenderTexture to the other one now.
+		CurrRenderTexture ^= RenderTextureToggle;
+		TempRenderTexture = RenderTexture[CurrRenderTexture];
+	}
 }
 
 //==========================================================================
@@ -1198,10 +1221,10 @@ void D3DFB::CopyNextFrontBuffer()
 	if (Windowed || PixelDoubling)
 	{
 		// Windowed mode or pixel doubling: TempRenderTexture has what we want
+		SAFE_RELEASE( FrontCopySurface );
 		if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &backbuff)))
 		{
-			D3DDevice->StretchRect(backbuff, NULL, FrontCopySurface, NULL, D3DTEXF_NONE);
-			backbuff->Release();
+			FrontCopySurface = backbuff;
 		}
 	}
 	else
diff --git a/src/win32/fb_d3d9_wipe.cpp b/src/win32/fb_d3d9_wipe.cpp
index 798a95080..9a3b34412 100644
--- a/src/win32/fb_d3d9_wipe.cpp
+++ b/src/win32/fb_d3d9_wipe.cpp
@@ -173,14 +173,14 @@ bool D3DFB::WipeStartScreen(int type)
 					1, D3DUSAGE_RENDERTARGET, desc.Format, D3DPOOL_DEFAULT,
 					&FinalWipeScreen, NULL)))
 			{
-				FinalWipeScreen = TempRenderTexture;
+				(FinalWipeScreen = TempRenderTexture)->AddRef();
 			}
 			tsurf->Release();
 		}
 	}
 	else
 	{
-		FinalWipeScreen = TempRenderTexture;
+		(FinalWipeScreen = TempRenderTexture)->AddRef();
 	}
 
 	// Make even fullscreen model render to the TempRenderTexture, so
@@ -229,7 +229,11 @@ void D3DFB::WipeEndScreen()
 
 	// If these are different, reverse their roles so we don't need to
 	// waste time copying from TempRenderTexture to FinalWipeScreen.
-	swap(FinalWipeScreen, TempRenderTexture);
+	if (FinalWipeScreen != TempRenderTexture)
+	{
+		swap(RenderTexture[CurrRenderTexture], FinalWipeScreen);
+		TempRenderTexture = RenderTexture[CurrRenderTexture];
+	}
 
 	// At this point, InitialWipeScreen holds the screen we are wiping from.
 	// FinalWipeScreen holds the screen we are wiping to, which may be the
@@ -315,11 +319,7 @@ void D3DFB::WipeCleanup()
 		ScreenWipe = NULL;
 	}
 	SAFE_RELEASE( InitialWipeScreen );
-	if (FinalWipeScreen != NULL && FinalWipeScreen != TempRenderTexture)
-	{
-		FinalWipeScreen->Release();
-	}
-	FinalWipeScreen = NULL;
+	SAFE_RELEASE( FinalWipeScreen );
 	GatheringWipeScreen = false;
 	if (!Accel2D)
 	{
diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h
index e311049b7..9bdfd1072 100644
--- a/src/win32/win32iface.h
+++ b/src/win32/win32iface.h
@@ -395,6 +395,8 @@ private:
 	int PixelDoubling;
 	int SkipAt;
 	int LBOffsetI;
+	int RenderTextureToggle;
+	int CurrRenderTexture;
 	float LBOffset;
 	float Gamma;
 	bool UpdatePending;
@@ -415,7 +417,7 @@ private:
 
 	IDirect3DDevice9 *D3DDevice;
 	IDirect3DTexture9 *FBTexture;
-	IDirect3DTexture9 *TempRenderTexture;
+	IDirect3DTexture9 *TempRenderTexture, *RenderTexture[2];
 	IDirect3DTexture9 *PaletteTexture;
 	IDirect3DTexture9 *GammaTexture;
 	IDirect3DTexture9 *ScreenshotTexture;