summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon
diff options
context:
space:
mode:
authorMatthew Parlane <parlane@gmail.com>2013-01-01 23:28:46 +1300
committerMatthew Parlane <parlane@gmail.com>2013-01-01 23:28:46 +1300
commite0c9a1fd09b9be953bf0ae41b9014485e750b07e (patch)
tree059744e17a2a35ca58dd9b817cab620faee38611 /Source/Core/VideoCommon
parentfe1fdc5e7b957312c906324134e42ca3484fa2d5 (diff)
parentc728ef2cd30ef803210d5db0a1ecab6b198a2c65 (diff)
Merge branch 'master' into wii-network
Conflicts: Source/Core/Common/Src/CommonPaths.h Source/Core/Core/CMakeLists.txt Source/Core/Core/Src/Boot/Boot_BS2Emu.cpp Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp
Diffstat (limited to 'Source/Core/VideoCommon')
-rw-r--r--Source/Core/VideoCommon/CMakeLists.txt1
-rw-r--r--Source/Core/VideoCommon/Src/AVIDump.cpp4
-rw-r--r--Source/Core/VideoCommon/Src/BPFunctions.cpp22
-rw-r--r--Source/Core/VideoCommon/Src/BPFunctions.h18
-rw-r--r--Source/Core/VideoCommon/Src/BPMemory.cpp25
-rw-r--r--Source/Core/VideoCommon/Src/BPStructs.cpp90
-rw-r--r--Source/Core/VideoCommon/Src/DLCache.cpp8
-rw-r--r--Source/Core/VideoCommon/Src/Debugger.h12
-rw-r--r--Source/Core/VideoCommon/Src/EmuWindow.cpp7
-rw-r--r--Source/Core/VideoCommon/Src/FPSCounter.cpp64
-rw-r--r--Source/Core/VideoCommon/Src/FPSCounter.h28
-rw-r--r--Source/Core/VideoCommon/Src/Fifo.cpp35
-rw-r--r--Source/Core/VideoCommon/Src/Fifo.h3
-rw-r--r--Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp31
-rw-r--r--Source/Core/VideoCommon/Src/FramebufferManagerBase.h11
-rw-r--r--Source/Core/VideoCommon/Src/HiresTextures.cpp35
-rw-r--r--Source/Core/VideoCommon/Src/HiresTextures.h3
-rw-r--r--Source/Core/VideoCommon/Src/MainBase.cpp69
-rw-r--r--Source/Core/VideoCommon/Src/OnScreenDisplay.cpp3
-rw-r--r--Source/Core/VideoCommon/Src/OpcodeDecoding.cpp3
-rw-r--r--Source/Core/VideoCommon/Src/PixelEngine.cpp2
-rw-r--r--Source/Core/VideoCommon/Src/PixelShaderGen.cpp124
-rw-r--r--Source/Core/VideoCommon/Src/PixelShaderManager.cpp30
-rw-r--r--Source/Core/VideoCommon/Src/PixelShaderManager.h3
-rw-r--r--Source/Core/VideoCommon/Src/RenderBase.cpp249
-rw-r--r--Source/Core/VideoCommon/Src/RenderBase.h27
-rw-r--r--Source/Core/VideoCommon/Src/TextureCacheBase.cpp256
-rw-r--r--Source/Core/VideoCommon/Src/TextureCacheBase.h29
-rw-r--r--Source/Core/VideoCommon/Src/VertexLoader.cpp10
-rw-r--r--Source/Core/VideoCommon/Src/VertexLoaderManager.cpp19
-rw-r--r--Source/Core/VideoCommon/Src/VertexLoader_Color.cpp2
-rw-r--r--Source/Core/VideoCommon/Src/VertexManagerBase.cpp42
-rw-r--r--Source/Core/VideoCommon/Src/VertexManagerBase.h9
-rw-r--r--Source/Core/VideoCommon/Src/VertexShaderManager.cpp38
-rw-r--r--Source/Core/VideoCommon/Src/VertexShaderManager.h7
-rw-r--r--Source/Core/VideoCommon/Src/VideoCommon.h23
-rw-r--r--Source/Core/VideoCommon/Src/VideoConfig.cpp136
-rw-r--r--Source/Core/VideoCommon/Src/VideoConfig.h17
-rw-r--r--Source/Core/VideoCommon/Src/VideoState.cpp32
-rw-r--r--Source/Core/VideoCommon/Src/XFStructs.cpp33
-rw-r--r--Source/Core/VideoCommon/VideoCommon.vcxproj10
-rw-r--r--Source/Core/VideoCommon/VideoCommon.vcxproj.filters6
42 files changed, 1059 insertions, 517 deletions
diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt
index d0e28f571c..6ed8e29c6b 100644
--- a/Source/Core/VideoCommon/CMakeLists.txt
+++ b/Source/Core/VideoCommon/CMakeLists.txt
@@ -6,6 +6,7 @@ set(SRCS Src/BPFunctions.cpp
Src/DLCache.cpp
Src/Debugger.cpp
Src/Fifo.cpp
+ Src/FPSCounter.cpp
Src/FramebufferManagerBase.cpp
Src/HiresTextures.cpp
Src/ImageWrite.cpp
diff --git a/Source/Core/VideoCommon/Src/AVIDump.cpp b/Source/Core/VideoCommon/Src/AVIDump.cpp
index 4c31798d9f..c172903b5d 100644
--- a/Source/Core/VideoCommon/Src/AVIDump.cpp
+++ b/Source/Core/VideoCommon/Src/AVIDump.cpp
@@ -252,7 +252,7 @@ bool AVIDump::CreateFile()
File::CreateFullPath(s_FormatContext->filename);
if (!(s_FormatContext->oformat = av_guess_format("avi", NULL, NULL)) ||
- !(s_Stream = av_new_stream(s_FormatContext, 0)))
+ !(s_Stream = avformat_new_stream(s_FormatContext, codec)))
{
CloseFile();
return false;
@@ -269,7 +269,7 @@ bool AVIDump::CreateFile()
s_Stream->codec->pix_fmt = g_Config.bUseFFV1 ? PIX_FMT_BGRA : PIX_FMT_YUV420P;
if (!(codec = avcodec_find_encoder(s_Stream->codec->codec_id)) ||
- (avcodec_open(s_Stream->codec, codec) < 0))
+ (avcodec_open2(s_Stream->codec, codec, NULL) < 0))
{
CloseFile();
return false;
diff --git a/Source/Core/VideoCommon/Src/BPFunctions.cpp b/Source/Core/VideoCommon/Src/BPFunctions.cpp
index 4f7315e832..b9a76ba7b6 100644
--- a/Source/Core/VideoCommon/Src/BPFunctions.cpp
+++ b/Source/Core/VideoCommon/Src/BPFunctions.cpp
@@ -39,7 +39,7 @@ void FlushPipeline()
VertexManager::Flush();
}
-void SetGenerationMode(const BPCmd &bp)
+void SetGenerationMode()
{
g_renderer->SetGenerationMode();
}
@@ -62,32 +62,34 @@ void SetScissor()
TargetRectangle trc = g_renderer->ConvertEFBRectangle(rc);
g_renderer->SetScissorRect(trc);
+
+ UpdateViewportWithCorrection();
}
-void SetLineWidth(const BPCmd &bp)
+void SetLineWidth()
{
g_renderer->SetLineWidth();
}
-void SetDepthMode(const BPCmd &bp)
+void SetDepthMode()
{
g_renderer->SetDepthMode();
}
-void SetBlendMode(const BPCmd &bp)
+void SetBlendMode()
{
g_renderer->SetBlendMode(false);
}
-void SetDitherMode(const BPCmd &bp)
+void SetDitherMode()
{
g_renderer->SetDitherMode();
}
-void SetLogicOpMode(const BPCmd &bp)
+void SetLogicOpMode()
{
g_renderer->SetLogicOpMode();
}
-void SetColorMask(const BPCmd &bp)
+void SetColorMask()
{
g_renderer->SetColorMask();
}
@@ -119,7 +121,7 @@ void CopyEFB(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat,
- convert the RGBA8 color to RGBA6/RGB8/RGB565 and convert it to RGBA8 again
- convert the Z24 depth value to Z16 and back to Z24
*/
-void ClearScreen(const BPCmd &bp, const EFBRectangle &rc)
+void ClearScreen(const EFBRectangle &rc)
{
bool colorEnable = bpmem.blendmode.colorupdate;
bool alphaEnable = bpmem.blendmode.alphaupdate;
@@ -152,7 +154,7 @@ void ClearScreen(const BPCmd &bp, const EFBRectangle &rc)
}
}
-void OnPixelFormatChange(const BPCmd &bp)
+void OnPixelFormatChange()
{
int convtype = -1;
@@ -234,7 +236,7 @@ bool GetConfig(const int &type)
case CONFIG_DISABLEFOG:
return g_ActiveConfig.bDisableFog;
case CONFIG_SHOWEFBREGIONS:
- return false;
+ return g_ActiveConfig.bShowEFBCopyRegions;
default:
PanicAlert("GetConfig Error: Unknown Config Type!");
return false;
diff --git a/Source/Core/VideoCommon/Src/BPFunctions.h b/Source/Core/VideoCommon/Src/BPFunctions.h
index 2b86523687..e7a8b0aeb4 100644
--- a/Source/Core/VideoCommon/Src/BPFunctions.h
+++ b/Source/Core/VideoCommon/Src/BPFunctions.h
@@ -37,18 +37,18 @@ enum
};
void FlushPipeline();
-void SetGenerationMode(const BPCmd &bp);
+void SetGenerationMode();
void SetScissor();
-void SetLineWidth(const BPCmd &bp);
-void SetDepthMode(const BPCmd &bp);
-void SetBlendMode(const BPCmd &bp);
-void SetDitherMode(const BPCmd &bp);
-void SetLogicOpMode(const BPCmd &bp);
-void SetColorMask(const BPCmd &bp);
+void SetLineWidth();
+void SetDepthMode();
+void SetBlendMode();
+void SetDitherMode();
+void SetLogicOpMode();
+void SetColorMask();
void CopyEFB(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat,
const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf);
-void ClearScreen(const BPCmd &bp, const EFBRectangle &rc);
-void OnPixelFormatChange(const BPCmd &bp);
+void ClearScreen(const EFBRectangle &rc);
+void OnPixelFormatChange();
u8 *GetPointer(const u32 &address);
bool GetConfig(const int &type);
void SetTextureMode(const BPCmd &bp);
diff --git a/Source/Core/VideoCommon/Src/BPMemory.cpp b/Source/Core/VideoCommon/Src/BPMemory.cpp
index d5b762c1a4..c452b238b6 100644
--- a/Source/Core/VideoCommon/Src/BPMemory.cpp
+++ b/Source/Core/VideoCommon/Src/BPMemory.cpp
@@ -43,31 +43,6 @@ void LoadBPReg(u32 value0)
BPWritten(bp);
}
-// Called when loading a saved state.
-// Needs more testing though.
-void BPReload()
-{
- for (int i = 0; i < 254; i++)
- {
- switch (i)
- {
- case BPMEM_BLENDMODE:
- case BPMEM_SETDRAWDONE:
- case BPMEM_TRIGGER_EFB_COPY:
- case BPMEM_LOADTLUT1:
- case BPMEM_PERF1:
- case BPMEM_PE_TOKEN_ID:
- case BPMEM_PE_TOKEN_INT_ID:
- // Cases in which we DON'T want to reload the BP
- continue;
- default:
- BPCmd bp = {i, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[i])};
- BPWritten(bp);
- }
- }
-}
-
-
void GetBPRegInfo(const u8* data, char* name, size_t name_size, char* desc, size_t desc_size)
{
const char* no_yes[2] = { "No", "Yes" };
diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp
index d59523e117..0bde9cc613 100644
--- a/Source/Core/VideoCommon/Src/BPStructs.cpp
+++ b/Source/Core/VideoCommon/Src/BPStructs.cpp
@@ -34,9 +34,9 @@
using namespace BPFunctions;
-u32 mapTexAddress;
-bool mapTexFound;
-int numWrites;
+static u32 mapTexAddress;
+static bool mapTexFound;
+static int numWrites;
extern volatile bool g_bSkipCurrentFrame;
@@ -81,6 +81,9 @@ void BPWritten(const BPCmd& bp)
just stuff geometry in them and don't put state changes there
----------------------------------------------------------------------------------------------------------------
*/
+
+ // check for invalid state, else unneeded configuration are built
+ g_video_backend->CheckInvalidState();
// Debugging only, this lets you skip a bp update
//static int times = 0;
@@ -128,7 +131,27 @@ void BPWritten(const BPCmd& bp)
FlushPipeline();
}
} // END ZTP SPEEDUP HACK
- else FlushPipeline();
+ else
+ {
+ if (((s32*)&bpmem)[bp.address] == bp.newvalue)
+ {
+ if (!(bp.address == BPMEM_TRIGGER_EFB_COPY
+ || bp.address == BPMEM_CLEARBBOX1
+ || bp.address == BPMEM_CLEARBBOX2
+ || bp.address == BPMEM_SETDRAWDONE
+ || bp.address == BPMEM_PE_TOKEN_ID
+ || bp.address == BPMEM_PE_TOKEN_INT_ID
+ || bp.address == BPMEM_LOADTLUT0
+ || bp.address == BPMEM_LOADTLUT1
+ || bp.address == BPMEM_TEXINVALIDATE
+ || bp.address == BPMEM_PRELOAD_MODE))
+ {
+ return;
+ }
+ }
+
+ FlushPipeline();
+ }
((u32*)&bpmem)[bp.address] = bp.newvalue;
@@ -140,7 +163,7 @@ void BPWritten(const BPCmd& bp)
bpmem.genMode.numtexgens, bpmem.genMode.numcolchans,
bpmem.genMode.ms_en, bpmem.genMode.numtevstages+1, bpmem.genMode.cullmode,
bpmem.genMode.numindstages, bpmem.genMode.zfreeze);
- SetGenerationMode(bp);
+ SetGenerationMode();
break;
}
case BPMEM_IND_MTXA: // Index Matrix Changed
@@ -168,12 +191,12 @@ void BPWritten(const BPCmd& bp)
SetScissor();
break;
case BPMEM_LINEPTWIDTH: // Line Width
- SetLineWidth(bp);
+ SetLineWidth();
break;
case BPMEM_ZMODE: // Depth Control
PRIM_LOG("zmode: test=%d, func=%d, upd=%d", bpmem.zmode.testenable, bpmem.zmode.func,
bpmem.zmode.updateenable);
- SetDepthMode(bp);
+ SetDepthMode();
break;
case BPMEM_BLENDMODE: // Blending Control
{
@@ -184,16 +207,16 @@ void BPWritten(const BPCmd& bp)
bpmem.blendmode.dstfactor, bpmem.blendmode.srcfactor, bpmem.blendmode.subtract, bpmem.blendmode.logicmode);
// Set LogicOp Blending Mode
if (bp.changes & 2)
- SetLogicOpMode(bp);
+ SetLogicOpMode();
// Set Dithering Mode
if (bp.changes & 4)
- SetDitherMode(bp);
+ SetDitherMode();
// Set Blending Mode
if (bp.changes & 0xFE1)
- SetBlendMode(bp);
+ SetBlendMode();
// Set Color Mask
if (bp.changes & 0x18)
- SetColorMask(bp);
+ SetColorMask();
}
break;
}
@@ -286,7 +309,7 @@ void BPWritten(const BPCmd& bp)
// Clear the rectangular region after copying it.
if (PE_copy.clear)
{
- ClearScreen(bp, rc);
+ ClearScreen(rc);
}
break;
@@ -311,8 +334,6 @@ void BPWritten(const BPCmd& bp)
else
PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tmem_config.tlut_src, bpmem.tmem_config.tlut_src << 5, (bpmem.tmem_config.tlut_src & 0xFFFFF)<< 5);
- // TODO(ector) : kill all textures that use this palette
- // Not sure if it's a good idea, though. For now, we hash texture palettes
break;
}
case BPMEM_FOGRANGE: // Fog Settings Control
@@ -429,13 +450,13 @@ void BPWritten(const BPCmd& bp)
}
}
break;
- case BPMEM_TEXINVALIDATE: // Used, if game has manual control the Texture Cache, which we don't allow
- DEBUG_LOG(VIDEO, "BP Texture Invalid: %08x", bp.newvalue);
+ case BPMEM_TEXINVALIDATE:
+ // TODO: Needs some restructuring in TextureCacheBase.
break;
case BPMEM_ZCOMPARE: // Set the Z-Compare and EFB pixel format
g_renderer->SetColorMask(); // alpha writing needs to be disabled if the new pixel format doesn't have an alpha channel
- OnPixelFormatChange(bp);
+ OnPixelFormatChange();
break;
case BPMEM_MIPMAP_STRIDE: // MipMap Stride Channel
@@ -473,7 +494,7 @@ void BPWritten(const BPCmd& bp)
break;
case BPMEM_PRELOAD_MODE: // Set to 0 when GX_TexModeSync() is called.
- // if this is different from 0, manual TMEM management is used.
+ // if this is different from 0, manual TMEM management is used (GX_PreloadEntireTexture).
if (bp.newvalue != 0)
{
// NOTE(neobrain): Apparently tmemodd doesn't affect hardware behavior at all (libogc uses it just as a buffer and switches its contents with tmemeven whenever this is called)
@@ -484,7 +505,6 @@ void BPWritten(const BPCmd& bp)
// Check if the game has overflowed TMEM, and copy up to the limit.
// Paper Mario does this when entering the Great Boogly Tree (Chap 2)
- // TODO: Does this wrap?
if ((tmem_addr + size) > TMEM_SIZE)
size = TMEM_SIZE - tmem_addr;
@@ -660,3 +680,35 @@ void BPWritten(const BPCmd& bp)
}
}
+// Called when loading a saved state.
+void BPReload()
+{
+ // restore anything that goes straight to the renderer.
+ // let's not risk actually replaying any writes.
+ // note that PixelShaderManager is already covered since it has its own DoState.
+ SetGenerationMode();
+ SetScissor();
+ SetLineWidth();
+ SetDepthMode();
+ SetLogicOpMode();
+ SetDitherMode();
+ SetBlendMode();
+ SetColorMask();
+ OnPixelFormatChange();
+ {
+ BPCmd bp = {BPMEM_TX_SETMODE0, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_TX_SETMODE0])};
+ SetTextureMode(bp);
+ }
+ {
+ BPCmd bp = {BPMEM_TX_SETMODE0_4, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_TX_SETMODE0_4])};
+ SetTextureMode(bp);
+ }
+ {
+ BPCmd bp = {BPMEM_FIELDMASK, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_FIELDMASK])};
+ SetInterlacingMode(bp);
+ }
+ {
+ BPCmd bp = {BPMEM_FIELDMODE, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_FIELDMODE])};
+ SetInterlacingMode(bp);
+ }
+}
diff --git a/Source/Core/VideoCommon/Src/DLCache.cpp b/Source/Core/VideoCommon/Src/DLCache.cpp
index 5499fa26f1..c828ea3a03 100644
--- a/Source/Core/VideoCommon/Src/DLCache.cpp
+++ b/Source/Core/VideoCommon/Src/DLCache.cpp
@@ -361,9 +361,9 @@ u32 AnalyzeAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
numVertices);
num_draw_call++;
- const int tc[12] = {
+ const u32 tc[12] = {
g_VtxDesc.Position, g_VtxDesc.Normal, g_VtxDesc.Color0, g_VtxDesc.Color1, g_VtxDesc.Tex0Coord, g_VtxDesc.Tex1Coord,
- g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord, g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const int)((g_VtxDesc.Hex >> 31) & 3)
+ g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord, g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const u32)((g_VtxDesc.Hex >> 31) & 3)
};
for(int i = 0; i < 12; i++)
{
@@ -563,9 +563,9 @@ void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
dl->InsertRegion(NewRegion);
memcpy(NewRegion->start_address, StartAddress, Vdatasize);
emitter.ABI_CallFunctionCCCP((void *)&VertexLoaderManager::RunCompiledVertices, cmd_byte & GX_VAT_MASK, (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, numVertices, NewRegion->start_address);
- const int tc[12] = {
+ const u32 tc[12] = {
g_VtxDesc.Position, g_VtxDesc.Normal, g_VtxDesc.Color0, g_VtxDesc.Color1, g_VtxDesc.Tex0Coord, g_VtxDesc.Tex1Coord,
- g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord, g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const int)((g_VtxDesc.Hex >> 31) & 3)
+ g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord, g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const u32)((g_VtxDesc.Hex >> 31) & 3)
};
for(int i = 0; i < 12; i++)
{
diff --git a/Source/Core/VideoCommon/Src/Debugger.h b/Source/Core/VideoCommon/Src/Debugger.h
index bcce50f223..fde31e4268 100644
--- a/Source/Core/VideoCommon/Src/Debugger.h
+++ b/Source/Core/VideoCommon/Src/Debugger.h
@@ -72,21 +72,9 @@ void GFXDebuggerCheckAndPause(bool update);
void GFXDebuggerToPause(bool update);
void GFXDebuggerUpdateScreen();
-#undef ENABLE_GFX_DEBUGGER
-#if defined(_DEBUG) || defined(DEBUGFAST)
-#define ENABLE_GFX_DEBUGGER
-#endif
-
-#ifdef ENABLE_GFX_DEBUGGER
#define GFX_DEBUGGER_PAUSE_AT(event,update) {if (((GFXDebuggerToPauseAtNext & event) && --GFXDebuggerEventToPauseCount<=0) || GFXDebuggerPauseFlag) GFXDebuggerToPause(update);}
#define GFX_DEBUGGER_PAUSE_LOG_AT(event,update,dumpfunc) {if (((GFXDebuggerToPauseAtNext & event) && --GFXDebuggerEventToPauseCount<=0) || GFXDebuggerPauseFlag) {{dumpfunc};GFXDebuggerToPause(update);}}
#define GFX_DEBUGGER_LOG_AT(event,dumpfunc) {if (( GFXDebuggerToPauseAtNext & event ) ) {{dumpfunc};}}
-#else
-// Disable debugging calls in Release build
-#define GFX_DEBUGGER_PAUSE_AT(event,update)
-#define GFX_DEBUGGER_PAUSE_LOG_AT(event,update,dumpfunc)
-#define GFX_DEBUGGER_LOG_AT(event,dumpfunc)
-#endif // ENABLE_GFX_DEBUGGER
#endif // _GFX_DEBUGGER_H_
diff --git a/Source/Core/VideoCommon/Src/EmuWindow.cpp b/Source/Core/VideoCommon/Src/EmuWindow.cpp
index 30dca24cb1..cbb0bc31ac 100644
--- a/Source/Core/VideoCommon/Src/EmuWindow.cpp
+++ b/Source/Core/VideoCommon/Src/EmuWindow.cpp
@@ -251,7 +251,7 @@ void OSDMenu(WPARAM wParam)
OSDChoice = 1;
// Toggle native resolution
g_Config.iEFBScale = g_Config.iEFBScale + 1;
- if (g_Config.iEFBScale > 4) g_Config.iEFBScale = 0;
+ if (g_Config.iEFBScale > 7) g_Config.iEFBScale = 0;
break;
case '4':
OSDChoice = 2;
@@ -280,11 +280,6 @@ void OSDMenu(WPARAM wParam)
OSDChoice = 4;
g_Config.bDisableFog = !g_Config.bDisableFog;
break;
- case '7':
- // TODO: Not implemented in the D3D backends, yet
- OSDChoice = 5;
- g_Config.bDisableLighting = !g_Config.bDisableLighting;
- break;
}
}
diff --git a/Source/Core/VideoCommon/Src/FPSCounter.cpp b/Source/Core/VideoCommon/Src/FPSCounter.cpp
new file mode 100644
index 0000000000..ea3f624c73
--- /dev/null
+++ b/Source/Core/VideoCommon/Src/FPSCounter.cpp
@@ -0,0 +1,64 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "FPSCounter.h"
+#include "FileUtil.h"
+#include "Timer.h"
+#include "VideoConfig.h"
+
+#define FPS_REFRESH_INTERVAL 1000
+
+static unsigned int s_counter = 0;
+static unsigned int s_fps = 0;
+static unsigned int s_fps_last_counter = 0;
+static unsigned long s_last_update_time = 0;
+static File::IOFile s_bench_file;
+
+void InitFPSCounter()
+{
+ s_counter = s_fps_last_counter = 0;
+ s_fps = 0;
+ s_last_update_time = Common::Timer::GetTimeMs();
+
+ if (s_bench_file.IsOpen())
+ s_bench_file.Close();
+}
+
+static void LogFPSToFile(unsigned long val)
+{
+ if (!s_bench_file.IsOpen())
+ s_bench_file.Open(File::GetUserPath(D_LOGS_IDX) + "fps.txt", "w");
+
+ char buffer[256];
+ snprintf(buffer, 256, "%ld\n", val);
+ s_bench_file.WriteArray(buffer, strlen(buffer));
+}
+
+int UpdateFPSCounter()
+{
+ if (Common::Timer::GetTimeMs() - s_last_update_time >= FPS_REFRESH_INTERVAL)
+ {
+ s_last_update_time = Common::Timer::GetTimeMs();
+ s_fps = s_counter - s_fps_last_counter;
+ s_fps_last_counter = s_counter;
+ if (g_ActiveConfig.bLogFPSToFile)
+ LogFPSToFile(s_fps);
+ }
+
+ s_counter++;
+ return s_fps;
+} \ No newline at end of file
diff --git a/Source/Core/VideoCommon/Src/FPSCounter.h b/Source/Core/VideoCommon/Src/FPSCounter.h
new file mode 100644
index 0000000000..314f4b0fc7
--- /dev/null
+++ b/Source/Core/VideoCommon/Src/FPSCounter.h
@@ -0,0 +1,28 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef _FPS_COUNTER_H_
+#define _FPS_COUNTER_H_
+
+// Initializes the FPS counter.
+void InitFPSCounter();
+
+// Called when a frame is rendered. Returns the value to be displayed on
+// screen as the FPS counter (updated every second).
+int UpdateFPSCounter();
+
+#endif // _FPS_COUNTER_H_ \ No newline at end of file
diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp
index 2e60055c97..50aa21ebbf 100644
--- a/Source/Core/VideoCommon/Src/Fifo.cpp
+++ b/Source/Core/VideoCommon/Src/Fifo.cpp
@@ -16,7 +16,6 @@
// http://code.google.com/p/dolphin-emu/
#include "VideoConfig.h"
-#include "Setup.h"
#include "MemoryUtil.h"
#include "Thread.h"
#include "Atomic.h"
@@ -26,6 +25,7 @@
#include "ChunkFile.h"
#include "Fifo.h"
#include "HW/Memmap.h"
+#include "Core.h"
volatile bool g_bSkipCurrentFrame = false;
extern u8* g_pVideoData;
@@ -34,22 +34,39 @@ namespace
{
static volatile bool GpuRunningState = false;
static volatile bool EmuRunningState = false;
-static u8 *videoBuffer;
+static std::mutex m_csHWVidOccupied;
// STATE_TO_SAVE
+static u8 *videoBuffer;
static int size = 0;
} // namespace
void Fifo_DoState(PointerWrap &p)
{
-
p.DoArray(videoBuffer, FIFO_SIZE);
p.Do(size);
- int pos = (int)(g_pVideoData - videoBuffer); // get offset
- p.Do(pos); // read or write offset (depends on the mode afaik)
- g_pVideoData = &videoBuffer[pos]; // overwrite g_pVideoData -> expected no change when load ss and change when save ss
+ p.DoPointer(g_pVideoData, videoBuffer);
+ p.Do(g_bSkipCurrentFrame);
+}
+void Fifo_PauseAndLock(bool doLock, bool unpauseOnUnlock)
+{
+ if (doLock)
+ {
+ EmulatorState(false);
+ if (!Core::IsGPUThread())
+ m_csHWVidOccupied.lock();
+ _dbg_assert_(COMMON, !CommandProcessor::fifo.isGpuReadingData);
+ }
+ else
+ {
+ if (unpauseOnUnlock)
+ EmulatorState(true);
+ if (!Core::IsGPUThread())
+ m_csHWVidOccupied.unlock();
+ }
}
+
void Fifo_Init()
{
videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE);
@@ -127,6 +144,7 @@ void ResetVideoBuffer()
// Purpose: Keep the Core HW updated about the CPU-GPU distance
void RunGpuLoop()
{
+ std::lock_guard<std::mutex> lk(m_csHWVidOccupied);
GpuRunningState = true;
SCPFifoStruct &fifo = CommandProcessor::fifo;
@@ -178,12 +196,13 @@ void RunGpuLoop()
Common::YieldCPU();
else
{
- // While the emu is paused, we still handle async request such as Savestates then sleep.
+ // While the emu is paused, we still handle async requests then sleep.
while (!EmuRunningState)
{
g_video_backend->PeekMessages();
- VideoFifo_CheckStateRequest();
+ m_csHWVidOccupied.unlock();
Common::SleepCurrentThread(1);
+ m_csHWVidOccupied.lock();
}
}
}
diff --git a/Source/Core/VideoCommon/Src/Fifo.h b/Source/Core/VideoCommon/Src/Fifo.h
index e73434a19f..75e7d782f5 100644
--- a/Source/Core/VideoCommon/Src/Fifo.h
+++ b/Source/Core/VideoCommon/Src/Fifo.h
@@ -30,7 +30,9 @@ extern volatile bool g_bSkipCurrentFrame;
void Fifo_Init();
void Fifo_Shutdown();
+
void Fifo_DoState(PointerWrap &f);
+void Fifo_PauseAndLock(bool doLock, bool unpauseOnUnlock);
void ReadDataFromFifo(u8* _uData, u32 len);
@@ -45,6 +47,5 @@ void Fifo_SetRendering(bool bEnabled);
// Implemented by the Video Backend
void VideoFifo_CheckAsyncRequest();
-void VideoFifo_CheckStateRequest();
#endif // _FIFO_H
diff --git a/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp b/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp
index b234a7c865..c883714daf 100644
--- a/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp
+++ b/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp
@@ -10,6 +10,9 @@ XFBSourceBase *FramebufferManagerBase::m_realXFBSource; // Only used in Real XFB
FramebufferManagerBase::VirtualXFBListType FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode
const XFBSourceBase* FramebufferManagerBase::m_overlappingXFBArray[MAX_VIRTUAL_XFB];
+unsigned int FramebufferManagerBase::s_last_xfb_width = 1;
+unsigned int FramebufferManagerBase::s_last_xfb_height = 1;
+
FramebufferManagerBase::FramebufferManagerBase()
{
m_realXFBSource = NULL;
@@ -226,3 +229,31 @@ void FramebufferManagerBase::ReplaceVirtualXFB()
}
}
}
+
+int FramebufferManagerBase::ScaleToVirtualXfbWidth(int x, unsigned int backbuffer_width)
+{
+ if (g_ActiveConfig.RealXFBEnabled())
+ return x;
+
+ if (g_ActiveConfig.b3DVision)
+ {
+ // This works, yet the version in the else doesn't. No idea why.
+ return x * (int)backbuffer_width / (int)FramebufferManagerBase::LastXfbWidth();
+ }
+ else
+ return x * (int)Renderer::GetTargetRectangle().GetWidth() / (int)FramebufferManagerBase::LastXfbWidth();
+}
+
+int FramebufferManagerBase::ScaleToVirtualXfbHeight(int y, unsigned int backbuffer_height)
+{
+ if (g_ActiveConfig.RealXFBEnabled())
+ return y;
+
+ if (g_ActiveConfig.b3DVision)
+ {
+ // This works, yet the version in the else doesn't. No idea why.
+ return y * (int)backbuffer_height / (int)FramebufferManagerBase::LastXfbHeight();
+ }
+ else
+ return y * (int)Renderer::GetTargetRectangle().GetHeight() / (int)FramebufferManagerBase::LastXfbHeight();
+}
diff --git a/Source/Core/VideoCommon/Src/FramebufferManagerBase.h b/Source/Core/VideoCommon/Src/FramebufferManagerBase.h
index 26d360647d..e529bb1a39 100644
--- a/Source/Core/VideoCommon/Src/FramebufferManagerBase.h
+++ b/Source/Core/VideoCommon/Src/FramebufferManagerBase.h
@@ -50,6 +50,14 @@ public:
static void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma);
static const XFBSourceBase* const* GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
+ static void SetLastXfbWidth(unsigned int width) { s_last_xfb_width = width; }
+ static void SetLastXfbHeight(unsigned int height) { s_last_xfb_height = height; }
+ static unsigned int LastXfbWidth() { return s_last_xfb_width; }
+ static unsigned int LastXfbHeight() { return s_last_xfb_height; }
+
+ static int ScaleToVirtualXfbWidth(int x, unsigned int backbuffer_width);
+ static int ScaleToVirtualXfbHeight(int y, unsigned int backbuffer_height);
+
protected:
struct VirtualXFB
{
@@ -85,6 +93,9 @@ private:
static VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
static const XFBSourceBase* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
+
+ static unsigned int s_last_xfb_width;
+ static unsigned int s_last_xfb_height;
};
extern FramebufferManagerBase *g_framebuffer_manager;
diff --git a/Source/Core/VideoCommon/Src/HiresTextures.cpp b/Source/Core/VideoCommon/Src/HiresTextures.cpp
index 50e8a194af..5a3fb051c3 100644
--- a/Source/Core/VideoCommon/Src/HiresTextures.cpp
+++ b/Source/Core/VideoCommon/Src/HiresTextures.cpp
@@ -90,10 +90,15 @@ void Init(const char *gameCode)
}
}
-PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned int *pHeight, int texformat, u8 *data)
+bool HiresTexExists(const char* filename)
{
- std::string key(fileName);
+ std::string key(filename);
+ return textureMap.find(key) != textureMap.end();
+}
+PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned int *pHeight, unsigned int *required_size, int texformat, unsigned int data_size, u8 *data)
+{
+ std::string key(fileName);
if (textureMap.find(key) == textureMap.end())
return PC_TEX_FMT_NONE;
@@ -102,23 +107,17 @@ PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned in
int channels;
u8 *temp = SOIL_load_image(textureMap[key].c_str(), &width, &height, &channels, SOIL_LOAD_RGBA);
-
if (temp == NULL)
{
ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[key].c_str());
- SOIL_free_image_data(temp);
return PC_TEX_FMT_NONE;
}
- if (width > 2048 || height > 2048)
- {
- ERROR_LOG(VIDEO, "Custom texture %s is too large (%ix%i); textures can only be 2048 pixels tall and wide", textureMap[key].c_str(), width, height);
- SOIL_free_image_data(temp);
- return PC_TEX_FMT_NONE;
- }
+ *pWidth = width;
+ *pHeight = height;
int offset = 0;
- PC_TexFormat returnTex;
+ PC_TexFormat returnTex = PC_TEX_FMT_NONE;
switch (texformat)
{
@@ -126,24 +125,32 @@ PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned in
case GX_TF_I8:
case GX_TF_IA4:
case GX_TF_IA8:
+ *required_size = width * height * 8;
+ if (data_size < *required_size)
+ goto cleanup;
+
for (int i = 0; i < width * height * 4; i += 4)
{
// Rather than use a luminosity function, just use the most intense color for luminance
+ // TODO(neobrain): Isn't this kind of.. stupid?
data[offset++] = *std::max_element(temp+i, temp+i+3);
data[offset++] = temp[i+3];
}
returnTex = PC_TEX_FMT_IA8;
break;
default:
+ *required_size = width * height * 4;
+ if (data_size < *required_size)
+ goto cleanup;
+
memcpy(data, temp, width * height * 4);
returnTex = PC_TEX_FMT_RGBA32;
break;
}
- *pWidth = width;
- *pHeight = height;
- SOIL_free_image_data(temp);
INFO_LOG(VIDEO, "loading custom texture from %s", textureMap[key].c_str());
+cleanup:
+ SOIL_free_image_data(temp);
return returnTex;
}
diff --git a/Source/Core/VideoCommon/Src/HiresTextures.h b/Source/Core/VideoCommon/Src/HiresTextures.h
index 409c2cc260..4b0db76fd9 100644
--- a/Source/Core/VideoCommon/Src/HiresTextures.h
+++ b/Source/Core/VideoCommon/Src/HiresTextures.h
@@ -25,7 +25,8 @@
namespace HiresTextures
{
void Init(const char *gameCode);
-PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned int *pHeight, int texformat, u8 *data);
+bool HiresTexExists(const char *filename);
+PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned int *pHeight, unsigned int *required_size, int texformat, unsigned int data_size, u8 *data);
};
diff --git a/Source/Core/VideoCommon/Src/MainBase.cpp b/Source/Core/VideoCommon/Src/MainBase.cpp
index 0b1258a662..726ef71b38 100644
--- a/Source/Core/VideoCommon/Src/MainBase.cpp
+++ b/Source/Core/VideoCommon/Src/MainBase.cpp
@@ -169,8 +169,7 @@ u32 VideoBackendHardware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32
return 0;
}
-static volatile u32 s_doStateRequested = false;
-
+
void VideoBackendHardware::InitializeShared()
{
VideoCommon_Init();
@@ -181,54 +180,50 @@ void VideoBackendHardware::InitializeShared()
memset((void*)&s_beginFieldArgs, 0, sizeof(s_beginFieldArgs));
memset(&s_accessEFBArgs, 0, sizeof(s_accessEFBArgs));
s_AccessEFBResult = 0;
+ m_invalid = false;
}
-static volatile struct
-{
- unsigned char **ptr;
- int mode;
-} s_doStateArgs;
-
-// Depending on the threading mode (DC/SC) this can be called
-// from either the GPU thread or the CPU thread
-void VideoFifo_CheckStateRequest()
+// Run from the CPU thread
+void VideoBackendHardware::DoState(PointerWrap& p)
{
- if (Common::AtomicLoadAcquire(s_doStateRequested))
+ VideoCommon_DoState(p);
+ p.DoMarker("VideoCommon");
+
+ p.Do(s_swapRequested);
+ p.Do(s_efbAccessRequested);
+ p.Do(s_beginFieldArgs);
+ p.Do(s_accessEFBArgs);
+ p.Do(s_AccessEFBResult);
+ p.DoMarker("VideoBackendHardware");
+
+ // Refresh state.
+ if (p.GetMode() == PointerWrap::MODE_READ)
{
+ m_invalid = true;
+ RecomputeCachedArraybases();
+
// Clear all caches that touch RAM
- TextureCache::Invalidate(false);
+ // (? these don't appear to touch any emulation state that gets saved. moved to on load only.)
VertexLoaderManager::MarkAllDirty();
-
- PointerWrap p(s_doStateArgs.ptr, s_doStateArgs.mode);
- VideoCommon_DoState(p);
-
- // Refresh state.
- if (s_doStateArgs.mode == PointerWrap::MODE_READ)
- {
- BPReload();
- RecomputeCachedArraybases();
- }
-
- Common::AtomicStoreRelease(s_doStateRequested, false);
}
}
-// Run from the CPU thread
-void VideoBackendHardware::DoState(PointerWrap& p)
-{
- s_doStateArgs.ptr = p.ptr;
- s_doStateArgs.mode = p.mode;
- Common::AtomicStoreRelease(s_doStateRequested, true);
- if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
+void VideoBackendHardware::CheckInvalidState() {
+ if (m_invalid)
{
- while (Common::AtomicLoadAcquire(s_doStateRequested) && !s_FifoShuttingDown)
- //Common::SleepCurrentThread(1);
- Common::YieldCPU();
+ m_invalid = false;
+
+ BPReload();
+ TextureCache::Invalidate();
}
- else
- VideoFifo_CheckStateRequest();
}
+void VideoBackendHardware::PauseAndLock(bool doLock, bool unpauseOnUnlock)
+{
+ Fifo_PauseAndLock(doLock, unpauseOnUnlock);
+}
+
+
void VideoBackendHardware::RunLoop(bool enable)
{
VideoCommon_RunLoop(enable);
diff --git a/Source/Core/VideoCommon/Src/OnScreenDisplay.cpp b/Source/Core/VideoCommon/Src/OnScreenDisplay.cpp
index f24bfc31b3..10cf5b84af 100644
--- a/Source/Core/VideoCommon/Src/OnScreenDisplay.cpp
+++ b/Source/Core/VideoCommon/Src/OnScreenDisplay.cpp
@@ -19,6 +19,7 @@
#include "Common.h"
+#include "ConfigManager.h"
#include "OnScreenDisplay.h"
#include "RenderBase.h"
#include "Timer.h"
@@ -47,6 +48,8 @@ void AddMessage(const char* pstr, u32 ms)
void DrawMessages()
{
+ if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bOnScreenDisplayMessages) return;
+
if (s_listMsgs.size() > 0)
{
int left = 25, top = 15;
diff --git a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
index 18d6726ae3..4f7f86d655 100644
--- a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
+++ b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
@@ -439,7 +439,8 @@ void OpcodeDecoder_Init()
#if _M_SSE >= 0x301
if (cpu_info.bSSSE3)
{
- *DataReadU32xFuncs = *DataReadU32xFuncs_SSSE3;
+ for (int i = 0; i < 16; ++i)
+ DataReadU32xFuncs[i] = DataReadU32xFuncs_SSSE3[i];
}
#endif
diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp
index 03a3a7547a..a488e52b42 100644
--- a/Source/Core/VideoCommon/Src/PixelEngine.cpp
+++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp
@@ -367,8 +367,6 @@ void UpdateFinishInterrupt(bool active)
{
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active);
interruptSetFinish = active;
- if (active)
- State::ProcessRequestedStates(0);
}
// TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate).
diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp
index 7500997fef..cc48276253 100644
--- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp
+++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp
@@ -129,15 +129,11 @@ void GetPixelShaderId(PIXELSHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 compo
return;
}
+ // numtexgens should be <= 8
for (unsigned int i = 0; i < bpmem.genMode.numtexgens; ++i)
- {
- if (18+i < 32)
- uid->values[0] |= xfregs.texMtxInfo[i].projection << (18+i); // 1
- else
- uid->values[1] |= xfregs.texMtxInfo[i].projection << (i - 14); // 1
- }
+ uid->values[0] |= xfregs.texMtxInfo[i].projection << (18+i); // 1
- uid->values[1] = bpmem.genMode.numindstages << 2; // 3
+ uid->values[1] = bpmem.genMode.numindstages; // 3
u32 indirectStagesUsed = 0;
for (unsigned int i = 0; i < bpmem.genMode.numindstages; ++i)
if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages)
@@ -145,20 +141,20 @@ void GetPixelShaderId(PIXELSHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 compo
assert(indirectStagesUsed == (indirectStagesUsed & 0xF));
- uid->values[1] |= indirectStagesUsed << 5; // 4;
+ uid->values[1] |= indirectStagesUsed << 3; // 4;
for (unsigned int i = 0; i < bpmem.genMode.numindstages; ++i)
{
if (indirectStagesUsed & (1 << i))
{
- uid->values[1] |= (bpmem.tevindref.getTexCoord(i) < bpmem.genMode.numtexgens) << (9 + 3*i); // 1
+ uid->values[1] |= (bpmem.tevindref.getTexCoord(i) < bpmem.genMode.numtexgens) << (7 + 3*i); // 1
if (bpmem.tevindref.getTexCoord(i) < bpmem.genMode.numtexgens)
- uid->values[1] |= bpmem.tevindref.getTexCoord(i) << (10 + 3*i); // 2
+ uid->values[1] |= bpmem.tevindref.getTexCoord(i) << (8 + 3*i); // 2
}
}
u32* ptr = &uid->values[2];
- for (unsigned int i = 0; i < bpmem.genMode.numtevstages+1; ++i)
+ for (int i = 0; i < bpmem.genMode.numtevstages+1; ++i)
{
StageHash(i, ptr);
ptr += 4; // max: ptr = &uid->values[66]
@@ -487,6 +483,15 @@ static char swapModeTable[4][5];
static char text[16384];
static bool DepthTextureEnable;
+struct RegisterState
+{
+ bool ColorNeedOverflowControl;
+ bool AlphaNeedOverflowControl;
+ bool AuxStored;
+};
+
+static RegisterState RegisterStates[4];
+
static void BuildSwapModeTable()
{
static const char *swapColors = "rgba";
@@ -617,7 +622,6 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
}
WRITE(p, " ) {\n");
- char* pmainstart = p;
int Pretest = AlphaPreTest();
if(Pretest >= 0 && !DepthTextureEnable)
{
@@ -717,6 +721,16 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
}
}
+ RegisterStates[0].AlphaNeedOverflowControl = false;
+ RegisterStates[0].ColorNeedOverflowControl = false;
+ RegisterStates[0].AuxStored = false;
+ for(int i = 1; i < 4; i++)
+ {
+ RegisterStates[i].AlphaNeedOverflowControl = true;
+ RegisterStates[i].ColorNeedOverflowControl = true;
+ RegisterStates[i].AuxStored = false;
+ }
+
for (int i = 0; i < numStages; i++)
WriteStage(p, i, ApiType); //build the equation for this stage
@@ -724,11 +738,22 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
{
// The results of the last texenv stage are put onto the screen,
// regardless of the used destination register
- WRITE(p, "prev.rgb = %s;\n",tevCOutputTable[bpmem.combiners[numStages-1].colorC.dest]);
- WRITE(p, "prev.a = %s;\n",tevAOutputTable[bpmem.combiners[numStages-1].alphaC.dest]);
+ if(bpmem.combiners[numStages - 1].colorC.dest != 0)
+ {
+ bool retrieveFromAuxRegister = !RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].ColorNeedOverflowControl && RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].AuxStored;
+ WRITE(p, "prev.rgb = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevCOutputTable[bpmem.combiners[numStages - 1].colorC.dest]);
+ RegisterStates[0].ColorNeedOverflowControl = RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].ColorNeedOverflowControl;
+ }
+ if(bpmem.combiners[numStages - 1].alphaC.dest != 0)
+ {
+ bool retrieveFromAuxRegister = !RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AlphaNeedOverflowControl && RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AuxStored;
+ WRITE(p, "prev.a = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevAOutputTable[bpmem.combiners[numStages - 1].alphaC.dest]);
+ RegisterStates[0].AlphaNeedOverflowControl = RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AlphaNeedOverflowControl;
+ }
}
- // emulation of unsigned 8 overflow when casting
- WRITE(p, "prev = frac(4.0f + prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");
+ // emulation of unsigned 8 overflow when casting if needed
+ if(RegisterStates[0].AlphaNeedOverflowControl || RegisterStates[0].ColorNeedOverflowControl)
+ WRITE(p, "prev = frac(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");
if(Pretest == -1)
{
@@ -917,7 +942,6 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
TevStageCombiner::ColorCombiner &cc = bpmem.combiners[n].colorC;
TevStageCombiner::AlphaCombiner &ac = bpmem.combiners[n].alphaC;
- // blah1
if(cc.a == TEVCOLORARG_RASA || cc.a == TEVCOLORARG_RASC
|| cc.b == TEVCOLORARG_RASA || cc.b == TEVCOLORARG_RASC
|| cc.c == TEVCOLORARG_RASA || cc.c == TEVCOLORARG_RASC
@@ -950,7 +974,6 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
WRITE(p, "textemp = float4(1.0f, 1.0f, 1.0f, 1.0f);\n");
- // blah2
if (cc.a == TEVCOLORARG_KONST || cc.b == TEVCOLORARG_KONST || cc.c == TEVCOLORARG_KONST || cc.d == TEVCOLORARG_KONST
|| ac.a == TEVALPHAARG_KONST || ac.b == TEVALPHAARG_KONST || ac.c == TEVALPHAARG_KONST || ac.d == TEVALPHAARG_KONST)
{
@@ -971,30 +994,78 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
|| cc.b == TEVCOLORARG_CPREV || cc.b == TEVCOLORARG_APREV
|| cc.c == TEVCOLORARG_CPREV || cc.c == TEVCOLORARG_APREV
|| ac.a == TEVALPHAARG_APREV || ac.b == TEVALPHAARG_APREV || ac.c == TEVALPHAARG_APREV)
- WRITE(p, "cprev = frac(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");
-
+ {
+ if(RegisterStates[0].AlphaNeedOverflowControl || RegisterStates[0].ColorNeedOverflowControl)
+ {
+ WRITE(p, "cprev = frac(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");
+ RegisterStates[0].AlphaNeedOverflowControl = false;
+ RegisterStates[0].ColorNeedOverflowControl = false;
+ }
+ else
+ {
+ WRITE(p, "cprev = prev;\n");
+ }
+ RegisterStates[0].AuxStored = true;
+ }
if(cc.a == TEVCOLORARG_C0 || cc.a == TEVCOLORARG_A0
|| cc.b == TEVCOLORARG_C0 || cc.b == TEVCOLORARG_A0
|| cc.c == TEVCOLORARG_C0 || cc.c == TEVCOLORARG_A0
|| ac.a == TEVALPHAARG_A0 || ac.b == TEVALPHAARG_A0 || ac.c == TEVALPHAARG_A0)
- WRITE(p, "cc0 = frac(c0 * (255.0f/256.0f)) * (256.0f/255.0f);\n");
-
+ {
+ if(RegisterStates[1].AlphaNeedOverflowControl || RegisterStates[1].ColorNeedOverflowControl)
+ {
+ WRITE(p, "cc0 = frac(c0 * (255.0f/256.0f)) * (256.0f/255.0f);\n");
+ RegisterStates[1].AlphaNeedOverflowControl = false;
+ RegisterStates[1].ColorNeedOverflowControl = false;
+ }
+ else
+ {
+ WRITE(p, "cc0 = c0;\n");
+ }
+ RegisterStates[1].AuxStored = true;
+ }
if(cc.a == TEVCOLORARG_C1 || cc.a == TEVCOLORARG_A1
|| cc.b == TEVCOLORARG_C1 || cc.b == TEVCOLORARG_A1
|| cc.c == TEVCOLORARG_C1 || cc.c == TEVCOLORARG_A1
|| ac.a == TEVALPHAARG_A1 || ac.b == TEVALPHAARG_A1 || ac.c == TEVALPHAARG_A1)
- WRITE(p, "cc1 = frac(c1 * (255.0f/256.0f)) * (256.0f/255.0f);\n");
-
+ {
+ if(RegisterStates[2].AlphaNeedOverflowControl || RegisterStates[2].ColorNeedOverflowControl)
+ {
+ WRITE(p, "cc1 = frac(c1 * (255.0f/256.0f)) * (256.0f/255.0f);\n");
+ RegisterStates[2].AlphaNeedOverflowControl = false;
+ RegisterStates[2].ColorNeedOverflowControl = false;
+ }
+ else
+ {
+ WRITE(p, "cc1 = c1;\n");
+ }
+ RegisterStates[2].AuxStored = true;
+ }
if(cc.a == TEVCOLORARG_C2 || cc.a == TEVCOLORARG_A2
|| cc.b == TEVCOLORARG_C2 || cc.b == TEVCOLORARG_A2
|| cc.c == TEVCOLORARG_C2 || cc.c == TEVCOLORARG_A2
|| ac.a == TEVALPHAARG_A2 || ac.b == TEVALPHAARG_A2 || ac.c == TEVALPHAARG_A2)
+ {
+ if(RegisterStates[3].AlphaNeedOverflowControl || RegisterStates[3].ColorNeedOverflowControl)
+ {
WRITE(p, "cc2 = frac(c2 * (255.0f/256.0f)) * (256.0f/255.0f);\n");
+ RegisterStates[3].AlphaNeedOverflowControl = false;
+ RegisterStates[3].ColorNeedOverflowControl = false;
+ }
+ else
+ {
+ WRITE(p, "cc2 = c2;\n");
+ }
+ RegisterStates[3].AuxStored = true;
+ }
+ RegisterStates[cc.dest].ColorNeedOverflowControl = (cc.clamp == 0);
+ RegisterStates[cc.dest].AuxStored = false;
+ // combine the color channel
WRITE(p, "// color combine\n");
if (cc.clamp)
WRITE(p, "%s = saturate(", tevCOutputTable[cc.dest]);
@@ -1042,8 +1113,11 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
WRITE(p, ")");
WRITE(p,";\n");
- WRITE(p, "// alpha combine\n");
+ RegisterStates[ac.dest].AlphaNeedOverflowControl = (ac.clamp == 0);
+ RegisterStates[ac.dest].AuxStored = false;
+
// combine the alpha channel
+ WRITE(p, "// alpha combine\n");
if (ac.clamp)
WRITE(p, "%s = saturate(", tevAOutputTable[ac.dest]);
else
diff --git a/Source/Core/VideoCommon/Src/PixelShaderManager.cpp b/Source/Core/VideoCommon/Src/PixelShaderManager.cpp
index 2521f80500..258ec04413 100644
--- a/Source/Core/VideoCommon/Src/PixelShaderManager.cpp
+++ b/Source/Core/VideoCommon/Src/PixelShaderManager.cpp
@@ -302,7 +302,7 @@ void PixelShaderManager::SetConstants()
float GC_ALIGNED16(material[4]);
float NormalizationCoef = 1 / 255.0f;
- for (int i = 0; i < 4; ++i)
+ for (int i = 0; i < 2; ++i)
{
if (nMaterialsChanged & (1 << i))
{
@@ -316,6 +316,21 @@ void PixelShaderManager::SetConstants()
SetPSConstant4fv(C_PMATERIALS + i, material);
}
}
+
+ for (int i = 0; i < 2; ++i)
+ {
+ if (nMaterialsChanged & (1 << (i + 2)))
+ {
+ u32 data = *(xfregs.matColor + i);
+
+ material[0] = ((data >> 24) & 0xFF) * NormalizationCoef;
+ material[1] = ((data >> 16) & 0xFF) * NormalizationCoef;
+ material[2] = ((data >> 8) & 0xFF) * NormalizationCoef;
+ material[3] = ( data & 0xFF) * NormalizationCoef;
+
+ SetPSConstant4fv(C_PMATERIALS + i + 2, material);
+ }
+ }
nMaterialsChanged = 0;
}
@@ -465,3 +480,16 @@ void PixelShaderManager::SetMaterialColorChanged(int index)
{
nMaterialsChanged |= (1 << index);
}
+
+void PixelShaderManager::DoState(PointerWrap &p)
+{
+ p.Do(lastRGBAfull);
+ p.Do(lastAlpha);
+ p.Do(lastTexDims);
+ p.Do(lastZBias);
+
+ if (p.GetMode() == PointerWrap::MODE_READ)
+ {
+ Dirty();
+ }
+}
diff --git a/Source/Core/VideoCommon/Src/PixelShaderManager.h b/Source/Core/VideoCommon/Src/PixelShaderManager.h
index 2d1c01cad6..a336287a6f 100644
--- a/Source/Core/VideoCommon/Src/PixelShaderManager.h
+++ b/Source/Core/VideoCommon/Src/PixelShaderManager.h
@@ -22,6 +22,8 @@
#include "XFMemory.h"
#include "PixelShaderGen.h"
+class PointerWrap;
+
// The non-API dependent parts.
class PixelShaderManager
{
@@ -30,6 +32,7 @@ public:
static void Init();
static void Dirty();
static void Shutdown();
+ static void DoState(PointerWrap &p);
static void SetConstants(); // sets pixel shader constants
diff --git a/Source/Core/VideoCommon/Src/RenderBase.cpp b/Source/Core/VideoCommon/Src/RenderBase.cpp
index ef0fff57f7..577570c568 100644
--- a/Source/Core/VideoCommon/Src/RenderBase.cpp
+++ b/Source/Core/VideoCommon/Src/RenderBase.cpp
@@ -67,12 +67,7 @@ int Renderer::s_target_height;
int Renderer::s_backbuffer_width;
int Renderer::s_backbuffer_height;
-// ratio of backbuffer size and render area size
-float Renderer::xScale;
-float Renderer::yScale;
-
-unsigned int Renderer::s_XFB_width;
-unsigned int Renderer::s_XFB_height;
+TargetRectangle Renderer::target_rc;
int Renderer::s_LastEFBScale;
@@ -81,10 +76,17 @@ bool Renderer::XFBWrited;
bool Renderer::s_EnableDLCachingAfterRecording;
unsigned int Renderer::prev_efb_format = (unsigned int)-1;
+unsigned int Renderer::efb_scale_numeratorX = 1;
+unsigned int Renderer::efb_scale_numeratorY = 1;
+unsigned int Renderer::efb_scale_denominatorX = 1;
+unsigned int Renderer::efb_scale_denominatorY = 1;
+unsigned int Renderer::ssaa_multiplier = 1;
+
Renderer::Renderer() : frame_data(NULL), bLastFrameDumped(false)
{
UpdateActiveConfig();
+ TextureCache::OnConfigChanged(g_ActiveConfig);
#if defined _WIN32 || defined HAVE_LIBAV
bAVIDumping = false;
@@ -96,6 +98,8 @@ Renderer::~Renderer()
// invalidate previous efb format
prev_efb_format = (unsigned int)-1;
+ efb_scale_numeratorX = efb_scale_numeratorY = efb_scale_denominatorX = efb_scale_denominatorY = ssaa_multiplier = 1;
+
#if defined _WIN32 || defined HAVE_LIBAV
if (g_ActiveConfig.bDumpFrames && bLastFrameDumped && bAVIDumping)
AVIDump::Stop();
@@ -119,69 +123,117 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect
VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight);
XFBWrited = true;
- // XXX: Without the VI, how would we know what kind of field this is? So
- // just use progressive.
if (g_ActiveConfig.bUseXFB)
{
FramebufferManagerBase::CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc,Gamma);
}
else
{
+ // XXX: Without the VI, how would we know what kind of field this is? So
+ // just use progressive.
g_renderer->Swap(xfbAddr, FIELD_PROGRESSIVE, fbWidth, fbHeight,sourceRc,Gamma);
Common::AtomicStoreRelease(s_swapRequested, false);
}
-
- if (TextureCache::DeferredInvalidate)
+}
+
+int Renderer::EFBToScaledX(int x)
+{
+ switch (g_ActiveConfig.iEFBScale)
{
- TextureCache::Invalidate(false);
- }
+ case 0: // fractional
+ return (int)ssaa_multiplier * FramebufferManagerBase::ScaleToVirtualXfbWidth(x, s_backbuffer_width);
+
+ default:
+ return x * (int)ssaa_multiplier * (int)efb_scale_numeratorX / (int)efb_scale_denominatorX;
+ };
}
-void Renderer::CalculateTargetScale(int x, int y, int &scaledX, int &scaledY)
+int Renderer::EFBToScaledY(int y)
{
switch (g_ActiveConfig.iEFBScale)
{
+ case 0: // fractional
+ return (int)ssaa_multiplier * FramebufferManagerBase::ScaleToVirtualXfbHeight(y, s_backbuffer_height);
+
+ default:
+ return y * (int)ssaa_multiplier * (int)efb_scale_numeratorY / (int)efb_scale_denominatorY;
+ };
+}
+
+void Renderer::CalculateTargetScale(int x, int y, int &scaledX, int &scaledY)
+{
+ if (g_ActiveConfig.iEFBScale == 0 || g_ActiveConfig.iEFBScale == 1)
+ {
+ scaledX = x;
+ scaledY = y;
+ }
+ else
+ {
+ scaledX = x * (int)efb_scale_numeratorX / (int)efb_scale_denominatorX;
+ scaledY = y * (int)efb_scale_numeratorY / (int)efb_scale_denominatorY;
+ }
+}
+
+// return true if target size changed
+bool Renderer::CalculateTargetSize(unsigned int framebuffer_width, unsigned int framebuffer_height, int multiplier)
+{
+ int newEFBWidth, newEFBHeight;
+
+ // TODO: Ugly. Clean up
+ switch (s_LastEFBScale)
+ {
+ case 2: // 1x
+ efb_scale_numeratorX = efb_scale_numeratorY = 1;
+ efb_scale_denominatorX = efb_scale_denominatorY = 1;
+ break;
+
case 3: // 1.5x
- scaledX = (x / 2) * 3;
- scaledY = (y / 2) * 3;
+ efb_scale_numeratorX = efb_scale_numeratorY = 3;
+ efb_scale_denominatorX = efb_scale_denominatorY = 2;
break;
+
case 4: // 2x
- scaledX = x * 2;
- scaledY = y * 2;
+ efb_scale_numeratorX = efb_scale_numeratorY = 2;
+ efb_scale_denominatorX = efb_scale_denominatorY = 1;
break;
+
case 5: // 2.5x
- scaledX = (x / 2) * 5;
- scaledY = (y / 2) * 5;
+ efb_scale_numeratorX = efb_scale_numeratorY = 5;
+ efb_scale_denominatorX = efb_scale_denominatorY = 2;
break;
+
case 6: // 3x
- scaledX = x * 3;
- scaledY = y * 3;
+ efb_scale_numeratorX = efb_scale_numeratorY = 3;
+ efb_scale_denominatorX = efb_scale_denominatorY = 1;
break;
+
case 7: // 4x
- scaledX = x * 4;
- scaledY = y * 4;
+ efb_scale_numeratorX = efb_scale_numeratorY = 4;
+ efb_scale_denominatorX = efb_scale_denominatorY = 1;
break;
- default:
- scaledX = x;
- scaledY = y;
+
+ default: // fractional & integral handled later
break;
- };
-}
+ }
-// return true if target size changed
-bool Renderer::CalculateTargetSize(int multiplier)
-{
- int newEFBWidth, newEFBHeight;
switch (s_LastEFBScale)
{
case 0: // fractional
- newEFBWidth = (int)(EFB_WIDTH * xScale);
- newEFBHeight = (int)(EFB_HEIGHT * yScale);
- break;
case 1: // integral
- newEFBWidth = EFB_WIDTH * (int)ceilf(xScale);
- newEFBHeight = EFB_HEIGHT * (int)ceilf(yScale);
+ newEFBWidth = FramebufferManagerBase::ScaleToVirtualXfbWidth(EFB_WIDTH, framebuffer_width);
+ newEFBHeight = FramebufferManagerBase::ScaleToVirtualXfbHeight(EFB_HEIGHT, framebuffer_height);
+
+ if (s_LastEFBScale == 1)
+ {
+ newEFBWidth = ((newEFBWidth-1) / EFB_WIDTH + 1) * EFB_WIDTH;
+ newEFBHeight = ((newEFBHeight-1) / EFB_HEIGHT + 1) * EFB_HEIGHT;
+ }
+ efb_scale_numeratorX = newEFBWidth;
+ efb_scale_denominatorX = EFB_WIDTH;
+ efb_scale_numeratorY = newEFBHeight;
+ efb_scale_denominatorY = EFB_HEIGHT;
break;
+
default:
CalculateTargetScale(EFB_WIDTH, EFB_HEIGHT, newEFBWidth, newEFBHeight);
break;
@@ -189,6 +241,7 @@ bool Renderer::CalculateTargetSize(int multiplier)
newEFBWidth *= multiplier;
newEFBHeight *= multiplier;
+ ssaa_multiplier = multiplier;
if (newEFBWidth != s_target_width || newEFBHeight != s_target_height)
{
@@ -276,7 +329,6 @@ void Renderer::DrawDebugText()
std::string("4: Aspect Ratio: ") + ar_text + (g_ActiveConfig.bCrop ? " (crop)" : ""),
std::string("5: Copy EFB: ") + efbcopy_text,
std::string("6: Fog: ") + (g_ActiveConfig.bDisableFog ? "Disabled" : "Enabled"),
- std::string("7: Material Lighting: ") + (g_ActiveConfig.bDisableLighting ? "Disabled" : "Enabled"),
};
enum { lines_count = sizeof(lines)/sizeof(*lines) };
@@ -315,27 +367,125 @@ void Renderer::DrawDebugText()
}
}
-void Renderer::CalculateXYScale(const TargetRectangle& dst_rect)
+// TODO: remove
+extern bool g_aspect_wide;
+
+void Renderer::UpdateDrawRectangle(int backbuffer_width, int backbuffer_height)
{
- if (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)
+ float FloatGLWidth = (float)backbuffer_width;
+ float FloatGLHeight = (float)backbuffer_height;
+ float FloatXOffset = 0;
+ float FloatYOffset = 0;
+
+ // The rendering window size
+ const float WinWidth = FloatGLWidth;
+ const float WinHeight = FloatGLHeight;
+
+ // Handle aspect ratio.
+ // Default to auto.
+ bool use16_9 = g_aspect_wide;
+
+ // Update aspect ratio hack values
+ // Won't take effect until next frame
+ // Don't know if there is a better place for this code so there isn't a 1 frame delay
+ if ( g_ActiveConfig.bWidescreenHack )
{
- xScale = 1.0f;
- yScale = 1.0f;
+ float source_aspect = use16_9 ? (16.0f / 9.0f) : (4.0f / 3.0f);
+ float target_aspect;
+
+ switch ( g_ActiveConfig.iAspectRatio )
+ {
+ case ASPECT_FORCE_16_9 :
+ target_aspect = 16.0f / 9.0f;
+ break;
+ case ASPECT_FORCE_4_3 :
+ target_aspect = 4.0f / 3.0f;
+ break;
+ case ASPECT_STRETCH :
+ target_aspect = WinWidth / WinHeight;
+ break;
+ default :
+ // ASPECT_AUTO == no hacking
+ target_aspect = source_aspect;
+ break;
+ }
+
+ float adjust = source_aspect / target_aspect;
+ if ( adjust > 1 )
+ {
+ // Vert+
+ g_Config.fAspectRatioHackW = 1;
+ g_Config.fAspectRatioHackH = 1/adjust;
+ }
+ else
+ {
+ // Hor+
+ g_Config.fAspectRatioHackW = adjust;
+ g_Config.fAspectRatioHackH = 1;
+ }
}
else
{
- if (g_ActiveConfig.b3DVision)
+ // Hack is disabled
+ g_Config.fAspectRatioHackW = 1;
+ g_Config.fAspectRatioHackH = 1;
+ }
+
+ // Check for force-settings and override.
+ if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_16_9)
+ use16_9 = true;
+ else if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_4_3)
+ use16_9 = false;
+
+ if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH)
+ {
+ // The rendering window aspect ratio as a proportion of the 4:3 or 16:9 ratio
+ float Ratio = (WinWidth / WinHeight) / (!use16_9 ? (4.0f / 3.0f) : (16.0f / 9.0f));
+ // Check if height or width is the limiting factor. If ratio > 1 the picture is too wide and have to limit the width.
+ if (Ratio > 1.0f)
{
- // This works, yet the version in the else doesn't. No idea why.
- xScale = (float)(s_backbuffer_width-1) / (float)(s_XFB_width-1);
- yScale = (float)(s_backbuffer_height-1) / (float)(s_XFB_height-1);
+ // Scale down and center in the X direction.
+ FloatGLWidth /= Ratio;
+ FloatXOffset = (WinWidth - FloatGLWidth) / 2.0f;
}
+ // The window is too high, we have to limit the height
else
{
- xScale = (float)(dst_rect.right - dst_rect.left - 1) / (float)(s_XFB_width-1);
- yScale = (float)(dst_rect.bottom - dst_rect.top - 1) / (float)(s_XFB_height-1);
+ // Scale down and center in the Y direction.
+ FloatGLHeight *= Ratio;
+ FloatYOffset = FloatYOffset + (WinHeight - FloatGLHeight) / 2.0f;
}
}
+
+ // -----------------------------------------------------------------------
+ // Crop the picture from 4:3 to 5:4 or from 16:9 to 16:10.
+ // Output: FloatGLWidth, FloatGLHeight, FloatXOffset, FloatYOffset
+ // ------------------
+ if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH && g_ActiveConfig.bCrop)
+ {
+ float Ratio = !use16_9 ? ((4.0f / 3.0f) / (5.0f / 4.0f)) : (((16.0f / 9.0f) / (16.0f / 10.0f)));
+ // The width and height we will add (calculate this before FloatGLWidth and FloatGLHeight is adjusted)
+ float IncreasedWidth = (Ratio - 1.0f) * FloatGLWidth;
+ float IncreasedHeight = (Ratio - 1.0f) * FloatGLHeight;
+ // The new width and height
+ FloatGLWidth = FloatGLWidth * Ratio;
+ FloatGLHeight = FloatGLHeight * Ratio;
+ // Adjust the X and Y offset
+ FloatXOffset = FloatXOffset - (IncreasedWidth * 0.5f);
+ FloatYOffset = FloatYOffset - (IncreasedHeight * 0.5f);
+ }
+
+ int XOffset = (int)(FloatXOffset + 0.5f);
+ int YOffset = (int)(FloatYOffset + 0.5f);
+ int iWhidth = (int)ceil(FloatGLWidth);
+ int iHeight = (int)ceil(FloatGLHeight);
+ iWhidth -= iWhidth % 4; // ensure divisibility by 4 to make it compatible with all the video encoders
+ iHeight -= iHeight % 4;
+
+ target_rc.left = XOffset;
+ target_rc.top = YOffset;
+ target_rc.right = XOffset + iWhidth;
+ target_rc.bottom = YOffset + iHeight;
}
void Renderer::SetWindowSize(int width, int height)
@@ -390,5 +540,6 @@ void Renderer::RecordVideoMemory()
void UpdateViewport(Matrix44& vpCorrection)
{
- g_renderer->UpdateViewport(vpCorrection);
+ if (xfregs.viewport.wd != 0 && xfregs.viewport.ht != 0)
+ g_renderer->UpdateViewport(vpCorrection);
}
diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h
index e8d4c55a20..4da80c9752 100644
--- a/Source/Core/VideoCommon/Src/RenderBase.h
+++ b/Source/Core/VideoCommon/Src/RenderBase.h
@@ -74,10 +74,6 @@ public:
static int GetBackbufferWidth() { return s_backbuffer_width; }
static int GetBackbufferHeight() { return s_backbuffer_height; }
- // XFB scale - TODO: Remove this and add two XFBToScaled functions instead
- static float GetXFBScaleX() { return xScale; }
- static float GetXFBScaleY() { return yScale; }
-
static void SetWindowSize(int width, int height);
// EFB coordinate conversion functions
@@ -85,9 +81,13 @@ public:
// Use this to convert a whole native EFB rect to backbuffer coordinates
virtual TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) = 0;
+ static const TargetRectangle& GetTargetRectangle() { return target_rc; }
+ static void UpdateDrawRectangle(int backbuffer_width, int backbuffer_height);
+
+
// Use this to upscale native EFB coordinates to IDEAL internal resolution
- static unsigned int EFBToScaledX(int x) { return x * GetTargetWidth() / EFB_WIDTH; }
- static unsigned int EFBToScaledY(int y) { return y * GetTargetHeight() / EFB_HEIGHT; }
+ static int EFBToScaledX(int x);
+ static int EFBToScaledY(int y);
// Floating point versions of the above - only use them if really necessary
static float EFBToScaledXf(float x) { return x * ((float)GetTargetWidth() / (float)EFB_WIDTH); }
@@ -133,8 +133,7 @@ public:
protected:
static void CalculateTargetScale(int x, int y, int &scaledX, int &scaledY);
- static bool CalculateTargetSize(int multiplier = 1);
- static void CalculateXYScale(const TargetRectangle& dst_rect);
+ static bool CalculateTargetSize(unsigned int framebuffer_width, unsigned int framebuffer_height, int multiplier = 1);
static void CheckFifoRecording();
static void RecordVideoMemory();
@@ -159,12 +158,7 @@ protected:
static int s_backbuffer_width;
static int s_backbuffer_height;
- // ratio of backbuffer size and render area size - TODO: Remove these!
- static float xScale;
- static float yScale;
-
- static unsigned int s_XFB_width;
- static unsigned int s_XFB_height;
+ static TargetRectangle target_rc;
// can probably eliminate this static var
static int s_LastEFBScale;
@@ -176,6 +170,11 @@ protected:
private:
static unsigned int prev_efb_format;
+ static unsigned int efb_scale_numeratorX;
+ static unsigned int efb_scale_numeratorY;
+ static unsigned int efb_scale_denominatorX;
+ static unsigned int efb_scale_denominatorY;
+ static unsigned int ssaa_multiplier;
};
extern Renderer *g_renderer;
diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp
index 00ff9610be..9fc18ef1bd 100644
--- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp
+++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp
@@ -33,16 +33,18 @@ extern int frameCount;
enum
{
- TEMP_SIZE = (2048 * 2048 * 4),
TEXTURE_KILL_THRESHOLD = 200,
};
TextureCache *g_texture_cache;
GC_ALIGNED16(u8 *TextureCache::temp) = NULL;
+unsigned int TextureCache::temp_size;
TextureCache::TexCache TextureCache::textures;
-bool TextureCache::DeferredInvalidate;
+
+TextureCache::BackupConfig TextureCache::backup_config;
+
TextureCache::TCacheEntryBase::~TCacheEntryBase()
{
@@ -50,42 +52,29 @@ TextureCache::TCacheEntryBase::~TCacheEntryBase()
TextureCache::TextureCache()
{
+ temp_size = 2048 * 2048 * 4;
if (!temp)
- temp = (u8*)AllocateAlignedMemory(TEMP_SIZE,16);
+ temp = (u8*)AllocateAlignedMemory(temp_size, 16);
TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter);
if(g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures)
HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures);
}
-void TextureCache::Invalidate(bool shutdown)
+void TextureCache::Invalidate()
{
TexCache::iterator
iter = textures.begin(),
tcend = textures.end();
for (; iter != tcend; ++iter)
- {
- if (shutdown)
- iter->second->addr = 0;
delete iter->second;
- }
textures.clear();
- if(g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures)
- HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
- SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures);
-
- DeferredInvalidate = false;
-}
-
-void TextureCache::InvalidateDefer()
-{
- DeferredInvalidate = true;
}
TextureCache::~TextureCache()
{
- Invalidate(true);
+ Invalidate();
if (temp)
{
FreeAlignedMemory(temp);
@@ -93,6 +82,48 @@ TextureCache::~TextureCache()
}
}
+void TextureCache::OnConfigChanged(VideoConfig& config)
+{
+ if (!g_texture_cache)
+ goto skip_checks;
+
+ // TODO: Invalidating texcache is really stupid in some of these cases
+ if (config.iSafeTextureCache_ColorSamples != backup_config.s_colorsamples ||
+ config.bTexFmtOverlayEnable != backup_config.s_texfmt_overlay ||
+ config.bTexFmtOverlayCenter != backup_config.s_texfmt_overlay_center ||
+ config.bHiresTextures != backup_config.s_hires_textures)
+ {
+ g_texture_cache->Invalidate();
+
+ if(g_ActiveConfig.bHiresTextures)
+ HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
+
+ SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures);
+ TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter);
+ }
+
+ // TODO: Probably shouldn't clear all render targets here, just mark them dirty or something.
+ if (config.bEFBCopyCacheEnable != backup_config.s_copy_cache_enable || // TODO: not sure if this is needed?
+ config.bCopyEFBToTexture != backup_config.s_copy_efb_to_texture ||
+ config.bCopyEFBScaled != backup_config.s_copy_efb_scaled ||
+ config.bEFBCopyEnable != backup_config.s_copy_efb ||
+ config.iEFBScale != backup_config.s_efb_scale)
+ {
+ g_texture_cache->ClearRenderTargets();
+ }
+
+skip_checks:
+ backup_config.s_colorsamples = config.iSafeTextureCache_ColorSamples;
+ backup_config.s_copy_efb_to_texture = config.bCopyEFBToTexture;
+ backup_config.s_copy_efb_scaled = config.bCopyEFBScaled;
+ backup_config.s_copy_efb = config.bEFBCopyEnable;
+ backup_config.s_efb_scale = config.iEFBScale;
+ backup_config.s_texfmt_overlay = config.bTexFmtOverlayEnable;
+ backup_config.s_texfmt_overlay_center = config.bTexFmtOverlayCenter;
+ backup_config.s_hires_textures = config.bHiresTextures;
+ backup_config.s_copy_cache_enable = config.bEFBCopyCacheEnable;
+}
+
void TextureCache::Cleanup()
{
TexCache::iterator iter = textures.begin();
@@ -174,8 +205,93 @@ void TextureCache::ClearRenderTargets()
tcend = textures.end();
for (; iter!=tcend; ++iter)
- if (iter->second->type != TCET_EC_DYNAMIC)
- iter->second->type = TCET_NORMAL;
+ if (iter->second->type == TCET_EC_VRAM)
+ {
+ delete iter->second;
+ textures.erase(iter++);
+ }
+}
+
+bool TextureCache::CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsigned int levels)
+{
+ // Just checking if the necessary files exist, if they can't be loaded or have incorrect dimensions LODs will be black
+ char texBasePathTemp[MAX_PATH];
+ char texPathTemp[MAX_PATH];
+
+ sprintf(texBasePathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat);
+
+ for (unsigned int level = 1; level < levels; ++level)
+ {
+ sprintf(texPathTemp, "%s_mip%i", texBasePathTemp, level);
+ if (!HiresTextures::HiresTexExists(texPathTemp))
+ {
+ if (level > 1)
+ WARN_LOG(VIDEO, "Couldn't find custom texture LOD with index %i (filename: %s), disabling custom LODs for this texture", level, texPathTemp);
+
+ return false;
+ }
+ }
+ return true;
+}
+
+PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsigned int level, unsigned int& width, unsigned int& height)
+{
+ char texPathTemp[MAX_PATH];
+ unsigned int newWidth = 0;
+ unsigned int newHeight = 0;
+
+ if (level == 0)
+ sprintf(texPathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat);
+ else
+ sprintf(texPathTemp, "%s_%08x_%i_mip%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat, level);
+
+ unsigned int required_size = 0;
+ PC_TexFormat ret = HiresTextures::GetHiresTex(texPathTemp, &newWidth, &newHeight, &required_size, texformat, temp_size, temp);
+ if (ret == PC_TEX_FMT_NONE && temp_size < required_size)
+ {
+ // Allocate more memory and try again
+ // TODO: Should probably check if newWidth and newHeight are texture dimensions which are actually supported by the current video backend
+ temp_size = required_size;
+ FreeAlignedMemory(temp);
+ temp = (u8*)AllocateAlignedMemory(temp_size, 16);
+ ret = HiresTextures::GetHiresTex(texPathTemp, &newWidth, &newHeight, &required_size, texformat, temp_size, temp);
+ }
+
+ if (ret != PC_TEX_FMT_NONE)
+ {
+ width = newWidth;
+ height = newHeight;
+ }
+ return ret;
+}
+
+void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level)
+{
+ char szTemp[MAX_PATH];
+ std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) +
+ SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID;
+
+ // make sure that the directory exists
+ if (false == File::Exists(szDir) || false == File::IsDirectory(szDir))
+ File::CreateDir(szDir.c_str());
+
+ // For compatibility with old texture packs, don't print the LOD index for level 0.
+ // TODO: TLUT format should actually be stored in filename? :/
+ if (level == 0)
+ {
+ sprintf(szTemp, "%s/%s_%08x_%i.png", szDir.c_str(),
+ SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(),
+ (u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF);
+ }
+ else
+ {
+ sprintf(szTemp, "%s/%s_%08x_%i_mip%i.png", szDir.c_str(),
+ SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(),
+ (u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF, level);
+ }
+
+ if (false == File::Exists(szTemp))
+ entry->Save(szTemp, level);
}
TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
@@ -194,6 +310,9 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
const unsigned int nativeW = width;
const unsigned int nativeH = height;
+ bool using_custom_texture = false;
+ bool using_custom_lods = false;
+
u32 texID = address;
u64 tex_hash = TEXHASH_INVALID; // Hash assigned to texcache entry (also used to generate filenames used for texture dumping and custom texture lookup)
u64 tlut_hash = TEXHASH_INVALID;
@@ -240,8 +359,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
// 2. a) For EFB copies, only the hash and the texture address need to match
if (entry->IsEfbCopy() && tex_hash == entry->hash && address == entry->addr)
{
- if (entry->type != TCET_EC_VRAM)
- entry->type = TCET_NORMAL;
+ entry->type = TCET_EC_VRAM;
// TODO: Print a warning if the format changes! In this case, we could reinterpret the internal texture object data to the new pixel format (similiar to what is already being done in Renderer::ReinterpretPixelFormat())
goto return_entry;
@@ -259,7 +377,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
//
// TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies?
// TODO: Actually, it should be enough if the internal texture format matches...
- if ((entry->type == TCET_NORMAL && width == entry->native_width && height == entry->native_height && full_format == entry->format && entry->num_mipmaps == maxlevel)
+ if ((entry->type == TCET_NORMAL && width == entry->virtual_width && height == entry->virtual_height && full_format == entry->format && entry->num_mipmaps == maxlevel)
|| (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height))
{
// reuse the texture
@@ -272,38 +390,39 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
}
}
+
if (g_ActiveConfig.bHiresTextures)
{
- // Load Custom textures
- char texPathTemp[MAX_PATH];
-
- unsigned int newWidth = width;
- unsigned int newHeight = height;
-
- sprintf(texPathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat);
- pcfmt = HiresTextures::GetHiresTex(texPathTemp, &newWidth, &newHeight, texformat, temp);
-
+ pcfmt = LoadCustomTexture(tex_hash, texformat, 0, width, height);
if (pcfmt != PC_TEX_FMT_NONE)
{
- expandedWidth = width = newWidth;
- expandedHeight = height = newHeight;
+ if (expandedWidth != width || expandedHeight != height)
+ {
+ expandedWidth = width;
+ expandedHeight = height;
+
+ // If we thought we could reuse the texture before, make sure to delete it now!
+ delete entry;
+ entry = NULL;
+ }
+ using_custom_texture = true;
}
}
- // TODO: RGBA8 textures are stored non-continuously in tmem, that might cause problems when preloading is enabled
- if (pcfmt == PC_TEX_FMT_NONE)
+ // TODO: RGBA8 textures are stored non-continuously in tmem, that might cause problems here when preloading is enabled
+ if (!using_custom_texture)
pcfmt = TexDecoder_Decode(temp, src_data, expandedWidth,
expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures);
+ // TODO: Cleanup. Plus, we still autogenerate mipmaps in certain cases (we shouldn't do that)
bool isPow2;
unsigned int texLevels;
- UseNativeMips = UseNativeMips && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions
isPow2 = !((width & (width - 1)) || (height & (height - 1)));
- texLevels = (isPow2 && UseNativeMips && maxlevel) ?
- GetPow2(std::max(width, height)) : !isPow2;
-
- if ((texLevels > (maxlevel + 1)) && maxlevel)
- texLevels = maxlevel + 1;
+ texLevels = (isPow2 && maxlevel) ? GetPow2(std::max(width, height)) : !isPow2;
+ texLevels = maxlevel ? std::min(texLevels, maxlevel + 1) : texLevels;
+ using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, texLevels);
+ UseNativeMips = UseNativeMips && !using_custom_lods && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions
+ texLevels = (UseNativeMips || using_custom_lods) ? texLevels : !isPow2;
// create the entry/texture
if (NULL == entry) {
@@ -329,8 +448,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
// load texture
entry->Load(width, height, expandedWidth, 0, (texLevels == 0));
+ if (g_ActiveConfig.bDumpTextures && !using_custom_texture)
+ DumpTexture(entry, 0);
+
// load mips - TODO: Loading mipmaps from tmem is untested!
- if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE)
+ if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && UseNativeMips)
{
const unsigned int bsdepth = TexDecoder_GetTexelSizeInNibbles(texformat);
@@ -361,31 +483,33 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
TexDecoder_Decode(temp, *ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures);
entry->Load(currentWidth, currentHeight, expandedWidth, level, false);
+ if (g_ActiveConfig.bDumpTextures)
+ DumpTexture(entry, level);
+
*ptr += ((std::max(mipWidth, bsw) * std::max(mipHeight, bsh) * bsdepth) >> 1);
mipWidth >>= 1;
mipHeight >>= 1;
++level;
}
}
-
- // TODO: won't this cause loaded hires textures to be dumped as well?
- // dump texture to file
- if (g_ActiveConfig.bDumpTextures)
+ else if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && using_custom_lods)
{
- char szTemp[MAX_PATH];
- std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) +
- SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID;
+ unsigned int level = 1;
+ unsigned int mipWidth = (width + 1) >> 1;
+ unsigned int mipHeight = (height + 1) >> 1;
- // make sure that the directory exists
- if (false == File::Exists(szDir) || false == File::IsDirectory(szDir))
- File::CreateDir(szDir.c_str());
+ while ((mipHeight || mipWidth) && (level < texLevels))
+ {
+ unsigned int currentWidth = (mipWidth > 0) ? mipWidth : 1;
+ unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1;
- sprintf(szTemp, "%s/%s_%08x_%i.png", szDir.c_str(),
- SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(),
- (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat);
+ LoadCustomTexture(tex_hash, texformat, level, currentWidth, currentHeight);
+ entry->Load(currentWidth, currentHeight, currentWidth, level, false);
- if (false == File::Exists(szTemp))
- entry->Save(szTemp);
+ mipWidth >>= 1;
+ mipHeight >>= 1;
+ ++level;
+ }
}
INCSTAT(stats.numTexturesCreated);
@@ -649,16 +773,12 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
TCacheEntryBase *entry = textures[dstAddr];
if (entry)
{
- if ((entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h)
- || (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h))
+ if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h)
{
- if (entry->type == TCET_EC_DYNAMIC)
- {
- scaled_tex_w = tex_w;
- scaled_tex_h = tex_h;
- }
+ scaled_tex_w = tex_w;
+ scaled_tex_h = tex_h;
}
- else
+ else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h))
{
// remove it and recreate it as a render target
delete entry;
@@ -672,7 +792,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
textures[dstAddr] = entry = g_texture_cache->CreateRenderTargetTexture(scaled_tex_w, scaled_tex_h);
// TODO: Using the wrong dstFormat, dumb...
- entry->SetGeneralParameters(dstAddr, 0, dstFormat, 0);
+ entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1);
entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h);
entry->SetHashes(TEXHASH_INVALID);
entry->type = TCET_EC_VRAM;
diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h
index 2924c5871f..4ef3b8a985 100644
--- a/Source/Core/VideoCommon/Src/TextureCacheBase.h
+++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h
@@ -27,6 +27,8 @@
#include "CommonTypes.h"
+struct VideoConfig;
+
class TextureCache
{
public:
@@ -84,7 +86,7 @@ public:
virtual ~TCacheEntryBase();
virtual void Bind(unsigned int stage) = 0;
- virtual bool Save(const char filename[]) = 0;
+ virtual bool Save(const char filename[], unsigned int level) = 0;
virtual void Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int level, bool autogen_mips) = 0;
@@ -100,10 +102,10 @@ public:
virtual ~TextureCache(); // needs virtual for DX11 dtor
+ static void OnConfigChanged(VideoConfig& config);
static void Cleanup();
- static void Invalidate(bool shutdown);
- static void InvalidateDefer();
+ static void Invalidate();
static void InvalidateRange(u32 start_address, u32 size);
static void MakeRangeDynamic(u32 start_address, u32 size);
static void ClearRenderTargets(); // currently only used by OGL
@@ -118,17 +120,34 @@ public:
static void CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat,
const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf);
- static bool DeferredInvalidate;
-
protected:
TextureCache();
static GC_ALIGNED16(u8 *temp);
+ static unsigned int temp_size;
private:
+ static bool CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsigned int levels);
+ static PC_TexFormat LoadCustomTexture(u64 tex_hash, int texformat, unsigned int level, unsigned int& width, unsigned int& height);
+ static void DumpTexture(TCacheEntryBase* entry, unsigned int level);
+
+
typedef std::map<u32, TCacheEntryBase*> TexCache;
static TexCache textures;
+
+ // Backup configuration values
+ static struct BackupConfig {
+ int s_colorsamples;
+ bool s_copy_efb_to_texture;
+ bool s_copy_efb_scaled;
+ bool s_copy_efb;
+ int s_efb_scale;
+ bool s_texfmt_overlay;
+ bool s_texfmt_overlay_center;
+ bool s_hires_textures;
+ bool s_copy_cache_enable;
+ } backup_config;
};
extern TextureCache *g_texture_cache;
diff --git a/Source/Core/VideoCommon/Src/VertexLoader.cpp b/Source/Core/VideoCommon/Src/VertexLoader.cpp
index fb34ce1bc1..5bffab8ee7 100644
--- a/Source/Core/VideoCommon/Src/VertexLoader.cpp
+++ b/Source/Core/VideoCommon/Src/VertexLoader.cpp
@@ -224,14 +224,14 @@ void VertexLoader::CompileVertexTranslator()
#endif
// Colors
- const int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
+ const u32 col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
// TextureCoord
// Since m_VtxDesc.Text7Coord is broken across a 32 bit word boundary, retrieve its value manually.
// If we didn't do this, the vertex format would be read as one bit offset from where it should be, making
// 01 become 00, and 10/11 become 01
- const int tc[8] = {
+ const u32 tc[8] = {
m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord,
- m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, (const int)((m_VtxDesc.Hex >> 31) & 3)
+ m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, (const u32)((m_VtxDesc.Hex >> 31) & 3)
};
// Reset pipeline
@@ -770,7 +770,7 @@ void VertexLoader::AppendToString(std::string *dest) const
dest->append(StringFromFormat("Nrm: %i %s-%s ",
m_VtxAttr.NormalElements, posMode[m_VtxDesc.Normal], posFormats[m_VtxAttr.NormalFormat]));
}
- int color_mode[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
+ u32 color_mode[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
for (int i = 0; i < 2; i++)
{
if (color_mode[i])
@@ -778,7 +778,7 @@ void VertexLoader::AppendToString(std::string *dest) const
dest->append(StringFromFormat("C%i: %i %s-%s ", i, m_VtxAttr.color[i].Elements, posMode[color_mode[i]], colorFormat[m_VtxAttr.color[i].Comp]));
}
}
- int tex_mode[8] = {
+ u32 tex_mode[8] = {
m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord,
m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, m_VtxDesc.Tex7Coord
};
diff --git a/Source/Core/VideoCommon/Src/VertexLoaderManager.cpp b/Source/Core/VideoCommon/Src/VertexLoaderManager.cpp
index 316941a639..153e69a8c3 100644
--- a/Source/Core/VideoCommon/Src/VertexLoaderManager.cpp
+++ b/Source/Core/VideoCommon/Src/VertexLoaderManager.cpp
@@ -19,9 +19,12 @@
#ifdef _MSC_VER
#include <hash_map>
using stdext::hash_map;
-#else
+#elif defined __APPLE__
#include <ext/hash_map>
using __gnu_cxx::hash_map;
+#else
+#include <unordered_map>
+using std::unordered_map;
#endif
#include <map>
#include <vector>
@@ -45,7 +48,12 @@ namespace stdext {
}
}
#else
-namespace __gnu_cxx {
+#ifdef __APPLE__
+namespace __gnu_cxx
+#else
+namespace std
+#endif
+{
template<> struct hash<VertexLoaderUID> {
size_t operator()(const VertexLoaderUID& uid) const {
return uid.GetHash();
@@ -54,10 +62,15 @@ namespace __gnu_cxx {
}
#endif
+#if defined _MSC_VER || defined __APPLE__
+typedef hash_map<VertexLoaderUID, VertexLoader*> VertexLoaderMap;
+#else
+typedef unordered_map<VertexLoaderUID, VertexLoader*> VertexLoaderMap;
+#endif
+
namespace VertexLoaderManager
{
-typedef hash_map<VertexLoaderUID, VertexLoader*> VertexLoaderMap;
static VertexLoaderMap g_VertexLoaderMap;
// TODO - change into array of pointers. Keep a map of all seen so far.
diff --git a/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp b/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp
index b16e7e6ee9..9cfa5efc31 100644
--- a/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp
+++ b/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp
@@ -149,7 +149,7 @@ void LOADERDECL Color_ReadIndex8_24b_888()
void LOADERDECL Color_ReadIndex8_32b_888x()
{
u8 Index = DataReadU8();
- const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR]+colIndex);
+ const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
_SetCol(_Read24(iAddress));
}
void LOADERDECL Color_ReadIndex8_16b_4444()
diff --git a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp
index 004b0f3cca..5be72e4fcf 100644
--- a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp
+++ b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp
@@ -9,6 +9,7 @@
#include "NativeVertexFormat.h"
#include "TextureCacheBase.h"
#include "RenderBase.h"
+#include "BPStructs.h"
#include "VertexManagerBase.h"
#include "VideoConfig.h"
@@ -159,16 +160,9 @@ void VertexManager::AddVertices(int primitive, int numVertices)
void VertexManager::Flush()
{
- // Disable Lighting
- // TODO - Is this a good spot for this code?
- if (g_ActiveConfig.bDisableLighting)
- {
- for (u32 i = 0; i < xfregs.numChan.numColorChans; i++)
- {
- xfregs.alpha[i].enablelighting = false;
- xfregs.color[i].enablelighting = false;
- }
- }
+ // loading a state will invalidate BP, so check for it
+ g_video_backend->CheckInvalidState();
+
g_vertex_manager->vFlush();
}
@@ -236,22 +230,13 @@ void VertexManager::Flush()
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
tex.texTlut[i&3].tlut_format,
- (tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8) && g_ActiveConfig.bUseNativeMips,
+ (tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8),
(tex.texMode1[i&3].max_lod >> 4));
if (tentry)
{
// 0s are probably for no manual wrapping needed.
PixelShaderManager::SetTexDims(i, tentry->nativeW, tentry->nativeH, 0, 0);
-
- // TODO:
- //if (g_ActiveConfig.iLog & CONF_SAVETEXTURES)
- //{
- // // save the textures
- // char strfile[255];
- // sprintf(strfile, "%stex%.3d_%d.tga", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_Config.iSaveTargetId, i);
- // SaveTexture(strfile, GL_TEXTURE_2D, tentry->texture, tentry->w, tentry->h);
- //}
}
else
ERROR_LOG(VIDEO, "error loading texture");
@@ -317,3 +302,20 @@ shader_fail:
ResetBuffer();
}
#endif
+
+void VertexManager::DoState(PointerWrap& p)
+{
+ g_vertex_manager->vDoState(p);
+}
+
+void VertexManager::DoStateShared(PointerWrap& p)
+{
+ p.DoPointer(s_pCurBufferPointer, LocalVBuffer);
+ p.DoArray(LocalVBuffer, MAXVBUFFERSIZE);
+ p.DoArray(TIBuffer, MAXIBUFFERSIZE);
+ p.DoArray(LIBuffer, MAXIBUFFERSIZE);
+ p.DoArray(PIBuffer, MAXIBUFFERSIZE);
+
+ if (p.GetMode() == PointerWrap::MODE_READ)
+ Flushed = false;
+}
diff --git a/Source/Core/VideoCommon/Src/VertexManagerBase.h b/Source/Core/VideoCommon/Src/VertexManagerBase.h
index 12dc02ae4b..f3a4aa72e3 100644
--- a/Source/Core/VideoCommon/Src/VertexManagerBase.h
+++ b/Source/Core/VideoCommon/Src/VertexManagerBase.h
@@ -3,6 +3,7 @@
#define _VERTEXMANAGERBASE_H
class NativeVertexFormat;
+class PointerWrap;
class VertexManager
{
@@ -20,7 +21,7 @@ public:
// values from DX11 backend
MAXVBUFFERSIZE = 0x50000,
- MAXIBUFFERSIZE = 0x10000,
+ MAXIBUFFERSIZE = 0xFFFF,
};
VertexManager();
@@ -44,6 +45,9 @@ public:
static u16* GetPointIndexBuffer() { return PIBuffer; }
static u8* GetVertexBuffer() { return LocalVBuffer; }
+ static void DoState(PointerWrap& p);
+ virtual void CreateDeviceObjects(){};
+ virtual void DestroyDeviceObjects(){};
protected:
// TODO: make private after Flush() is merged
static void ResetBuffer();
@@ -55,6 +59,9 @@ protected:
static bool Flushed;
+ virtual void vDoState(PointerWrap& p) { DoStateShared(p); }
+ void DoStateShared(PointerWrap& p);
+
private:
static void AddIndices(int primitive, int numVertices);
//virtual void Draw(u32 stride, bool alphapass) = 0;
diff --git a/Source/Core/VideoCommon/Src/VertexShaderManager.cpp b/Source/Core/VideoCommon/Src/VertexShaderManager.cpp
index b6afbc61c6..d960710ada 100644
--- a/Source/Core/VideoCommon/Src/VertexShaderManager.cpp
+++ b/Source/Core/VideoCommon/Src/VertexShaderManager.cpp
@@ -51,6 +51,11 @@ static float s_fViewRotation[2];
void UpdateViewport(Matrix44& vpCorrection);
+void UpdateViewportWithCorrection()
+{
+ UpdateViewport(s_viewportCorrection);
+}
+
inline void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{
g_renderer->SetVSConstant4f(const_number, f1, f2, f3, f4);
@@ -202,6 +207,7 @@ void VertexShaderManager::SetConstants()
int endn = (nPostTransformMatricesChanged[1] + 3 ) / 4;
const float* pstart = (const float*)&xfmem[XFMEM_POSTMATRICES + startn * 4];
SetMultiVSConstant4fv(C_POSTTRANSFORMMATRICES + startn, endn - startn, pstart);
+ nPostTransformMatricesChanged[0] = nPostTransformMatricesChanged[1] = -1;
}
if (nLightsChanged[0] >= 0)
@@ -245,7 +251,7 @@ void VertexShaderManager::SetConstants()
float GC_ALIGNED16(material[4]);
float NormalizationCoef = 1 / 255.0f;
- for (int i = 0; i < 4; ++i)
+ for (int i = 0; i < 2; ++i)
{
if (nMaterialsChanged & (1 << i))
{
@@ -259,6 +265,21 @@ void VertexShaderManager::SetConstants()
SetVSConstant4fv(C_MATERIALS + i, material);
}
}
+
+ for (int i = 0; i < 2; ++i)
+ {
+ if (nMaterialsChanged & (1 << (i + 2)))
+ {
+ u32 data = *(xfregs.matColor + i);
+
+ material[0] = ((data >> 24) & 0xFF) * NormalizationCoef;
+ material[1] = ((data >> 16) & 0xFF) * NormalizationCoef;
+ material[2] = ((data >> 8) & 0xFF) * NormalizationCoef;
+ material[3] = ( data & 0xFF) * NormalizationCoef;
+
+ SetVSConstant4fv(C_MATERIALS + i + 2, material);
+ }
+ }
nMaterialsChanged = 0;
}
@@ -616,3 +637,18 @@ void VertexShaderManager::ResetView()
bProjectionChanged = true;
}
+
+void VertexShaderManager::DoState(PointerWrap &p)
+{
+ p.Do(g_fProjectionMatrix);
+ p.Do(s_viewportCorrection);
+ p.Do(s_viewRotationMatrix);
+ p.Do(s_viewInvRotationMatrix);
+ p.Do(s_fViewTranslationVector);
+ p.Do(s_fViewRotation);
+
+ if (p.GetMode() == PointerWrap::MODE_READ)
+ {
+ Dirty();
+ }
+}
diff --git a/Source/Core/VideoCommon/Src/VertexShaderManager.h b/Source/Core/VideoCommon/Src/VertexShaderManager.h
index ddbde1c0dd..86f77ee3da 100644
--- a/Source/Core/VideoCommon/Src/VertexShaderManager.h
+++ b/Source/Core/VideoCommon/Src/VertexShaderManager.h
@@ -20,6 +20,8 @@
#include "VertexShaderGen.h"
+class PointerWrap;
+
struct ProjectionHack
{
float sign;
@@ -31,6 +33,8 @@ struct ProjectionHack
void UpdateProjectionHack(int iParams[], std::string sParams[]);
+void UpdateViewportWithCorrection();
+
// The non-API dependent parts.
class VertexShaderManager
{
@@ -38,7 +42,8 @@ public:
static void Init();
static void Dirty();
static void Shutdown();
-
+ static void DoState(PointerWrap &p);
+;
// constant management
static void SetConstants();
diff --git a/Source/Core/VideoCommon/Src/VideoCommon.h b/Source/Core/VideoCommon/Src/VideoCommon.h
index 9f6dd59cd3..1eeed20b82 100644
--- a/Source/Core/VideoCommon/Src/VideoCommon.h
+++ b/Source/Core/VideoCommon/Src/VideoCommon.h
@@ -44,17 +44,14 @@ enum
EFB_HEIGHT = 528,
};
-enum
-{
- // XFB width is decided by EFB copy operation. The VI can do horizontal
- // scaling (TODO: emulate).
- MAX_XFB_WIDTH = EFB_WIDTH,
-
- // Although EFB height is 528, 574-line XFB's can be created either with
- // vertical scaling by the EFB copy operation or copying to multiple XFB's
- // that are next to each other in memory (TODO: handle that situation).
- MAX_XFB_HEIGHT = 574
-};
+// XFB width is decided by EFB copy operation. The VI can do horizontal
+// scaling (TODO: emulate).
+const u32 MAX_XFB_WIDTH = EFB_WIDTH;
+
+// Although EFB height is 528, 574-line XFB's can be created either with
+// vertical scaling by the EFB copy operation or copying to multiple XFB's
+// that are next to each other in memory (TODO: handle that situation).
+const u32 MAX_XFB_HEIGHT = 574;
// Logging
// ----------
@@ -88,9 +85,9 @@ struct TargetRectangle : public MathUtil::Rectangle<int>
};
#ifdef _WIN32
-#define PRIM_LOG(...) {DEBUG_LOG(VIDEO, __VA_ARGS__)}
+#define PRIM_LOG(...) DEBUG_LOG(VIDEO, __VA_ARGS__)
#else
-#define PRIM_LOG(...) {DEBUG_LOG(VIDEO, ##__VA_ARGS__)}
+#define PRIM_LOG(...) DEBUG_LOG(VIDEO, ##__VA_ARGS__)
#endif
diff --git a/Source/Core/VideoCommon/Src/VideoConfig.cpp b/Source/Core/VideoCommon/Src/VideoConfig.cpp
index 5bb6e4dd99..c702b577e2 100644
--- a/Source/Core/VideoCommon/Src/VideoConfig.cpp
+++ b/Source/Core/VideoCommon/Src/VideoConfig.cpp
@@ -57,9 +57,9 @@ void VideoConfig::Load(const char *ini_file)
iniFile.Get("Settings", "Crop", &bCrop, false);
iniFile.Get("Settings", "UseXFB", &bUseXFB, 0);
iniFile.Get("Settings", "UseRealXFB", &bUseRealXFB, 0);
- iniFile.Get("Settings", "UseNativeMips", &bUseNativeMips, false);
iniFile.Get("Settings", "SafeTextureCacheColorSamples", &iSafeTextureCache_ColorSamples,128);
iniFile.Get("Settings", "ShowFPS", &bShowFPS, false); // Settings
+ iniFile.Get("Settings", "LogFPSToFile", &bLogFPSToFile, false);
iniFile.Get("Settings", "ShowInputDisplay", &bShowInputDisplay, false);
iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false);
iniFile.Get("Settings", "OverlayProjStats", &bOverlayProjStats, false);
@@ -85,8 +85,6 @@ void VideoConfig::Load(const char *ini_file)
iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0);
iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0);
iniFile.Get("Settings", "WireFrame", &bWireFrame, 0);
- iniFile.Get("Settings", "DisableLighting", &bDisableLighting, 0);
- iniFile.Get("Settings", "DisableTexturing", &bDisableTexturing, 0);
iniFile.Get("Settings", "DisableFog", &bDisableFog, 0);
iniFile.Get("Settings", "EnableOpenCL", &bEnableOpenCL, false);
@@ -129,7 +127,6 @@ void VideoConfig::GameIniLoad(const char *ini_file)
iniFile.GetIfExists("Video_Settings", "Crop", &bCrop);
iniFile.GetIfExists("Video_Settings", "UseXFB", &bUseXFB);
iniFile.GetIfExists("Video_Settings", "UseRealXFB", &bUseRealXFB);
- iniFile.GetIfExists("Video_Settings", "UseNativeMips", &bUseNativeMips);
iniFile.GetIfExists("Video_Settings", "SafeTextureCacheColorSamples", &iSafeTextureCache_ColorSamples);
iniFile.GetIfExists("Video_Settings", "DLOptimize", &iCompileDLsLevel);
iniFile.GetIfExists("Video_Settings", "HiresTextures", &bHiresTextures);
@@ -141,8 +138,6 @@ void VideoConfig::GameIniLoad(const char *ini_file)
iniFile.GetIfExists("Video_Settings", "MSAA", &iMultisampleMode);
iniFile.GetIfExists("Video_Settings", "EFBScale", &iEFBScale); // integral
iniFile.GetIfExists("Video_Settings", "DstAlphaPass", &bDstAlphaPass);
- iniFile.GetIfExists("Video_Settings", "DisableLighting", &bDisableLighting);
- iniFile.GetIfExists("Video_Settings", "DisableTexturing", &bDisableTexturing);
iniFile.GetIfExists("Video_Settings", "DisableFog", &bDisableFog);
iniFile.GetIfExists("Video_Settings", "EnableOpenCL", &bEnableOpenCL);
iniFile.GetIfExists("Video_Settings", "OMPDecoder", &bOMPDecoder);
@@ -190,9 +185,9 @@ void VideoConfig::Save(const char *ini_file)
iniFile.Set("Settings", "wideScreenHack", bWidescreenHack);
iniFile.Set("Settings", "UseXFB", bUseXFB);
iniFile.Set("Settings", "UseRealXFB", bUseRealXFB);
- iniFile.Set("Settings", "UseNativeMips", bUseNativeMips);
iniFile.Set("Settings", "SafeTextureCacheColorSamples", iSafeTextureCache_ColorSamples);
iniFile.Set("Settings", "ShowFPS", bShowFPS);
+ iniFile.Set("Settings", "LogFPSToFile", bLogFPSToFile);
iniFile.Set("Settings", "ShowInputDisplay", bShowInputDisplay);
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
iniFile.Set("Settings", "OverlayProjStats", bOverlayProjStats);
@@ -217,8 +212,6 @@ void VideoConfig::Save(const char *ini_file)
iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable);
iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter);
iniFile.Set("Settings", "Wireframe", bWireFrame);
- iniFile.Set("Settings", "DisableLighting", bDisableLighting);
- iniFile.Set("Settings", "DisableTexturing", bDisableTexturing);
iniFile.Set("Settings", "DstAlphaPass", bDstAlphaPass);
iniFile.Set("Settings", "DisableFog", bDisableFog);
@@ -269,7 +262,6 @@ void VideoConfig::GameIniSave(const char* default_ini, const char* game_ini)
SET_IF_DIFFERS("Video_Settings", "Crop", bCrop);
SET_IF_DIFFERS("Video_Settings", "UseXFB", bUseXFB);
SET_IF_DIFFERS("Video_Settings", "UseRealXFB", bUseRealXFB);
- SET_IF_DIFFERS("Video_Settings", "UseNativeMips", bUseNativeMips);
SET_IF_DIFFERS("Video_Settings", "SafeTextureCacheColorSamples", iSafeTextureCache_ColorSamples);
SET_IF_DIFFERS("Video_Settings", "DLOptimize", iCompileDLsLevel);
SET_IF_DIFFERS("Video_Settings", "HiresTextures", bHiresTextures);
@@ -281,8 +273,6 @@ void VideoConfig::GameIniSave(const char* default_ini, const char* game_ini)
SET_IF_DIFFERS("Video_Settings", "MSAA", iMultisampleMode);
SET_IF_DIFFERS("Video_Settings", "EFBScale", iEFBScale); // integral
SET_IF_DIFFERS("Video_Settings", "DstAlphaPass", bDstAlphaPass);
- SET_IF_DIFFERS("Video_Settings", "DisableLighting", bDisableLighting);
- SET_IF_DIFFERS("Video_Settings", "DisableTexturing", bDisableTexturing);
SET_IF_DIFFERS("Video_Settings", "DisableFog", bDisableFog);
SET_IF_DIFFERS("Video_Settings", "EnableOpenCL", bEnableOpenCL);
SET_IF_DIFFERS("Video_Settings", "OMPDecoder", bOMPDecoder);
@@ -302,125 +292,3 @@ void VideoConfig::GameIniSave(const char* default_ini, const char* game_ini)
iniFile.Save(game_ini);
}
-
-
-// TODO: remove
-extern bool g_aspect_wide;
-
-// TODO: Figure out a better place for this function.
-void ComputeDrawRectangle(int backbuffer_width, int backbuffer_height, bool flip, TargetRectangle *rc)
-{
- float FloatGLWidth = (float)backbuffer_width;
- float FloatGLHeight = (float)backbuffer_height;
- float FloatXOffset = 0;
- float FloatYOffset = 0;
-
- // The rendering window size
- const float WinWidth = FloatGLWidth;
- const float WinHeight = FloatGLHeight;
-
- // Handle aspect ratio.
- // Default to auto.
- bool use16_9 = g_aspect_wide;
-
- // Update aspect ratio hack values
- // Won't take effect until next frame
- // Don't know if there is a better place for this code so there isn't a 1 frame delay
- if ( g_ActiveConfig.bWidescreenHack )
- {
- float source_aspect = use16_9 ? (16.0f / 9.0f) : (4.0f / 3.0f);
- float target_aspect;
-
- switch ( g_ActiveConfig.iAspectRatio )
- {
- case ASPECT_FORCE_16_9 :
- target_aspect = 16.0f / 9.0f;
- break;
- case ASPECT_FORCE_4_3 :
- target_aspect = 4.0f / 3.0f;
- break;
- case ASPECT_STRETCH :
- target_aspect = WinWidth / WinHeight;
- break;
- default :
- // ASPECT_AUTO == no hacking
- target_aspect = source_aspect;
- break;
- }
-
- float adjust = source_aspect / target_aspect;
- if ( adjust > 1 )
- {
- // Vert+
- g_Config.fAspectRatioHackW = 1;
- g_Config.fAspectRatioHackH = 1/adjust;
- }
- else
- {
- // Hor+
- g_Config.fAspectRatioHackW = adjust;
- g_Config.fAspectRatioHackH = 1;
- }
- }
- else
- {
- // Hack is disabled
- g_Config.fAspectRatioHackW = 1;
- g_Config.fAspectRatioHackH = 1;
- }
-
- // Check for force-settings and override.
- if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_16_9)
- use16_9 = true;
- else if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_4_3)
- use16_9 = false;
-
- if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH)
- {
- // The rendering window aspect ratio as a proportion of the 4:3 or 16:9 ratio
- float Ratio = (WinWidth / WinHeight) / (!use16_9 ? (4.0f / 3.0f) : (16.0f / 9.0f));
- // Check if height or width is the limiting factor. If ratio > 1 the picture is too wide and have to limit the width.
- if (Ratio > 1.0f)
- {
- // Scale down and center in the X direction.
- FloatGLWidth /= Ratio;
- FloatXOffset = (WinWidth - FloatGLWidth) / 2.0f;
- }
- // The window is too high, we have to limit the height
- else
- {
- // Scale down and center in the Y direction.
- FloatGLHeight *= Ratio;
- FloatYOffset = FloatYOffset + (WinHeight - FloatGLHeight) / 2.0f;
- }
- }
-
- // -----------------------------------------------------------------------
- // Crop the picture from 4:3 to 5:4 or from 16:9 to 16:10.
- // Output: FloatGLWidth, FloatGLHeight, FloatXOffset, FloatYOffset
- // ------------------
- if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH && g_ActiveConfig.bCrop)
- {
- float Ratio = !use16_9 ? ((4.0f / 3.0f) / (5.0f / 4.0f)) : (((16.0f / 9.0f) / (16.0f / 10.0f)));
- // The width and height we will add (calculate this before FloatGLWidth and FloatGLHeight is adjusted)
- float IncreasedWidth = (Ratio - 1.0f) * FloatGLWidth;
- float IncreasedHeight = (Ratio - 1.0f) * FloatGLHeight;
- // The new width and height
- FloatGLWidth = FloatGLWidth * Ratio;
- FloatGLHeight = FloatGLHeight * Ratio;
- // Adjust the X and Y offset
- FloatXOffset = FloatXOffset - (IncreasedWidth * 0.5f);
- FloatYOffset = FloatYOffset - (IncreasedHeight * 0.5f);
- }
-
- int XOffset = (int)(FloatXOffset + 0.5f);
- int YOffset = (int)(FloatYOffset + 0.5f);
- int iWhidth = (int)ceil(FloatGLWidth);
- int iHeight = (int)ceil(FloatGLHeight);
- iWhidth -= iWhidth % 4; // ensure divisibility by 4 to make it compatible with all the video encoders
- iHeight -= iHeight % 4;
- rc->left = XOffset;
- rc->top = flip ? (int)(YOffset + iHeight) : YOffset;
- rc->right = XOffset + iWhidth;
- rc->bottom = flip ? YOffset : (int)(YOffset + iHeight);
-}
diff --git a/Source/Core/VideoCommon/Src/VideoConfig.h b/Source/Core/VideoCommon/Src/VideoConfig.h
index 7c846676bb..fe883e0dbe 100644
--- a/Source/Core/VideoCommon/Src/VideoConfig.h
+++ b/Source/Core/VideoCommon/Src/VideoConfig.h
@@ -34,7 +34,6 @@
// Log in two categories, and save three other options in the same byte
#define CONF_LOG 1
#define CONF_PRIMLOG 2
-#define CONF_SAVETEXTURES 4
#define CONF_SAVETARGETS 8
#define CONF_SAVESHADERS 16
@@ -78,7 +77,6 @@ struct VideoConfig
bool bCrop; // Aspect ratio controls.
bool bUseXFB;
bool bUseRealXFB;
- bool bUseNativeMips;
// OpenCL/OpenMP
bool bEnableOpenCL;
@@ -99,11 +97,10 @@ struct VideoConfig
bool bTexFmtOverlayEnable;
bool bTexFmtOverlayCenter;
bool bShowEFBCopyRegions;
+ bool bLogFPSToFile;
// Render
bool bWireFrame;
- bool bDisableLighting;
- bool bDisableTexturing;
bool bDstAlphaPass;
bool bDisableFog;
@@ -139,8 +136,8 @@ struct VideoConfig
bool bEnablePerPixelDepth;
int iLog; // CONF_ bits
- int iSaveTargetId;
-
+ int iSaveTargetId; // TODO: Should be dropped
+
//currently unused:
int iCompileDLsLevel;
@@ -166,6 +163,12 @@ struct VideoConfig
bool bSupportsFormatReinterpretation;
bool bSupportsPixelLighting;
} backend_info;
+
+ // Utility
+ bool RealXFBEnabled() const { return bUseXFB && bUseRealXFB; }
+ bool VirtualXFBEnabled() const { return bUseXFB && !bUseRealXFB; }
+ bool EFBCopiesToTextureEnabled() const { return bEFBCopyEnable && bCopyEFBToTexture; }
+ bool EFBCopiesToRamEnabled() const { return bEFBCopyEnable && !bCopyEFBToTexture; }
};
extern VideoConfig g_Config;
@@ -174,6 +177,4 @@ extern VideoConfig g_ActiveConfig;
// Called every frame.
void UpdateActiveConfig();
-void ComputeDrawRectangle(int backbuffer_width, int backbuffer_height, bool flip, TargetRectangle *rc);
-
#endif // _VIDEO_CONFIG_H_
diff --git a/Source/Core/VideoCommon/Src/VideoState.cpp b/Source/Core/VideoCommon/Src/VideoState.cpp
index b1c1ed0889..ad5384cda9 100644
--- a/Source/Core/VideoCommon/Src/VideoState.cpp
+++ b/Source/Core/VideoCommon/Src/VideoState.cpp
@@ -24,36 +24,60 @@
#include "Fifo.h"
#include "CommandProcessor.h"
#include "PixelEngine.h"
+#include "PixelShaderManager.h"
+#include "VertexShaderManager.h"
+#include "VertexManagerBase.h"
static void DoState(PointerWrap &p)
{
// BP Memory
p.Do(bpmem);
- // CP Memory
+ p.DoMarker("BP Memory");
+
+ // CP Memory
p.DoArray(arraybases, 16);
p.DoArray(arraystrides, 16);
p.Do(MatrixIndexA);
p.Do(MatrixIndexB);
p.Do(g_VtxDesc.Hex);
p.DoArray(g_VtxAttr, 8);
+ p.DoMarker("CP Memory");
// XF Memory
p.Do(xfregs);
p.DoArray(xfmem, XFMEM_SIZE);
- // Texture decoder
+ p.DoMarker("XF Memory");
+
+ // Texture decoder
p.DoArray(texMem, TMEM_SIZE);
+ p.DoMarker("texMem");
// FIFO
Fifo_DoState(p);
+ p.DoMarker("Fifo");
CommandProcessor::DoState(p);
- PixelEngine::DoState(p);
+ p.DoMarker("CommandProcessor");
+
+ PixelEngine::DoState(p);
+ p.DoMarker("PixelEngine");
+
+ // the old way of replaying current bpmem as writes to push side effects to pixel shader manager doesn't really work.
+ PixelShaderManager::DoState(p);
+ p.DoMarker("PixelShaderManager");
+
+ VertexShaderManager::DoState(p);
+ p.DoMarker("VertexShaderManager");
+
+ VertexManager::DoState(p);
+ p.DoMarker("VertexManager");
+
+ // TODO: search for more data that should be saved and add it here
}
void VideoCommon_DoState(PointerWrap &p)
{
DoState(p);
- //TODO: search for more data that should be saved and add it here
}
void VideoCommon_RunLoop(bool enable)
diff --git a/Source/Core/VideoCommon/Src/XFStructs.cpp b/Source/Core/VideoCommon/Src/XFStructs.cpp
index ec3975cb07..9f395bfecf 100644
--- a/Source/Core/VideoCommon/Src/XFStructs.cpp
+++ b/Source/Core/VideoCommon/Src/XFStructs.cpp
@@ -143,7 +143,7 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData)
case XFMEM_SETNUMTEXGENS: // GXSetNumTexGens
if (xfregs.numTexGen.numTexGens != (newValue & 15))
- VertexManager::Flush();
+ VertexManager::Flush();
break;
case XFMEM_SETTEXMTXINFO:
@@ -257,13 +257,26 @@ void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
// TODO - verify that it is correct. Seems to work, though.
void LoadIndexedXF(u32 val, int refarray)
{
- int index = val >> 16;
- int address = val & 0xFFF; // check mask
- int size = ((val >> 12) & 0xF) + 1;
- //load stuff from array to address in xf mem
-
- XFMemWritten(size, address);
-
- for (int i = 0; i < size; i++)
- xfmem[address + i] = Memory::Read_U32(arraybases[refarray] + arraystrides[refarray] * index + i * 4);
+ int index = val >> 16;
+ int address = val & 0xFFF; // check mask
+ int size = ((val >> 12) & 0xF) + 1;
+ //load stuff from array to address in xf mem
+
+ u32* currData = (u32*)(xfmem + address);
+ u32* newData = (u32*)Memory::GetPointer(arraybases[refarray] + arraystrides[refarray] * index);
+ bool changed = false;
+ for (int i = 0; i < size; ++i)
+ {
+ if (currData[i] != Common::swap32(newData[i]))
+ {
+ changed = true;
+ XFMemWritten(size, address);
+ break;
+ }
+ }
+ if (changed)
+ {
+ for (int i = 0; i < size; ++i)
+ currData[i] = Common::swap32(newData[i]);
+ }
}
diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj
index f53c18cb37..bf9122e6b5 100644
--- a/Source/Core/VideoCommon/VideoCommon.vcxproj
+++ b/Source/Core/VideoCommon/VideoCommon.vcxproj
@@ -111,7 +111,8 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\Common\Src;..\Core\Src;..\..\..\Externals\SOIL;..\..\..\Externals\CLRun\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ClCompile>
+ <OpenMPSupport>false</OpenMPSupport>
+ </ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
@@ -129,7 +130,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\Common\Src;..\Core\Src;..\..\..\Externals\SOIL;..\..\..\Externals\CLRun\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <OpenMPSupport>true</OpenMPSupport>
+ <OpenMPSupport>false</OpenMPSupport>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -141,7 +142,8 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\Common\Src;..\Core\Src;..\..\..\Externals\SOIL;..\..\..\Externals\CLRun\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ClCompile>
+ <OpenMPSupport>false</OpenMPSupport>
+ </ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -183,6 +185,7 @@
<ClCompile Include="Src\DLCache.cpp" />
<ClCompile Include="Src\EmuWindow.cpp" />
<ClCompile Include="Src\Fifo.cpp" />
+ <ClCompile Include="Src\FPSCounter.cpp" />
<ClCompile Include="Src\FramebufferManagerBase.cpp" />
<ClCompile Include="Src\HiresTextures.cpp" />
<ClCompile Include="Src\ImageWrite.cpp" />
@@ -228,6 +231,7 @@
<ClInclude Include="Src\DLCache.h" />
<ClInclude Include="Src\EmuWindow.h" />
<ClInclude Include="Src\Fifo.h" />
+ <ClInclude Include="Src\FPSCounter.h" />
<ClInclude Include="Src\FramebufferManagerBase.h" />
<ClInclude Include="Src\HiresTextures.h" />
<ClInclude Include="Src\ImageWrite.h" />
diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
index c933fbc939..e7019f17ed 100644
--- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
+++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
@@ -119,6 +119,9 @@
<ClCompile Include="Src\LightingShaderGen.cpp">
<Filter>Shader Generators</Filter>
</ClCompile>
+ <ClCompile Include="Src\FPSCounter.cpp">
+ <Filter>Util</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Src\CommandProcessor.h" />
@@ -246,6 +249,9 @@
<ClInclude Include="Src\LightingShaderGen.h">
<Filter>Shader Generators</Filter>
</ClInclude>
+ <ClInclude Include="Src\FPSCounter.h">
+ <Filter>Util</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />