mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
VideoSW: Use more VideoCommon
Now we require lots of empty functions, but this removes by far more duplicated code.
This commit is contained in:
@@ -1,178 +0,0 @@
|
||||
// Copyright 2009 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
|
||||
#include "VideoBackends/Software/BPMemLoader.h"
|
||||
#include "VideoBackends/Software/EfbCopy.h"
|
||||
#include "VideoBackends/Software/EfbInterface.h"
|
||||
#include "VideoBackends/Software/Rasterizer.h"
|
||||
#include "VideoBackends/Software/Tev.h"
|
||||
|
||||
#include "VideoCommon/BoundingBox.h"
|
||||
#include "VideoCommon/PixelEngine.h"
|
||||
#include "VideoCommon/TextureDecoder.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
|
||||
void InitBPMemory()
|
||||
{
|
||||
memset(&bpmem, 0, sizeof(bpmem));
|
||||
bpmem.bpMask = 0xFFFFFF;
|
||||
}
|
||||
|
||||
void SWLoadBPReg(u32 value)
|
||||
{
|
||||
//handle the mask register
|
||||
int address = value >> 24;
|
||||
int oldval = ((u32*)&bpmem)[address];
|
||||
int newval = (oldval & ~bpmem.bpMask) | (value & bpmem.bpMask);
|
||||
|
||||
((u32*)&bpmem)[address] = newval;
|
||||
|
||||
//reset the mask register
|
||||
if (address != 0xFE)
|
||||
bpmem.bpMask = 0xFFFFFF;
|
||||
|
||||
SWBPWritten(address, newval);
|
||||
}
|
||||
|
||||
void SWBPWritten(int address, int newvalue)
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
case BPMEM_SCISSORTL:
|
||||
case BPMEM_SCISSORBR:
|
||||
case BPMEM_SCISSOROFFSET:
|
||||
Rasterizer::SetScissor();
|
||||
break;
|
||||
case BPMEM_SETDRAWDONE: // This is called when the game is done drawing (eg: like in DX: Begin(); Draw(); End();)
|
||||
switch (bpmem.drawdone & 0xFF)
|
||||
{
|
||||
case 0x02:
|
||||
PixelEngine::SetFinish(); // may generate interrupt
|
||||
DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN_LOG(VIDEO, "GXSetDrawDone ??? (value 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID
|
||||
DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bpmem.petoken & 0xFFFF));
|
||||
PixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), false);
|
||||
break;
|
||||
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
|
||||
DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bpmem.petokenint & 0xFFFF));
|
||||
PixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), true);
|
||||
break;
|
||||
case BPMEM_TRIGGER_EFB_COPY:
|
||||
EfbCopy::CopyEfb();
|
||||
break;
|
||||
case BPMEM_CLEARBBOX1:
|
||||
BoundingBox::coords[BoundingBox::LEFT] = newvalue >> 10;
|
||||
BoundingBox::coords[BoundingBox::RIGHT] = newvalue & 0x3ff;
|
||||
break;
|
||||
case BPMEM_CLEARBBOX2:
|
||||
BoundingBox::coords[BoundingBox::TOP] = newvalue >> 10;
|
||||
BoundingBox::coords[BoundingBox::BOTTOM] = newvalue & 0x3ff;
|
||||
break;
|
||||
case BPMEM_CLEAR_PIXEL_PERF:
|
||||
// TODO: I didn't test if the value written to this register affects the amount of cleared registers
|
||||
memset(EfbInterface::perf_values, 0, sizeof(EfbInterface::perf_values));
|
||||
break;
|
||||
case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here.
|
||||
break;
|
||||
case BPMEM_LOADTLUT1: // Load a Texture Look Up Table
|
||||
{
|
||||
u32 tlutTMemAddr = (newvalue & 0x3FF) << 9;
|
||||
u32 tlutXferCount = (newvalue & 0x1FFC00) >> 5;
|
||||
u32 addr = bpmem.tmem_config.tlut_src << 5;
|
||||
|
||||
// The GameCube ignores the upper bits of this address. Some games (WW, MKDD) set them.
|
||||
if (!SConfig::GetInstance().bWii)
|
||||
addr = addr & 0x01FFFFFF;
|
||||
|
||||
Memory::CopyFromEmu(texMem + tlutTMemAddr, addr, tlutXferCount);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BPMEM_PRELOAD_MODE:
|
||||
if (newvalue != 0)
|
||||
{
|
||||
// TODO: Not quite sure if this is completely correct (likely not)
|
||||
// NOTE: libogc's implementation of GX_PreloadEntireTexture seems flawed, so it's not necessarily a good reference for RE'ing this feature.
|
||||
|
||||
BPS_TmemConfig& tmem_cfg = bpmem.tmem_config;
|
||||
u32 src_addr = tmem_cfg.preload_addr << 5; // TODO: Should we add mask here on GC?
|
||||
u32 size = tmem_cfg.preload_tile_info.count * TMEM_LINE_SIZE;
|
||||
u32 tmem_addr_even = tmem_cfg.preload_tmem_even * TMEM_LINE_SIZE;
|
||||
|
||||
if (tmem_cfg.preload_tile_info.type != 3)
|
||||
{
|
||||
if (tmem_addr_even + size > TMEM_SIZE)
|
||||
size = TMEM_SIZE - tmem_addr_even;
|
||||
|
||||
Memory::CopyFromEmu(texMem + tmem_addr_even, src_addr, size);
|
||||
}
|
||||
else // RGBA8 tiles (and CI14, but that might just be stupid libogc!)
|
||||
{
|
||||
u8* src_ptr = Memory::GetPointer(src_addr);
|
||||
|
||||
// AR and GB tiles are stored in separate TMEM banks => can't use a single memcpy for everything
|
||||
u32 tmem_addr_odd = tmem_cfg.preload_tmem_odd * TMEM_LINE_SIZE;
|
||||
|
||||
for (unsigned int i = 0; i < tmem_cfg.preload_tile_info.count; ++i)
|
||||
{
|
||||
if (tmem_addr_even + TMEM_LINE_SIZE > TMEM_SIZE ||
|
||||
tmem_addr_odd + TMEM_LINE_SIZE > TMEM_SIZE)
|
||||
break;
|
||||
|
||||
memcpy(texMem + tmem_addr_even, src_ptr, TMEM_LINE_SIZE);
|
||||
memcpy(texMem + tmem_addr_odd, src_ptr + TMEM_LINE_SIZE, TMEM_LINE_SIZE);
|
||||
tmem_addr_even += TMEM_LINE_SIZE;
|
||||
tmem_addr_odd += TMEM_LINE_SIZE;
|
||||
src_ptr += TMEM_LINE_SIZE * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_TEV_COLOR_RA:
|
||||
case BPMEM_TEV_COLOR_RA + 2:
|
||||
case BPMEM_TEV_COLOR_RA + 4:
|
||||
case BPMEM_TEV_COLOR_RA + 6:
|
||||
{
|
||||
int regNum = (address >> 1 ) & 0x3;
|
||||
TevReg& reg = bpmem.tevregs[regNum];
|
||||
bool is_konst = reg.type_ra != 0;
|
||||
|
||||
Rasterizer::SetTevReg(regNum, Tev::ALP_C, is_konst, static_cast<s16>(reg.alpha));
|
||||
Rasterizer::SetTevReg(regNum, Tev::RED_C, is_konst, static_cast<s16>(reg.red));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BPMEM_TEV_COLOR_BG:
|
||||
case BPMEM_TEV_COLOR_BG + 2:
|
||||
case BPMEM_TEV_COLOR_BG + 4:
|
||||
case BPMEM_TEV_COLOR_BG + 6:
|
||||
{
|
||||
int regNum = (address >> 1 ) & 0x3;
|
||||
TevReg& reg = bpmem.tevregs[regNum];
|
||||
bool is_konst = reg.type_bg != 0;
|
||||
|
||||
Rasterizer::SetTevReg(regNum, Tev::GRN_C, is_konst, static_cast<s16>(reg.green));
|
||||
Rasterizer::SetTevReg(regNum, Tev::BLU_C, is_konst, static_cast<s16>(reg.blue));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoCommon/BPMemory.h"
|
||||
|
||||
void InitBPMemory();
|
||||
void SWBPWritten(int address, int newvalue);
|
||||
void SWLoadBPReg(u32 value);
|
||||
@@ -1,24 +1,17 @@
|
||||
set(SRCS BPMemLoader.cpp
|
||||
CPMemLoader.cpp
|
||||
Clipper.cpp
|
||||
set(SRCS Clipper.cpp
|
||||
DebugUtil.cpp
|
||||
EfbCopy.cpp
|
||||
EfbInterface.cpp
|
||||
OpcodeDecoder.cpp
|
||||
Rasterizer.cpp
|
||||
SWCommandProcessor.cpp
|
||||
SWOGLWindow.cpp
|
||||
SWRenderer.cpp
|
||||
SWStatistics.cpp
|
||||
SWVertexLoader.cpp
|
||||
SWVideoConfig.cpp
|
||||
SWmain.cpp
|
||||
SetupUnit.cpp
|
||||
Tev.cpp
|
||||
TextureEncoder.cpp
|
||||
TextureSampler.cpp
|
||||
TransformUnit.cpp
|
||||
XFMemLoader.cpp)
|
||||
TransformUnit.cpp)
|
||||
|
||||
set(LIBS videocommon
|
||||
SOIL
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
// Copyright 2009 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "VideoBackends/Software/CPMemLoader.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
|
||||
void SWLoadCPReg(u32 sub_cmd, u32 value)
|
||||
{
|
||||
switch (sub_cmd & 0xF0)
|
||||
{
|
||||
case 0x30:
|
||||
g_main_cp_state.matrix_index_a.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
g_main_cp_state.matrix_index_b.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
g_main_cp_state.vtx_desc.Hex &= ~0x1FFFF; // keep the Upper bits
|
||||
g_main_cp_state.vtx_desc.Hex |= value;
|
||||
g_main_cp_state.bases_dirty = true;
|
||||
break;
|
||||
|
||||
case 0x60:
|
||||
g_main_cp_state.vtx_desc.Hex &= 0x1FFFF; // keep the lower 17Bits
|
||||
g_main_cp_state.vtx_desc.Hex |= (u64)value << 17;
|
||||
g_main_cp_state.bases_dirty = true;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
_assert_((sub_cmd & 0x0F) < 8);
|
||||
g_main_cp_state.vtx_attr[sub_cmd & 7].g0.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
_assert_((sub_cmd & 0x0F) < 8);
|
||||
g_main_cp_state.vtx_attr[sub_cmd & 7].g1.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x90:
|
||||
_assert_((sub_cmd & 0x0F) < 8);
|
||||
g_main_cp_state.vtx_attr[sub_cmd & 7].g2.Hex = value;
|
||||
break;
|
||||
|
||||
// Pointers to vertex arrays in GC RAM
|
||||
case 0xA0:
|
||||
g_main_cp_state.array_bases[sub_cmd & 0xF] = value;
|
||||
g_main_cp_state.bases_dirty = true;
|
||||
break;
|
||||
|
||||
case 0xB0:
|
||||
g_main_cp_state.array_strides[sub_cmd & 0xF] = value & 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoCommon/CPMemory.h"
|
||||
|
||||
void SWLoadCPReg(u32 sub_cmd, u32 value);
|
||||
@@ -36,12 +36,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "VideoBackends/Software/BPMemLoader.h"
|
||||
#include "VideoBackends/Software/Clipper.h"
|
||||
#include "VideoBackends/Software/NativeVertexFormat.h"
|
||||
#include "VideoBackends/Software/Rasterizer.h"
|
||||
#include "VideoBackends/Software/SWStatistics.h"
|
||||
#include "VideoBackends/Software/XFMemLoader.h"
|
||||
|
||||
#include "VideoCommon/BPMemory.h"
|
||||
#include "VideoCommon/Statistics.h"
|
||||
#include "VideoCommon/XFMemory.h"
|
||||
|
||||
namespace Clipper
|
||||
{
|
||||
@@ -56,13 +57,6 @@ namespace Clipper
|
||||
static OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES];
|
||||
static OutputVertexData *Vertices[NUM_INDICES];
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.DoArray(m_ViewOffset);
|
||||
for (auto& ClippedVertice : ClippedVertices)
|
||||
ClippedVertice.DoState(p);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
|
||||
@@ -220,7 +214,7 @@ namespace Clipper
|
||||
POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1);
|
||||
POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
|
||||
|
||||
INCSTAT(swstats.thisFrame.numTrianglesClipped);
|
||||
INCSTAT(stats.thisFrame.numTrianglesClipped);
|
||||
|
||||
// transform the poly in inlist into triangles
|
||||
indices[0] = inlist[0];
|
||||
@@ -287,7 +281,7 @@ namespace Clipper
|
||||
|
||||
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesIn)
|
||||
INCSTAT(stats.thisFrame.numTrianglesIn)
|
||||
|
||||
bool backface;
|
||||
|
||||
@@ -411,7 +405,7 @@ namespace Clipper
|
||||
|
||||
if (mask)
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesRejected)
|
||||
INCSTAT(stats.thisFrame.numTrianglesRejected)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -431,13 +425,13 @@ namespace Clipper
|
||||
|
||||
if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesCulled)
|
||||
INCSTAT(stats.thisFrame.numTrianglesCulled)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((bpmem.genMode.cullmode & 2) && backface) // cull backfacing
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesCulled)
|
||||
INCSTAT(stats.thisFrame.numTrianglesCulled)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
struct OutputVertexData;
|
||||
class PointerWrap;
|
||||
|
||||
namespace Clipper
|
||||
{
|
||||
@@ -20,6 +19,4 @@ namespace Clipper
|
||||
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface);
|
||||
|
||||
void PerspectiveDivide(OutputVertexData *vertex);
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
}
|
||||
|
||||
@@ -8,18 +8,16 @@
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
|
||||
#include "VideoBackends/Software/BPMemLoader.h"
|
||||
#include "VideoBackends/Software/DebugUtil.h"
|
||||
#include "VideoBackends/Software/EfbInterface.h"
|
||||
#include "VideoBackends/Software/SWCommandProcessor.h"
|
||||
#include "VideoBackends/Software/SWRenderer.h"
|
||||
#include "VideoBackends/Software/SWStatistics.h"
|
||||
#include "VideoBackends/Software/SWVideoConfig.h"
|
||||
#include "VideoBackends/Software/TextureSampler.h"
|
||||
|
||||
#include "VideoCommon/BPMemory.h"
|
||||
#include "VideoCommon/Fifo.h"
|
||||
#include "VideoCommon/ImageWrite.h"
|
||||
|
||||
#include "VideoCommon/Statistics.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
namespace DebugUtil
|
||||
{
|
||||
@@ -109,7 +107,7 @@ void DumpActiveTextures()
|
||||
{
|
||||
SaveTexture(StringFromFormat("%star%i_ind%i_map%i_mip%i.png",
|
||||
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
||||
swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip), texmap, mip);
|
||||
stats.thisFrame.numDrawnObjects, stageNum, texmap, mip), texmap, mip);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +124,7 @@ void DumpActiveTextures()
|
||||
{
|
||||
SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.png",
|
||||
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
||||
swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip), texmap, mip);
|
||||
stats.thisFrame.numDrawnObjects, stageNum, texmap, mip), texmap, mip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,13 +152,6 @@ static void DumpEfb(const std::string& filename)
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DumpColorTexture(const std::string& filename, u32 width, u32 height)
|
||||
{
|
||||
TextureToPng(SWRenderer::GetCurrentColorTexture(), width * 4, filename, width, height, true);
|
||||
}
|
||||
|
||||
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name)
|
||||
{
|
||||
int buffer = bufferBase + subBuffer;
|
||||
@@ -202,7 +193,7 @@ void OnObjectBegin()
|
||||
{
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_SWVideoConfig.bDumpTextures && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
|
||||
if (g_ActiveConfig.bDumpTextures && stats.thisFrame.numDrawnObjects >= g_ActiveConfig.drawStart && stats.thisFrame.numDrawnObjects < g_ActiveConfig.drawEnd)
|
||||
DumpActiveTextures();
|
||||
}
|
||||
}
|
||||
@@ -211,10 +202,10 @@ void OnObjectEnd()
|
||||
{
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_SWVideoConfig.bDumpObjects && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
|
||||
if (g_ActiveConfig.bDumpObjects && stats.thisFrame.numDrawnObjects >= g_ActiveConfig.drawStart && stats.thisFrame.numDrawnObjects < g_ActiveConfig.drawEnd)
|
||||
DumpEfb(StringFromFormat("%sobject%i.png",
|
||||
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
|
||||
swstats.thisFrame.numDrawnObjects));
|
||||
stats.thisFrame.numDrawnObjects));
|
||||
|
||||
for (int i = 0; i < NUM_OBJECT_BUFFERS; i++)
|
||||
{
|
||||
@@ -223,7 +214,7 @@ void OnObjectEnd()
|
||||
DrawnToBuffer[i] = false;
|
||||
std::string filename = StringFromFormat("%sobject%i_%s(%i).png",
|
||||
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
|
||||
swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]);
|
||||
stats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]);
|
||||
|
||||
TextureToPng((u8*)ObjectBuffer[i], EFB_WIDTH * 4, filename, EFB_WIDTH, EFB_HEIGHT, true);
|
||||
memset(ObjectBuffer[i], 0, EFB_WIDTH * EFB_HEIGHT * sizeof(u32));
|
||||
@@ -231,20 +222,7 @@ void OnObjectEnd()
|
||||
}
|
||||
}
|
||||
|
||||
swstats.thisFrame.numDrawnObjects++;
|
||||
}
|
||||
}
|
||||
|
||||
// If frame dumping is enabled, dump whatever is drawn to the screen.
|
||||
void OnFrameEnd(u32 width, u32 height)
|
||||
{
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (SConfig::GetInstance().m_DumpFrames)
|
||||
{
|
||||
DumpColorTexture(StringFromFormat("%sframe%i_color.png",
|
||||
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount), width, height);
|
||||
}
|
||||
stats.thisFrame.numDrawnObjects++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,6 @@ namespace DebugUtil
|
||||
void OnObjectBegin();
|
||||
void OnObjectEnd();
|
||||
|
||||
void OnFrameEnd(u32 width, u32 height);
|
||||
|
||||
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name);
|
||||
|
||||
void DrawTempBuffer(u8 *color, int buffer);
|
||||
|
||||
@@ -5,15 +5,13 @@
|
||||
#include "Common/GL/GLInterfaceBase.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "VideoBackends/Software/BPMemLoader.h"
|
||||
#include "VideoBackends/Software/DebugUtil.h"
|
||||
#include "VideoBackends/Software/EfbCopy.h"
|
||||
#include "VideoBackends/Software/EfbInterface.h"
|
||||
#include "VideoBackends/Software/SWCommandProcessor.h"
|
||||
#include "VideoBackends/Software/SWRenderer.h"
|
||||
#include "VideoBackends/Software/SWStatistics.h"
|
||||
#include "VideoBackends/Software/SWVideoConfig.h"
|
||||
#include "VideoBackends/Software/TextureEncoder.h"
|
||||
|
||||
#include "VideoCommon/BPMemory.h"
|
||||
#include "VideoCommon/Fifo.h"
|
||||
|
||||
static const float s_gammaLUT[] =
|
||||
@@ -33,31 +31,9 @@ namespace EfbCopy
|
||||
INFO_LOG(VIDEO, "xfbaddr: %x, fbwidth: %i, fbheight: %i, source: (%i, %i, %i, %i), Gamma %f",
|
||||
xfbAddr, fbWidth, fbHeight, sourceRc.top, sourceRc.left, sourceRc.bottom, sourceRc.right, Gamma);
|
||||
|
||||
if (!g_SWVideoConfig.bBypassXFB)
|
||||
{
|
||||
EfbInterface::yuv422_packed* xfb_in_ram = (EfbInterface::yuv422_packed *) Memory::GetPointer(xfbAddr);
|
||||
EfbInterface::yuv422_packed* xfb_in_ram = (EfbInterface::yuv422_packed*) Memory::GetPointer(xfbAddr);
|
||||
|
||||
EfbInterface::CopyToXFB(xfb_in_ram, fbWidth, fbHeight, sourceRc, Gamma);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ask SWRenderer for the next color texture
|
||||
u8 *colorTexture = SWRenderer::GetNextColorTexture();
|
||||
|
||||
EfbInterface::BypassXFB(colorTexture, fbWidth, fbHeight, sourceRc, Gamma);
|
||||
|
||||
// Tell SWRenderer we are now finished with it.
|
||||
SWRenderer::SwapColorTexture();
|
||||
|
||||
// FifoPlayer is broken and never calls BeginFrame/EndFrame.
|
||||
// Hence, we manually force a swap now. This emulates the behavior
|
||||
// of hardware backends with XFB emulation disabled.
|
||||
// TODO: Fix FifoPlayer by making proper use of VideoInterface!
|
||||
// This requires careful synchronization since GPU commands
|
||||
// are processed on a different thread than VI commands.
|
||||
SWRenderer::Swap(fbWidth, fbHeight);
|
||||
DebugUtil::OnFrameEnd(fbWidth, fbHeight);
|
||||
}
|
||||
EfbInterface::CopyToXFB(xfb_in_ram, fbWidth, fbHeight, sourceRc, Gamma);
|
||||
}
|
||||
|
||||
static void CopyToRam()
|
||||
@@ -67,7 +43,7 @@ namespace EfbCopy
|
||||
TextureEncoder::Encode(dest_ptr);
|
||||
}
|
||||
|
||||
static void ClearEfb()
|
||||
void ClearEfb()
|
||||
{
|
||||
u32 clearColor = (bpmem.clearcolorAR & 0xff) << 24 | bpmem.clearcolorGB << 8 | (bpmem.clearcolorAR & 0xff00) >> 8;
|
||||
|
||||
@@ -128,11 +104,6 @@ namespace EfbCopy
|
||||
{
|
||||
CopyToRam(); // FIXME: should use the rectangle we have already created above
|
||||
}
|
||||
|
||||
if (bpmem.triggerEFBCopy.clear)
|
||||
{
|
||||
ClearEfb();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
namespace EfbCopy
|
||||
{
|
||||
// Copy the EFB to RAM as a texture format or XFB
|
||||
// Clear the EFB if needed
|
||||
void CopyEfb();
|
||||
|
||||
void ClearEfb();
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
|
||||
#include "VideoBackends/Software/BPMemLoader.h"
|
||||
#include "VideoBackends/Software/EfbInterface.h"
|
||||
|
||||
#include "VideoCommon/BPMemory.h"
|
||||
#include "VideoCommon/LookUpTables.h"
|
||||
#include "VideoCommon/PixelEngine.h"
|
||||
|
||||
@@ -31,11 +31,6 @@ namespace EfbInterface
|
||||
return (x + y * EFB_WIDTH) * 3 + DEPTH_BUFFER_START;
|
||||
}
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.DoArray(efb);
|
||||
}
|
||||
|
||||
static void SetPixelAlphaOnly(u32 offset, u8 a)
|
||||
{
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
|
||||
@@ -58,8 +58,6 @@ namespace EfbInterface
|
||||
void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma);
|
||||
void BypassXFB(u8* texture, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma);
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
extern u32 perf_values[PQ_NUM_MEMBERS];
|
||||
inline void IncPerfCounterQuadCount(PerfQueryType type)
|
||||
{
|
||||
|
||||
@@ -77,16 +77,4 @@ struct OutputVertexData
|
||||
#undef LINTERP
|
||||
#undef LINTERP_INT
|
||||
}
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
mvPosition.DoState(p);
|
||||
p.Do(projectedPosition);
|
||||
screenPosition.DoState(p);
|
||||
for (auto& vec : normal)
|
||||
vec.DoState(p);
|
||||
p.DoArray(color, sizeof color);
|
||||
for (auto& vec : texCoords)
|
||||
vec.DoState(p);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -1,304 +0,0 @@
|
||||
// Copyright 2009 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "VideoBackends/Software/BPMemLoader.h"
|
||||
#include "VideoBackends/Software/CPMemLoader.h"
|
||||
#include "VideoBackends/Software/DebugUtil.h"
|
||||
#include "VideoBackends/Software/OpcodeDecoder.h"
|
||||
#include "VideoBackends/Software/SWCommandProcessor.h"
|
||||
#include "VideoBackends/Software/SWStatistics.h"
|
||||
#include "VideoBackends/Software/SWVertexLoader.h"
|
||||
#include "VideoBackends/Software/SWVideoConfig.h"
|
||||
#include "VideoBackends/Software/XFMemLoader.h"
|
||||
#include "VideoCommon/Fifo.h"
|
||||
#include "VideoCommon/VertexLoaderUtils.h"
|
||||
|
||||
typedef void (*DecodingFunction)(u32);
|
||||
|
||||
namespace OpcodeDecoder
|
||||
{
|
||||
static DecodingFunction currentFunction = nullptr;
|
||||
static u32 minCommandSize;
|
||||
static u16 streamSize;
|
||||
static u16 streamAddress;
|
||||
static bool readOpcode;
|
||||
static SWVertexLoader vertexLoader;
|
||||
static bool inObjectStream;
|
||||
static u8 lastPrimCmd;
|
||||
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(minCommandSize);
|
||||
// Not sure what is wrong with this. Something(s) in here is causing Dolphin to crash/hang when loading states saved from another run of Dolphin. Doesn't seem too important anyway...
|
||||
//vertexLoader.DoState(p);
|
||||
p.Do(readOpcode);
|
||||
p.Do(inObjectStream);
|
||||
p.Do(lastPrimCmd);
|
||||
p.Do(streamSize);
|
||||
p.Do(streamAddress);
|
||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||
ResetDecoding();
|
||||
}
|
||||
|
||||
static void DecodePrimitiveStream(u32 iBufferSize)
|
||||
{
|
||||
u32 vertexSize = vertexLoader.GetVertexSize();
|
||||
|
||||
bool skipPrimitives = g_bSkipCurrentFrame ||
|
||||
swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawStart ||
|
||||
swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawEnd;
|
||||
|
||||
if (skipPrimitives)
|
||||
{
|
||||
while (streamSize > 0 && iBufferSize >= vertexSize)
|
||||
{
|
||||
g_video_buffer_read_ptr += vertexSize;
|
||||
iBufferSize -= vertexSize;
|
||||
streamSize--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (streamSize > 0 && iBufferSize >= vertexSize)
|
||||
{
|
||||
vertexLoader.LoadVertex();
|
||||
iBufferSize -= vertexSize;
|
||||
streamSize--;
|
||||
}
|
||||
}
|
||||
|
||||
if (streamSize == 0)
|
||||
{
|
||||
// return to normal command processing
|
||||
ResetDecoding();
|
||||
}
|
||||
}
|
||||
|
||||
static void ReadXFData(u32 iBufferSize)
|
||||
{
|
||||
_assert_msg_(VIDEO, iBufferSize >= (u32)(streamSize * 4), "Underflow during standard opcode decoding");
|
||||
|
||||
u32 pData[16];
|
||||
for (int i = 0; i < streamSize; i++)
|
||||
pData[i] = DataRead<u32>();
|
||||
SWLoadXFReg(streamSize, streamAddress, pData);
|
||||
|
||||
// return to normal command processing
|
||||
ResetDecoding();
|
||||
}
|
||||
|
||||
static void ExecuteDisplayList(u32 addr, u32 count)
|
||||
{
|
||||
u8 *videoDataSave = g_video_buffer_read_ptr;
|
||||
|
||||
u8 *dlStart = Memory::GetPointer(addr);
|
||||
|
||||
g_video_buffer_read_ptr = dlStart;
|
||||
|
||||
while (OpcodeDecoder::CommandRunnable(count))
|
||||
{
|
||||
OpcodeDecoder::Run(count);
|
||||
|
||||
// if data was read by the opcode decoder then the video data pointer changed
|
||||
u32 readCount = (u32)(g_video_buffer_read_ptr - dlStart);
|
||||
dlStart = g_video_buffer_read_ptr;
|
||||
|
||||
_assert_msg_(VIDEO, count >= readCount, "Display list underrun");
|
||||
|
||||
count -= readCount;
|
||||
}
|
||||
|
||||
g_video_buffer_read_ptr = videoDataSave;
|
||||
}
|
||||
|
||||
static void DecodeStandard(u32 bufferSize)
|
||||
{
|
||||
_assert_msg_(VIDEO, CommandRunnable(bufferSize), "Underflow during standard opcode decoding");
|
||||
|
||||
int Cmd = DataRead<u8>();
|
||||
|
||||
if (Cmd == GX_NOP)
|
||||
return;
|
||||
// Causes a SIGBUS error on Android
|
||||
// XXX: Investigate
|
||||
#ifndef ANDROID
|
||||
// check if switching in or out of an object
|
||||
// only used for debugging
|
||||
if (inObjectStream && (Cmd & 0x87) != lastPrimCmd)
|
||||
{
|
||||
inObjectStream = false;
|
||||
DebugUtil::OnObjectEnd();
|
||||
}
|
||||
if (Cmd & 0x80 && !inObjectStream)
|
||||
{
|
||||
inObjectStream = true;
|
||||
lastPrimCmd = Cmd & 0x87;
|
||||
DebugUtil::OnObjectBegin();
|
||||
}
|
||||
#endif
|
||||
switch (Cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
u32 SubCmd = DataRead<u8>();
|
||||
u32 Value = DataRead<u32>();
|
||||
SWLoadCPReg(SubCmd, Value);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = DataRead<u32>();
|
||||
streamSize = ((Cmd2 >> 16) & 15) + 1;
|
||||
streamAddress = Cmd2 & 0xFFFF;
|
||||
currentFunction = ReadXFData;
|
||||
minCommandSize = streamSize * 4;
|
||||
readOpcode = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
SWLoadIndexedXF(DataRead<u32>(), 0xC);
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
SWLoadIndexedXF(DataRead<u32>(), 0xD);
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
SWLoadIndexedXF(DataRead<u32>(), 0xE);
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
SWLoadIndexedXF(DataRead<u32>(), 0xF);
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
{
|
||||
u32 dwAddr = DataRead<u32>();
|
||||
u32 dwCount = DataRead<u32>();
|
||||
ExecuteDisplayList(dwAddr, dwCount);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
// zelda 4 swords calls it and checks the metrics registers after that
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
u32 cmd = DataRead<u32>();
|
||||
SWLoadBPReg(cmd);
|
||||
}
|
||||
break;
|
||||
|
||||
// draw primitives
|
||||
default:
|
||||
if ((Cmd & 0xC0) == 0x80)
|
||||
{
|
||||
u8 vatIndex = Cmd & GX_VAT_MASK;
|
||||
u8 primitiveType = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
vertexLoader.SetFormat(vatIndex, primitiveType);
|
||||
|
||||
// switch to primitive processing
|
||||
streamSize = DataRead<u16>();
|
||||
currentFunction = DecodePrimitiveStream;
|
||||
minCommandSize = vertexLoader.GetVertexSize();
|
||||
readOpcode = false;
|
||||
|
||||
INCSTAT(swstats.thisFrame.numPrimatives);
|
||||
DEBUG_LOG(VIDEO, "Draw begin");
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("GFX: Unknown Opcode (0x%x).\n", Cmd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Init()
|
||||
{
|
||||
inObjectStream = false;
|
||||
lastPrimCmd = 0;
|
||||
ResetDecoding();
|
||||
}
|
||||
|
||||
void ResetDecoding()
|
||||
{
|
||||
currentFunction = DecodeStandard;
|
||||
minCommandSize = 1;
|
||||
readOpcode = true;
|
||||
}
|
||||
|
||||
bool CommandRunnable(u32 iBufferSize)
|
||||
{
|
||||
if (iBufferSize < minCommandSize)
|
||||
return false;
|
||||
|
||||
if (readOpcode)
|
||||
{
|
||||
u8 Cmd = DataPeek<u8>(0);
|
||||
u32 minSize = 1;
|
||||
|
||||
switch (Cmd)
|
||||
{
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
minSize = 6;
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
minSize = 5;
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
minSize = 5;
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
minSize = 9;
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
minSize = 5;
|
||||
break;
|
||||
|
||||
// draw primitives
|
||||
default:
|
||||
if ((Cmd & 0xC0) == 0x80)
|
||||
minSize = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return (iBufferSize >= minSize);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Run(u32 iBufferSize)
|
||||
{
|
||||
currentFunction(iBufferSize);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright 2009 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
class PointerWrap;
|
||||
|
||||
namespace OpcodeDecoder
|
||||
{
|
||||
|
||||
#define GX_NOP 0x00
|
||||
|
||||
#define GX_LOAD_BP_REG 0x61
|
||||
#define GX_LOAD_CP_REG 0x08
|
||||
#define GX_LOAD_XF_REG 0x10
|
||||
#define GX_LOAD_INDX_A 0x20
|
||||
#define GX_LOAD_INDX_B 0x28
|
||||
#define GX_LOAD_INDX_C 0x30
|
||||
#define GX_LOAD_INDX_D 0x38
|
||||
|
||||
#define GX_CMD_CALL_DL 0x40
|
||||
#define GX_CMD_INVL_VC 0x48
|
||||
|
||||
#define GX_PRIMITIVE_MASK 0x38
|
||||
#define GX_PRIMITIVE_SHIFT 3
|
||||
#define GX_VAT_MASK 0x07
|
||||
|
||||
// These values are the values extracted using GX_PRIMITIVE_MASK
|
||||
// and GX_PRIMITIVE_SHIFT.
|
||||
// GX_DRAW_QUADS_2 behaves the same way as GX_DRAW_QUADS.
|
||||
#define GX_DRAW_QUADS 0x0 //0x80
|
||||
#define GX_DRAW_QUADS_2 0x1 //0x88
|
||||
#define GX_DRAW_TRIANGLES 0x2 //0x90
|
||||
#define GX_DRAW_TRIANGLE_STRIP 0x3 //0x98
|
||||
#define GX_DRAW_TRIANGLE_FAN 0x4 //0xA0
|
||||
#define GX_DRAW_LINES 0x5 //0xA8
|
||||
#define GX_DRAW_LINE_STRIP 0x6 //0xB0
|
||||
#define GX_DRAW_POINTS 0x7 //0xB8
|
||||
|
||||
void Init();
|
||||
|
||||
void ResetDecoding();
|
||||
|
||||
bool CommandRunnable(u32 iBufferSize);
|
||||
|
||||
void Run(u32 iBufferSize);
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
}
|
||||
@@ -6,15 +6,14 @@
|
||||
#include <cstring>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoBackends/Software/BPMemLoader.h"
|
||||
#include "VideoBackends/Software/EfbInterface.h"
|
||||
#include "VideoBackends/Software/NativeVertexFormat.h"
|
||||
#include "VideoBackends/Software/Rasterizer.h"
|
||||
#include "VideoBackends/Software/SWStatistics.h"
|
||||
#include "VideoBackends/Software/SWVideoConfig.h"
|
||||
#include "VideoBackends/Software/Tev.h"
|
||||
#include "VideoBackends/Software/XFMemLoader.h"
|
||||
#include "VideoCommon/BoundingBox.h"
|
||||
#include "VideoCommon/Statistics.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
#include "VideoCommon/XFMemory.h"
|
||||
|
||||
namespace Rasterizer
|
||||
{
|
||||
@@ -38,28 +37,6 @@ static s32 scissorBottom = 0;
|
||||
static Tev tev;
|
||||
static RasterBlock rasterBlock;
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
ZSlope.DoState(p);
|
||||
WSlope.DoState(p);
|
||||
for (auto& color_slopes_1d : ColorSlopes)
|
||||
for (Slope& color_slope : color_slopes_1d)
|
||||
color_slope.DoState(p);
|
||||
for (auto& tex_slopes_1d : TexSlopes)
|
||||
for (Slope& tex_slope : tex_slopes_1d)
|
||||
tex_slope.DoState(p);
|
||||
p.Do(vertex0X);
|
||||
p.Do(vertex0Y);
|
||||
p.Do(vertexOffsetX);
|
||||
p.Do(vertexOffsetY);
|
||||
p.Do(scissorLeft);
|
||||
p.Do(scissorTop);
|
||||
p.Do(scissorRight);
|
||||
p.Do(scissorBottom);
|
||||
tev.DoState(p);
|
||||
p.Do(rasterBlock);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
tev.Init();
|
||||
@@ -121,14 +98,14 @@ void SetTevReg(int reg, int comp, bool konst, s16 color)
|
||||
|
||||
static void Draw(s32 x, s32 y, s32 xi, s32 yi)
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.rasterizedPixels);
|
||||
INCSTAT(stats.thisFrame.rasterizedPixels);
|
||||
|
||||
float dx = vertexOffsetX + (float)(x - vertex0X);
|
||||
float dy = vertexOffsetY + (float)(y - vertex0Y);
|
||||
|
||||
s32 z = (s32)MathUtil::Clamp<float>(ZSlope.GetValue(dx, dy), 0.0f, 16777215.0f);
|
||||
|
||||
if (bpmem.UseEarlyDepthTest() && g_SWVideoConfig.bZComploc)
|
||||
if (bpmem.UseEarlyDepthTest() && g_ActiveConfig.bZComploc)
|
||||
{
|
||||
// TODO: Test if perf regs are incremented even if test is disabled
|
||||
EfbInterface::IncPerfCounterQuadCount(PQ_ZCOMP_INPUT_ZCOMPLOC);
|
||||
@@ -314,7 +291,7 @@ static void BuildBlock(s32 blockX, s32 blockY)
|
||||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesDrawn);
|
||||
INCSTAT(stats.thisFrame.numTrianglesDrawn);
|
||||
|
||||
// adapted from http://devmaster.net/posts/6145/advanced-rasterization
|
||||
|
||||
@@ -378,7 +355,7 @@ void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVer
|
||||
// Many things might prevent us from reaching this line (culling, clipping, scissoring).
|
||||
// However, the zslope is always guaranteed to be calculated unless all vertices are trivially rejected during clipping!
|
||||
// We're currently sloppy at this since we abort early if any of the culling/clipping/scissoring tests fail.
|
||||
if (!bpmem.genMode.zfreeze || !g_SWVideoConfig.bZFreeze)
|
||||
if (!bpmem.genMode.zfreeze || !g_ActiveConfig.bZFreeze)
|
||||
InitSlope(&ZSlope, v0->screenPosition[2], v1->screenPosition[2], v2->screenPosition[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
|
||||
|
||||
@@ -25,12 +25,6 @@ namespace Rasterizer
|
||||
float f0;
|
||||
|
||||
float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); }
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(dfdx);
|
||||
p.Do(dfdy);
|
||||
p.Do(f0);
|
||||
}
|
||||
};
|
||||
|
||||
struct RasterBlockPixel
|
||||
@@ -47,6 +41,4 @@ namespace Rasterizer
|
||||
s32 TextureLod[16];
|
||||
bool TextureLinear[16];
|
||||
};
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
}
|
||||
|
||||
@@ -1,354 +0,0 @@
|
||||
// Copyright 2009 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <atomic>
|
||||
#include "Common/Atomic.h"
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/FPURoundMode.h"
|
||||
#include "Common/MathUtil.h"
|
||||
#include "Common/Thread.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/HW/MMIO.h"
|
||||
#include "Core/HW/ProcessorInterface.h"
|
||||
|
||||
#include "VideoBackends/Software/OpcodeDecoder.h"
|
||||
#include "VideoBackends/Software/SWCommandProcessor.h"
|
||||
#include "VideoBackends/Software/VideoBackend.h"
|
||||
|
||||
#include "VideoCommon/Fifo.h"
|
||||
#include "VideoCommon/VertexLoaderUtils.h"
|
||||
|
||||
namespace SWCommandProcessor
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
GATHER_PIPE_SIZE = 32,
|
||||
INT_CAUSE_CP = 0x800
|
||||
};
|
||||
|
||||
// STATE_TO_SAVE
|
||||
// variables
|
||||
|
||||
static const int commandBufferSize = 1024 * 1024;
|
||||
static const int maxCommandBufferWrite = commandBufferSize - GATHER_PIPE_SIZE;
|
||||
static u8 commandBuffer[commandBufferSize];
|
||||
static u32 readPos;
|
||||
static u32 writePos;
|
||||
static int et_UpdateInterrupts;
|
||||
static std::atomic<bool> interruptSet;
|
||||
static std::atomic<bool> interruptWaiting;
|
||||
|
||||
static CPReg cpreg; // shared between gfx and emulator thread
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.DoPOD(cpreg);
|
||||
p.DoArray(commandBuffer, commandBufferSize);
|
||||
p.Do(readPos);
|
||||
p.Do(writePos);
|
||||
p.Do(et_UpdateInterrupts);
|
||||
p.Do(interruptSet);
|
||||
p.Do(interruptWaiting);
|
||||
|
||||
// Is this right?
|
||||
p.DoArray(g_video_buffer_read_ptr, writePos);
|
||||
}
|
||||
|
||||
static void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
|
||||
{
|
||||
UpdateInterrupts(userdata);
|
||||
}
|
||||
|
||||
static inline bool AtBreakpoint()
|
||||
{
|
||||
return cpreg.ctrl.BPEnable && (cpreg.readptr == cpreg.breakpt);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
cpreg.status.Hex = 0;
|
||||
cpreg.status.CommandIdle = 1;
|
||||
cpreg.status.ReadIdle = 1;
|
||||
|
||||
cpreg.ctrl.Hex = 0;
|
||||
cpreg.clear.Hex = 0;
|
||||
|
||||
cpreg.bboxleft = 0;
|
||||
cpreg.bboxtop = 0;
|
||||
cpreg.bboxright = 0;
|
||||
cpreg.bboxbottom = 0;
|
||||
|
||||
cpreg.token = 0;
|
||||
|
||||
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
|
||||
|
||||
// internal buffer position
|
||||
readPos = 0;
|
||||
writePos = 0;
|
||||
|
||||
interruptSet.store(false);
|
||||
interruptWaiting.store(false);
|
||||
|
||||
g_video_buffer_read_ptr = nullptr;
|
||||
g_bSkipCurrentFrame = false;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
void RunGpu()
|
||||
{
|
||||
if (!SConfig::GetInstance().bCPUThread)
|
||||
{
|
||||
// We are going to do FP math on the main thread so have to save the current state
|
||||
FPURoundMode::SaveSIMDState();
|
||||
FPURoundMode::LoadDefaultSIMDState();
|
||||
|
||||
// run the opcode decoder
|
||||
do
|
||||
{
|
||||
RunBuffer();
|
||||
} while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr);
|
||||
|
||||
FPURoundMode::LoadSIMDState();
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
{
|
||||
// Directly map reads and writes to the cpreg structure.
|
||||
for (u32 i = 0; i < sizeof (cpreg) / sizeof (u16); ++i)
|
||||
{
|
||||
u16* ptr = ((u16*)&cpreg) + i;
|
||||
mmio->Register(base | (i * 2),
|
||||
MMIO::DirectRead<u16>(ptr),
|
||||
MMIO::DirectWrite<u16>(ptr)
|
||||
);
|
||||
}
|
||||
|
||||
// Bleh. Apparently SWCommandProcessor does not know about regs 0x40 to
|
||||
// 0x64...
|
||||
for (u32 i = 0x40; i < 0x64; ++i)
|
||||
{
|
||||
mmio->Register(base | i,
|
||||
MMIO::Constant<u16>(0),
|
||||
MMIO::Nop<u16>()
|
||||
);
|
||||
}
|
||||
|
||||
// The low part of MMIO regs for FIFO addresses needs to be aligned to 32
|
||||
// bytes.
|
||||
u32 fifo_addr_lo_regs[] = {
|
||||
CommandProcessor::FIFO_BASE_LO,
|
||||
CommandProcessor::FIFO_END_LO,
|
||||
CommandProcessor::FIFO_WRITE_POINTER_LO,
|
||||
CommandProcessor::FIFO_READ_POINTER_LO,
|
||||
CommandProcessor::FIFO_BP_LO,
|
||||
CommandProcessor::FIFO_RW_DISTANCE_LO,
|
||||
};
|
||||
for (u32 reg : fifo_addr_lo_regs)
|
||||
{
|
||||
mmio->RegisterWrite(base | reg,
|
||||
MMIO::DirectWrite<u16>(((u16*)&cpreg) + (reg / 2), 0xFFE0)
|
||||
);
|
||||
}
|
||||
|
||||
// The clear register needs to perform some more complicated operations on
|
||||
// writes.
|
||||
mmio->RegisterWrite(base | CommandProcessor::CLEAR_REGISTER,
|
||||
MMIO::ComplexWrite<u16>([](u32, u16 val) {
|
||||
UCPClearReg tmpClear(val);
|
||||
|
||||
if (tmpClear.ClearFifoOverflow)
|
||||
cpreg.status.OverflowHiWatermark = 0;
|
||||
if (tmpClear.ClearFifoUnderflow)
|
||||
cpreg.status.UnderflowLoWatermark = 0;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
void GatherPipeBursted()
|
||||
{
|
||||
if (cpreg.ctrl.GPLinkEnable)
|
||||
{
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t WGP burst. write thru : %08x", cpreg.writeptr);
|
||||
|
||||
if (cpreg.writeptr == cpreg.fifoend)
|
||||
cpreg.writeptr = cpreg.fifobase;
|
||||
else
|
||||
cpreg.writeptr += GATHER_PIPE_SIZE;
|
||||
|
||||
Common::AtomicAdd(cpreg.rwdistance, GATHER_PIPE_SIZE);
|
||||
}
|
||||
|
||||
RunGpu();
|
||||
}
|
||||
|
||||
void UpdateInterrupts(u64 userdata)
|
||||
{
|
||||
if (userdata)
|
||||
{
|
||||
interruptSet.store(true);
|
||||
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
interruptSet.store(false);
|
||||
INFO_LOG(COMMANDPROCESSOR,"Interrupt cleared");
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, false);
|
||||
}
|
||||
interruptWaiting.store(false);
|
||||
}
|
||||
|
||||
void UpdateInterruptsFromVideoBackend(u64 userdata)
|
||||
{
|
||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_UpdateInterrupts, userdata);
|
||||
}
|
||||
|
||||
static void ReadFifo()
|
||||
{
|
||||
bool canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
|
||||
bool atBreakpoint = AtBreakpoint();
|
||||
|
||||
if (canRead && !atBreakpoint)
|
||||
{
|
||||
// read from fifo
|
||||
u8 *ptr = Memory::GetPointer(cpreg.readptr);
|
||||
int bytesRead = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// copy to buffer
|
||||
memcpy(&commandBuffer[writePos], ptr, GATHER_PIPE_SIZE);
|
||||
writePos += GATHER_PIPE_SIZE;
|
||||
bytesRead += GATHER_PIPE_SIZE;
|
||||
|
||||
if (cpreg.readptr == cpreg.fifoend)
|
||||
{
|
||||
cpreg.readptr = cpreg.fifobase;
|
||||
ptr = Memory::GetPointer(cpreg.readptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpreg.readptr += GATHER_PIPE_SIZE;
|
||||
ptr += GATHER_PIPE_SIZE;
|
||||
}
|
||||
|
||||
canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
|
||||
atBreakpoint = AtBreakpoint();
|
||||
} while (canRead && !atBreakpoint);
|
||||
|
||||
Common::AtomicAdd(cpreg.rwdistance, -bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetStatus()
|
||||
{
|
||||
// overflow check
|
||||
if (cpreg.rwdistance > cpreg.hiwatermark)
|
||||
cpreg.status.OverflowHiWatermark = 1;
|
||||
|
||||
// underflow check
|
||||
if (cpreg.rwdistance < cpreg.lowatermark)
|
||||
cpreg.status.UnderflowLoWatermark = 1;
|
||||
|
||||
// breakpoint
|
||||
if (cpreg.ctrl.BPEnable)
|
||||
{
|
||||
if (cpreg.breakpt == cpreg.readptr)
|
||||
{
|
||||
if (!cpreg.status.Breakpoint)
|
||||
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %x", cpreg.readptr);
|
||||
cpreg.status.Breakpoint = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cpreg.status.Breakpoint)
|
||||
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %x", cpreg.readptr);
|
||||
cpreg.status.Breakpoint = 0;
|
||||
}
|
||||
|
||||
cpreg.status.ReadIdle = cpreg.readptr == cpreg.writeptr;
|
||||
|
||||
bool bpInt = cpreg.status.Breakpoint && cpreg.ctrl.BPInt;
|
||||
bool ovfInt = cpreg.status.OverflowHiWatermark && cpreg.ctrl.FifoOverflowIntEnable;
|
||||
bool undfInt = cpreg.status.UnderflowLoWatermark && cpreg.ctrl.FifoUnderflowIntEnable;
|
||||
|
||||
bool interrupt = bpInt || ovfInt || undfInt;
|
||||
|
||||
if (interrupt != interruptSet.load() && !interruptWaiting.load())
|
||||
{
|
||||
u64 userdata = interrupt?1:0;
|
||||
if (SConfig::GetInstance().bCPUThread)
|
||||
{
|
||||
interruptWaiting.store(true);
|
||||
SWCommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
SWCommandProcessor::UpdateInterrupts(userdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RunBuffer()
|
||||
{
|
||||
// fifo is read 32 bytes at a time
|
||||
// read fifo data to internal buffer
|
||||
if (cpreg.ctrl.GPReadEnable)
|
||||
ReadFifo();
|
||||
|
||||
SetStatus();
|
||||
|
||||
_dbg_assert_(COMMANDPROCESSOR, writePos >= readPos);
|
||||
|
||||
g_video_buffer_read_ptr = &commandBuffer[readPos];
|
||||
|
||||
u32 availableBytes = writePos - readPos;
|
||||
|
||||
while (OpcodeDecoder::CommandRunnable(availableBytes))
|
||||
{
|
||||
cpreg.status.CommandIdle = 0;
|
||||
|
||||
OpcodeDecoder::Run(availableBytes);
|
||||
|
||||
// if data was read by the opcode decoder then the video data pointer changed
|
||||
readPos = (u32)(g_video_buffer_read_ptr - &commandBuffer[0]);
|
||||
_dbg_assert_(VIDEO, writePos >= readPos);
|
||||
availableBytes = writePos - readPos;
|
||||
}
|
||||
|
||||
cpreg.status.CommandIdle = 1;
|
||||
|
||||
bool ranDecoder = false;
|
||||
|
||||
// move data remaining in the command buffer
|
||||
if (readPos > 0)
|
||||
{
|
||||
memmove(&commandBuffer[0], &commandBuffer[readPos], availableBytes);
|
||||
writePos -= readPos;
|
||||
readPos = 0;
|
||||
|
||||
ranDecoder = true;
|
||||
}
|
||||
|
||||
return ranDecoder;
|
||||
}
|
||||
|
||||
void SetRendering(bool enabled)
|
||||
{
|
||||
g_bSkipCurrentFrame = !enabled;
|
||||
}
|
||||
|
||||
} // end of namespace SWCommandProcessor
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
// Copyright 2009 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "VideoCommon/CommandProcessor.h"
|
||||
|
||||
class PointerWrap;
|
||||
namespace MMIO { class Mapping; }
|
||||
|
||||
namespace SWCommandProcessor
|
||||
{
|
||||
using UCPStatusReg = CommandProcessor::UCPStatusReg;
|
||||
using UCPCtrlReg = CommandProcessor::UCPCtrlReg;
|
||||
using UCPClearReg = CommandProcessor::UCPClearReg;
|
||||
|
||||
struct CPReg
|
||||
{
|
||||
UCPStatusReg status; // 0x00
|
||||
UCPCtrlReg ctrl; // 0x02
|
||||
UCPClearReg clear; // 0x04
|
||||
u32 unk0; // 0x08
|
||||
u16 unk1; // 0x0c
|
||||
u16 token; // 0x0e
|
||||
u16 bboxleft; // 0x10
|
||||
u16 bboxtop; // 0x12
|
||||
u16 bboxright; // 0x14
|
||||
u16 bboxbottom; // 0x16
|
||||
u32 unk2; // 0x18
|
||||
u32 unk3; // 0x1c
|
||||
u32 fifobase; // 0x20
|
||||
u32 fifoend; // 0x24
|
||||
u32 hiwatermark; // 0x28
|
||||
u32 lowatermark; // 0x2c
|
||||
u32 rwdistance; // 0x30
|
||||
u32 writeptr; // 0x34
|
||||
u32 readptr; // 0x38
|
||||
u32 breakpt; // 0x3c
|
||||
};
|
||||
|
||||
// Init
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
|
||||
|
||||
bool RunBuffer();
|
||||
void RunGpu();
|
||||
|
||||
// for CGPFIFO
|
||||
void GatherPipeBursted();
|
||||
void UpdateInterrupts(u64 userdata);
|
||||
void UpdateInterruptsFromVideoBackend(u64 userdata);
|
||||
|
||||
void SetRendering(bool enabled);
|
||||
|
||||
} // end of namespace SWCommandProcessor
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user