D3D9: Make sure to use powers of two as render target dimensions if it's needed by the device.

Some other cleanups.

Possibly fixes issue 3256.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6725 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
NeoBrainX 2011-01-02 23:13:29 +00:00
parent 4b15325acd
commit ecf92f5c3c
9 changed files with 69 additions and 64 deletions

View File

@ -27,15 +27,6 @@ TextureCache *g_texture_cache;
u8 *TextureCache::temp;
TextureCache::TexCache TextureCache::textures;
// returns the exponent of the smallest power of two which is greater than val
unsigned int GetPow2(unsigned int val)
{
unsigned int ret = 0;
for (; val; val >>= 1)
++ret;
return ret;
}
TextureCache::TCacheEntryBase::~TCacheEntryBase()
{
if (0 == addr)

View File

@ -181,4 +181,13 @@ inline u32 Z24ToZ16ToZ24(u32 src)
return (src & 0xFFFF00) | (src >> 16);
}
// returns the exponent of the smallest power of two which is greater than val
static unsigned int GetPow2(unsigned int val)
{
unsigned int ret = 0;
for (; val; val >>= 1)
++ret;
return ret;
}
#endif // _VIDEOCOMMON_H

View File

@ -20,6 +20,7 @@
#include "Render.h"
#include "XFStructs.h"
#include "StringUtil.h"
#include "VideoCommon.h"
// D3DX
HINSTANCE hD3DXDll = NULL;
@ -434,6 +435,29 @@ const D3DCAPS9 &GetCaps()
return caps;
}
// returns true if size was changed
bool FixTextureSize(int& width, int& height)
{
int oldw = width, oldh = height;
// conditional nonpow2 support should work fine for us
if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
{
// all texture dimensions need to be powers of two
width = GetPow2(width);
height = GetPow2(height);
}
if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
{
width = height = max(width, height);
}
width = min(width, (int)caps.MaxTextureWidth);
height = min(height, (int)caps.MaxTextureHeight);
return (width != oldw) || (height != oldh);
}
const char *VertexShaderVersionString()
{
static const char *versions[5] = {"ERROR", "vs_1_4", "vs_2_0", "vs_3_0", "vs_4_0"};

View File

@ -71,6 +71,9 @@ const char *PixelShaderVersionString();
const char *VertexShaderVersionString();
void ShowD3DError(HRESULT err);
// returns true if size was changed
bool FixTextureSize(int& width, int& height);
// The following are "filtered" versions of the corresponding D3Ddev-> functions.
void SetTexture(DWORD Stage, IDirect3DBaseTexture9 *pTexture);
void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value);

View File

@ -192,9 +192,6 @@ const int TS[6][2] =
{D3DTSS_ALPHAARG2, D3DTA_DIFFUSE },
};
static LPDIRECT3DPIXELSHADER9 ps_old = NULL;
static LPDIRECT3DVERTEXSHADER9 vs_old = NULL;
void RestoreShaders()
{
D3D::SetTexture(0, 0);
@ -339,22 +336,6 @@ int CD3DFont::DrawTextScaled(float x, float y, float fXScale, float fYScale, flo
return S_OK;
}
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2)
{
struct Q2DVertex { float x,y,z,rhw;u32 color;float u,v,w,h; } coords[4] = {
{x1-0.5f, y1-0.5f, 0, 1, color, u1, v1},
{x2-0.5f, y1-0.5f, 0, 1, color, u2, v1},
{x2-0.5f, y2-0.5f, 0, 1, color, u2, v2},
{x1-0.5f, y2-0.5f, 0, 1, color, u1, v2},
};
dev->SetPixelShader(0);
dev->SetVertexShader(0);
dev->SetVertexDeclaration(NULL);
dev->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
}
/* Explanation of texture copying via drawShadedTexQuad and drawShadedTexSubQuad:
From MSDN: "When rendering 2D output using pre-transformed vertices,
care must be taken to ensure that each texel area correctly corresponds

View File

@ -33,25 +33,6 @@ FramebufferManager::Efb FramebufferManager::s_efb;
FramebufferManager::FramebufferManager()
{
s_efb.color_texture = NULL;
s_efb.colorRead_texture = NULL;
s_efb.depth_texture = NULL;
s_efb.depthRead_texture = NULL;
s_efb.depth_surface = NULL;
s_efb.color_surface = NULL;
s_efb.color_ReadBuffer = NULL;
s_efb.depth_ReadBuffer = NULL;
s_efb.color_OffScreenReadBuffer = NULL;
s_efb.depth_OffScreenReadBuffer = NULL;
s_efb.color_reinterpret_texture = NULL;
s_efb.color_reinterpret_surface = NULL;
s_efb.color_surface_Format = D3DFMT_FORCE_DWORD;
s_efb.depth_surface_Format = D3DFMT_FORCE_DWORD;
s_efb.depth_ReadBuffer_Format = D3DFMT_FORCE_DWORD;
// Simplest possible setup to start with.
int target_width = Renderer::GetFullTargetWidth();
int target_height = Renderer::GetFullTargetHeight();

View File

@ -105,6 +105,13 @@ private:
static struct Efb
{
Efb() : color_texture(NULL), colorRead_texture(NULL), depth_texture(NULL), depthRead_texture(NULL),
color_reinterpret_texture(NULL), color_reinterpret_surface(NULL),
depth_surface(NULL), color_surface(NULL), color_ReadBuffer(NULL), depth_ReadBuffer(NULL),
color_OffScreenReadBuffer(NULL), depth_OffScreenReadBuffer(NULL),
color_surface_Format(D3DFMT_UNKNOWN), depth_surface_Format(D3DFMT_UNKNOWN),
depth_ReadBuffer_Format(D3DFMT_UNKNOWN) {}
LPDIRECT3DTEXTURE9 color_texture;//Texture thats contains the color data of the render target
LPDIRECT3DTEXTURE9 colorRead_texture;//1 pixel texture for temporal data store
LPDIRECT3DTEXTURE9 depth_texture;//Texture thats contains the depth data of the render target

View File

@ -283,13 +283,16 @@ Renderer::Renderer()
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
CalculateXYScale(dst_rect);
s_LastAA = g_ActiveConfig.iMultisampleMode;
int SupersampleCoeficient = s_LastAA + 1;
s_LastEFBScale = g_ActiveConfig.iEFBScale;
CalculateTargetSize(SupersampleCoeficient);
// Make sure to use valid texture sizes
D3D::FixTextureSize(s_Fulltarget_width, s_Fulltarget_height);
s_bLastFrameDumped = false;
s_bAVIDumping = false;
@ -317,8 +320,8 @@ Renderer::Renderer()
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
vp.X = (s_Fulltarget_width - s_target_width) / 2;
vp.Y = (s_Fulltarget_height - s_target_height) / 2;
vp.X = TargetStrideX();
vp.Y = TargetStrideY();
vp.Width = s_target_width;
vp.Height = s_target_height;
D3D::dev->SetViewport(&vp);
@ -766,18 +769,24 @@ void Renderer::UpdateViewport()
}
if (sizeChanged)
{
D3DCAPS9 caps = D3D::GetCaps();
// Make sure that the requested size is actually supported by the GFX driver
if (Renderer::GetFullTargetWidth() > (int)caps.MaxTextureWidth || Renderer::GetFullTargetHeight() > (int)caps.MaxTextureHeight)
{
// Skip EFB recreation and viewport setting. Most likely causes glitches in this case, but prevents crashes at least
ERROR_LOG(VIDEO, "Tried to set a viewport which is too wide to emulate with Direct3D9. Requested EFB size is %dx%d, keeping the %dx%d EFB now\n", Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), old_fulltarget_w, old_fulltarget_h);
const int ideal_width = s_Fulltarget_width;
const int ideal_height = s_Fulltarget_height;
// Fix the viewport to fit to the old EFB size
X *= (old_fulltarget_w-1) / (Renderer::GetFullTargetWidth()-1);
Y *= (old_fulltarget_h-1) / (Renderer::GetFullTargetHeight()-1);
Width *= (old_fulltarget_w-1) / (Renderer::GetFullTargetWidth()-1);
Height *= (old_fulltarget_h-1) / (Renderer::GetFullTargetHeight()-1);
// Make sure that the requested size is actually supported by the GFX driver
D3D::FixTextureSize(s_Fulltarget_width, s_Fulltarget_height);
// If the new EFB size is big enough for the requested viewport, we just recreate the internal buffer.
// Otherwise we use a hack to make the viewport fit into the smaller buffer by rendering at a lower resolution.
if (s_Fulltarget_width < ideal_width || s_Fulltarget_height < ideal_height)
{
// HACK: Skip EFB recreation and viewport setting. Most likely causes glitches in this case, but prevents crashes at least
ERROR_LOG(VIDEO, "Tried to set a viewport which is too wide to emulate with Direct3D9. Requested EFB size is %dx%d, keeping the %dx%d EFB now\n", ideal_width, ideal_height, old_fulltarget_w, old_fulltarget_h);
// Modify the viewport to fit to the old EFB size (effectively makes us render at a lower resolution)
X = X * old_fulltarget_w / ideal_width;
Y = Y * old_fulltarget_h / ideal_height;
Width = Width * old_fulltarget_w / ideal_width;
Height = Height * old_fulltarget_h / ideal_height;
s_Fulltarget_width = old_fulltarget_w;
s_Fulltarget_height = old_fulltarget_h;
@ -786,7 +795,7 @@ void Renderer::UpdateViewport()
{
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
delete g_framebuffer_manager;
g_framebuffer_manager = new FramebufferManager;

View File

@ -83,7 +83,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB
texture->GetSurfaceLevel(0, &Rendersurf);
D3D::dev->SetDepthStencilSurface(NULL);
D3D::dev->SetRenderTarget(0, Rendersurf);
D3DVIEWPORT9 vp;
// Stretch picture with increased internal resolution