- Since I am currently without a primary video card and stuck with this

Mobility Radeon 9000 (on a PCI card, no less!), I have decided to give the
  PS14 support some loving: D3D windowed gamma now works on these cards using
  a texture lookup for the gamma table. Sadly, this halves my framerate, so
  setting gamma to 1 will skip the gamma correction, as it was before, for
  full speed. (On my 8800 GT, the gamma correction was free.)


SVN r1898 (trunk)
This commit is contained in:
Randy Heit 2009-10-08 04:03:32 +00:00
commit da31d9f8a3
6 changed files with 119 additions and 17 deletions

View file

@ -273,10 +273,12 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
ScreenshotSurface = NULL;
FinalWipeScreen = NULL;
PaletteTexture = NULL;
GammaTexture = NULL;
for (int i = 0; i < NUM_SHADERS; ++i)
{
Shaders[i] = NULL;
}
GammaShader = NULL;
BlockSurface[0] = NULL;
BlockSurface[1] = NULL;
FBFormat = D3DFMT_UNKNOWN;
@ -416,12 +418,17 @@ void D3DFB::SetInitialState()
CurPixelShader = NULL;
memset(Constant, 0, sizeof(Constant));
Texture[0] = NULL;
Texture[1] = NULL;
D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, SM14 ? D3DTADDRESS_BORDER : D3DTADDRESS_CLAMP);
D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, SM14 ? D3DTADDRESS_BORDER : D3DTADDRESS_CLAMP);
for (int i = 0; i < countof(Texture); ++i)
{
Texture[i] = NULL;
D3DDevice->SetSamplerState(i, D3DSAMP_ADDRESSU, (i == 1 && SM14) ? D3DTADDRESS_BORDER : D3DTADDRESS_CLAMP);
D3DDevice->SetSamplerState(i, D3DSAMP_ADDRESSV, (i == 1 && SM14) ? D3DTADDRESS_BORDER : D3DTADDRESS_CLAMP);
if (i > 1)
{
// Set linear filtering for the SM14 gamma texture.
D3DDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
}
}
NeedGammaUpdate = true;
NeedPalUpdate = true;
@ -534,6 +541,7 @@ bool D3DFB::CreateResources()
{
return false;
}
CreateGammaTexture();
CreateBlockSurfaces();
return true;
}
@ -549,7 +557,7 @@ bool D3DFB::CreateResources()
bool D3DFB::LoadShaders()
{
static const char *const models[] = { "30/", "20/", "14/" };
static const char models[][4] = { "30/", "20/", "14/" };
FString shaderdir, shaderpath;
int model, i, lump;
@ -568,7 +576,7 @@ bool D3DFB::LoadShaders()
{
FMemLump data = Wads.ReadLump(lump);
if (FAILED(D3DDevice->CreatePixelShader((DWORD *)data.GetMem(), &Shaders[i])) &&
i != SHADER_GammaCorrection && i != SHADER_BurnWipe)
i < SHADER_BurnWipe)
{
break;
}
@ -607,6 +615,7 @@ void D3DFB::ReleaseResources ()
{
SAFE_RELEASE( Shaders[i] );
}
GammaShader = NULL;
if (ScreenWipe != NULL)
{
delete ScreenWipe;
@ -782,6 +791,19 @@ bool D3DFB::CreatePaletteTexture ()
return true;
}
bool D3DFB::CreateGammaTexture ()
{
// If this fails, you just won't get gamma correction in a window
// on SM14 cards.
assert(GammaTexture == NULL);
if (SM14)
{
return SUCCEEDED(D3DDevice->CreateTexture(256, 1, 1, 0, D3DFMT_A8R8G8B8,
D3DPOOL_MANAGED, &GammaTexture, NULL));
}
return false;
}
bool D3DFB::CreateVertexes ()
{
VertexPos = -1;
@ -992,8 +1014,20 @@ void D3DFB::Update ()
LOG("SetGammaRamp\n");
D3DDevice->SetGammaRamp(0, D3DSGR_CALIBRATE, &ramp);
}
else
{
if (igamma != 1)
{
UpdateGammaTexture(igamma);
GammaShader = Shaders[SHADER_GammaCorrection];
}
else
{
GammaShader = NULL;
}
}
psgamma[2] = psgamma[1] = psgamma[0] = igamma;
psgamma[3] = 1;
psgamma[3] = 0.5; // For SM14 version
D3DDevice->SetPixelShaderConstantF(PSCONST_Gamma, psgamma, 1);
}
@ -1105,7 +1139,7 @@ void D3DFB::Draw3DPart(bool copy3d)
D3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, vid_hwaalines);
assert(OldRenderTarget == NULL);
if (TempRenderTexture != NULL &&
((Windowed && Shaders[SHADER_GammaCorrection] && TempRenderTexture != FinalWipeScreen) || GatheringWipeScreen || PixelDoubling))
((Windowed && GammaShader && TempRenderTexture != FinalWipeScreen) || GatheringWipeScreen || PixelDoubling))
{
IDirect3DSurface9 *targetsurf;
if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &targetsurf)))
@ -1196,12 +1230,50 @@ void D3DFB::DoWindowedGamma()
D3DDevice->SetRenderTarget(0, OldRenderTarget);
D3DDevice->SetFVF(D3DFVF_FBVERTEX);
SetTexture(0, TempRenderTexture);
SetPixelShader(Shaders[(Windowed && Shaders[SHADER_GammaCorrection]) ? SHADER_GammaCorrection : SHADER_NormalColor]);
SetPixelShader(Windowed && GammaShader ? GammaShader : Shaders[SHADER_NormalColor]);
if (SM14 && Windowed && GammaShader)
{
SetTexture(2, GammaTexture);
SetTexture(3, GammaTexture);
SetTexture(4, GammaTexture);
}
SetAlphaBlend(D3DBLENDOP(0));
EnableAlphaTest(FALSE);
D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX));
OldRenderTarget->Release();
OldRenderTarget = NULL;
if (SM14 && Windowed && GammaShader)
{
// SetTexture(0, GammaTexture);
// SetPixelShader(Shaders[SHADER_NormalColor]);
// D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX));
}
}
}
//==========================================================================
//
// D3DFB :: UpdateGammaTexture
//
// Updates the gamma texture used by the PS14 shader. We only use the first
// half of the texture so that we needn't worry about imprecision causing
// it to grab from the border.
//
//==========================================================================
void D3DFB::UpdateGammaTexture(float igamma)
{
D3DLOCKED_RECT lockrect;
if (GammaTexture != NULL && SUCCEEDED(GammaTexture->LockRect(0, &lockrect, NULL, 0)))
{
BYTE *pix = (BYTE *)lockrect.pBits;
for (int i = 0; i <= 128; ++i)
{
pix[i*4+2] = pix[i*4+1] = pix[i*4] = BYTE(255.f * powf(i / 128.f, igamma));
pix[i*4+3] = 255;
}
GammaTexture->UnlockRect(0);
}
}
@ -1221,6 +1293,9 @@ void D3DFB::UploadPalette ()
// is similarly affected, which basically means that all Shader Model
// 1.4 cards suffer from this problem, since they all use some variant
// of the ATI R200.
//
// [Oh, gee. Looking over the old documentation, I guess this is
// documented that PS 1.x cards don't have a lot of precision.]
skipat = SM14 ? 256 - 8 : 256;
for (i = 0; i < skipat; ++i, pix += 4)
@ -3395,6 +3470,7 @@ void D3DFB::SetPixelShader(IDirect3DPixelShader9 *shader)
void D3DFB::SetTexture(int tnum, IDirect3DTexture9 *texture)
{
assert(tnum >= 0 && tnum < countof(Texture));
if (Texture[tnum] != texture)
{
Texture[tnum] = texture;
@ -3402,8 +3478,6 @@ void D3DFB::SetTexture(int tnum, IDirect3DTexture9 *texture)
}
}
CVAR(Float, pal, 0.5f, 0)
CVAR(Float, pc, 255.f, 0)
void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count, D3DCOLOR border_color)
{
if (SM14)
@ -3430,7 +3504,7 @@ void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count, D3DCOLOR bo
// The constant register c2 is used to hold the multiplier in the
// x part and the adder in the y part.
float fcount = 1 / float(count);
SetConstant(PSCONST_PaletteMod, pc * fcount, pal * fcount, 0, 0);
SetConstant(PSCONST_PaletteMod, 255 * fcount, 0.5f * fcount, 0, 0);
}
SetTexture(1, texture);
}