Add Turntable.cpp to SCons build.

Set native eol-style on recently added files.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6252 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Soren Jorvang
2010-10-03 08:20:24 +00:00
parent c6fa5804de
commit 4b5b9ad05c
98 changed files with 18965 additions and 18964 deletions
+32 -32
View File
@@ -1,32 +1,32 @@
// Copyright (C) 2010 Dolphin Project. // Copyright (C) 2010 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _CPUCOREBASE_H #ifndef _CPUCOREBASE_H
#define _CPUCOREBASE_H #define _CPUCOREBASE_H
class CPUCoreBase class CPUCoreBase
{ {
public: public:
virtual void Init() = 0; virtual void Init() = 0;
virtual void Shutdown() = 0; virtual void Shutdown() = 0;
virtual void ClearCache() = 0; virtual void ClearCache() = 0;
virtual void Run() = 0; virtual void Run() = 0;
virtual void SingleStep() = 0; virtual void SingleStep() = 0;
virtual const char *GetName() = 0; virtual const char *GetName() = 0;
}; };
#endif #endif
+158 -158
View File
@@ -1,158 +1,158 @@
#include "Common.h" #include "Common.h"
#include "Statistics.h" #include "Statistics.h"
#include "OpcodeDecoding.h" #include "OpcodeDecoding.h"
#include "IndexGenerator.h" #include "IndexGenerator.h"
#include "VertexManagerBase.h" #include "VertexManagerBase.h"
VertexManager *g_vertex_manager; VertexManager *g_vertex_manager;
u8 *VertexManager::s_pCurBufferPointer; u8 *VertexManager::s_pCurBufferPointer;
u8 *VertexManager::s_pBaseBufferPointer; u8 *VertexManager::s_pBaseBufferPointer;
u8 *VertexManager::LocalVBuffer; u8 *VertexManager::LocalVBuffer;
u16 *VertexManager::TIBuffer; u16 *VertexManager::TIBuffer;
u16 *VertexManager::LIBuffer; u16 *VertexManager::LIBuffer;
u16 *VertexManager::PIBuffer; u16 *VertexManager::PIBuffer;
bool VertexManager::Flushed; bool VertexManager::Flushed;
VertexManager::VertexManager() VertexManager::VertexManager()
{ {
Flushed = false; Flushed = false;
LocalVBuffer = new u8[MAXVBUFFERSIZE]; LocalVBuffer = new u8[MAXVBUFFERSIZE];
s_pCurBufferPointer = s_pBaseBufferPointer = LocalVBuffer; s_pCurBufferPointer = s_pBaseBufferPointer = LocalVBuffer;
TIBuffer = new u16[MAXIBUFFERSIZE]; TIBuffer = new u16[MAXIBUFFERSIZE];
LIBuffer = new u16[MAXIBUFFERSIZE]; LIBuffer = new u16[MAXIBUFFERSIZE];
PIBuffer = new u16[MAXIBUFFERSIZE]; PIBuffer = new u16[MAXIBUFFERSIZE];
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer); IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
} }
void VertexManager::ResetBuffer() void VertexManager::ResetBuffer()
{ {
s_pCurBufferPointer = LocalVBuffer; s_pCurBufferPointer = LocalVBuffer;
} }
VertexManager::~VertexManager() VertexManager::~VertexManager()
{ {
delete[] LocalVBuffer; delete[] LocalVBuffer;
delete[] TIBuffer; delete[] TIBuffer;
delete[] LIBuffer; delete[] LIBuffer;
delete[] PIBuffer; delete[] PIBuffer;
// TODO: necessary?? // TODO: necessary??
ResetBuffer(); ResetBuffer();
} }
void VertexManager::AddIndices(int primitive, int numVertices) void VertexManager::AddIndices(int primitive, int numVertices)
{ {
//switch (primitive) //switch (primitive)
//{ //{
//case GX_DRAW_QUADS: IndexGenerator::AddQuads(numVertices); break; //case GX_DRAW_QUADS: IndexGenerator::AddQuads(numVertices); break;
//case GX_DRAW_TRIANGLES: IndexGenerator::AddList(numVertices); break; //case GX_DRAW_TRIANGLES: IndexGenerator::AddList(numVertices); break;
//case GX_DRAW_TRIANGLE_STRIP: IndexGenerator::AddStrip(numVertices); break; //case GX_DRAW_TRIANGLE_STRIP: IndexGenerator::AddStrip(numVertices); break;
//case GX_DRAW_TRIANGLE_FAN: IndexGenerator::AddFan(numVertices); break; //case GX_DRAW_TRIANGLE_FAN: IndexGenerator::AddFan(numVertices); break;
//case GX_DRAW_LINES: IndexGenerator::AddLineList(numVertices); break; //case GX_DRAW_LINES: IndexGenerator::AddLineList(numVertices); break;
//case GX_DRAW_LINE_STRIP: IndexGenerator::AddLineStrip(numVertices); break; //case GX_DRAW_LINE_STRIP: IndexGenerator::AddLineStrip(numVertices); break;
//case GX_DRAW_POINTS: IndexGenerator::AddPoints(numVertices); break; //case GX_DRAW_POINTS: IndexGenerator::AddPoints(numVertices); break;
//} //}
static void (*const primitive_table[])(int) = static void (*const primitive_table[])(int) =
{ {
IndexGenerator::AddQuads, IndexGenerator::AddQuads,
NULL, NULL,
IndexGenerator::AddList, IndexGenerator::AddList,
IndexGenerator::AddStrip, IndexGenerator::AddStrip,
IndexGenerator::AddFan, IndexGenerator::AddFan,
IndexGenerator::AddLineList, IndexGenerator::AddLineList,
IndexGenerator::AddLineStrip, IndexGenerator::AddLineStrip,
IndexGenerator::AddPoints, IndexGenerator::AddPoints,
}; };
primitive_table[primitive](numVertices); primitive_table[primitive](numVertices);
} }
int VertexManager::GetRemainingSize() int VertexManager::GetRemainingSize()
{ {
return MAXVBUFFERSIZE - (int)(s_pCurBufferPointer - LocalVBuffer); return MAXVBUFFERSIZE - (int)(s_pCurBufferPointer - LocalVBuffer);
} }
int VertexManager::GetRemainingVertices(int primitive) int VertexManager::GetRemainingVertices(int primitive)
{ {
switch (primitive) switch (primitive)
{ {
case GX_DRAW_QUADS: case GX_DRAW_QUADS:
case GX_DRAW_TRIANGLES: case GX_DRAW_TRIANGLES:
case GX_DRAW_TRIANGLE_STRIP: case GX_DRAW_TRIANGLE_STRIP:
case GX_DRAW_TRIANGLE_FAN: case GX_DRAW_TRIANGLE_FAN:
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3; return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3;
break; break;
case GX_DRAW_LINES: case GX_DRAW_LINES:
case GX_DRAW_LINE_STRIP: case GX_DRAW_LINE_STRIP:
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2; return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2;
break; break;
case GX_DRAW_POINTS: case GX_DRAW_POINTS:
return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen()); return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen());
break; break;
default: default:
return 0; return 0;
break; break;
} }
} }
void VertexManager::AddVertices(int primitive, int numVertices) void VertexManager::AddVertices(int primitive, int numVertices)
{ {
if (numVertices <= 0) if (numVertices <= 0)
return; return;
switch (primitive) switch (primitive)
{ {
case GX_DRAW_QUADS: case GX_DRAW_QUADS:
case GX_DRAW_TRIANGLES: case GX_DRAW_TRIANGLES:
case GX_DRAW_TRIANGLE_STRIP: case GX_DRAW_TRIANGLE_STRIP:
case GX_DRAW_TRIANGLE_FAN: case GX_DRAW_TRIANGLE_FAN:
if (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen() < 3 * numVertices) if (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen() < 3 * numVertices)
Flush(); Flush();
break; break;
case GX_DRAW_LINES: case GX_DRAW_LINES:
case GX_DRAW_LINE_STRIP: case GX_DRAW_LINE_STRIP:
if (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen() < 2 * numVertices) if (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen() < 2 * numVertices)
Flush(); Flush();
break; break;
case GX_DRAW_POINTS: case GX_DRAW_POINTS:
if (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen() < numVertices) if (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen() < numVertices)
Flush(); Flush();
break; break;
default: default:
return; return;
break; break;
} }
if (Flushed) if (Flushed)
{ {
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer); IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
Flushed = false; Flushed = false;
} }
ADDSTAT(stats.thisFrame.numPrims, numVertices); ADDSTAT(stats.thisFrame.numPrims, numVertices);
INCSTAT(stats.thisFrame.numPrimitiveJoins); INCSTAT(stats.thisFrame.numPrimitiveJoins);
AddIndices(primitive, numVertices); AddIndices(primitive, numVertices);
} }
// TODO: merge this func, (need to merge TextureCache) // TODO: merge this func, (need to merge TextureCache)
void VertexManager::Flush() void VertexManager::Flush()
{ {
g_vertex_manager->vFlush(); g_vertex_manager->vFlush();
} }
+57 -57
View File
@@ -1,57 +1,57 @@
#ifndef _VERTEXMANAGERBASE_H #ifndef _VERTEXMANAGERBASE_H
#define _VERTEXMANAGERBASE_H #define _VERTEXMANAGERBASE_H
class VertexManager class VertexManager
{ {
public: public:
enum enum
{ {
// values from OGL plugin // values from OGL plugin
//MAXVBUFFERSIZE = 0x1FFFF, //MAXVBUFFERSIZE = 0x1FFFF,
//MAXIBUFFERSIZE = 0xFFFF, //MAXIBUFFERSIZE = 0xFFFF,
// values from DX9 plugin // values from DX9 plugin
//MAXVBUFFERSIZE = 0x50000, //MAXVBUFFERSIZE = 0x50000,
//MAXIBUFFERSIZE = 0xFFFF, //MAXIBUFFERSIZE = 0xFFFF,
// values from DX11 plugin // values from DX11 plugin
MAXVBUFFERSIZE = 0x50000, MAXVBUFFERSIZE = 0x50000,
MAXIBUFFERSIZE = 0x10000, MAXIBUFFERSIZE = 0x10000,
}; };
VertexManager(); VertexManager();
virtual ~VertexManager(); // needs to be virtual for DX11's dtor virtual ~VertexManager(); // needs to be virtual for DX11's dtor
static void AddVertices(int _primitive, int _numVertices); static void AddVertices(int _primitive, int _numVertices);
// TODO: protected? // TODO: protected?
static u8 *s_pCurBufferPointer; static u8 *s_pCurBufferPointer;
static u8 *s_pBaseBufferPointer; static u8 *s_pBaseBufferPointer;
static int GetRemainingSize(); static int GetRemainingSize();
static int GetRemainingVertices(int primitive); static int GetRemainingVertices(int primitive);
static void Flush(); static void Flush();
protected: protected:
// TODO: make private after Flush() is merged // TODO: make private after Flush() is merged
static void ResetBuffer(); static void ResetBuffer();
static u8 *LocalVBuffer; static u8 *LocalVBuffer;
static u16 *TIBuffer; static u16 *TIBuffer;
static u16 *LIBuffer; static u16 *LIBuffer;
static u16 *PIBuffer; static u16 *PIBuffer;
static bool Flushed; static bool Flushed;
private: private:
static void AddIndices(int primitive, int numVertices); static void AddIndices(int primitive, int numVertices);
// temporary // temporary
virtual void vFlush() = 0; virtual void vFlush() = 0;
}; };
extern VertexManager *g_vertex_manager; extern VertexManager *g_vertex_manager;
#endif #endif
File diff suppressed because it is too large Load Diff
@@ -1,144 +1,144 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Common // Common
#include "Common.h" #include "Common.h"
// VideoCommon // VideoCommon
#include "VideoConfig.h" #include "VideoConfig.h"
#include "BPFunctions.h" #include "BPFunctions.h"
#include "Renderer.h" #include "Renderer.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "VertexManager.h" #include "VertexManager.h"
#include "Main.h" #include "Main.h"
namespace BPFunctions namespace BPFunctions
{ {
void FlushPipeline() void FlushPipeline()
{ {
g_vertex_manager->Flush(); g_vertex_manager->Flush();
} }
void SetGenerationMode(const BPCmd &bp) void SetGenerationMode(const BPCmd &bp)
{ {
g_renderer->SetGenerationMode(); g_renderer->SetGenerationMode();
} }
void SetScissor(const BPCmd &bp) void SetScissor(const BPCmd &bp)
{ {
g_renderer->SetScissorRect(); g_renderer->SetScissorRect();
} }
void SetLineWidth(const BPCmd &bp) void SetLineWidth(const BPCmd &bp)
{ {
g_renderer->SetLineWidth(); g_renderer->SetLineWidth();
} }
void SetDepthMode(const BPCmd &bp) void SetDepthMode(const BPCmd &bp)
{ {
g_renderer->SetDepthMode(); g_renderer->SetDepthMode();
} }
void SetBlendMode(const BPCmd &bp) void SetBlendMode(const BPCmd &bp)
{ {
g_renderer->SetBlendMode(false); g_renderer->SetBlendMode(false);
} }
void SetDitherMode(const BPCmd &bp) void SetDitherMode(const BPCmd &bp)
{ {
g_renderer->SetDitherMode(); g_renderer->SetDitherMode();
} }
void SetLogicOpMode(const BPCmd &bp) void SetLogicOpMode(const BPCmd &bp)
{ {
g_renderer->SetLogicOpMode(); g_renderer->SetLogicOpMode();
} }
void SetColorMask(const BPCmd &bp) void SetColorMask(const BPCmd &bp)
{ {
g_renderer->SetColorMask(); g_renderer->SetColorMask();
} }
void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 &copyfmt, const int &scaleByHalf) void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 &copyfmt, const int &scaleByHalf)
{ {
if (!g_ActiveConfig.bEFBCopyDisable) if (!g_ActiveConfig.bEFBCopyDisable)
{ {
// if (g_ActiveConfig.bCopyEFBToTexture) // if (g_ActiveConfig.bCopyEFBToTexture)
// { // {
g_texture_cache->CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, !!scaleByHalf, rc); g_texture_cache->CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, !!scaleByHalf, rc);
// } // }
// else // else
// { // {
// PanicAlert("TODO: Implement EFB copying to RAM %s %d\n", __FILE__, __LINE__); // PanicAlert("TODO: Implement EFB copying to RAM %s %d\n", __FILE__, __LINE__);
// } // }
} }
} }
void ClearScreen(const BPCmd &bp, const EFBRectangle &rc) void ClearScreen(const BPCmd &bp, const EFBRectangle &rc)
{ {
bool colorEnable = bpmem.blendmode.colorupdate; bool colorEnable = bpmem.blendmode.colorupdate;
bool alphaEnable = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24 && bpmem.blendmode.alphaupdate); bool alphaEnable = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24 && bpmem.blendmode.alphaupdate);
bool zEnable = bpmem.zmode.updateenable; bool zEnable = bpmem.zmode.updateenable;
if (colorEnable || alphaEnable || zEnable) if (colorEnable || alphaEnable || zEnable)
{ {
u32 color = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB; u32 color = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
u32 z = bpmem.clearZValue; u32 z = bpmem.clearZValue;
g_renderer->ClearScreen(rc, colorEnable, alphaEnable, zEnable, color, z); g_renderer->ClearScreen(rc, colorEnable, alphaEnable, zEnable, color, z);
} }
} }
void RestoreRenderState(const BPCmd &bp) void RestoreRenderState(const BPCmd &bp)
{ {
g_renderer->RestoreAPIState(); g_renderer->RestoreAPIState();
} }
bool GetConfig(const int &type) bool GetConfig(const int &type)
{ {
switch (type) switch (type)
{ {
case CONFIG_ISWII: case CONFIG_ISWII:
return g_VideoInitialize.bWii; return g_VideoInitialize.bWii;
case CONFIG_DISABLEFOG: case CONFIG_DISABLEFOG:
return g_ActiveConfig.bDisableFog; return g_ActiveConfig.bDisableFog;
case CONFIG_SHOWEFBREGIONS: case CONFIG_SHOWEFBREGIONS:
return false; return false;
default: default:
PanicAlert("GetConfig Error: Unknown Config Type!"); PanicAlert("GetConfig Error: Unknown Config Type!");
return false; return false;
} }
} }
u8 *GetPointer(const u32 &address) u8 *GetPointer(const u32 &address)
{ {
return g_VideoInitialize.pGetMemoryPointer(address); return g_VideoInitialize.pGetMemoryPointer(address);
} }
void SetTextureMode(const BPCmd &bp) void SetTextureMode(const BPCmd &bp)
{ {
g_renderer->SetSamplerState(bp.address & 3, (bp.address & 0xE0) == 0xA0); g_renderer->SetSamplerState(bp.address & 3, (bp.address & 0xE0) == 0xA0);
} }
void SetInterlacingMode(const BPCmd &bp) void SetInterlacingMode(const BPCmd &bp)
{ {
// TODO // TODO
} }
} }
@@ -1,338 +1,338 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Common // Common
#include "StringUtil.h" #include "StringUtil.h"
// VideoCommon // VideoCommon
#include "VideoConfig.h" #include "VideoConfig.h"
#include "XFStructs.h" #include "XFStructs.h"
// DX11 // DX11
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
#include "DX11_D3DTexture.h" #include "DX11_D3DTexture.h"
#include "DX11_D3DShader.h" #include "DX11_D3DShader.h"
#include "DX11_Render.h" #include "DX11_Render.h"
#include <D3Dcompiler.h> #include <D3Dcompiler.h>
#pragma comment(lib, "dxguid.lib") #pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "d3d11.lib") #pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib") #pragma comment(lib, "dxgi.lib")
namespace DX11 namespace DX11
{ {
HINSTANCE hD3DXDll = NULL; HINSTANCE hD3DXDll = NULL;
D3DX11COMPILEFROMMEMORYTYPE PD3DX11CompileFromMemory = NULL; D3DX11COMPILEFROMMEMORYTYPE PD3DX11CompileFromMemory = NULL;
D3DX11FILTERTEXTURETYPE PD3DX11FilterTexture = NULL; D3DX11FILTERTEXTURETYPE PD3DX11FilterTexture = NULL;
D3DX11SAVETEXTURETOFILEATYPE PD3DX11SaveTextureToFileA = NULL; D3DX11SAVETEXTURETOFILEATYPE PD3DX11SaveTextureToFileA = NULL;
D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW = NULL; D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW = NULL;
namespace D3D namespace D3D
{ {
ID3D11Device* device = NULL; ID3D11Device* device = NULL;
ID3D11DeviceContext* context = NULL; ID3D11DeviceContext* context = NULL;
IDXGISwapChain* swapchain = NULL; IDXGISwapChain* swapchain = NULL;
D3D_FEATURE_LEVEL featlevel; D3D_FEATURE_LEVEL featlevel;
D3DTexture2D* backbuf = NULL; D3DTexture2D* backbuf = NULL;
HWND hWnd; HWND hWnd;
bool bgra_textures_supported; bool bgra_textures_supported;
#define NUM_SUPPORTED_FEATURE_LEVELS 3 #define NUM_SUPPORTED_FEATURE_LEVELS 3
const D3D_FEATURE_LEVEL supported_feature_levels[NUM_SUPPORTED_FEATURE_LEVELS] = { const D3D_FEATURE_LEVEL supported_feature_levels[NUM_SUPPORTED_FEATURE_LEVELS] = {
D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0 D3D_FEATURE_LEVEL_10_0
}; };
unsigned int xres, yres; unsigned int xres, yres;
bool bFrameInProgress = false; bool bFrameInProgress = false;
HRESULT Create(HWND wnd) HRESULT Create(HWND wnd)
{ {
hWnd = wnd; hWnd = wnd;
HRESULT hr; HRESULT hr;
RECT client; RECT client;
GetClientRect(hWnd, &client); GetClientRect(hWnd, &client);
xres = client.right - client.left; xres = client.right - client.left;
yres = client.bottom - client.top; yres = client.bottom - client.top;
// try to load D3DX11 first to check whether we have proper runtime support // try to load D3DX11 first to check whether we have proper runtime support
// try to use the dll the plugin was compiled against first - don't bother about debug runtimes // try to use the dll the plugin was compiled against first - don't bother about debug runtimes
hD3DXDll = LoadLibraryA(StringFromFormat("d3dx11_%d.dll", D3DX11_SDK_VERSION).c_str()); hD3DXDll = LoadLibraryA(StringFromFormat("d3dx11_%d.dll", D3DX11_SDK_VERSION).c_str());
if (!hD3DXDll) if (!hD3DXDll)
{ {
// if that fails, use the dll which should be available in every SDK which officially supports DX11. // if that fails, use the dll which should be available in every SDK which officially supports DX11.
hD3DXDll = LoadLibraryA("d3dx11_42.dll"); hD3DXDll = LoadLibraryA("d3dx11_42.dll");
if (!hD3DXDll) if (!hD3DXDll)
{ {
MessageBoxA(NULL, "Failed to load d3dx11_42.dll, update your DX11 runtime, please", "Critical error", MB_OK | MB_ICONERROR); MessageBoxA(NULL, "Failed to load d3dx11_42.dll, update your DX11 runtime, please", "Critical error", MB_OK | MB_ICONERROR);
return E_FAIL; return E_FAIL;
} }
else else
{ {
NOTICE_LOG(VIDEO, "Successfully loaded d3dx11_42.dll. If you're having trouble, try updating your DX runtime first."); NOTICE_LOG(VIDEO, "Successfully loaded d3dx11_42.dll. If you're having trouble, try updating your DX runtime first.");
} }
} }
else else
{ {
NOTICE_LOG(VIDEO, "Successfully loaded %s.", StringFromFormat("d3dx11_%d.dll", D3DX11_SDK_VERSION).c_str()); NOTICE_LOG(VIDEO, "Successfully loaded %s.", StringFromFormat("d3dx11_%d.dll", D3DX11_SDK_VERSION).c_str());
} }
PD3DX11CompileFromMemory = (D3DX11COMPILEFROMMEMORYTYPE)GetProcAddress(hD3DXDll, "D3DX11CompileFromMemory"); PD3DX11CompileFromMemory = (D3DX11COMPILEFROMMEMORYTYPE)GetProcAddress(hD3DXDll, "D3DX11CompileFromMemory");
if (PD3DX11CompileFromMemory == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11CompileFromMemory!", "Critical error", MB_OK | MB_ICONERROR); if (PD3DX11CompileFromMemory == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11CompileFromMemory!", "Critical error", MB_OK | MB_ICONERROR);
PD3DX11FilterTexture = (D3DX11FILTERTEXTURETYPE)GetProcAddress(hD3DXDll, "D3DX11FilterTexture"); PD3DX11FilterTexture = (D3DX11FILTERTEXTURETYPE)GetProcAddress(hD3DXDll, "D3DX11FilterTexture");
if (PD3DX11FilterTexture == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11FilterTexture!", "Critical error", MB_OK | MB_ICONERROR); if (PD3DX11FilterTexture == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11FilterTexture!", "Critical error", MB_OK | MB_ICONERROR);
PD3DX11SaveTextureToFileA = (D3DX11SAVETEXTURETOFILEATYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileA"); PD3DX11SaveTextureToFileA = (D3DX11SAVETEXTURETOFILEATYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileA");
if (PD3DX11SaveTextureToFileA == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileA!", "Critical error", MB_OK | MB_ICONERROR); if (PD3DX11SaveTextureToFileA == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileA!", "Critical error", MB_OK | MB_ICONERROR);
PD3DX11SaveTextureToFileW = (D3DX11SAVETEXTURETOFILEWTYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileW"); PD3DX11SaveTextureToFileW = (D3DX11SAVETEXTURETOFILEWTYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileW");
if (PD3DX11SaveTextureToFileW == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileW!", "Critical error", MB_OK | MB_ICONERROR); if (PD3DX11SaveTextureToFileW == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileW!", "Critical error", MB_OK | MB_ICONERROR);
// D3DX11 is fine, initialize D3D11 // D3DX11 is fine, initialize D3D11
IDXGIFactory* factory; IDXGIFactory* factory;
IDXGIAdapter* adapter; IDXGIAdapter* adapter;
IDXGIOutput* output; IDXGIOutput* output;
hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory); hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
if (FAILED(hr)) MessageBox(wnd, _T("Failed to create IDXGIFactory object"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR); if (FAILED(hr)) MessageBox(wnd, _T("Failed to create IDXGIFactory object"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter); hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter);
if (FAILED(hr)) if (FAILED(hr))
{ {
// try using the first one // try using the first one
hr = factory->EnumAdapters(0, &adapter); hr = factory->EnumAdapters(0, &adapter);
if (FAILED(hr)) MessageBox(wnd, _T("Failed to enumerate adapters"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR); if (FAILED(hr)) MessageBox(wnd, _T("Failed to enumerate adapters"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
} }
// TODO: Make this configurable // TODO: Make this configurable
hr = adapter->EnumOutputs(0, &output); hr = adapter->EnumOutputs(0, &output);
if (FAILED(hr)) if (FAILED(hr))
{ {
// try using the first one // try using the first one
hr = adapter->EnumOutputs(0, &output); hr = adapter->EnumOutputs(0, &output);
if (FAILED(hr)) MessageBox(wnd, _T("Failed to enumerate outputs"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR); if (FAILED(hr)) MessageBox(wnd, _T("Failed to enumerate outputs"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
} }
// this will need to be changed once multisampling gets implemented // this will need to be changed once multisampling gets implemented
DXGI_SWAP_CHAIN_DESC swap_chain_desc; DXGI_SWAP_CHAIN_DESC swap_chain_desc;
memset(&swap_chain_desc, 0, sizeof(swap_chain_desc)); memset(&swap_chain_desc, 0, sizeof(swap_chain_desc));
swap_chain_desc.BufferCount = 1; swap_chain_desc.BufferCount = 1;
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swap_chain_desc.OutputWindow = wnd; swap_chain_desc.OutputWindow = wnd;
swap_chain_desc.SampleDesc.Count = 1; swap_chain_desc.SampleDesc.Count = 1;
swap_chain_desc.SampleDesc.Quality = 0; swap_chain_desc.SampleDesc.Quality = 0;
swap_chain_desc.Windowed = TRUE; swap_chain_desc.Windowed = TRUE;
DXGI_MODE_DESC mode_desc; DXGI_MODE_DESC mode_desc;
memset(&mode_desc, 0, sizeof(mode_desc)); memset(&mode_desc, 0, sizeof(mode_desc));
mode_desc.Width = xres; mode_desc.Width = xres;
mode_desc.Height = yres; mode_desc.Height = yres;
mode_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; mode_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
mode_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; mode_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
hr = output->FindClosestMatchingMode(&mode_desc, &swap_chain_desc.BufferDesc, NULL); hr = output->FindClosestMatchingMode(&mode_desc, &swap_chain_desc.BufferDesc, NULL);
if (FAILED(hr)) if (FAILED(hr))
MessageBox(wnd, _T("Failed to find a supported video mode"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR); MessageBox(wnd, _T("Failed to find a supported video mode"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
// forcing buffer resolution to xres and yres.. TODO: The new video mode might not actually be supported! // forcing buffer resolution to xres and yres.. TODO: The new video mode might not actually be supported!
swap_chain_desc.BufferDesc.Width = xres; swap_chain_desc.BufferDesc.Width = xres;
swap_chain_desc.BufferDesc.Height = yres; swap_chain_desc.BufferDesc.Height = yres;
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
D3D11_CREATE_DEVICE_FLAG device_flags = (D3D11_CREATE_DEVICE_FLAG)(D3D11_CREATE_DEVICE_DEBUG|D3D11_CREATE_DEVICE_SINGLETHREADED); D3D11_CREATE_DEVICE_FLAG device_flags = (D3D11_CREATE_DEVICE_FLAG)(D3D11_CREATE_DEVICE_DEBUG|D3D11_CREATE_DEVICE_SINGLETHREADED);
#else #else
D3D11_CREATE_DEVICE_FLAG device_flags = D3D11_CREATE_DEVICE_SINGLETHREADED; D3D11_CREATE_DEVICE_FLAG device_flags = D3D11_CREATE_DEVICE_SINGLETHREADED;
#endif #endif
hr = D3D11CreateDeviceAndSwapChain(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, device_flags, hr = D3D11CreateDeviceAndSwapChain(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, device_flags,
supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS, supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS,
D3D11_SDK_VERSION, &swap_chain_desc, &swapchain, &device, D3D11_SDK_VERSION, &swap_chain_desc, &swapchain, &device,
&featlevel, &context); &featlevel, &context);
if (FAILED(hr) || !device || !context || !swapchain) if (FAILED(hr) || !device || !context || !swapchain)
{ {
MessageBox(wnd, _T("Failed to initialize Direct3D.\nMake sure your video card supports at least D3D 10.0"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR); MessageBox(wnd, _T("Failed to initialize Direct3D.\nMake sure your video card supports at least D3D 10.0"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
SAFE_RELEASE(device); SAFE_RELEASE(device);
SAFE_RELEASE(context); SAFE_RELEASE(context);
SAFE_RELEASE(swapchain); SAFE_RELEASE(swapchain);
return E_FAIL; return E_FAIL;
} }
SetDebugObjectName((ID3D11DeviceChild*)context, "device context"); SetDebugObjectName((ID3D11DeviceChild*)context, "device context");
SAFE_RELEASE(factory); SAFE_RELEASE(factory);
SAFE_RELEASE(output); SAFE_RELEASE(output);
SAFE_RELEASE(adapter); SAFE_RELEASE(adapter);
ID3D11Texture2D* buf; ID3D11Texture2D* buf;
hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf); hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf);
if (FAILED(hr)) if (FAILED(hr))
{ {
MessageBox(wnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR); MessageBox(wnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
SAFE_RELEASE(device); SAFE_RELEASE(device);
SAFE_RELEASE(context); SAFE_RELEASE(context);
SAFE_RELEASE(swapchain); SAFE_RELEASE(swapchain);
return E_FAIL; return E_FAIL;
} }
backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET); backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
SAFE_RELEASE(buf); SAFE_RELEASE(buf);
CHECK(backbuf!=NULL, "Create back buffer texture"); CHECK(backbuf!=NULL, "Create back buffer texture");
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetTex(), "backbuffer texture"); SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetTex(), "backbuffer texture");
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetRTV(), "backbuffer render target view"); SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetRTV(), "backbuffer render target view");
context->OMSetRenderTargets(1, &backbuf->GetRTV(), NULL); context->OMSetRenderTargets(1, &backbuf->GetRTV(), NULL);
// BGRA textures are easier to deal with in TextureCache, but might not be supported by the hardware // BGRA textures are easier to deal with in TextureCache, but might not be supported by the hardware
UINT format_support; UINT format_support;
device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &format_support); device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &format_support);
bgra_textures_supported = (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0; bgra_textures_supported = (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
gfxstate = new EmuGfxState; gfxstate = new EmuGfxState;
stateman = new StateManager; stateman = new StateManager;
return S_OK; return S_OK;
} }
void Close() void Close()
{ {
// unload D3DX11 // unload D3DX11
FreeLibrary(hD3DXDll); FreeLibrary(hD3DXDll);
PD3DX11FilterTexture = NULL; PD3DX11FilterTexture = NULL;
PD3DX11SaveTextureToFileA = NULL; PD3DX11SaveTextureToFileA = NULL;
PD3DX11SaveTextureToFileW = NULL; PD3DX11SaveTextureToFileW = NULL;
// release all bound resources // release all bound resources
context->ClearState(); context->ClearState();
SAFE_RELEASE(backbuf); SAFE_RELEASE(backbuf);
SAFE_RELEASE(swapchain); SAFE_RELEASE(swapchain);
SAFE_DELETE(gfxstate); SAFE_DELETE(gfxstate);
SAFE_DELETE(stateman); SAFE_DELETE(stateman);
context->Flush(); // immediately destroy device objects context->Flush(); // immediately destroy device objects
SAFE_RELEASE(context); SAFE_RELEASE(context);
ULONG references = device->Release(); ULONG references = device->Release();
if (references) if (references)
{ {
ERROR_LOG(VIDEO, "Unreleased references: %i.", references); ERROR_LOG(VIDEO, "Unreleased references: %i.", references);
} }
else else
{ {
NOTICE_LOG(VIDEO, "Successfully released all device references!"); NOTICE_LOG(VIDEO, "Successfully released all device references!");
} }
device = NULL; device = NULL;
} }
/* just returning the 4_0 ones here */ /* just returning the 4_0 ones here */
const char* VertexShaderVersionString() { return "vs_4_0"; } const char* VertexShaderVersionString() { return "vs_4_0"; }
const char* PixelShaderVersionString() { return "ps_4_0"; } const char* PixelShaderVersionString() { return "ps_4_0"; }
D3DTexture2D* &GetBackBuffer() { return backbuf; } D3DTexture2D* &GetBackBuffer() { return backbuf; }
unsigned int GetBackBufferWidth() { return xres; } unsigned int GetBackBufferWidth() { return xres; }
unsigned int GetBackBufferHeight() { return yres; } unsigned int GetBackBufferHeight() { return yres; }
bool BGRATexturesSupported() { return bgra_textures_supported; } bool BGRATexturesSupported() { return bgra_textures_supported; }
// Returns the maximum width/height of a texture. This value only depends upon the feature level in DX11 // Returns the maximum width/height of a texture. This value only depends upon the feature level in DX11
unsigned int GetMaxTextureSize() unsigned int GetMaxTextureSize()
{ {
switch (featlevel) switch (featlevel)
{ {
case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_11_0:
return 16384; return 16384;
break; break;
case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_1:
case D3D_FEATURE_LEVEL_10_0: case D3D_FEATURE_LEVEL_10_0:
return 8192; return 8192;
break; break;
case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_3:
return 4096; return 4096;
break; break;
case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_2:
case D3D_FEATURE_LEVEL_9_1: case D3D_FEATURE_LEVEL_9_1:
return 2048; return 2048;
break; break;
default: default:
return 0; return 0;
break; break;
} }
} }
void Reset() void Reset()
{ {
// release all back buffer references // release all back buffer references
SAFE_RELEASE(backbuf); SAFE_RELEASE(backbuf);
// resize swapchain buffers // resize swapchain buffers
RECT client; RECT client;
GetClientRect(hWnd, &client); GetClientRect(hWnd, &client);
xres = client.right - client.left; xres = client.right - client.left;
yres = client.bottom - client.top; yres = client.bottom - client.top;
D3D::swapchain->ResizeBuffers(1, xres, yres, DXGI_FORMAT_R8G8B8A8_UNORM, 0); D3D::swapchain->ResizeBuffers(1, xres, yres, DXGI_FORMAT_R8G8B8A8_UNORM, 0);
// recreate back buffer texture // recreate back buffer texture
ID3D11Texture2D* buf; ID3D11Texture2D* buf;
HRESULT hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf); HRESULT hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf);
if (FAILED(hr)) if (FAILED(hr))
{ {
MessageBox(hWnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR); MessageBox(hWnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
SAFE_RELEASE(device); SAFE_RELEASE(device);
SAFE_RELEASE(context); SAFE_RELEASE(context);
SAFE_RELEASE(swapchain); SAFE_RELEASE(swapchain);
return; return;
} }
backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET); backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
SAFE_RELEASE(buf); SAFE_RELEASE(buf);
CHECK(backbuf!=NULL, "Create back buffer texture"); CHECK(backbuf!=NULL, "Create back buffer texture");
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetTex(), "backbuffer texture"); SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetTex(), "backbuffer texture");
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetRTV(), "backbuffer render target view"); SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetRTV(), "backbuffer render target view");
} }
bool BeginFrame() bool BeginFrame()
{ {
if (bFrameInProgress) if (bFrameInProgress)
{ {
PanicAlert("BeginFrame called although a frame is already in progress"); PanicAlert("BeginFrame called although a frame is already in progress");
return false; return false;
} }
bFrameInProgress = true; bFrameInProgress = true;
return (device != NULL); return (device != NULL);
} }
void EndFrame() void EndFrame()
{ {
if (!bFrameInProgress) if (!bFrameInProgress)
{ {
PanicAlert("EndFrame called although no frame is in progress"); PanicAlert("EndFrame called although no frame is in progress");
return; return;
} }
bFrameInProgress = false; bFrameInProgress = false;
} }
void Present() void Present()
{ {
// TODO: Is 1 the correct value for vsyncing? // TODO: Is 1 the correct value for vsyncing?
swapchain->Present((UINT)g_ActiveConfig.bVSync, 0); swapchain->Present((UINT)g_ActiveConfig.bVSync, 0);
} }
} // namespace } // namespace
} }
@@ -1,96 +1,96 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#pragma once #pragma once
// Common // Common
#include "Common.h" #include "Common.h"
// DX11 // DX11
#include <d3dx11.h> #include <d3dx11.h>
#include "DX11_GfxState.h" #include "DX11_GfxState.h"
#include "DX11_D3DBlob.h" #include "DX11_D3DBlob.h"
namespace DX11 namespace DX11
{ {
#define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; } #define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; }
#define SAFE_DELETE(x) { delete (x); (x) = NULL; } #define SAFE_DELETE(x) { delete (x); (x) = NULL; }
#define SAFE_DELETE_ARRAY(x) { delete[] (x); (x) = NULL; } #define SAFE_DELETE_ARRAY(x) { delete[] (x); (x) = NULL; }
#define CHECK(cond, Message, ...) if (!(cond)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); } #define CHECK(cond, Message, ...) if (!(cond)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); }
class D3DTexture2D; class D3DTexture2D;
namespace D3D namespace D3D
{ {
HRESULT Create(HWND wnd); HRESULT Create(HWND wnd);
void Close(); void Close();
extern ID3D11Device* device; extern ID3D11Device* device;
extern ID3D11DeviceContext* context; extern ID3D11DeviceContext* context;
extern IDXGISwapChain* swapchain; extern IDXGISwapChain* swapchain;
extern bool bFrameInProgress; extern bool bFrameInProgress;
void Reset(); void Reset();
bool BeginFrame(); bool BeginFrame();
void EndFrame(); void EndFrame();
void Present(); void Present();
unsigned int GetBackBufferWidth(); unsigned int GetBackBufferWidth();
unsigned int GetBackBufferHeight(); unsigned int GetBackBufferHeight();
D3DTexture2D* &GetBackBuffer(); D3DTexture2D* &GetBackBuffer();
const char* PixelShaderVersionString(); const char* PixelShaderVersionString();
const char* VertexShaderVersionString(); const char* VertexShaderVersionString();
bool BGRATexturesSupported(); bool BGRATexturesSupported();
unsigned int GetMaxTextureSize(); unsigned int GetMaxTextureSize();
// Ihis function will assign a name to the given resource. // Ihis function will assign a name to the given resource.
// The DirectX debug layer will make it easier to identify resources that way, // The DirectX debug layer will make it easier to identify resources that way,
// e.g. when listing up all resources who have unreleased references. // e.g. when listing up all resources who have unreleased references.
inline void SetDebugObjectName(ID3D11DeviceChild* resource, const char* name) inline void SetDebugObjectName(ID3D11DeviceChild* resource, const char* name)
{ {
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
resource->SetPrivateData( WKPDID_D3DDebugObjectName, (UINT)strlen(name), name); resource->SetPrivateData( WKPDID_D3DDebugObjectName, (UINT)strlen(name), name);
#endif #endif
} }
} // namespace } // namespace
// Used to not require the SDK and runtime versions to match: // Used to not require the SDK and runtime versions to match:
// Linking with d3dx11.lib makes the most recent d3dx11_xx.dll of the // Linking with d3dx11.lib makes the most recent d3dx11_xx.dll of the
// compiler's SDK a requirement, but this plugin works with DX11 runtimes // compiler's SDK a requirement, but this plugin works with DX11 runtimes
// back to August 2009 even if the plugin was built with June 2010. // back to August 2009 even if the plugin was built with June 2010.
// Add any d3dx11 functions which you want to use here and load them in Create() // Add any d3dx11 functions which you want to use here and load them in Create()
typedef HRESULT (WINAPI* D3DX11COMPILEFROMMEMORYTYPE)(LPCSTR, SIZE_T, LPCSTR, const D3D10_SHADER_MACRO*, LPD3D10INCLUDE, LPCSTR, LPCSTR, UINT, UINT, ID3DX11ThreadPump*, ID3D10Blob**, ID3D10Blob**, HRESULT*); typedef HRESULT (WINAPI* D3DX11COMPILEFROMMEMORYTYPE)(LPCSTR, SIZE_T, LPCSTR, const D3D10_SHADER_MACRO*, LPD3D10INCLUDE, LPCSTR, LPCSTR, UINT, UINT, ID3DX11ThreadPump*, ID3D10Blob**, ID3D10Blob**, HRESULT*);
typedef HRESULT (WINAPI* D3DX11FILTERTEXTURETYPE)(ID3D11DeviceContext*, ID3D11Resource*, UINT, UINT); typedef HRESULT (WINAPI* D3DX11FILTERTEXTURETYPE)(ID3D11DeviceContext*, ID3D11Resource*, UINT, UINT);
typedef HRESULT (WINAPI* D3DX11SAVETEXTURETOFILEATYPE)(ID3D11DeviceContext*, ID3D11Resource*, D3DX11_IMAGE_FILE_FORMAT, LPCSTR); typedef HRESULT (WINAPI* D3DX11SAVETEXTURETOFILEATYPE)(ID3D11DeviceContext*, ID3D11Resource*, D3DX11_IMAGE_FILE_FORMAT, LPCSTR);
typedef HRESULT (WINAPI* D3DX11SAVETEXTURETOFILEWTYPE)(ID3D11DeviceContext*, ID3D11Resource*, D3DX11_IMAGE_FILE_FORMAT, LPCWSTR); typedef HRESULT (WINAPI* D3DX11SAVETEXTURETOFILEWTYPE)(ID3D11DeviceContext*, ID3D11Resource*, D3DX11_IMAGE_FILE_FORMAT, LPCWSTR);
extern D3DX11COMPILEFROMMEMORYTYPE PD3DX11CompileFromMemory; extern D3DX11COMPILEFROMMEMORYTYPE PD3DX11CompileFromMemory;
extern D3DX11FILTERTEXTURETYPE PD3DX11FilterTexture; extern D3DX11FILTERTEXTURETYPE PD3DX11FilterTexture;
extern D3DX11SAVETEXTURETOFILEATYPE PD3DX11SaveTextureToFileA; extern D3DX11SAVETEXTURETOFILEATYPE PD3DX11SaveTextureToFileA;
extern D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW; extern D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW;
#ifdef UNICODE #ifdef UNICODE
#define PD3DX11SaveTextureToFile PD3DX11SaveTextureToFileW #define PD3DX11SaveTextureToFile PD3DX11SaveTextureToFileW
#else #else
#define PD3DX11SaveTextureToFile PD3DX11SaveTextureToFileA #define PD3DX11SaveTextureToFile PD3DX11SaveTextureToFileA
#endif #endif
} }
@@ -1,68 +1,68 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "DX11_D3DBlob.h" #include "DX11_D3DBlob.h"
namespace DX11 namespace DX11
{ {
D3DBlob::D3DBlob(unsigned int blob_size, const u8* init_data) : ref(1), size(blob_size), blob(NULL) D3DBlob::D3DBlob(unsigned int blob_size, const u8* init_data) : ref(1), size(blob_size), blob(NULL)
{ {
data = new u8[blob_size]; data = new u8[blob_size];
if (init_data) memcpy(data, init_data, size); if (init_data) memcpy(data, init_data, size);
} }
D3DBlob::D3DBlob(ID3D10Blob* d3dblob) : ref(1) D3DBlob::D3DBlob(ID3D10Blob* d3dblob) : ref(1)
{ {
blob = d3dblob; blob = d3dblob;
data = (u8*)blob->GetBufferPointer(); data = (u8*)blob->GetBufferPointer();
size = blob->GetBufferSize(); size = blob->GetBufferSize();
d3dblob->AddRef(); d3dblob->AddRef();
} }
D3DBlob::~D3DBlob() D3DBlob::~D3DBlob()
{ {
if (blob) blob->Release(); if (blob) blob->Release();
else delete[] data; else delete[] data;
} }
void D3DBlob::AddRef() void D3DBlob::AddRef()
{ {
++ref; ++ref;
} }
unsigned int D3DBlob::Release() unsigned int D3DBlob::Release()
{ {
if (--ref == 0) if (--ref == 0)
{ {
delete this; delete this;
return 0; return 0;
} }
return ref; return ref;
} }
unsigned int D3DBlob::Size() unsigned int D3DBlob::Size()
{ {
return size; return size;
} }
u8* D3DBlob::Data() u8* D3DBlob::Data()
{ {
return data; return data;
} }
} }
@@ -1,52 +1,52 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#pragma once #pragma once
#include "Common.h" #include "Common.h"
#include <d3d11.h> #include <d3d11.h>
namespace DX11 namespace DX11
{ {
// use this class instead ID3D10Blob or ID3D11Blob whenever possible // use this class instead ID3D10Blob or ID3D11Blob whenever possible
class D3DBlob class D3DBlob
{ {
public: public:
// memory will be copied into an own buffer // memory will be copied into an own buffer
D3DBlob(unsigned int blob_size, const u8* init_data = NULL); D3DBlob(unsigned int blob_size, const u8* init_data = NULL);
// d3dblob will be AddRef'd // d3dblob will be AddRef'd
D3DBlob(ID3D10Blob* d3dblob); D3DBlob(ID3D10Blob* d3dblob);
void AddRef(); void AddRef();
unsigned int Release(); unsigned int Release();
unsigned int Size(); unsigned int Size();
u8* Data(); u8* Data();
private: private:
~D3DBlob(); ~D3DBlob();
unsigned int ref; unsigned int ref;
unsigned int size; unsigned int size;
u8* data; u8* data;
ID3D10Blob* blob; ID3D10Blob* blob;
}; };
} }
@@ -1,150 +1,150 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <d3dx11.h> #include <d3dx11.h>
#include <d3dcompiler.h> #include <d3dcompiler.h>
#include <string> #include <string>
#include "VideoConfig.h" #include "VideoConfig.h"
#include "DX11_D3DShader.h" #include "DX11_D3DShader.h"
namespace DX11 namespace DX11
{ {
namespace D3D namespace D3D
{ {
// bytecode->shader // bytecode->shader
ID3D11VertexShader* CreateVertexShaderFromByteCode(void* bytecode, unsigned int len) ID3D11VertexShader* CreateVertexShaderFromByteCode(void* bytecode, unsigned int len)
{ {
ID3D11VertexShader* v_shader; ID3D11VertexShader* v_shader;
HRESULT hr = D3D::device->CreateVertexShader(bytecode, len, NULL, &v_shader); HRESULT hr = D3D::device->CreateVertexShader(bytecode, len, NULL, &v_shader);
if (FAILED(hr)) if (FAILED(hr))
{ {
PanicAlert("CreateVertexShaderFromByteCode failed from %p (size %d) at %s %d\n", bytecode, len, __FILE__, __LINE__); PanicAlert("CreateVertexShaderFromByteCode failed from %p (size %d) at %s %d\n", bytecode, len, __FILE__, __LINE__);
v_shader = NULL; v_shader = NULL;
} }
return v_shader; return v_shader;
} }
// code->bytecode // code->bytecode
bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob) bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob)
{ {
ID3D10Blob* shaderBuffer = NULL; ID3D10Blob* shaderBuffer = NULL;
ID3D10Blob* errorBuffer = NULL; ID3D10Blob* errorBuffer = NULL;
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS; UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS;
#else #else
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_OPTIMIZATION_LEVEL3|D3D10_SHADER_SKIP_VALIDATION; UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_OPTIMIZATION_LEVEL3|D3D10_SHADER_SKIP_VALIDATION;
#endif #endif
HRESULT hr = PD3DX11CompileFromMemory(code, len, NULL, NULL, NULL, "main", D3D::VertexShaderVersionString(), HRESULT hr = PD3DX11CompileFromMemory(code, len, NULL, NULL, NULL, "main", D3D::VertexShaderVersionString(),
flags, 0, NULL, &shaderBuffer, &errorBuffer, NULL); flags, 0, NULL, &shaderBuffer, &errorBuffer, NULL);
if (FAILED(hr) || errorBuffer) if (FAILED(hr) || errorBuffer)
{ {
std::string msg = (char*)errorBuffer->GetBufferPointer(); std::string msg = (char*)errorBuffer->GetBufferPointer();
msg += "\n\n"; msg += "\n\n";
msg += code; msg += code;
MessageBoxA(0, msg.c_str(), "Error compiling pixel shader", MB_ICONERROR); MessageBoxA(0, msg.c_str(), "Error compiling pixel shader", MB_ICONERROR);
*blob = NULL; *blob = NULL;
errorBuffer->Release(); errorBuffer->Release();
} }
else else
{ {
*blob = new D3DBlob(shaderBuffer); *blob = new D3DBlob(shaderBuffer);
shaderBuffer->Release(); shaderBuffer->Release();
} }
return SUCCEEDED(hr); return SUCCEEDED(hr);
} }
// bytecode->shader // bytecode->shader
ID3D11PixelShader* CreatePixelShaderFromByteCode(void* bytecode, unsigned int len) ID3D11PixelShader* CreatePixelShaderFromByteCode(void* bytecode, unsigned int len)
{ {
ID3D11PixelShader* p_shader; ID3D11PixelShader* p_shader;
HRESULT hr = D3D::device->CreatePixelShader(bytecode, len, NULL, &p_shader); HRESULT hr = D3D::device->CreatePixelShader(bytecode, len, NULL, &p_shader);
if (FAILED(hr)) if (FAILED(hr))
{ {
PanicAlert("CreatePixelShaderFromByteCode failed at %s %d\n", __FILE__, __LINE__); PanicAlert("CreatePixelShaderFromByteCode failed at %s %d\n", __FILE__, __LINE__);
p_shader = NULL; p_shader = NULL;
} }
return p_shader; return p_shader;
} }
// code->bytecode // code->bytecode
bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob) bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob)
{ {
ID3D10Blob* shaderBuffer = NULL; ID3D10Blob* shaderBuffer = NULL;
ID3D10Blob* errorBuffer = NULL; ID3D10Blob* errorBuffer = NULL;
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
UINT flags = D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS; UINT flags = D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS;
#else #else
UINT flags = D3D10_SHADER_OPTIMIZATION_LEVEL3; UINT flags = D3D10_SHADER_OPTIMIZATION_LEVEL3;
#endif #endif
HRESULT hr = PD3DX11CompileFromMemory(code, len, NULL, NULL, NULL, "main", D3D::PixelShaderVersionString(), HRESULT hr = PD3DX11CompileFromMemory(code, len, NULL, NULL, NULL, "main", D3D::PixelShaderVersionString(),
flags, 0, NULL, &shaderBuffer, &errorBuffer, NULL); flags, 0, NULL, &shaderBuffer, &errorBuffer, NULL);
if (FAILED(hr) || errorBuffer) if (FAILED(hr) || errorBuffer)
{ {
std::string msg = (char*)errorBuffer->GetBufferPointer(); std::string msg = (char*)errorBuffer->GetBufferPointer();
msg += "\n\n"; msg += "\n\n";
msg += code; msg += code;
MessageBoxA(0, msg.c_str(), "Error compiling pixel shader", MB_ICONERROR); MessageBoxA(0, msg.c_str(), "Error compiling pixel shader", MB_ICONERROR);
*blob = NULL; *blob = NULL;
errorBuffer->Release(); errorBuffer->Release();
} }
else else
{ {
*blob = new D3DBlob(shaderBuffer); *blob = new D3DBlob(shaderBuffer);
shaderBuffer->Release(); shaderBuffer->Release();
} }
return SUCCEEDED(hr); return SUCCEEDED(hr);
} }
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len) ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len)
{ {
D3DBlob* blob = NULL; D3DBlob* blob = NULL;
if (CompileVertexShader(code, len, &blob)) if (CompileVertexShader(code, len, &blob))
{ {
ID3D11VertexShader* v_shader = CreateVertexShaderFromByteCode(blob); ID3D11VertexShader* v_shader = CreateVertexShaderFromByteCode(blob);
blob->Release(); blob->Release();
return v_shader; return v_shader;
} }
PanicAlert("Failed to compile and create vertex shader from %p (size %d) at %s %d\n", code, len, __FILE__, __LINE__); PanicAlert("Failed to compile and create vertex shader from %p (size %d) at %s %d\n", code, len, __FILE__, __LINE__);
return NULL; return NULL;
} }
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code, unsigned int len) ID3D11PixelShader* CompileAndCreatePixelShader(const char* code, unsigned int len)
{ {
D3DBlob* blob = NULL; D3DBlob* blob = NULL;
CompilePixelShader(code, len, &blob); CompilePixelShader(code, len, &blob);
if (blob) if (blob)
{ {
ID3D11PixelShader* p_shader = CreatePixelShaderFromByteCode(blob); ID3D11PixelShader* p_shader = CreatePixelShaderFromByteCode(blob);
blob->Release(); blob->Release();
return p_shader; return p_shader;
} }
PanicAlert("Failed to compile and create pixel shader, %s %d\n", __FILE__, __LINE__); PanicAlert("Failed to compile and create pixel shader, %s %d\n", __FILE__, __LINE__);
return NULL; return NULL;
} }
} // namespace } // namespace
} }
@@ -1,44 +1,44 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#pragma once #pragma once
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
namespace DX11 namespace DX11
{ {
namespace D3D namespace D3D
{ {
ID3D11VertexShader* CreateVertexShaderFromByteCode(void* bytecode, unsigned int len); ID3D11VertexShader* CreateVertexShaderFromByteCode(void* bytecode, unsigned int len);
ID3D11PixelShader* CreatePixelShaderFromByteCode(void* bytecode, unsigned int len); ID3D11PixelShader* CreatePixelShaderFromByteCode(void* bytecode, unsigned int len);
// The returned bytecode buffers should be Release()d. // The returned bytecode buffers should be Release()d.
bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob); bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob);
bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob); bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob);
// Utility functions // Utility functions
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len); ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len);
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code, unsigned int len); ID3D11PixelShader* CompileAndCreatePixelShader(const char* code, unsigned int len);
inline ID3D11VertexShader* CreateVertexShaderFromByteCode(D3DBlob* bytecode) { return CreateVertexShaderFromByteCode(bytecode->Data(), bytecode->Size()); } inline ID3D11VertexShader* CreateVertexShaderFromByteCode(D3DBlob* bytecode) { return CreateVertexShaderFromByteCode(bytecode->Data(), bytecode->Size()); }
inline ID3D11PixelShader* CreatePixelShaderFromByteCode(D3DBlob* bytecode) { return CreatePixelShaderFromByteCode(bytecode->Data(), bytecode->Size()); } inline ID3D11PixelShader* CreatePixelShaderFromByteCode(D3DBlob* bytecode) { return CreatePixelShaderFromByteCode(bytecode->Data(), bytecode->Size()); }
inline ID3D11VertexShader* CompileAndCreateVertexShader(D3DBlob* code) { return CompileAndCreateVertexShader((const char*)code->Data(), code->Size()); } inline ID3D11VertexShader* CompileAndCreateVertexShader(D3DBlob* code) { return CompileAndCreateVertexShader((const char*)code->Data(), code->Size()); }
inline ID3D11PixelShader* CompileAndCreatePixelShader(D3DBlob* code) { return CompileAndCreatePixelShader((const char*)code->Data(), code->Size()); } inline ID3D11PixelShader* CompileAndCreatePixelShader(D3DBlob* code) { return CompileAndCreatePixelShader((const char*)code->Data(), code->Size()); }
} }
} }
@@ -1,125 +1,125 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <d3dx11.h> #include <d3dx11.h>
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
#include "DX11_D3DTexture.h" #include "DX11_D3DTexture.h"
namespace DX11 namespace DX11
{ {
namespace D3D namespace D3D
{ {
void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage) void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage)
{ {
if (usage == D3D11_USAGE_DYNAMIC) if (usage == D3D11_USAGE_DYNAMIC)
{ {
D3D11_MAPPED_SUBRESOURCE map; D3D11_MAPPED_SUBRESOURCE map;
HRESULT hr = D3D::context->Map(pTexture, level, D3D11_MAP_WRITE_DISCARD, 0, &map); HRESULT hr = D3D::context->Map(pTexture, level, D3D11_MAP_WRITE_DISCARD, 0, &map);
CHECK(SUCCEEDED(hr), "ID3D11DeviceContext::Map failed! (%x)", hr); CHECK(SUCCEEDED(hr), "ID3D11DeviceContext::Map failed! (%x)", hr);
if (4 * pitch == map.RowPitch) if (4 * pitch == map.RowPitch)
{ {
memcpy(map.pData, buffer, map.RowPitch * height); memcpy(map.pData, buffer, map.RowPitch * height);
} }
else else
{ {
for (unsigned int y = 0; y < height; ++y) for (unsigned int y = 0; y < height; ++y)
memcpy((u8*)map.pData + y * map.RowPitch, (u32*)buffer + y * pitch, map.RowPitch); memcpy((u8*)map.pData + y * map.RowPitch, (u32*)buffer + y * pitch, map.RowPitch);
} }
D3D::context->Unmap(pTexture, level); D3D::context->Unmap(pTexture, level);
} }
else else
{ {
D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1); D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1);
D3D::context->UpdateSubresource(pTexture, level, &dest_region, buffer, 4*pitch, 4*pitch*height); D3D::context->UpdateSubresource(pTexture, level, &dest_region, buffer, 4*pitch, 4*pitch*height);
} }
} }
} // namespace } // namespace
D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels) D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels)
{ {
ID3D11Texture2D* pTexture = NULL; ID3D11Texture2D* pTexture = NULL;
HRESULT hr; HRESULT hr;
D3D11_CPU_ACCESS_FLAG cpuflags; D3D11_CPU_ACCESS_FLAG cpuflags;
if (usage == D3D11_USAGE_STAGING) if (usage == D3D11_USAGE_STAGING)
cpuflags = (D3D11_CPU_ACCESS_FLAG)((int)D3D11_CPU_ACCESS_WRITE|(int)D3D11_CPU_ACCESS_READ); cpuflags = (D3D11_CPU_ACCESS_FLAG)((int)D3D11_CPU_ACCESS_WRITE|(int)D3D11_CPU_ACCESS_READ);
else if (usage == D3D11_USAGE_DYNAMIC) else if (usage == D3D11_USAGE_DYNAMIC)
cpuflags = D3D11_CPU_ACCESS_WRITE; cpuflags = D3D11_CPU_ACCESS_WRITE;
else else
cpuflags = (D3D11_CPU_ACCESS_FLAG)0; cpuflags = (D3D11_CPU_ACCESS_FLAG)0;
D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(fmt, width, height, 1, levels, bind, usage, cpuflags); D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(fmt, width, height, 1, levels, bind, usage, cpuflags);
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &pTexture); hr = D3D::device->CreateTexture2D(&texdesc, NULL, &pTexture);
if (FAILED(hr)) if (FAILED(hr))
{ {
PanicAlert("Failed to create texture at %s, line %d: hr=%#x\n", __FILE__, __LINE__, hr); PanicAlert("Failed to create texture at %s, line %d: hr=%#x\n", __FILE__, __LINE__, hr);
return NULL; return NULL;
} }
D3DTexture2D* ret = new D3DTexture2D(pTexture, bind); D3DTexture2D* ret = new D3DTexture2D(pTexture, bind);
SAFE_RELEASE(pTexture); SAFE_RELEASE(pTexture);
return ret; return ret;
} }
void D3DTexture2D::AddRef() void D3DTexture2D::AddRef()
{ {
++ref; ++ref;
} }
UINT D3DTexture2D::Release() UINT D3DTexture2D::Release()
{ {
--ref; --ref;
if (ref == 0) if (ref == 0)
{ {
delete this; delete this;
return 0; return 0;
} }
return ref; return ref;
} }
D3DTexture2D::D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, D3DTexture2D::D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind,
DXGI_FORMAT srv_format, DXGI_FORMAT dsv_format, DXGI_FORMAT rtv_format) DXGI_FORMAT srv_format, DXGI_FORMAT dsv_format, DXGI_FORMAT rtv_format)
: ref(1), tex(texptr), srv(NULL), rtv(NULL), dsv(NULL) : ref(1), tex(texptr), srv(NULL), rtv(NULL), dsv(NULL)
{ {
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = CD3D11_SHADER_RESOURCE_VIEW_DESC(D3D11_SRV_DIMENSION_TEXTURE2D, srv_format); D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = CD3D11_SHADER_RESOURCE_VIEW_DESC(D3D11_SRV_DIMENSION_TEXTURE2D, srv_format);
D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D, dsv_format); D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D, dsv_format);
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = CD3D11_RENDER_TARGET_VIEW_DESC(D3D11_RTV_DIMENSION_TEXTURE2D, rtv_format); D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = CD3D11_RENDER_TARGET_VIEW_DESC(D3D11_RTV_DIMENSION_TEXTURE2D, rtv_format);
if (bind & D3D11_BIND_SHADER_RESOURCE) if (bind & D3D11_BIND_SHADER_RESOURCE)
D3D::device->CreateShaderResourceView(tex, &srv_desc, &srv); D3D::device->CreateShaderResourceView(tex, &srv_desc, &srv);
if (bind & D3D11_BIND_RENDER_TARGET) if (bind & D3D11_BIND_RENDER_TARGET)
D3D::device->CreateRenderTargetView(tex, &rtv_desc, &rtv); D3D::device->CreateRenderTargetView(tex, &rtv_desc, &rtv);
if (bind & D3D11_BIND_DEPTH_STENCIL) if (bind & D3D11_BIND_DEPTH_STENCIL)
D3D::device->CreateDepthStencilView(tex, &dsv_desc, &dsv); D3D::device->CreateDepthStencilView(tex, &dsv_desc, &dsv);
tex->AddRef(); tex->AddRef();
} }
D3DTexture2D::~D3DTexture2D() D3DTexture2D::~D3DTexture2D()
{ {
SAFE_RELEASE(srv); SAFE_RELEASE(srv);
SAFE_RELEASE(rtv); SAFE_RELEASE(rtv);
SAFE_RELEASE(dsv); SAFE_RELEASE(dsv);
SAFE_RELEASE(tex); SAFE_RELEASE(tex);
} }
} }
@@ -1,60 +1,60 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#pragma once #pragma once
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
namespace DX11 namespace DX11
{ {
namespace D3D namespace D3D
{ {
void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage); void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage);
} }
class D3DTexture2D class D3DTexture2D
{ {
public: public:
// there are two ways to create a D3DTexture2D object: // there are two ways to create a D3DTexture2D object:
// either create an ID3D11Texture2D object, pass it to the constructor and specify what views to create // either create an ID3D11Texture2D object, pass it to the constructor and specify what views to create
// or let the texture automatically be created by D3DTexture2D::Create // or let the texture automatically be created by D3DTexture2D::Create
D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN); D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN);
static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1); static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1);
// reference counting, use AddRef() when creating a new reference and Release() it when you don't need it anymore // reference counting, use AddRef() when creating a new reference and Release() it when you don't need it anymore
void AddRef(); void AddRef();
UINT Release(); UINT Release();
ID3D11Texture2D* &GetTex() { return tex; } ID3D11Texture2D* &GetTex() { return tex; }
ID3D11ShaderResourceView* &GetSRV() { return srv; } ID3D11ShaderResourceView* &GetSRV() { return srv; }
ID3D11RenderTargetView* &GetRTV() { return rtv; } ID3D11RenderTargetView* &GetRTV() { return rtv; }
ID3D11DepthStencilView* &GetDSV() { return dsv; } ID3D11DepthStencilView* &GetDSV() { return dsv; }
private: private:
~D3DTexture2D(); ~D3DTexture2D();
ID3D11Texture2D* tex; ID3D11Texture2D* tex;
ID3D11ShaderResourceView* srv; ID3D11ShaderResourceView* srv;
ID3D11RenderTargetView* rtv; ID3D11RenderTargetView* rtv;
ID3D11DepthStencilView* dsv; ID3D11DepthStencilView* dsv;
D3D11_BIND_FLAG bindflags; D3D11_BIND_FLAG bindflags;
UINT ref; UINT ref;
}; };
} }
File diff suppressed because it is too large Load Diff
@@ -1,91 +1,91 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#pragma once #pragma once
#include <math.h> #include <math.h>
#include <MathUtil.h> #include <MathUtil.h>
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
namespace DX11 namespace DX11
{ {
namespace D3D namespace D3D
{ {
// Font creation flags // Font creation flags
#define D3DFONT_BOLD 0x0001 #define D3DFONT_BOLD 0x0001
#define D3DFONT_ITALIC 0x0002 #define D3DFONT_ITALIC 0x0002
// Font rendering flags // Font rendering flags
#define D3DFONT_CENTERED 0x0001 #define D3DFONT_CENTERED 0x0001
class CD3DFont class CD3DFont
{ {
ID3D11ShaderResourceView* m_pTexture; ID3D11ShaderResourceView* m_pTexture;
ID3D11Buffer* m_pVB; ID3D11Buffer* m_pVB;
ID3D11InputLayout* m_InputLayout; ID3D11InputLayout* m_InputLayout;
ID3D11PixelShader* m_pshader; ID3D11PixelShader* m_pshader;
ID3D11VertexShader* m_vshader; ID3D11VertexShader* m_vshader;
ID3D11BlendState* m_blendstate; ID3D11BlendState* m_blendstate;
ID3D11RasterizerState* m_raststate; ID3D11RasterizerState* m_raststate;
const int m_dwTexWidth; const int m_dwTexWidth;
const int m_dwTexHeight; const int m_dwTexHeight;
unsigned int m_LineHeight; unsigned int m_LineHeight;
float m_fTexCoords[128-32][4]; float m_fTexCoords[128-32][4];
public: public:
CD3DFont(); CD3DFont();
// 2D text drawing function // 2D text drawing function
// Initializing and destroying device-dependent objects // Initializing and destroying device-dependent objects
int Init(); int Init();
int Shutdown(); int Shutdown();
int DrawTextScaled(float x, float y, int DrawTextScaled(float x, float y,
float size, float size,
float spacing, u32 dwColor, float spacing, u32 dwColor,
const char* strText, bool center=true); const char* strText, bool center=true);
}; };
extern CD3DFont font; extern CD3DFont font;
void InitUtils(); void InitUtils();
void ShutdownUtils(); void ShutdownUtils();
void SetPointCopySampler(); void SetPointCopySampler();
void SetLinearCopySampler(); void SetLinearCopySampler();
void drawShadedTexQuad(ID3D11ShaderResourceView* texture, void drawShadedTexQuad(ID3D11ShaderResourceView* texture,
const D3D11_RECT* rSource, const D3D11_RECT* rSource,
int SourceWidth, int SourceWidth,
int SourceHeight, int SourceHeight,
ID3D11PixelShader* PShader, ID3D11PixelShader* PShader,
ID3D11VertexShader* VShader, ID3D11VertexShader* VShader,
ID3D11InputLayout* layout); ID3D11InputLayout* layout);
void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture, void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
const MathUtil::Rectangle<float>* rSource, const MathUtil::Rectangle<float>* rSource,
int SourceWidth, int SourceWidth,
int SourceHeight, int SourceHeight,
const MathUtil::Rectangle<float>* rDest, const MathUtil::Rectangle<float>* rDest,
ID3D11PixelShader* PShader, ID3D11PixelShader* PShader,
ID3D11VertexShader* Vshader, ID3D11VertexShader* Vshader,
ID3D11InputLayout* layout); ID3D11InputLayout* layout);
void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout); void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout);
void SaveRenderStates(); void SaveRenderStates();
void RestoreRenderStates(); void RestoreRenderStates();
} }
} }
@@ -1,162 +1,162 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// VideoCommon // VideoCommon
#include "VideoConfig.h" #include "VideoConfig.h"
// DX11 // DX11
#include "DX11_Render.h" #include "DX11_Render.h"
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
#include "DX11_D3DTexture.h" #include "DX11_D3DTexture.h"
#include "DX11_D3DUtil.h" #include "DX11_D3DUtil.h"
#include "DX11_FramebufferManager.h" #include "DX11_FramebufferManager.h"
#include "DX11_PixelShaderCache.h" #include "DX11_PixelShaderCache.h"
#include "DX11_VertexShaderCache.h" #include "DX11_VertexShaderCache.h"
#include "../Main.h" #include "../Main.h"
namespace DX11 namespace DX11
{ {
XFBSource FramebufferManager::m_realXFBSource; // used in real XFB mode XFBSource FramebufferManager::m_realXFBSource; // used in real XFB mode
FramebufferManager::EFB FramebufferManager::m_efb; FramebufferManager::EFB FramebufferManager::m_efb;
D3DTexture2D* &FramebufferManager::GetEFBColorTexture() { return m_efb.color_tex; } D3DTexture2D* &FramebufferManager::GetEFBColorTexture() { return m_efb.color_tex; }
ID3D11Texture2D* &FramebufferManager::GetEFBColorStagingBuffer() { return m_efb.color_staging_buf; } ID3D11Texture2D* &FramebufferManager::GetEFBColorStagingBuffer() { return m_efb.color_staging_buf; }
D3DTexture2D* &FramebufferManager::GetEFBDepthTexture() { return m_efb.depth_tex; } D3DTexture2D* &FramebufferManager::GetEFBDepthTexture() { return m_efb.depth_tex; }
D3DTexture2D* &FramebufferManager::GetEFBDepthReadTexture() { return m_efb.depth_read_texture; } D3DTexture2D* &FramebufferManager::GetEFBDepthReadTexture() { return m_efb.depth_read_texture; }
ID3D11Texture2D* &FramebufferManager::GetEFBDepthStagingBuffer() { return m_efb.depth_staging_buf; } ID3D11Texture2D* &FramebufferManager::GetEFBDepthStagingBuffer() { return m_efb.depth_staging_buf; }
FramebufferManager::FramebufferManager() FramebufferManager::FramebufferManager()
{ {
m_efb.color_tex = NULL; m_efb.color_tex = NULL;
m_efb.color_staging_buf = NULL; m_efb.color_staging_buf = NULL;
m_efb.depth_tex = NULL; m_efb.depth_tex = NULL;
m_efb.depth_staging_buf = NULL; m_efb.depth_staging_buf = NULL;
m_efb.depth_read_texture = NULL; m_efb.depth_read_texture = NULL;
m_realXFBSource.tex = NULL; m_realXFBSource.tex = NULL;
unsigned int target_width = Renderer::GetFullTargetWidth(); unsigned int target_width = Renderer::GetFullTargetWidth();
unsigned int target_height = Renderer::GetFullTargetHeight(); unsigned int target_height = Renderer::GetFullTargetHeight();
ID3D11Texture2D* buf; ID3D11Texture2D* buf;
D3D11_TEXTURE2D_DESC texdesc; D3D11_TEXTURE2D_DESC texdesc;
HRESULT hr; HRESULT hr;
// create framebuffer color texture // create framebuffer color texture
m_efb.color_tex = D3DTexture2D::Create(target_width, target_height, m_efb.color_tex = D3DTexture2D::Create(target_width, target_height,
(D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE), (D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE),
D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM); D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM);
CHECK(m_efb.color_tex, "create EFB color texture (size: %dx%d)", target_width, target_height); CHECK(m_efb.color_tex, "create EFB color texture (size: %dx%d)", target_width, target_height);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetTex(), "EFB color texture"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetTex(), "EFB color texture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetRTV(), "EFB color texture render target view"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetRTV(), "EFB color texture render target view");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetSRV(), "EFB color texture shader resource view"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetSRV(), "EFB color texture shader resource view");
// create a staging texture for Renderer::AccessEFB // create a staging texture for Renderer::AccessEFB
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 1, 1, 0, texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 1, 1, 0,
D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_WRITE|D3D11_CPU_ACCESS_READ); D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_WRITE|D3D11_CPU_ACCESS_READ);
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.color_staging_buf); hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.color_staging_buf);
CHECK(SUCCEEDED(hr), "create EFB color staging buffer (hr=%#x)", hr); CHECK(SUCCEEDED(hr), "create EFB color staging buffer (hr=%#x)", hr);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_staging_buf, "EFB color staging texture (used for Renderer::AccessEFB)"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_staging_buf, "EFB color staging texture (used for Renderer::AccessEFB)");
// EFB depth buffer // EFB depth buffer
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width, texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width,
target_height, 1, 1, D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE); target_height, 1, 1, D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE);
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf); hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf);
CHECK(hr==S_OK, "create EFB depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); CHECK(hr==S_OK, "create EFB depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
m_efb.depth_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE), m_efb.depth_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE),
DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT); DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT);
SAFE_RELEASE(buf); SAFE_RELEASE(buf);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetTex(), "EFB depth texture"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetTex(), "EFB depth texture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetDSV(), "EFB depth texture depth stencil view"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetDSV(), "EFB depth texture depth stencil view");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetSRV(), "EFB depth texture shader resource view"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetSRV(), "EFB depth texture shader resource view");
// render target for depth buffer access in Renderer::AccessEFB // render target for depth buffer access in Renderer::AccessEFB
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 4, 4, 1, 1, D3D11_BIND_RENDER_TARGET); texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 4, 4, 1, 1, D3D11_BIND_RENDER_TARGET);
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf); hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf);
CHECK(hr==S_OK, "create EFB depth read texture (hr=%#x)", hr); CHECK(hr==S_OK, "create EFB depth read texture (hr=%#x)", hr);
m_efb.depth_read_texture = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET); m_efb.depth_read_texture = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
SAFE_RELEASE(buf); SAFE_RELEASE(buf);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_read_texture->GetTex(), "EFB depth read texture (used in Renderer::AccessEFB)"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_read_texture->GetTex(), "EFB depth read texture (used in Renderer::AccessEFB)");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_read_texture->GetRTV(), "EFB depth read texture render target view (used in Renderer::AccessEFB)"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_read_texture->GetRTV(), "EFB depth read texture render target view (used in Renderer::AccessEFB)");
// staging texture to which we copy the data from m_efb.depth_read_texture // staging texture to which we copy the data from m_efb.depth_read_texture
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 4, 4, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE); texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 4, 4, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE);
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.depth_staging_buf); hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.depth_staging_buf);
CHECK(hr==S_OK, "create EFB depth staging buffer (hr=%#x)", hr); CHECK(hr==S_OK, "create EFB depth staging buffer (hr=%#x)", hr);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_staging_buf, "EFB depth staging texture (used for Renderer::AccessEFB)"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_staging_buf, "EFB depth staging texture (used for Renderer::AccessEFB)");
} }
FramebufferManager::~FramebufferManager() FramebufferManager::~FramebufferManager()
{ {
SAFE_RELEASE(m_efb.color_tex); SAFE_RELEASE(m_efb.color_tex);
SAFE_RELEASE(m_efb.color_staging_buf); SAFE_RELEASE(m_efb.color_staging_buf);
SAFE_RELEASE(m_efb.depth_tex); SAFE_RELEASE(m_efb.depth_tex);
SAFE_RELEASE(m_efb.depth_staging_buf); SAFE_RELEASE(m_efb.depth_staging_buf);
SAFE_RELEASE(m_efb.depth_read_texture); SAFE_RELEASE(m_efb.depth_read_texture);
SAFE_RELEASE(m_realXFBSource.tex); SAFE_RELEASE(m_realXFBSource.tex);
} }
void XFBSource::CopyEFB(const TargetRectangle& efbSource) void XFBSource::CopyEFB(const TargetRectangle& efbSource)
{ {
// copy EFB data to XFB and restore render target again // copy EFB data to XFB and restore render target again
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)texWidth, (float)texHeight); D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)texWidth, (float)texHeight);
D3D::context->RSSetViewports(1, &vp); D3D::context->RSSetViewports(1, &vp);
D3D::context->OMSetRenderTargets(1, &tex->GetRTV(), NULL); D3D::context->OMSetRenderTargets(1, &tex->GetRTV(), NULL);
D3D::SetLinearCopySampler(); D3D::SetLinearCopySampler();
D3DTexture2D* const ctex = FramebufferManager::GetEFBColorTexture(); D3DTexture2D* const ctex = FramebufferManager::GetEFBColorTexture();
D3D::drawShadedTexQuad(ctex->GetSRV(), efbSource.AsRECT(), D3D::drawShadedTexQuad(ctex->GetSRV(), efbSource.AsRECT(),
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
PixelShaderCache::GetColorCopyProgram(), VertexShaderCache::GetSimpleVertexShader(), PixelShaderCache::GetColorCopyProgram(), VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout()); VertexShaderCache::GetSimpleInputLayout());
D3D::context->OMSetRenderTargets(1, &ctex->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); D3D::context->OMSetRenderTargets(1, &ctex->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
} }
XFBSource::~XFBSource() XFBSource::~XFBSource()
{ {
tex->Release(); tex->Release();
} }
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height) XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
{ {
XFBSource* const xfbs = new XFBSource; XFBSource* const xfbs = new XFBSource;
xfbs->tex = D3DTexture2D::Create(target_width, target_height, xfbs->tex = D3DTexture2D::Create(target_width, target_height,
(D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE), (D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE),
D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM); D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM);
return xfbs; return xfbs;
} }
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{ {
// TODO // TODO
PanicAlert("copyToRealXFB not implemented, yet\n"); PanicAlert("copyToRealXFB not implemented, yet\n");
} }
const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount) const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{ {
PanicAlert("getRealXFBSource not implemented, yet\n"); PanicAlert("getRealXFBSource not implemented, yet\n");
return NULL; return NULL;
} }
} }
@@ -1,108 +1,108 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _DX11_FBMANAGER_D3D_H_ #ifndef _DX11_FBMANAGER_D3D_H_
#define _DX11_FBMANAGER_D3D_H_ #define _DX11_FBMANAGER_D3D_H_
#include <list> #include <list>
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
#include "../FramebufferManager.h" #include "../FramebufferManager.h"
namespace DX11 namespace DX11
{ {
// On the GameCube, the game sends a request for the graphics processor to // On the GameCube, the game sends a request for the graphics processor to
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM // transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
// called the XFB (External Framebuffer). The size and location of the XFB is // called the XFB (External Framebuffer). The size and location of the XFB is
// decided at the time of the copy, and the format is always YUYV. The video // decided at the time of the copy, and the format is always YUYV. The video
// interface is given a pointer to the XFB, which will be decoded and // interface is given a pointer to the XFB, which will be decoded and
// displayed on the TV. // displayed on the TV.
// //
// There are two ways for Dolphin to emulate this: // There are two ways for Dolphin to emulate this:
// //
// Real XFB mode: // Real XFB mode:
// //
// Dolphin will behave like the GameCube and encode the EFB to // Dolphin will behave like the GameCube and encode the EFB to
// a portion of GameCube RAM. The emulated video interface will decode the data // a portion of GameCube RAM. The emulated video interface will decode the data
// for output to the screen. // for output to the screen.
// //
// Advantages: Behaves exactly like the GameCube. // Advantages: Behaves exactly like the GameCube.
// Disadvantages: Resolution will be limited. // Disadvantages: Resolution will be limited.
// //
// Virtual XFB mode: // Virtual XFB mode:
// //
// When a request is made to copy the EFB to an XFB, Dolphin // When a request is made to copy the EFB to an XFB, Dolphin
// will remember the RAM location and size of the XFB in a Virtual XFB list. // will remember the RAM location and size of the XFB in a Virtual XFB list.
// The video interface will look up the XFB in the list and use the enhanced // The video interface will look up the XFB in the list and use the enhanced
// data stored there, if available. // data stored there, if available.
// //
// Advantages: Enables high resolution graphics, better than real hardware. // Advantages: Enables high resolution graphics, better than real hardware.
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is // Disadvantages: If the GameCube CPU writes directly to the XFB (which is
// possible but uncommon), the Virtual XFB will not capture this information. // possible but uncommon), the Virtual XFB will not capture this information.
// There may be multiple XFBs in GameCube RAM. This is the maximum number to // There may be multiple XFBs in GameCube RAM. This is the maximum number to
// virtualize. // virtualize.
struct XFBSource : public XFBSourceBase struct XFBSource : public XFBSourceBase
{ {
XFBSource() : tex(NULL) {} XFBSource() : tex(NULL) {}
~XFBSource(); ~XFBSource();
void CopyEFB(const TargetRectangle& efbSource); void CopyEFB(const TargetRectangle& efbSource);
D3DTexture2D* tex; D3DTexture2D* tex;
}; };
class FramebufferManager : public ::FramebufferManagerBase class FramebufferManager : public ::FramebufferManagerBase
{ {
friend struct XFBSource; friend struct XFBSource;
public: public:
FramebufferManager(); FramebufferManager();
~FramebufferManager(); ~FramebufferManager();
static D3DTexture2D* &GetEFBColorTexture(); static D3DTexture2D* &GetEFBColorTexture();
static ID3D11Texture2D* &GetEFBColorStagingBuffer(); static ID3D11Texture2D* &GetEFBColorStagingBuffer();
static D3DTexture2D* &GetEFBDepthTexture(); static D3DTexture2D* &GetEFBDepthTexture();
static D3DTexture2D* &GetEFBDepthReadTexture(); static D3DTexture2D* &GetEFBDepthReadTexture();
static ID3D11Texture2D* &GetEFBDepthStagingBuffer(); static ID3D11Texture2D* &GetEFBDepthStagingBuffer();
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height); XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
private: private:
static void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc); static void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
static const XFBSource** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount); static const XFBSource** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
static XFBSource m_realXFBSource; // used in real XFB mode static XFBSource m_realXFBSource; // used in real XFB mode
static struct EFB static struct EFB
{ {
D3DTexture2D* color_tex; D3DTexture2D* color_tex;
ID3D11Texture2D* color_staging_buf; ID3D11Texture2D* color_staging_buf;
D3DTexture2D* depth_tex; D3DTexture2D* depth_tex;
ID3D11Texture2D* depth_staging_buf; ID3D11Texture2D* depth_staging_buf;
D3DTexture2D* depth_read_texture; D3DTexture2D* depth_read_texture;
} m_efb; } m_efb;
}; };
} }
#endif #endif
@@ -1,372 +1,372 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "VideoConfig.h" #include "VideoConfig.h"
#include "DX11_GfxState.h" #include "DX11_GfxState.h"
namespace DX11 namespace DX11
{ {
namespace D3D namespace D3D
{ {
EmuGfxState* gfxstate; EmuGfxState* gfxstate;
StateManager* stateman; StateManager* stateman;
EmuGfxState::EmuGfxState() : vertexshader(NULL), vsbytecode(NULL), pixelshader(NULL), psbytecode(NULL), apply_called(false) EmuGfxState::EmuGfxState() : vertexshader(NULL), vsbytecode(NULL), pixelshader(NULL), psbytecode(NULL), apply_called(false)
{ {
for (unsigned int k = 0;k < 8;k++) for (unsigned int k = 0;k < 8;k++)
{ {
float border[4] = {0.f, 0.f, 0.f, 0.f}; float border[4] = {0.f, 0.f, 0.f, 0.f};
shader_resources[k] = NULL; shader_resources[k] = NULL;
samplerdesc[k] = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, 0.f, 16, D3D11_COMPARISON_ALWAYS, border, -D3D11_FLOAT32_MAX, D3D11_FLOAT32_MAX); samplerdesc[k] = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, 0.f, 16, D3D11_COMPARISON_ALWAYS, border, -D3D11_FLOAT32_MAX, D3D11_FLOAT32_MAX);
if(g_ActiveConfig.iMaxAnisotropy > 1) samplerdesc[k].Filter = D3D11_FILTER_ANISOTROPIC; if(g_ActiveConfig.iMaxAnisotropy > 1) samplerdesc[k].Filter = D3D11_FILTER_ANISOTROPIC;
} }
memset(&blenddesc, 0, sizeof(blenddesc)); memset(&blenddesc, 0, sizeof(blenddesc));
blenddesc.AlphaToCoverageEnable = FALSE; blenddesc.AlphaToCoverageEnable = FALSE;
blenddesc.IndependentBlendEnable = FALSE; blenddesc.IndependentBlendEnable = FALSE;
blenddesc.RenderTarget[0].BlendEnable = FALSE; blenddesc.RenderTarget[0].BlendEnable = FALSE;
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
blenddesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; blenddesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
blenddesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO; blenddesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
blenddesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; blenddesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
memset(&depthdesc, 0, sizeof(depthdesc)); memset(&depthdesc, 0, sizeof(depthdesc));
depthdesc.DepthEnable = TRUE; depthdesc.DepthEnable = TRUE;
depthdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthdesc.DepthFunc = D3D11_COMPARISON_LESS; depthdesc.DepthFunc = D3D11_COMPARISON_LESS;
depthdesc.StencilEnable = FALSE; depthdesc.StencilEnable = FALSE;
depthdesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; depthdesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
depthdesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; depthdesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
// this probably must be changed once multisampling support gets added // this probably must be changed once multisampling support gets added
rastdesc = CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID, D3D11_CULL_NONE, false, 0, 0.f, 0, false, true, false, false); rastdesc = CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID, D3D11_CULL_NONE, false, 0, 0.f, 0, false, true, false, false);
pscbuf = NULL; pscbuf = NULL;
vscbuf = NULL; vscbuf = NULL;
vshaderchanged = false; vshaderchanged = false;
inp_layout = NULL; inp_layout = NULL;
num_inp_elems = 0; num_inp_elems = 0;
pscbufchanged = false; pscbufchanged = false;
vscbufchanged = false; vscbufchanged = false;
} }
EmuGfxState::~EmuGfxState() EmuGfxState::~EmuGfxState()
{ {
for (unsigned int k = 0;k < 8;k++) for (unsigned int k = 0;k < 8;k++)
SAFE_RELEASE(shader_resources[k]) SAFE_RELEASE(shader_resources[k])
SAFE_RELEASE(vsbytecode); SAFE_RELEASE(vsbytecode);
SAFE_RELEASE(psbytecode); SAFE_RELEASE(psbytecode);
SAFE_RELEASE(vertexshader); SAFE_RELEASE(vertexshader);
SAFE_RELEASE(pixelshader); SAFE_RELEASE(pixelshader);
SAFE_RELEASE(pscbuf); SAFE_RELEASE(pscbuf);
SAFE_RELEASE(vscbuf); SAFE_RELEASE(vscbuf);
SAFE_RELEASE(inp_layout); SAFE_RELEASE(inp_layout);
} }
// TODO: No need to store the whole bytecode, signature might be enough (?) // TODO: No need to store the whole bytecode, signature might be enough (?)
void EmuGfxState::SetVShader(ID3D11VertexShader* shader, D3DBlob* bcode) void EmuGfxState::SetVShader(ID3D11VertexShader* shader, D3DBlob* bcode)
{ {
// TODO: vshaderchanged actually just needs to be true if the signature changed // TODO: vshaderchanged actually just needs to be true if the signature changed
if (bcode && vsbytecode != bcode) vshaderchanged = true; if (bcode && vsbytecode != bcode) vshaderchanged = true;
SAFE_RELEASE(vsbytecode); SAFE_RELEASE(vsbytecode);
SAFE_RELEASE(vertexshader); SAFE_RELEASE(vertexshader);
if (shader && bcode) if (shader && bcode)
{ {
vertexshader = shader; vertexshader = shader;
shader->AddRef(); shader->AddRef();
vsbytecode = bcode; vsbytecode = bcode;
bcode->AddRef(); bcode->AddRef();
} }
else if (shader || bcode) else if (shader || bcode)
{ {
PanicAlert("Invalid parameters!\n"); PanicAlert("Invalid parameters!\n");
} }
} }
void EmuGfxState::SetPShader(ID3D11PixelShader* shader) void EmuGfxState::SetPShader(ID3D11PixelShader* shader)
{ {
if (pixelshader) pixelshader->Release(); if (pixelshader) pixelshader->Release();
pixelshader = shader; pixelshader = shader;
if (shader) shader->AddRef(); if (shader) shader->AddRef();
} }
void EmuGfxState::SetInputElements(const D3D11_INPUT_ELEMENT_DESC* elems, UINT num) void EmuGfxState::SetInputElements(const D3D11_INPUT_ELEMENT_DESC* elems, UINT num)
{ {
num_inp_elems = num; num_inp_elems = num;
memcpy(inp_elems, elems, num*sizeof(D3D11_INPUT_ELEMENT_DESC)); memcpy(inp_elems, elems, num*sizeof(D3D11_INPUT_ELEMENT_DESC));
} }
void EmuGfxState::SetShaderResource(unsigned int stage, ID3D11ShaderResourceView* srv) void EmuGfxState::SetShaderResource(unsigned int stage, ID3D11ShaderResourceView* srv)
{ {
if (shader_resources[stage]) if (shader_resources[stage])
shader_resources[stage]->Release(); shader_resources[stage]->Release();
shader_resources[stage] = srv; shader_resources[stage] = srv;
if (srv) if (srv)
srv->AddRef(); srv->AddRef();
} }
void EmuGfxState::ApplyState() void EmuGfxState::ApplyState()
{ {
HRESULT hr; HRESULT hr;
// input layout (only needs to be updated if the vertex shader signature changed) // input layout (only needs to be updated if the vertex shader signature changed)
if (vshaderchanged) if (vshaderchanged)
{ {
SAFE_RELEASE(inp_layout); SAFE_RELEASE(inp_layout);
hr = D3D::device->CreateInputLayout(inp_elems, num_inp_elems, vsbytecode->Data(), vsbytecode->Size(), &inp_layout); hr = D3D::device->CreateInputLayout(inp_elems, num_inp_elems, vsbytecode->Data(), vsbytecode->Size(), &inp_layout);
if (FAILED(hr)) PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__); if (FAILED(hr)) PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__);
SetDebugObjectName((ID3D11DeviceChild*)inp_layout, "an input layout of EmuGfxState"); SetDebugObjectName((ID3D11DeviceChild*)inp_layout, "an input layout of EmuGfxState");
vshaderchanged = false; vshaderchanged = false;
} }
D3D::context->IASetInputLayout(inp_layout); D3D::context->IASetInputLayout(inp_layout);
// vertex shader // vertex shader
// TODO: divide the global variables of the generated shaders into about 5 constant buffers // TODO: divide the global variables of the generated shaders into about 5 constant buffers
// TODO: improve interaction between EmuGfxState and global state management, so that we don't need to set the constant buffers every time // TODO: improve interaction between EmuGfxState and global state management, so that we don't need to set the constant buffers every time
if (!vscbuf) if (!vscbuf)
{ {
unsigned int size = ((sizeof(vsconstants))&(~0xf))+0x10; // must be a multiple of 16 unsigned int size = ((sizeof(vsconstants))&(~0xf))+0x10; // must be a multiple of 16
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
hr = device->CreateBuffer(&cbdesc, NULL, &vscbuf); hr = device->CreateBuffer(&cbdesc, NULL, &vscbuf);
CHECK(hr==S_OK, "Create vertex shader constant buffer (size=%u)", size); CHECK(hr==S_OK, "Create vertex shader constant buffer (size=%u)", size);
SetDebugObjectName((ID3D11DeviceChild*)vscbuf, "a vertex shader constant buffer of EmuGfxState"); SetDebugObjectName((ID3D11DeviceChild*)vscbuf, "a vertex shader constant buffer of EmuGfxState");
} }
if (vscbufchanged) if (vscbufchanged)
{ {
D3D11_MAPPED_SUBRESOURCE map; D3D11_MAPPED_SUBRESOURCE map;
context->Map(vscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); context->Map(vscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, vsconstants, sizeof(vsconstants)); memcpy(map.pData, vsconstants, sizeof(vsconstants));
context->Unmap(vscbuf, 0); context->Unmap(vscbuf, 0);
} }
D3D::context->VSSetConstantBuffers(0, 1, &vscbuf); D3D::context->VSSetConstantBuffers(0, 1, &vscbuf);
// pixel shader // pixel shader
if (!pscbuf) if (!pscbuf)
{ {
unsigned int size = ((sizeof(psconstants))&(~0xf))+0x10; // must be a multiple of 16 unsigned int size = ((sizeof(psconstants))&(~0xf))+0x10; // must be a multiple of 16
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
device->CreateBuffer(&cbdesc, NULL, &pscbuf); device->CreateBuffer(&cbdesc, NULL, &pscbuf);
CHECK(hr==S_OK, "Create pixel shader constant buffer (size=%u)", size); CHECK(hr==S_OK, "Create pixel shader constant buffer (size=%u)", size);
SetDebugObjectName((ID3D11DeviceChild*)pscbuf, "a pixel shader constant buffer of EmuGfxState"); SetDebugObjectName((ID3D11DeviceChild*)pscbuf, "a pixel shader constant buffer of EmuGfxState");
} }
if (pscbufchanged) if (pscbufchanged)
{ {
D3D11_MAPPED_SUBRESOURCE map; D3D11_MAPPED_SUBRESOURCE map;
context->Map(pscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); context->Map(pscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, psconstants, sizeof(psconstants)); memcpy(map.pData, psconstants, sizeof(psconstants));
context->Unmap(pscbuf, 0); context->Unmap(pscbuf, 0);
pscbufchanged = false; pscbufchanged = false;
} }
D3D::context->PSSetConstantBuffers(0, 1, &pscbuf); D3D::context->PSSetConstantBuffers(0, 1, &pscbuf);
ID3D11SamplerState* samplerstate[8]; ID3D11SamplerState* samplerstate[8];
for (unsigned int stage = 0; stage < 8; stage++) for (unsigned int stage = 0; stage < 8; stage++)
{ {
if (shader_resources[stage]) if (shader_resources[stage])
{ {
if(g_ActiveConfig.iMaxAnisotropy > 1) samplerdesc[stage].Filter = D3D11_FILTER_ANISOTROPIC; if(g_ActiveConfig.iMaxAnisotropy > 1) samplerdesc[stage].Filter = D3D11_FILTER_ANISOTROPIC;
hr = D3D::device->CreateSamplerState(&samplerdesc[stage], &samplerstate[stage]); hr = D3D::device->CreateSamplerState(&samplerdesc[stage], &samplerstate[stage]);
if (FAILED(hr)) PanicAlert("Fail %s %d, stage=%d\n", __FILE__, __LINE__, stage); if (FAILED(hr)) PanicAlert("Fail %s %d, stage=%d\n", __FILE__, __LINE__, stage);
else SetDebugObjectName((ID3D11DeviceChild*)samplerstate[stage], "a sampler state of EmuGfxState"); else SetDebugObjectName((ID3D11DeviceChild*)samplerstate[stage], "a sampler state of EmuGfxState");
} }
else samplerstate[stage] = NULL; else samplerstate[stage] = NULL;
} }
D3D::context->PSSetSamplers(0, 8, samplerstate); D3D::context->PSSetSamplers(0, 8, samplerstate);
for (unsigned int stage = 0; stage < 8; stage++) for (unsigned int stage = 0; stage < 8; stage++)
SAFE_RELEASE(samplerstate[stage]); SAFE_RELEASE(samplerstate[stage]);
ID3D11BlendState* blstate; ID3D11BlendState* blstate;
hr = device->CreateBlendState(&blenddesc, &blstate); hr = device->CreateBlendState(&blenddesc, &blstate);
if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__); if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
stateman->PushBlendState(blstate); stateman->PushBlendState(blstate);
SetDebugObjectName((ID3D11DeviceChild*)blstate, "a blend state of EmuGfxState"); SetDebugObjectName((ID3D11DeviceChild*)blstate, "a blend state of EmuGfxState");
SAFE_RELEASE(blstate); SAFE_RELEASE(blstate);
rastdesc.FillMode = (g_ActiveConfig.bWireFrame) ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID; rastdesc.FillMode = (g_ActiveConfig.bWireFrame) ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID;
ID3D11RasterizerState* raststate; ID3D11RasterizerState* raststate;
hr = device->CreateRasterizerState(&rastdesc, &raststate); hr = device->CreateRasterizerState(&rastdesc, &raststate);
if (FAILED(hr)) PanicAlert("Failed to create rasterizer state at %s %d\n", __FILE__, __LINE__); if (FAILED(hr)) PanicAlert("Failed to create rasterizer state at %s %d\n", __FILE__, __LINE__);
SetDebugObjectName((ID3D11DeviceChild*)raststate, "a rasterizer state of EmuGfxState"); SetDebugObjectName((ID3D11DeviceChild*)raststate, "a rasterizer state of EmuGfxState");
stateman->PushRasterizerState(raststate); stateman->PushRasterizerState(raststate);
SAFE_RELEASE(raststate); SAFE_RELEASE(raststate);
ID3D11DepthStencilState* depth_state; ID3D11DepthStencilState* depth_state;
hr = device->CreateDepthStencilState(&depthdesc, &depth_state); hr = device->CreateDepthStencilState(&depthdesc, &depth_state);
if (SUCCEEDED(hr)) SetDebugObjectName((ID3D11DeviceChild*)depth_state, "a depth-stencil state of EmuGfxState"); if (SUCCEEDED(hr)) SetDebugObjectName((ID3D11DeviceChild*)depth_state, "a depth-stencil state of EmuGfxState");
else PanicAlert("Failed to create depth state at %s %d\n", __FILE__, __LINE__); else PanicAlert("Failed to create depth state at %s %d\n", __FILE__, __LINE__);
D3D::stateman->PushDepthState(depth_state); D3D::stateman->PushDepthState(depth_state);
SAFE_RELEASE(depth_state); SAFE_RELEASE(depth_state);
context->PSSetShader(pixelshader, NULL, 0); context->PSSetShader(pixelshader, NULL, 0);
context->VSSetShader(vertexshader, NULL, 0); context->VSSetShader(vertexshader, NULL, 0);
context->PSSetShaderResources(0, 8, shader_resources); context->PSSetShaderResources(0, 8, shader_resources);
stateman->Apply(); stateman->Apply();
apply_called = true; apply_called = true;
} }
void EmuGfxState::AlphaPass() void EmuGfxState::AlphaPass()
{ {
if (!apply_called) ERROR_LOG(VIDEO, "EmuGfxState::AlphaPass called without having called ApplyState before!") if (!apply_called) ERROR_LOG(VIDEO, "EmuGfxState::AlphaPass called without having called ApplyState before!")
else stateman->PopBlendState(); else stateman->PopBlendState();
// pixel shader for alpha pass is different, so update it // pixel shader for alpha pass is different, so update it
context->PSSetShader(pixelshader, NULL, 0); context->PSSetShader(pixelshader, NULL, 0);
ID3D11BlendState* blstate; ID3D11BlendState* blstate;
D3D11_BLEND_DESC desc = blenddesc; D3D11_BLEND_DESC desc = blenddesc;
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALPHA; desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALPHA;
desc.RenderTarget[0].BlendEnable = FALSE; desc.RenderTarget[0].BlendEnable = FALSE;
HRESULT hr = device->CreateBlendState(&desc, &blstate); HRESULT hr = device->CreateBlendState(&desc, &blstate);
if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__); if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
SetDebugObjectName((ID3D11DeviceChild*)blstate, "a blend state of EmuGfxState (created during alpha pass)"); SetDebugObjectName((ID3D11DeviceChild*)blstate, "a blend state of EmuGfxState (created during alpha pass)");
stateman->PushBlendState(blstate); stateman->PushBlendState(blstate);
blstate->Release(); blstate->Release();
stateman->Apply(); stateman->Apply();
} }
void EmuGfxState::Reset() void EmuGfxState::Reset()
{ {
for (unsigned int k = 0;k < 8;k++) for (unsigned int k = 0;k < 8;k++)
SAFE_RELEASE(shader_resources[k]); SAFE_RELEASE(shader_resources[k]);
context->PSSetShaderResources(0, 8, shader_resources); // unbind all textures context->PSSetShaderResources(0, 8, shader_resources); // unbind all textures
if (apply_called) if (apply_called)
{ {
stateman->PopBlendState(); stateman->PopBlendState();
stateman->PopDepthState(); stateman->PopDepthState();
stateman->PopRasterizerState(); stateman->PopRasterizerState();
apply_called = false; apply_called = false;
} }
} }
void EmuGfxState::SetAlphaBlendEnable(bool enable) void EmuGfxState::SetAlphaBlendEnable(bool enable)
{ {
blenddesc.RenderTarget[0].BlendEnable = enable; blenddesc.RenderTarget[0].BlendEnable = enable;
} }
void EmuGfxState::SetRenderTargetWriteMask(UINT8 mask) void EmuGfxState::SetRenderTargetWriteMask(UINT8 mask)
{ {
blenddesc.RenderTarget[0].RenderTargetWriteMask = mask; blenddesc.RenderTarget[0].RenderTargetWriteMask = mask;
} }
void EmuGfxState::SetSrcBlend(D3D11_BLEND val) void EmuGfxState::SetSrcBlend(D3D11_BLEND val)
{ {
// TODO: Check whether e.g. the dest color check is needed here // TODO: Check whether e.g. the dest color check is needed here
blenddesc.RenderTarget[0].SrcBlend = val; blenddesc.RenderTarget[0].SrcBlend = val;
if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA; else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA;
else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA; else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
else blenddesc.RenderTarget[0].SrcBlendAlpha = val; else blenddesc.RenderTarget[0].SrcBlendAlpha = val;
} }
void EmuGfxState::SetDestBlend(D3D11_BLEND val) void EmuGfxState::SetDestBlend(D3D11_BLEND val)
{ {
// TODO: Check whether e.g. the source color check is needed here // TODO: Check whether e.g. the source color check is needed here
blenddesc.RenderTarget[0].DestBlend = val; blenddesc.RenderTarget[0].DestBlend = val;
if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_SRC_ALPHA; if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_SRC_ALPHA;
else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA; else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA;
else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA; else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
else blenddesc.RenderTarget[0].DestBlendAlpha = val; else blenddesc.RenderTarget[0].DestBlendAlpha = val;
} }
void EmuGfxState::SetBlendOp(D3D11_BLEND_OP val) void EmuGfxState::SetBlendOp(D3D11_BLEND_OP val)
{ {
blenddesc.RenderTarget[0].BlendOp = val; blenddesc.RenderTarget[0].BlendOp = val;
blenddesc.RenderTarget[0].BlendOpAlpha = val; blenddesc.RenderTarget[0].BlendOpAlpha = val;
} }
void EmuGfxState::SetSamplerFilter(DWORD stage, D3D11_FILTER filter) void EmuGfxState::SetSamplerFilter(DWORD stage, D3D11_FILTER filter)
{ {
samplerdesc[stage].Filter = filter; samplerdesc[stage].Filter = filter;
} }
template<typename T> AutoState<T>::AutoState(const T* object) : state(object) template<typename T> AutoState<T>::AutoState(const T* object) : state(object)
{ {
((IUnknown*)state)->AddRef(); ((IUnknown*)state)->AddRef();
} }
template<typename T> AutoState<T>::AutoState(const AutoState<T> &source) template<typename T> AutoState<T>::AutoState(const AutoState<T> &source)
{ {
state = source.GetPtr(); state = source.GetPtr();
((T*)state)->AddRef(); ((T*)state)->AddRef();
} }
template<typename T> AutoState<T>::~AutoState() template<typename T> AutoState<T>::~AutoState()
{ {
if(state) ((T*)state)->Release(); if(state) ((T*)state)->Release();
state = NULL; state = NULL;
} }
StateManager::StateManager() : cur_blendstate(NULL), cur_depthstate(NULL), cur_raststate(NULL) {} StateManager::StateManager() : cur_blendstate(NULL), cur_depthstate(NULL), cur_raststate(NULL) {}
void StateManager::PushBlendState(const ID3D11BlendState* state) { blendstates.push(AutoBlendState(state)); } void StateManager::PushBlendState(const ID3D11BlendState* state) { blendstates.push(AutoBlendState(state)); }
void StateManager::PushDepthState(const ID3D11DepthStencilState* state) { depthstates.push(AutoDepthStencilState(state)); } void StateManager::PushDepthState(const ID3D11DepthStencilState* state) { depthstates.push(AutoDepthStencilState(state)); }
void StateManager::PushRasterizerState(const ID3D11RasterizerState* state) { raststates.push(AutoRasterizerState(state)); } void StateManager::PushRasterizerState(const ID3D11RasterizerState* state) { raststates.push(AutoRasterizerState(state)); }
void StateManager::PopBlendState() { blendstates.pop(); } void StateManager::PopBlendState() { blendstates.pop(); }
void StateManager::PopDepthState() { depthstates.pop(); } void StateManager::PopDepthState() { depthstates.pop(); }
void StateManager::PopRasterizerState() { raststates.pop(); } void StateManager::PopRasterizerState() { raststates.pop(); }
void StateManager::Apply() void StateManager::Apply()
{ {
if (!blendstates.empty()) if (!blendstates.empty())
{ {
if (cur_blendstate != blendstates.top().GetPtr()) if (cur_blendstate != blendstates.top().GetPtr())
{ {
cur_blendstate = (ID3D11BlendState*)blendstates.top().GetPtr(); cur_blendstate = (ID3D11BlendState*)blendstates.top().GetPtr();
D3D::context->OMSetBlendState(cur_blendstate, NULL, 0xFFFFFFFF); D3D::context->OMSetBlendState(cur_blendstate, NULL, 0xFFFFFFFF);
} }
} }
else ERROR_LOG(VIDEO, "Tried to apply without blend state!"); else ERROR_LOG(VIDEO, "Tried to apply without blend state!");
if (!depthstates.empty()) if (!depthstates.empty())
{ {
if (cur_depthstate != depthstates.top().GetPtr()) if (cur_depthstate != depthstates.top().GetPtr())
{ {
cur_depthstate = (ID3D11DepthStencilState*)depthstates.top().GetPtr(); cur_depthstate = (ID3D11DepthStencilState*)depthstates.top().GetPtr();
D3D::context->OMSetDepthStencilState(cur_depthstate, 0); D3D::context->OMSetDepthStencilState(cur_depthstate, 0);
} }
} }
else ERROR_LOG(VIDEO, "Tried to apply without depth state!"); else ERROR_LOG(VIDEO, "Tried to apply without depth state!");
if (!raststates.empty()) if (!raststates.empty())
{ {
if (cur_raststate != raststates.top().GetPtr()) if (cur_raststate != raststates.top().GetPtr())
{ {
cur_raststate = (ID3D11RasterizerState*)raststates.top().GetPtr(); cur_raststate = (ID3D11RasterizerState*)raststates.top().GetPtr();
D3D::context->RSSetState(cur_raststate); D3D::context->RSSetState(cur_raststate);
} }
} }
else ERROR_LOG(VIDEO, "Tried to apply without rasterizer state!"); else ERROR_LOG(VIDEO, "Tried to apply without rasterizer state!");
} }
} // namespace } // namespace
} }
@@ -1,142 +1,142 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#pragma once #pragma once
#include <stack> #include <stack>
// VideoCommon // VideoCommon
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
#include "PixelShaderGen.h" #include "PixelShaderGen.h"
// DX11 // DX11
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
#include "DX11_D3DBlob.h" #include "DX11_D3DBlob.h"
namespace DX11 namespace DX11
{ {
namespace D3D namespace D3D
{ {
// stores the pipeline state to use when calling VertexManager::Flush() // stores the pipeline state to use when calling VertexManager::Flush()
class EmuGfxState class EmuGfxState
{ {
public: public:
EmuGfxState(); EmuGfxState();
~EmuGfxState(); ~EmuGfxState();
void SetVShader(ID3D11VertexShader* shader, D3DBlob* bcode); void SetVShader(ID3D11VertexShader* shader, D3DBlob* bcode);
void SetPShader(ID3D11PixelShader* shader); void SetPShader(ID3D11PixelShader* shader);
void SetInputElements(const D3D11_INPUT_ELEMENT_DESC* elems, UINT num); void SetInputElements(const D3D11_INPUT_ELEMENT_DESC* elems, UINT num);
void SetShaderResource(unsigned int stage, ID3D11ShaderResourceView* srv); void SetShaderResource(unsigned int stage, ID3D11ShaderResourceView* srv);
void ApplyState(); // apply current state void ApplyState(); // apply current state
void AlphaPass(); // only modify the current state to enable the alpha pass void AlphaPass(); // only modify the current state to enable the alpha pass
void Reset(); void Reset();
// blend state // blend state
void SetAlphaBlendEnable(bool enable); void SetAlphaBlendEnable(bool enable);
void SetRenderTargetWriteMask(UINT8 mask); void SetRenderTargetWriteMask(UINT8 mask);
void SetSrcBlend(D3D11_BLEND val); void SetSrcBlend(D3D11_BLEND val);
void SetDestBlend(D3D11_BLEND val); void SetDestBlend(D3D11_BLEND val);
void SetBlendOp(D3D11_BLEND_OP val); void SetBlendOp(D3D11_BLEND_OP val);
// sampler states // sampler states
void SetSamplerFilter(DWORD stage, D3D11_FILTER filter); void SetSamplerFilter(DWORD stage, D3D11_FILTER filter);
// TODO: add methods for changing the other states instead of modifying them directly // TODO: add methods for changing the other states instead of modifying them directly
D3D11_SAMPLER_DESC samplerdesc[8]; D3D11_SAMPLER_DESC samplerdesc[8];
D3D11_RASTERIZER_DESC rastdesc; D3D11_RASTERIZER_DESC rastdesc;
D3D11_DEPTH_STENCIL_DESC depthdesc; D3D11_DEPTH_STENCIL_DESC depthdesc;
float psconstants[C_PENVCONST_END*4]; float psconstants[C_PENVCONST_END*4];
float vsconstants[C_VENVCONST_END*4]; float vsconstants[C_VENVCONST_END*4];
bool vscbufchanged; bool vscbufchanged;
bool pscbufchanged; bool pscbufchanged;
private: private:
ID3D11VertexShader* vertexshader; ID3D11VertexShader* vertexshader;
D3DBlob* vsbytecode; D3DBlob* vsbytecode;
ID3D11PixelShader* pixelshader; ID3D11PixelShader* pixelshader;
D3DBlob* psbytecode; D3DBlob* psbytecode;
bool vshaderchanged; bool vshaderchanged;
ID3D11Buffer* vscbuf; ID3D11Buffer* vscbuf;
ID3D11Buffer* pscbuf; ID3D11Buffer* pscbuf;
ID3D11InputLayout* inp_layout; ID3D11InputLayout* inp_layout;
D3D11_INPUT_ELEMENT_DESC inp_elems[32]; D3D11_INPUT_ELEMENT_DESC inp_elems[32];
int num_inp_elems; int num_inp_elems;
ID3D11ShaderResourceView* shader_resources[8]; ID3D11ShaderResourceView* shader_resources[8];
D3D11_BLEND_DESC blenddesc; D3D11_BLEND_DESC blenddesc;
bool apply_called; bool apply_called;
}; };
template<typename T> class AutoState template<typename T> class AutoState
{ {
public: public:
AutoState(const T* object); AutoState(const T* object);
AutoState(const AutoState<T> &source); AutoState(const AutoState<T> &source);
~AutoState(); ~AutoState();
const inline T* GetPtr() const { return state; } const inline T* GetPtr() const { return state; }
private: private:
const T* state; const T* state;
}; };
typedef AutoState<ID3D11BlendState> AutoBlendState; typedef AutoState<ID3D11BlendState> AutoBlendState;
typedef AutoState<ID3D11DepthStencilState> AutoDepthStencilState; typedef AutoState<ID3D11DepthStencilState> AutoDepthStencilState;
typedef AutoState<ID3D11RasterizerState> AutoRasterizerState; typedef AutoState<ID3D11RasterizerState> AutoRasterizerState;
class StateManager class StateManager
{ {
public: public:
StateManager(); StateManager();
// call any of these to change the affected states // call any of these to change the affected states
void PushBlendState(const ID3D11BlendState* state); void PushBlendState(const ID3D11BlendState* state);
void PushDepthState(const ID3D11DepthStencilState* state); void PushDepthState(const ID3D11DepthStencilState* state);
void PushRasterizerState(const ID3D11RasterizerState* state); void PushRasterizerState(const ID3D11RasterizerState* state);
// call these after drawing // call these after drawing
void PopBlendState(); void PopBlendState();
void PopDepthState(); void PopDepthState();
void PopRasterizerState(); void PopRasterizerState();
// call this before any drawing operation if states could have changed meanwhile // call this before any drawing operation if states could have changed meanwhile
void Apply(); void Apply();
private: private:
std::stack<AutoBlendState> blendstates; std::stack<AutoBlendState> blendstates;
std::stack<AutoDepthStencilState> depthstates; std::stack<AutoDepthStencilState> depthstates;
std::stack<AutoRasterizerState> raststates; std::stack<AutoRasterizerState> raststates;
ID3D11BlendState* cur_blendstate; ID3D11BlendState* cur_blendstate;
ID3D11DepthStencilState* cur_depthstate; ID3D11DepthStencilState* cur_depthstate;
ID3D11RasterizerState* cur_raststate; ID3D11RasterizerState* cur_raststate;
}; };
extern EmuGfxState* gfxstate; extern EmuGfxState* gfxstate;
extern StateManager* stateman; extern StateManager* stateman;
} // namespace } // namespace
} }
@@ -1,150 +1,150 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Common // Common
#include "MemoryUtil.h" #include "MemoryUtil.h"
#include "x64Emitter.h" #include "x64Emitter.h"
#include "ABI.h" #include "ABI.h"
// VideoCommon // VideoCommon
#include "Profiler.h" #include "Profiler.h"
#include "CPMemory.h" #include "CPMemory.h"
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
#include "NativeVertexFormat.h" #include "NativeVertexFormat.h"
// DX11 // DX11
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
#include "DX11_VertexShaderCache.h" #include "DX11_VertexShaderCache.h"
#include "DX11_VertexManager.h" #include "DX11_VertexManager.h"
namespace DX11 namespace DX11
{ {
class D3DVertexFormat : public NativeVertexFormat class D3DVertexFormat : public NativeVertexFormat
{ {
D3D11_INPUT_ELEMENT_DESC m_elems[32]; D3D11_INPUT_ELEMENT_DESC m_elems[32];
UINT m_num_elems; UINT m_num_elems;
public: public:
D3DVertexFormat() : m_num_elems(0) {} D3DVertexFormat() : m_num_elems(0) {}
void Initialize(const PortableVertexDeclaration &_vtx_decl); void Initialize(const PortableVertexDeclaration &_vtx_decl);
void SetupVertexPointers() const; void SetupVertexPointers() const;
}; };
NativeVertexFormat* VertexManager::CreateNativeVertexFormat() NativeVertexFormat* VertexManager::CreateNativeVertexFormat()
{ {
return new D3DVertexFormat; return new D3DVertexFormat;
} }
DXGI_FORMAT VarToD3D(VarType t, int size) DXGI_FORMAT VarToD3D(VarType t, int size)
{ {
DXGI_FORMAT retval = DXGI_FORMAT_UNKNOWN; DXGI_FORMAT retval = DXGI_FORMAT_UNKNOWN;
static const DXGI_FORMAT lookup1[5] = { static const DXGI_FORMAT lookup1[5] = {
DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R32_FLOAT DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R32_FLOAT
}; };
static const DXGI_FORMAT lookup2[5] = { static const DXGI_FORMAT lookup2[5] = {
DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R32G32_FLOAT DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R32G32_FLOAT
}; };
static const DXGI_FORMAT lookup3[5] = { static const DXGI_FORMAT lookup3[5] = {
DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32_FLOAT DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32_FLOAT
}; };
static const DXGI_FORMAT lookup4[5] = { static const DXGI_FORMAT lookup4[5] = {
DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R32G32B32A32_FLOAT DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R32G32B32A32_FLOAT
}; };
switch (size) switch (size)
{ {
case 1: retval = lookup1[t]; break; case 1: retval = lookup1[t]; break;
case 2: retval = lookup2[t]; break; case 2: retval = lookup2[t]; break;
case 3: retval = lookup3[t]; break; case 3: retval = lookup3[t]; break;
case 4: retval = lookup4[t]; break; case 4: retval = lookup4[t]; break;
default: break; default: break;
} }
if (retval == DXGI_FORMAT_UNKNOWN) if (retval == DXGI_FORMAT_UNKNOWN)
{ {
PanicAlert("VarToD3D: Invalid type/size combo %i , %i", (int)t, size); PanicAlert("VarToD3D: Invalid type/size combo %i , %i", (int)t, size);
} }
return retval; return retval;
} }
void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl) void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
{ {
vertex_stride = _vtx_decl.stride; vertex_stride = _vtx_decl.stride;
memset(m_elems, 0, sizeof(m_elems)); memset(m_elems, 0, sizeof(m_elems));
m_elems[m_num_elems].SemanticName = "POSITION"; m_elems[m_num_elems].SemanticName = "POSITION";
m_elems[m_num_elems].AlignedByteOffset = 0; m_elems[m_num_elems].AlignedByteOffset = 0;
m_elems[m_num_elems].Format = DXGI_FORMAT_R32G32B32_FLOAT; m_elems[m_num_elems].Format = DXGI_FORMAT_R32G32B32_FLOAT;
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
++m_num_elems; ++m_num_elems;
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
if (_vtx_decl.normal_offset[i] > 0) if (_vtx_decl.normal_offset[i] > 0)
{ {
m_elems[m_num_elems].SemanticName = "NORMAL"; m_elems[m_num_elems].SemanticName = "NORMAL";
m_elems[m_num_elems].SemanticIndex = i; m_elems[m_num_elems].SemanticIndex = i;
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.normal_offset[i]; m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.normal_offset[i];
m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.normal_gl_type, _vtx_decl.normal_gl_size); m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.normal_gl_type, _vtx_decl.normal_gl_size);
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
++m_num_elems; ++m_num_elems;
} }
} }
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
if (_vtx_decl.color_offset[i] > 0) if (_vtx_decl.color_offset[i] > 0)
{ {
m_elems[m_num_elems].SemanticName = "COLOR"; m_elems[m_num_elems].SemanticName = "COLOR";
m_elems[m_num_elems].SemanticIndex = i; m_elems[m_num_elems].SemanticIndex = i;
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.color_offset[i]; m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.color_offset[i];
m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.color_gl_type, 4); m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.color_gl_type, 4);
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
++m_num_elems; ++m_num_elems;
} }
} }
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
if (_vtx_decl.texcoord_offset[i] > 0) if (_vtx_decl.texcoord_offset[i] > 0)
{ {
m_elems[m_num_elems].SemanticName = "TEXCOORD"; m_elems[m_num_elems].SemanticName = "TEXCOORD";
m_elems[m_num_elems].SemanticIndex = i; m_elems[m_num_elems].SemanticIndex = i;
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.texcoord_offset[i]; m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.texcoord_offset[i];
m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.texcoord_gl_type[i], _vtx_decl.texcoord_size[i]); m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.texcoord_gl_type[i], _vtx_decl.texcoord_size[i]);
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
++m_num_elems; ++m_num_elems;
} }
} }
if (_vtx_decl.posmtx_offset != -1) if (_vtx_decl.posmtx_offset != -1)
{ {
m_elems[m_num_elems].SemanticName = "BLENDINDICES"; m_elems[m_num_elems].SemanticName = "BLENDINDICES";
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.posmtx_offset; m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.posmtx_offset;
m_elems[m_num_elems].Format = DXGI_FORMAT_R8G8B8A8_UNORM; m_elems[m_num_elems].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
++m_num_elems; ++m_num_elems;
} }
} }
void D3DVertexFormat::SetupVertexPointers() const void D3DVertexFormat::SetupVertexPointers() const
{ {
D3D::gfxstate->SetInputElements(m_elems, m_num_elems); D3D::gfxstate->SetInputElements(m_elems, m_num_elems);
} }
} }
@@ -1,306 +1,306 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Common // Common
#include "Common.h" #include "Common.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "LinearDiskCache.h" #include "LinearDiskCache.h"
// VideoCommon // VideoCommon
#include "Statistics.h" #include "Statistics.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "VertexLoader.h" #include "VertexLoader.h"
#include "BPMemory.h" #include "BPMemory.h"
#include "XFMemory.h" #include "XFMemory.h"
#include "ImageWrite.h" #include "ImageWrite.h"
#include "PixelShaderGen.h" #include "PixelShaderGen.h"
#include "PixelShaderManager.h" #include "PixelShaderManager.h"
// DX11 // DX11
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
#include "DX11_D3DShader.h" #include "DX11_D3DShader.h"
#include "DX11_PixelShaderCache.h" #include "DX11_PixelShaderCache.h"
#include <D3Dcompiler.h> #include <D3Dcompiler.h>
#include "../Main.h" #include "../Main.h"
namespace DX11 namespace DX11
{ {
PixelShaderCache::PSCache PixelShaderCache::PixelShaders; PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
const PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry; const PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry;
LinearDiskCache g_ps_disk_cache; LinearDiskCache g_ps_disk_cache;
ID3D11PixelShader* s_ColorMatrixProgram = NULL; ID3D11PixelShader* s_ColorMatrixProgram = NULL;
ID3D11PixelShader* s_ColorCopyProgram = NULL; ID3D11PixelShader* s_ColorCopyProgram = NULL;
ID3D11PixelShader* s_DepthMatrixProgram = NULL; ID3D11PixelShader* s_DepthMatrixProgram = NULL;
ID3D11PixelShader* s_ClearProgram = NULL; ID3D11PixelShader* s_ClearProgram = NULL;
const char clear_program_code[] = { const char clear_program_code[] = {
"void main(\n" "void main(\n"
"out float4 ocol0 : SV_Target,\n" "out float4 ocol0 : SV_Target,\n"
"in float4 pos : SV_Position,\n" "in float4 pos : SV_Position,\n"
"in float4 incol0 : COLOR0){\n" "in float4 incol0 : COLOR0){\n"
"ocol0 = incol0;\n" "ocol0 = incol0;\n"
"}\n" "}\n"
}; };
const char color_copy_program_code[] = { const char color_copy_program_code[] = {
"sampler samp0 : register(s0);\n" "sampler samp0 : register(s0);\n"
"Texture2D Tex0 : register(t0);\n" "Texture2D Tex0 : register(t0);\n"
"void main(\n" "void main(\n"
"out float4 ocol0 : SV_Target,\n" "out float4 ocol0 : SV_Target,\n"
"in float4 pos : SV_Position,\n" "in float4 pos : SV_Position,\n"
"in float2 uv0 : TEXCOORD0){\n" "in float2 uv0 : TEXCOORD0){\n"
"ocol0 = Tex0.Sample(samp0,uv0);\n" "ocol0 = Tex0.Sample(samp0,uv0);\n"
"}\n" "}\n"
}; };
const char color_matrix_program_code[] = { const char color_matrix_program_code[] = {
"sampler samp0 : register(s0);\n" "sampler samp0 : register(s0);\n"
"Texture2D Tex0 : register(t0);\n" "Texture2D Tex0 : register(t0);\n"
"uniform float4 cColMatrix[5] : register(c0);\n" "uniform float4 cColMatrix[5] : register(c0);\n"
"void main(\n" "void main(\n"
"out float4 ocol0 : SV_Target,\n" "out float4 ocol0 : SV_Target,\n"
"in float4 pos : SV_Position,\n" "in float4 pos : SV_Position,\n"
" in float2 uv0 : TEXCOORD0){\n" " in float2 uv0 : TEXCOORD0){\n"
"float4 texcol = Tex0.Sample(samp0,uv0);\n" "float4 texcol = Tex0.Sample(samp0,uv0);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n" "ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n" "}\n"
}; };
const char depth_matrix_program[] = { const char depth_matrix_program[] = {
"sampler samp0 : register(s0);\n" "sampler samp0 : register(s0);\n"
"Texture2D Tex0 : register(t0);\n" "Texture2D Tex0 : register(t0);\n"
"uniform float4 cColMatrix[5] : register(c0);\n" "uniform float4 cColMatrix[5] : register(c0);\n"
"void main(\n" "void main(\n"
"out float4 ocol0 : SV_Target,\n" "out float4 ocol0 : SV_Target,\n"
" in float4 pos : SV_Position,\n" " in float4 pos : SV_Position,\n"
" in float2 uv0 : TEXCOORD0){\n" " in float2 uv0 : TEXCOORD0){\n"
"float4 texcol = Tex0.Sample(samp0,uv0);\n" "float4 texcol = Tex0.Sample(samp0,uv0);\n"
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n" "float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n" "texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n" "ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n" "}\n"
}; };
ID3D11PixelShader* PixelShaderCache::GetColorMatrixProgram() ID3D11PixelShader* PixelShaderCache::GetColorMatrixProgram()
{ {
return s_ColorMatrixProgram; return s_ColorMatrixProgram;
} }
ID3D11PixelShader* PixelShaderCache::GetDepthMatrixProgram() ID3D11PixelShader* PixelShaderCache::GetDepthMatrixProgram()
{ {
return s_DepthMatrixProgram; return s_DepthMatrixProgram;
} }
ID3D11PixelShader* PixelShaderCache::GetColorCopyProgram() ID3D11PixelShader* PixelShaderCache::GetColorCopyProgram()
{ {
return s_ColorCopyProgram; return s_ColorCopyProgram;
} }
ID3D11PixelShader* PixelShaderCache::GetClearProgram() ID3D11PixelShader* PixelShaderCache::GetClearProgram()
{ {
return s_ClearProgram; return s_ClearProgram;
} }
// HACK to avoid some invasive VideoCommon changes // HACK to avoid some invasive VideoCommon changes
// these values are hardcoded, they depend on internal D3DCompile behavior; TODO: Solve this with D3DReflect or something // these values are hardcoded, they depend on internal D3DCompile behavior; TODO: Solve this with D3DReflect or something
// offset given in floats, table index is float4 // offset given in floats, table index is float4
unsigned int ps_constant_offset_table[] = { unsigned int ps_constant_offset_table[] = {
0, 4, 8, 12, // C_COLORS, 16 0, 4, 8, 12, // C_COLORS, 16
16, 20, 24, 28, // C_KCOLORS, 16 16, 20, 24, 28, // C_KCOLORS, 16
32, // C_ALPHA, 4 32, // C_ALPHA, 4
36, 40, 44, 48, 52, 56, 60, 64, // C_TEXDIMS, 32 36, 40, 44, 48, 52, 56, 60, 64, // C_TEXDIMS, 32
68, 72, // C_ZBIAS, 8 68, 72, // C_ZBIAS, 8
76, 80, // C_INDTEXSCALE, 8 76, 80, // C_INDTEXSCALE, 8
84, 88, 92, 96, 100, 104, // C_INDTEXMTX, 24 84, 88, 92, 96, 100, 104, // C_INDTEXMTX, 24
108, 112, // C_FOG, 8 108, 112, // C_FOG, 8
116, 120, 124 ,128, // C_COLORMATRIX, 16 116, 120, 124 ,128, // C_COLORMATRIX, 16
132, 136, 140, 144, 148, // C_PLIGHTS0, 20 132, 136, 140, 144, 148, // C_PLIGHTS0, 20
152, 156, 160, 164, 168, // C_PLIGHTS1, 20 152, 156, 160, 164, 168, // C_PLIGHTS1, 20
172, 176, 180, 184, 188, // C_PLIGHTS2, 20 172, 176, 180, 184, 188, // C_PLIGHTS2, 20
192, 196, 200, 204, 208, // C_PLIGHTS3, 20 192, 196, 200, 204, 208, // C_PLIGHTS3, 20
212, 216, 220, 224, 228, // C_PLIGHTS4, 20 212, 216, 220, 224, 228, // C_PLIGHTS4, 20
232, 236, 240, 244, 248, // C_PLIGHTS5, 20 232, 236, 240, 244, 248, // C_PLIGHTS5, 20
252, 256, 260, 264, 268, // C_PLIGHTS6, 20 252, 256, 260, 264, 268, // C_PLIGHTS6, 20
272, 276, 280, 284, 288, // C_PLIGHTS7, 20 272, 276, 280, 284, 288, // C_PLIGHTS7, 20
292, 296, 300, 304, // C_PMATERIALS, 16 292, 296, 300, 304, // C_PMATERIALS, 16
}; };
void PixelShaderCache::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) void PixelShaderCache::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{ {
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number] ] = f1; D3D::gfxstate->psconstants[ps_constant_offset_table[const_number] ] = f1;
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+1] = f2; D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+1] = f2;
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+2] = f3; D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+2] = f3;
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+3] = f4; D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+3] = f4;
D3D::gfxstate->pscbufchanged = true; D3D::gfxstate->pscbufchanged = true;
} }
void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float* f) void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float* f)
{ {
memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4); memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4);
D3D::gfxstate->pscbufchanged = true; D3D::gfxstate->pscbufchanged = true;
} }
void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float* f) void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float* f)
{ {
memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4*count); memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4*count);
D3D::gfxstate->pscbufchanged = true; D3D::gfxstate->pscbufchanged = true;
} }
// this class will load the precompiled shaders into our cache // this class will load the precompiled shaders into our cache
class PixelShaderCacheInserter : public LinearDiskCacheReader class PixelShaderCacheInserter : public LinearDiskCacheReader
{ {
public: public:
void Read(const u8* key, int key_size, const u8* value, int value_size) void Read(const u8* key, int key_size, const u8* value, int value_size)
{ {
PIXELSHADERUID uid; PIXELSHADERUID uid;
if (key_size != sizeof(uid)) { if (key_size != sizeof(uid)) {
ERROR_LOG(VIDEO, "Wrong key size in pixel shader cache"); ERROR_LOG(VIDEO, "Wrong key size in pixel shader cache");
return; return;
} }
memcpy(&uid, key, key_size); memcpy(&uid, key, key_size);
PixelShaderCache::InsertByteCode(uid, (void*)value, value_size); PixelShaderCache::InsertByteCode(uid, (void*)value, value_size);
} }
}; };
PixelShaderCache::PixelShaderCache() PixelShaderCache::PixelShaderCache()
{ {
// used when drawing clear quads // used when drawing clear quads
s_ClearProgram = D3D::CompileAndCreatePixelShader(clear_program_code, sizeof(clear_program_code)); s_ClearProgram = D3D::CompileAndCreatePixelShader(clear_program_code, sizeof(clear_program_code));
CHECK(s_ClearProgram!=NULL, "Create clear pixel shader"); CHECK(s_ClearProgram!=NULL, "Create clear pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "clear pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "clear pixel shader");
// used when copying/resolving the color buffer // used when copying/resolving the color buffer
s_ColorCopyProgram = D3D::CompileAndCreatePixelShader(color_copy_program_code, sizeof(color_copy_program_code)); s_ColorCopyProgram = D3D::CompileAndCreatePixelShader(color_copy_program_code, sizeof(color_copy_program_code));
CHECK(s_ColorCopyProgram!=NULL, "Create color copy pixel shader"); CHECK(s_ColorCopyProgram!=NULL, "Create color copy pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "color copy pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "color copy pixel shader");
// used for color conversion // used for color conversion
s_ColorMatrixProgram = D3D::CompileAndCreatePixelShader(color_matrix_program_code, sizeof(color_matrix_program_code)); s_ColorMatrixProgram = D3D::CompileAndCreatePixelShader(color_matrix_program_code, sizeof(color_matrix_program_code));
CHECK(s_ColorMatrixProgram!=NULL, "Create color matrix pixel shader"); CHECK(s_ColorMatrixProgram!=NULL, "Create color matrix pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "color matrix pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "color matrix pixel shader");
// used for depth copy // used for depth copy
s_DepthMatrixProgram = D3D::CompileAndCreatePixelShader(depth_matrix_program, sizeof(depth_matrix_program)); s_DepthMatrixProgram = D3D::CompileAndCreatePixelShader(depth_matrix_program, sizeof(depth_matrix_program));
CHECK(s_DepthMatrixProgram!=NULL, "Create depth matrix pixel shader"); CHECK(s_DepthMatrixProgram!=NULL, "Create depth matrix pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "depth matrix pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "depth matrix pixel shader");
Clear(); Clear();
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
char cache_filename[MAX_PATH]; char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx11-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id); sprintf(cache_filename, "%sdx11-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
PixelShaderCacheInserter inserter; PixelShaderCacheInserter inserter;
g_ps_disk_cache.OpenAndRead(cache_filename, &inserter); g_ps_disk_cache.OpenAndRead(cache_filename, &inserter);
} }
// ONLY to be used during shutdown. // ONLY to be used during shutdown.
void PixelShaderCache::Clear() void PixelShaderCache::Clear()
{ {
for (PSCache::iterator iter = PixelShaders.begin(); iter != PixelShaders.end(); iter++) for (PSCache::iterator iter = PixelShaders.begin(); iter != PixelShaders.end(); iter++)
iter->second.Destroy(); iter->second.Destroy();
PixelShaders.clear(); PixelShaders.clear();
} }
PixelShaderCache::~PixelShaderCache() PixelShaderCache::~PixelShaderCache()
{ {
SAFE_RELEASE(s_ColorMatrixProgram); SAFE_RELEASE(s_ColorMatrixProgram);
SAFE_RELEASE(s_ColorCopyProgram); SAFE_RELEASE(s_ColorCopyProgram);
SAFE_RELEASE(s_DepthMatrixProgram); SAFE_RELEASE(s_DepthMatrixProgram);
SAFE_RELEASE(s_ClearProgram); SAFE_RELEASE(s_ClearProgram);
Clear(); Clear();
g_ps_disk_cache.Sync(); g_ps_disk_cache.Sync();
g_ps_disk_cache.Close(); g_ps_disk_cache.Close();
} }
bool PixelShaderCache::SetShader(bool dstAlpha) bool PixelShaderCache::SetShader(bool dstAlpha)
{ {
PIXELSHADERUID uid; PIXELSHADERUID uid;
GetPixelShaderId(&uid, dstAlpha); GetPixelShaderId(&uid, dstAlpha);
// check if the shader is already set // check if the shader is already set
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount) if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
{ {
PSCache::const_iterator iter = PixelShaders.find(uid); PSCache::const_iterator iter = PixelShaders.find(uid);
return (iter != PixelShaders.end() && iter->second.shader); return (iter != PixelShaders.end() && iter->second.shader);
} }
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID)); memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
// check if the shader is already in the cache // check if the shader is already in the cache
PSCache::iterator iter = PixelShaders.find(uid); PSCache::iterator iter = PixelShaders.find(uid);
if (iter != PixelShaders.end()) if (iter != PixelShaders.end())
{ {
iter->second.frameCount = frameCount; iter->second.frameCount = frameCount;
const PSCacheEntry &entry = iter->second; const PSCacheEntry &entry = iter->second;
last_entry = &entry; last_entry = &entry;
D3D::gfxstate->SetPShader(entry.shader); D3D::gfxstate->SetPShader(entry.shader);
return (entry.shader != NULL); return (entry.shader != NULL);
} }
// need to compile a new shader // need to compile a new shader
const char* code = GeneratePixelShaderCode(dstAlpha, API_D3D11); const char* code = GeneratePixelShaderCode(dstAlpha, API_D3D11);
D3DBlob* pbytecode; D3DBlob* pbytecode;
if (!D3D::CompilePixelShader(code, (unsigned int)strlen(code), &pbytecode)) if (!D3D::CompilePixelShader(code, (unsigned int)strlen(code), &pbytecode))
{ {
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code); PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
return false; return false;
} }
// insert the bytecode into the caches // insert the bytecode into the caches
g_ps_disk_cache.Append((u8*)&uid, sizeof(uid), (const u8*)pbytecode->Data(), pbytecode->Size()); g_ps_disk_cache.Append((u8*)&uid, sizeof(uid), (const u8*)pbytecode->Data(), pbytecode->Size());
g_ps_disk_cache.Sync(); g_ps_disk_cache.Sync();
bool result = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size()); bool result = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size());
D3D::gfxstate->SetPShader(last_entry->shader); D3D::gfxstate->SetPShader(last_entry->shader);
pbytecode->Release(); pbytecode->Release();
return result; return result;
} }
bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, void* bytecode, unsigned int bytecodelen) bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, void* bytecode, unsigned int bytecodelen)
{ {
ID3D11PixelShader* shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen); ID3D11PixelShader* shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
if (shader == NULL) if (shader == NULL)
{ {
PanicAlert("Failed to create pixel shader at %s %d\n", __FILE__, __LINE__); PanicAlert("Failed to create pixel shader at %s %d\n", __FILE__, __LINE__);
return false; return false;
} }
// TODO: Somehow make the debug name a bit more specific // TODO: Somehow make the debug name a bit more specific
D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a pixel shader of PixelShaderCache"); D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a pixel shader of PixelShaderCache");
// make an entry in the table // make an entry in the table
PSCacheEntry newentry; PSCacheEntry newentry;
newentry.shader = shader; newentry.shader = shader;
newentry.frameCount = frameCount; newentry.frameCount = frameCount;
PixelShaders[uid] = newentry; PixelShaders[uid] = newentry;
last_entry = &PixelShaders[uid]; last_entry = &PixelShaders[uid];
INCSTAT(stats.numPixelShadersCreated); INCSTAT(stats.numPixelShadersCreated);
SETSTAT(stats.numPixelShadersAlive, PixelShaders.size()); SETSTAT(stats.numPixelShadersAlive, PixelShaders.size());
return true; return true;
} }
} }
@@ -1,74 +1,74 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#pragma once #pragma once
#include <map> #include <map>
// Common // Common
#include "Common.h" #include "Common.h"
#include "LinearDiskCache.h" #include "LinearDiskCache.h"
// VideoCommon // VideoCommon
#include "PixelShaderGen.h" #include "PixelShaderGen.h"
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
// DX11 // DX11
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
#include "../PixelShaderCache.h" #include "../PixelShaderCache.h"
namespace DX11 namespace DX11
{ {
class PixelShaderCache : public ::PixelShaderCacheBase class PixelShaderCache : public ::PixelShaderCacheBase
{ {
public: public:
PixelShaderCache(); PixelShaderCache();
~PixelShaderCache(); ~PixelShaderCache();
void Clear(); void Clear();
bool SetShader(bool dstAlpha); bool SetShader(bool dstAlpha);
static bool InsertByteCode(const PIXELSHADERUID &uid, void* bytecode, unsigned int bytecodelen); static bool InsertByteCode(const PIXELSHADERUID &uid, void* bytecode, unsigned int bytecodelen);
static ID3D11PixelShader* GetColorMatrixProgram(); static ID3D11PixelShader* GetColorMatrixProgram();
static ID3D11PixelShader* GetColorCopyProgram(); static ID3D11PixelShader* GetColorCopyProgram();
static ID3D11PixelShader* GetDepthMatrixProgram(); static ID3D11PixelShader* GetDepthMatrixProgram();
static ID3D11PixelShader* GetClearProgram(); static ID3D11PixelShader* GetClearProgram();
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4); void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
void SetPSConstant4fv(unsigned int const_number, const float *f); void SetPSConstant4fv(unsigned int const_number, const float *f);
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f); void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
private: private:
struct PSCacheEntry struct PSCacheEntry
{ {
ID3D11PixelShader* shader; ID3D11PixelShader* shader;
int frameCount; int frameCount;
PSCacheEntry() : shader(NULL), frameCount(0) {} PSCacheEntry() : shader(NULL), frameCount(0) {}
void Destroy() { SAFE_RELEASE(shader); } void Destroy() { SAFE_RELEASE(shader); }
}; };
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache; typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
static PSCache PixelShaders; static PSCache PixelShaders;
static const PSCacheEntry* last_entry; static const PSCacheEntry* last_entry;
}; };
} }
@@ -1,52 +1,52 @@
#pragma once #pragma once
#include "MathUtil.h" #include "MathUtil.h"
#include "VideoCommon.h" #include "VideoCommon.h"
#include "Renderer.h" #include "Renderer.h"
#include "pluginspecs_video.h" #include "pluginspecs_video.h"
namespace DX11 namespace DX11
{ {
class Renderer : public ::RendererBase class Renderer : public ::RendererBase
{ {
public: public:
Renderer(); Renderer();
~Renderer(); ~Renderer();
// What's the real difference between these? Too similar names. // What's the real difference between these? Too similar names.
void ResetAPIState(); void ResetAPIState();
void RestoreAPIState(); void RestoreAPIState();
static void SetupDeviceObjects(); static void SetupDeviceObjects();
static void TeardownDeviceObjects(); static void TeardownDeviceObjects();
void SetColorMask(); void SetColorMask();
void SetBlendMode(bool forceUpdate); void SetBlendMode(bool forceUpdate);
bool SetScissorRect(); bool SetScissorRect();
void SetGenerationMode(); void SetGenerationMode();
void SetDepthMode(); void SetDepthMode();
void SetLogicOpMode(); void SetLogicOpMode();
void SetSamplerState(int stage,int texindex); void SetSamplerState(int stage,int texindex);
u32 AccessEFB(EFBAccessType type, int x, int y); u32 AccessEFB(EFBAccessType type, int x, int y);
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z); void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
void UpdateViewport(); void UpdateViewport();
// virtual funcs used by RendererBase::Swap // virtual funcs used by RendererBase::Swap
void PrepareXFBCopy(const TargetRectangle &dst_rect); void PrepareXFBCopy(const TargetRectangle &dst_rect);
void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc, void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc); const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc);
void EndFrame(); void EndFrame();
void Present(); void Present();
bool CheckForResize(); bool CheckForResize();
void GetBackBufferSize(int* w, int* h); void GetBackBufferSize(int* w, int* h);
void RecreateFramebufferManger(); void RecreateFramebufferManger();
void BeginFrame(); void BeginFrame();
}; };
} }
@@ -1,230 +1,230 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <d3dx11.h> #include <d3dx11.h>
// Common // Common
#include "CommonPaths.h" #include "CommonPaths.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "MemoryUtil.h" #include "MemoryUtil.h"
#include "Hash.h" #include "Hash.h"
// VideoCommon // VideoCommon
#include "VideoConfig.h" #include "VideoConfig.h"
#include "Statistics.h" #include "Statistics.h"
#include "PixelShaderManager.h" #include "PixelShaderManager.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "TextureDecoder.h" #include "TextureDecoder.h"
#include "HiresTextures.h" #include "HiresTextures.h"
// DX11 // DX11
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
#include "DX11_D3DTexture.h" #include "DX11_D3DTexture.h"
#include "DX11_D3DUtil.h" #include "DX11_D3DUtil.h"
#include "DX11_FramebufferManager.h" #include "DX11_FramebufferManager.h"
#include "DX11_PixelShaderCache.h" #include "DX11_PixelShaderCache.h"
#include "DX11_VertexShaderCache.h" #include "DX11_VertexShaderCache.h"
#include "DX11_TextureCache.h" #include "DX11_TextureCache.h"
#include "../Main.h" #include "../Main.h"
namespace DX11 namespace DX11
{ {
ID3D11BlendState* efbcopyblendstate = NULL; ID3D11BlendState* efbcopyblendstate = NULL;
ID3D11RasterizerState* efbcopyraststate = NULL; ID3D11RasterizerState* efbcopyraststate = NULL;
ID3D11DepthStencilState* efbcopydepthstate = NULL; ID3D11DepthStencilState* efbcopydepthstate = NULL;
ID3D11Buffer* efbcopycbuf[20] = {}; ID3D11Buffer* efbcopycbuf[20] = {};
TextureCache::TCacheEntry::~TCacheEntry() TextureCache::TCacheEntry::~TCacheEntry()
{ {
SAFE_RELEASE(texture); SAFE_RELEASE(texture);
} }
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int level) unsigned int expanded_width, unsigned int level)
{ {
D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, expanded_width, level, usage); D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, expanded_width, level, usage);
} }
void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf, void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect) unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect)
{ {
// stretch picture with increased internal resolution // stretch picture with increased internal resolution
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)Scaledw, (float)Scaledh); const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)Scaledw, (float)Scaledh);
D3D::context->RSSetViewports(1, &vp); D3D::context->RSSetViewports(1, &vp);
// set transformation // set transformation
if (NULL == efbcopycbuf[cbufid]) if (NULL == efbcopycbuf[cbufid])
{ {
const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(20 * sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT); const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(20 * sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT);
D3D11_SUBRESOURCE_DATA data; D3D11_SUBRESOURCE_DATA data;
data.pSysMem = colmat; data.pSysMem = colmat;
HRESULT hr = D3D::device->CreateBuffer(&cbdesc, &data, &efbcopycbuf[cbufid]); HRESULT hr = D3D::device->CreateBuffer(&cbdesc, &data, &efbcopycbuf[cbufid]);
CHECK(SUCCEEDED(hr), "Create efb copy constant buffer %d", cbufid); CHECK(SUCCEEDED(hr), "Create efb copy constant buffer %d", cbufid);
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopycbuf[cbufid], "a constant buffer used in TextureCache::CopyRenderTargetToTexture"); D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopycbuf[cbufid], "a constant buffer used in TextureCache::CopyRenderTargetToTexture");
} }
D3D::context->PSSetConstantBuffers(0, 1, &efbcopycbuf[cbufid]); D3D::context->PSSetConstantBuffers(0, 1, &efbcopycbuf[cbufid]);
const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(source_rect); const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(source_rect);
// TODO: try targetSource.asRECT(); // TODO: try targetSource.asRECT();
const D3D11_RECT sourcerect = CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom); const D3D11_RECT sourcerect = CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom);
// Use linear filtering if (bScaleByHalf), use point filtering otherwise // Use linear filtering if (bScaleByHalf), use point filtering otherwise
if (bScaleByHalf) if (bScaleByHalf)
D3D::SetLinearCopySampler(); D3D::SetLinearCopySampler();
else else
D3D::SetPointCopySampler(); D3D::SetPointCopySampler();
D3D::stateman->PushBlendState(efbcopyblendstate); D3D::stateman->PushBlendState(efbcopyblendstate);
D3D::stateman->PushRasterizerState(efbcopyraststate); D3D::stateman->PushRasterizerState(efbcopyraststate);
D3D::stateman->PushDepthState(efbcopydepthstate); D3D::stateman->PushDepthState(efbcopydepthstate);
D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), NULL); D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), NULL);
D3D::drawShadedTexQuad( D3D::drawShadedTexQuad(
(bFromZBuffer) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(), (bFromZBuffer) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(),
&sourcerect, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight(), &sourcerect, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight(),
(bFromZBuffer) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram(), (bFromZBuffer) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram(),
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout()); VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
D3D::stateman->PopBlendState(); D3D::stateman->PopBlendState();
D3D::stateman->PopDepthState(); D3D::stateman->PopDepthState();
D3D::stateman->PopRasterizerState(); D3D::stateman->PopRasterizerState();
} }
void TextureCache::TCacheEntry::Bind(unsigned int stage) void TextureCache::TCacheEntry::Bind(unsigned int stage)
{ {
D3D::gfxstate->SetShaderResource(stage, texture->GetSRV()); D3D::gfxstate->SetShaderResource(stage, texture->GetSRV());
} }
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
unsigned int height, unsigned int expanded_width, unsigned int height, unsigned int expanded_width,
unsigned int tex_levels, PC_TexFormat pcfmt) unsigned int tex_levels, PC_TexFormat pcfmt)
{ {
D3D11_SUBRESOURCE_DATA srdata; D3D11_SUBRESOURCE_DATA srdata;
D3D11_SUBRESOURCE_DATA *data = NULL; D3D11_SUBRESOURCE_DATA *data = NULL;
D3D11_CPU_ACCESS_FLAG cpu_access = (D3D11_CPU_ACCESS_FLAG)0; D3D11_CPU_ACCESS_FLAG cpu_access = (D3D11_CPU_ACCESS_FLAG)0;
D3D11_USAGE usage = D3D11_USAGE_DEFAULT; D3D11_USAGE usage = D3D11_USAGE_DEFAULT;
// TODO: temp // TODO: temp
tex_levels = 1; tex_levels = 1;
if (1 == tex_levels) if (1 == tex_levels)
{ {
cpu_access = D3D11_CPU_ACCESS_WRITE; cpu_access = D3D11_CPU_ACCESS_WRITE;
usage = D3D11_USAGE_DYNAMIC; usage = D3D11_USAGE_DYNAMIC;
srdata.pSysMem = temp; srdata.pSysMem = temp;
srdata.SysMemPitch = 4 * expanded_width; srdata.SysMemPitch = 4 * expanded_width;
data = &srdata; data = &srdata;
} }
const D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, const D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM,
width, height, 1, tex_levels, D3D11_BIND_SHADER_RESOURCE, usage, cpu_access); width, height, 1, tex_levels, D3D11_BIND_SHADER_RESOURCE, usage, cpu_access);
ID3D11Texture2D *pTexture; ID3D11Texture2D *pTexture;
HRESULT hr = D3D::device->CreateTexture2D(&texdesc, data, &pTexture); HRESULT hr = D3D::device->CreateTexture2D(&texdesc, data, &pTexture);
CHECK(SUCCEEDED(hr), "Create texture of the TextureCache"); CHECK(SUCCEEDED(hr), "Create texture of the TextureCache");
TCacheEntry* const entry = new TCacheEntry(new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE)); TCacheEntry* const entry = new TCacheEntry(new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE));
entry->usage = usage; entry->usage = usage;
// TODO: silly debug names // TODO: silly debug names
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry->texture->GetTex(), "a texture of the TextureCache"); D3D::SetDebugObjectName((ID3D11DeviceChild*)entry->texture->GetTex(), "a texture of the TextureCache");
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry->texture->GetSRV(), "shader resource view of a texture of the TextureCache"); D3D::SetDebugObjectName((ID3D11DeviceChild*)entry->texture->GetSRV(), "shader resource view of a texture of the TextureCache");
// wuts this? // wuts this?
//if (0 == tex_levels) //if (0 == tex_levels)
// PD3DX11FilterTexture(D3D::context, entry->texture->GetTex(), 0, D3DX11_DEFAULT); // PD3DX11FilterTexture(D3D::context, entry->texture->GetTex(), 0, D3DX11_DEFAULT);
// TODO: this good? // TODO: this good?
//if (1 != tex_levels) //if (1 != tex_levels)
// entry->Load(width, height, expanded_width, 0); // entry->Load(width, height, expanded_width, 0);
SAFE_RELEASE(pTexture); SAFE_RELEASE(pTexture);
return entry; return entry;
} }
TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h) TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h)
{ {
return new TCacheEntry(D3DTexture2D::Create(scaled_tex_w, scaled_tex_h, return new TCacheEntry(D3DTexture2D::Create(scaled_tex_w, scaled_tex_h,
(D3D11_BIND_FLAG)((int)D3D11_BIND_RENDER_TARGET | (int)D3D11_BIND_SHADER_RESOURCE), (D3D11_BIND_FLAG)((int)D3D11_BIND_RENDER_TARGET | (int)D3D11_BIND_SHADER_RESOURCE),
D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM)); D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM));
} }
TextureCache::TextureCache() TextureCache::TextureCache()
{ {
HRESULT hr; HRESULT hr;
D3D11_BLEND_DESC blenddesc; D3D11_BLEND_DESC blenddesc;
blenddesc.AlphaToCoverageEnable = FALSE; blenddesc.AlphaToCoverageEnable = FALSE;
blenddesc.IndependentBlendEnable = FALSE; blenddesc.IndependentBlendEnable = FALSE;
blenddesc.RenderTarget[0].BlendEnable = FALSE; blenddesc.RenderTarget[0].BlendEnable = FALSE;
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
blenddesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; blenddesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
blenddesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO; blenddesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
blenddesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; blenddesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
hr = D3D::device->CreateBlendState(&blenddesc, &efbcopyblendstate); hr = D3D::device->CreateBlendState(&blenddesc, &efbcopyblendstate);
CHECK(hr==S_OK, "Create blend state for CopyRenderTargetToTexture"); CHECK(hr==S_OK, "Create blend state for CopyRenderTargetToTexture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopyblendstate, "blend state used in CopyRenderTargetToTexture"); D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopyblendstate, "blend state used in CopyRenderTargetToTexture");
D3D11_DEPTH_STENCIL_DESC depthdesc; D3D11_DEPTH_STENCIL_DESC depthdesc;
depthdesc.DepthEnable = FALSE; depthdesc.DepthEnable = FALSE;
depthdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthdesc.DepthFunc = D3D11_COMPARISON_LESS; depthdesc.DepthFunc = D3D11_COMPARISON_LESS;
depthdesc.StencilEnable = FALSE; depthdesc.StencilEnable = FALSE;
depthdesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; depthdesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
depthdesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; depthdesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
hr = D3D::device->CreateDepthStencilState(&depthdesc, &efbcopydepthstate); hr = D3D::device->CreateDepthStencilState(&depthdesc, &efbcopydepthstate);
CHECK(hr==S_OK, "Create depth state for CopyRenderTargetToTexture"); CHECK(hr==S_OK, "Create depth state for CopyRenderTargetToTexture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopydepthstate, "depth stencil state used in CopyRenderTargetToTexture"); D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopydepthstate, "depth stencil state used in CopyRenderTargetToTexture");
D3D11_RASTERIZER_DESC rastdesc; D3D11_RASTERIZER_DESC rastdesc;
rastdesc.CullMode = D3D11_CULL_NONE; rastdesc.CullMode = D3D11_CULL_NONE;
rastdesc.FillMode = D3D11_FILL_SOLID; rastdesc.FillMode = D3D11_FILL_SOLID;
rastdesc.FrontCounterClockwise = false; rastdesc.FrontCounterClockwise = false;
rastdesc.DepthBias = false; rastdesc.DepthBias = false;
rastdesc.DepthBiasClamp = 0; rastdesc.DepthBiasClamp = 0;
rastdesc.SlopeScaledDepthBias = 0; rastdesc.SlopeScaledDepthBias = 0;
rastdesc.DepthClipEnable = false; rastdesc.DepthClipEnable = false;
rastdesc.ScissorEnable = false; rastdesc.ScissorEnable = false;
rastdesc.MultisampleEnable = false; rastdesc.MultisampleEnable = false;
rastdesc.AntialiasedLineEnable = false; rastdesc.AntialiasedLineEnable = false;
hr = D3D::device->CreateRasterizerState(&rastdesc, &efbcopyraststate); hr = D3D::device->CreateRasterizerState(&rastdesc, &efbcopyraststate);
CHECK(hr==S_OK, "Create rasterizer state for CopyRenderTargetToTexture"); CHECK(hr==S_OK, "Create rasterizer state for CopyRenderTargetToTexture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopyraststate, "rasterizer state used in CopyRenderTargetToTexture"); D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopyraststate, "rasterizer state used in CopyRenderTargetToTexture");
} }
TextureCache::~TextureCache() TextureCache::~TextureCache()
{ {
SAFE_RELEASE(efbcopyblendstate); SAFE_RELEASE(efbcopyblendstate);
SAFE_RELEASE(efbcopyraststate); SAFE_RELEASE(efbcopyraststate);
SAFE_RELEASE(efbcopydepthstate); SAFE_RELEASE(efbcopydepthstate);
for (unsigned int k = 0; k < 20; ++k) for (unsigned int k = 0; k < 20; ++k)
SAFE_RELEASE(efbcopycbuf[k]); SAFE_RELEASE(efbcopycbuf[k]);
} }
} }
@@ -1,66 +1,66 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#pragma once #pragma once
// VideoCommon // VideoCommon
#include "VideoCommon.h" #include "VideoCommon.h"
#include "BPMemory.h" #include "BPMemory.h"
// DX11 // DX11
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
#include "DX11_D3DTexture.h" #include "DX11_D3DTexture.h"
#include "../TextureCache.h" #include "../TextureCache.h"
namespace DX11 namespace DX11
{ {
class TextureCache : public ::TextureCacheBase class TextureCache : public ::TextureCacheBase
{ {
public: public:
struct TCacheEntry : TCacheEntryBase struct TCacheEntry : TCacheEntryBase
{ {
D3DTexture2D* texture; D3DTexture2D* texture;
D3D11_USAGE usage; D3D11_USAGE usage;
TCacheEntry(D3DTexture2D* _texture) : texture(_texture) {} TCacheEntry(D3DTexture2D* _texture) : texture(_texture) {}
~TCacheEntry(); ~TCacheEntry();
void Load(unsigned int width, unsigned int height, void Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int level); unsigned int expanded_width, unsigned int level);
void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf, void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect); unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect);
void Bind(unsigned int stage); void Bind(unsigned int stage);
}; };
TextureCache(); TextureCache();
~TextureCache(); ~TextureCache();
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height, TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt); unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt);
TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h); TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h);
void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, unsigned int bScaleByHalf, const EFBRectangle &source_rect); void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, unsigned int bScaleByHalf, const EFBRectangle &source_rect);
}; };
} }
@@ -1,194 +1,194 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <string> #include <string>
// Common // Common
#include "Common.h" #include "Common.h"
#include "FileUtil.h" #include "FileUtil.h"
// VideoCommon // VideoCommon
#include "BPStructs.h" #include "BPStructs.h"
#include "XFStructs.h" #include "XFStructs.h"
#include "Fifo.h" #include "Fifo.h"
#include "Statistics.h" #include "Statistics.h"
#include "Profiler.h" #include "Profiler.h"
#include "OpcodeDecoding.h" #include "OpcodeDecoding.h"
#include "IndexGenerator.h" #include "IndexGenerator.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "PixelShaderManager.h" #include "PixelShaderManager.h"
#include "NativeVertexFormat.h" #include "NativeVertexFormat.h"
#include "NativeVertexWriter.h" #include "NativeVertexWriter.h"
// DX11 // DX11
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
#include "DX11_D3DShader.h" #include "DX11_D3DShader.h"
#include "DX11_D3DUtil.h" #include "DX11_D3DUtil.h"
#include "DX11_VertexManager.h" #include "DX11_VertexManager.h"
#include "DX11_VertexShaderCache.h" #include "DX11_VertexShaderCache.h"
#include "DX11_PixelShaderCache.h" #include "DX11_PixelShaderCache.h"
#include "DX11_TextureCache.h" #include "DX11_TextureCache.h"
#include "DX11_FramebufferManager.h" #include "DX11_FramebufferManager.h"
#include "DX11_Render.h" #include "DX11_Render.h"
#include "../Main.h" #include "../Main.h"
//using std::string; //using std::string;
namespace DX11 namespace DX11
{ {
using namespace D3D; using namespace D3D;
ID3D11Buffer* indexbuffers[NUM_INDEXBUFFERS] = {}; ID3D11Buffer* indexbuffers[NUM_INDEXBUFFERS] = {};
ID3D11Buffer* vertexbuffers[NUM_VERTEXBUFFERS] = {}; ID3D11Buffer* vertexbuffers[NUM_VERTEXBUFFERS] = {};
// TODO: these seem ugly // TODO: these seem ugly
inline ID3D11Buffer* GetSuitableIndexBuffer(const u32 minsize) inline ID3D11Buffer* GetSuitableIndexBuffer(const u32 minsize)
{ {
for (u32 k = 0; k < NUM_INDEXBUFFERS - 1; ++k) for (u32 k = 0; k < NUM_INDEXBUFFERS - 1; ++k)
if (minsize > (((u32)MAXIBUFFERSIZE) >> k)) if (minsize > (((u32)MAXIBUFFERSIZE) >> k))
return indexbuffers[k]; return indexbuffers[k];
return indexbuffers[NUM_INDEXBUFFERS - 1]; return indexbuffers[NUM_INDEXBUFFERS - 1];
} }
inline ID3D11Buffer* GetSuitableVertexBuffer(const u32 minsize) inline ID3D11Buffer* GetSuitableVertexBuffer(const u32 minsize)
{ {
for (u32 k = 0; k < NUM_VERTEXBUFFERS - 1; ++k) for (u32 k = 0; k < NUM_VERTEXBUFFERS - 1; ++k)
if (minsize > (((u32)MAXVBUFFERSIZE) >> (k + 1))) if (minsize > (((u32)MAXVBUFFERSIZE) >> (k + 1)))
return vertexbuffers[k]; return vertexbuffers[k];
return vertexbuffers[NUM_VERTEXBUFFERS - 1]; return vertexbuffers[NUM_VERTEXBUFFERS - 1];
} }
void CreateDeviceObjects() void CreateDeviceObjects()
{ {
D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(MAXIBUFFERSIZE * 2, D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(MAXIBUFFERSIZE * 2,
D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
for (u32 k = 0; k < NUM_INDEXBUFFERS; ++k, bufdesc.ByteWidth >>= 1) for (u32 k = 0; k < NUM_INDEXBUFFERS; ++k, bufdesc.ByteWidth >>= 1)
{ {
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, indexbuffers + k)), CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, indexbuffers + k)),
"Failed to create index buffer [%i].", k); "Failed to create index buffer [%i].", k);
D3D::SetDebugObjectName((ID3D11DeviceChild*)indexbuffers[k], "an index buffer of VertexManager"); D3D::SetDebugObjectName((ID3D11DeviceChild*)indexbuffers[k], "an index buffer of VertexManager");
} }
bufdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; bufdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufdesc.ByteWidth = MAXVBUFFERSIZE; bufdesc.ByteWidth = MAXVBUFFERSIZE;
for (u32 k = 0; k < NUM_VERTEXBUFFERS; ++k, bufdesc.ByteWidth >>= 1) for (u32 k = 0; k < NUM_VERTEXBUFFERS; ++k, bufdesc.ByteWidth >>= 1)
{ {
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, vertexbuffers + k)), CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, vertexbuffers + k)),
"Failed to create vertex buffer [%i].", k); "Failed to create vertex buffer [%i].", k);
D3D::SetDebugObjectName((ID3D11DeviceChild*)vertexbuffers[k], "a vertex buffer of VertexManager"); D3D::SetDebugObjectName((ID3D11DeviceChild*)vertexbuffers[k], "a vertex buffer of VertexManager");
} }
} }
void DestroyDeviceObjects() void DestroyDeviceObjects()
{ {
for (u32 k = 0; k < NUM_INDEXBUFFERS; ++k) for (u32 k = 0; k < NUM_INDEXBUFFERS; ++k)
SAFE_RELEASE(indexbuffers[k]); SAFE_RELEASE(indexbuffers[k]);
for (u32 k = 0; k < NUM_VERTEXBUFFERS; ++k) for (u32 k = 0; k < NUM_VERTEXBUFFERS; ++k)
SAFE_RELEASE(vertexbuffers[k]); SAFE_RELEASE(vertexbuffers[k]);
} }
VertexManager::VertexManager() VertexManager::VertexManager()
{ {
CreateDeviceObjects(); CreateDeviceObjects();
} }
VertexManager::~VertexManager() VertexManager::~VertexManager()
{ {
DestroyDeviceObjects(); DestroyDeviceObjects();
ResetBuffer(); ResetBuffer();
} }
void VertexManager::Draw(u32 stride, bool alphapass) void VertexManager::Draw(u32 stride, bool alphapass)
{ {
static const UINT bufoffset = 0; static const UINT bufoffset = 0;
const UINT bufstride = stride; const UINT bufstride = stride;
D3D11_MAPPED_SUBRESOURCE map; D3D11_MAPPED_SUBRESOURCE map;
ID3D11Buffer* const vertexbuffer = GetSuitableVertexBuffer((u32)(s_pCurBufferPointer - LocalVBuffer)); ID3D11Buffer* const vertexbuffer = GetSuitableVertexBuffer((u32)(s_pCurBufferPointer - LocalVBuffer));
if (alphapass) if (alphapass)
{ {
gfxstate->AlphaPass(); gfxstate->AlphaPass();
} }
else else
{ {
context->Map(vertexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); context->Map(vertexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, LocalVBuffer, (u32)(s_pCurBufferPointer - LocalVBuffer)); memcpy(map.pData, LocalVBuffer, (u32)(s_pCurBufferPointer - LocalVBuffer));
context->Unmap(vertexbuffer, 0); context->Unmap(vertexbuffer, 0);
gfxstate->ApplyState(); gfxstate->ApplyState();
} }
D3D::context->IASetVertexBuffers(0, 1, &vertexbuffer, &bufstride, &bufoffset); D3D::context->IASetVertexBuffers(0, 1, &vertexbuffer, &bufstride, &bufoffset);
if (IndexGenerator::GetNumTriangles() > 0) if (IndexGenerator::GetNumTriangles() > 0)
{ {
u32 indexbuffersize = IndexGenerator::GetTriangleindexLen(); u32 indexbuffersize = IndexGenerator::GetTriangleindexLen();
ID3D11Buffer* indexbuffer = GetSuitableIndexBuffer(2*indexbuffersize); ID3D11Buffer* indexbuffer = GetSuitableIndexBuffer(2*indexbuffersize);
if (!alphapass) if (!alphapass)
{ {
D3D::context->Map(indexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); D3D::context->Map(indexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, TIBuffer, 2*indexbuffersize); memcpy(map.pData, TIBuffer, 2*indexbuffersize);
D3D::context->Unmap(indexbuffer, 0); D3D::context->Unmap(indexbuffer, 0);
} }
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
D3D::context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R16_UINT, 0); D3D::context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R16_UINT, 0);
D3D::context->DrawIndexed(indexbuffersize, 0, 0); D3D::context->DrawIndexed(indexbuffersize, 0, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
} }
if (IndexGenerator::GetNumLines() > 0) if (IndexGenerator::GetNumLines() > 0)
{ {
u32 indexbuffersize = IndexGenerator::GetLineindexLen(); u32 indexbuffersize = IndexGenerator::GetLineindexLen();
ID3D11Buffer* indexbuffer = GetSuitableIndexBuffer(2*indexbuffersize); ID3D11Buffer* indexbuffer = GetSuitableIndexBuffer(2*indexbuffersize);
if (!alphapass) if (!alphapass)
{ {
D3D::context->Map(indexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); D3D::context->Map(indexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, LIBuffer, 2*indexbuffersize); memcpy(map.pData, LIBuffer, 2*indexbuffersize);
D3D::context->Unmap(indexbuffer, 0); D3D::context->Unmap(indexbuffer, 0);
} }
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
D3D::context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R16_UINT, 0); D3D::context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R16_UINT, 0);
D3D::context->DrawIndexed(indexbuffersize, 0, 0); D3D::context->DrawIndexed(indexbuffersize, 0, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
} }
if (IndexGenerator::GetNumPoints() > 0) if (IndexGenerator::GetNumPoints() > 0)
{ {
u32 indexbuffersize = IndexGenerator::GetPointindexLen(); u32 indexbuffersize = IndexGenerator::GetPointindexLen();
ID3D11Buffer* indexbuffer = GetSuitableIndexBuffer(2*indexbuffersize); ID3D11Buffer* indexbuffer = GetSuitableIndexBuffer(2*indexbuffersize);
if (!alphapass) if (!alphapass)
{ {
D3D::context->Map(indexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); D3D::context->Map(indexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, PIBuffer, 2*indexbuffersize); memcpy(map.pData, PIBuffer, 2*indexbuffersize);
D3D::context->Unmap(indexbuffer, 0); D3D::context->Unmap(indexbuffer, 0);
} }
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
D3D::context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R16_UINT, 0); D3D::context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R16_UINT, 0);
D3D::context->DrawIndexed(indexbuffersize, 0, 0); D3D::context->DrawIndexed(indexbuffersize, 0, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
} }
} }
} }
@@ -1,49 +1,49 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _DX11_VERTEXMANAGER_H #ifndef _DX11_VERTEXMANAGER_H
#define _DX11_VERTEXMANAGER_H #define _DX11_VERTEXMANAGER_H
#include "CPMemory.h" #include "CPMemory.h"
#include "VertexLoader.h" #include "VertexLoader.h"
#include "../VertexManager.h" #include "../VertexManager.h"
namespace DX11 namespace DX11
{ {
enum enum
{ {
// TODO: find sensible values for these two // TODO: find sensible values for these two
NUM_VERTEXBUFFERS = 8, NUM_VERTEXBUFFERS = 8,
NUM_INDEXBUFFERS = 10, NUM_INDEXBUFFERS = 10,
}; };
class VertexManager : public ::VertexManagerBase class VertexManager : public ::VertexManagerBase
{ {
public: public:
VertexManager(); VertexManager();
~VertexManager(); ~VertexManager();
void Draw(u32 stride, bool alphapass); void Draw(u32 stride, bool alphapass);
NativeVertexFormat* CreateNativeVertexFormat(); NativeVertexFormat* CreateNativeVertexFormat();
}; };
} }
#endif #endif
@@ -1,283 +1,283 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <map> #include <map>
// Common // Common
#include "Common.h" #include "Common.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "LinearDiskCache.h" #include "LinearDiskCache.h"
// VideoCommon // VideoCommon
#include "VideoConfig.h" #include "VideoConfig.h"
#include "Statistics.h" #include "Statistics.h"
#include "Profiler.h" #include "Profiler.h"
#include "VertexLoader.h" #include "VertexLoader.h"
#include "BPMemory.h" #include "BPMemory.h"
#include "XFMemory.h" #include "XFMemory.h"
// DX11 // DX11
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
#include "DX11_D3DShader.h" #include "DX11_D3DShader.h"
#include "DX11_VertexShaderCache.h" #include "DX11_VertexShaderCache.h"
#include "DX11_Render.h" #include "DX11_Render.h"
#include "../Main.h" #include "../Main.h"
namespace DX11 namespace DX11
{ {
VertexShaderCache::VSCache VertexShaderCache::vshaders; VertexShaderCache::VSCache VertexShaderCache::vshaders;
const VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry; const VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry;
static ID3D11VertexShader* SimpleVertexShader = NULL; static ID3D11VertexShader* SimpleVertexShader = NULL;
static ID3D11VertexShader* ClearVertexShader = NULL; static ID3D11VertexShader* ClearVertexShader = NULL;
static ID3D11InputLayout* SimpleLayout = NULL; static ID3D11InputLayout* SimpleLayout = NULL;
static ID3D11InputLayout* ClearLayout = NULL; static ID3D11InputLayout* ClearLayout = NULL;
LinearDiskCache g_vs_disk_cache; LinearDiskCache g_vs_disk_cache;
ID3D11VertexShader* VertexShaderCache::GetSimpleVertexShader() { return SimpleVertexShader; } ID3D11VertexShader* VertexShaderCache::GetSimpleVertexShader() { return SimpleVertexShader; }
ID3D11VertexShader* VertexShaderCache::GetClearVertexShader() { return ClearVertexShader; } ID3D11VertexShader* VertexShaderCache::GetClearVertexShader() { return ClearVertexShader; }
ID3D11InputLayout* VertexShaderCache::GetSimpleInputLayout() { return SimpleLayout; } ID3D11InputLayout* VertexShaderCache::GetSimpleInputLayout() { return SimpleLayout; }
ID3D11InputLayout* VertexShaderCache::GetClearInputLayout() { return ClearLayout; } ID3D11InputLayout* VertexShaderCache::GetClearInputLayout() { return ClearLayout; }
// maps the constant numbers to float indices in the constant buffer // maps the constant numbers to float indices in the constant buffer
unsigned int vs_constant_offset_table[C_VENVCONST_END]; unsigned int vs_constant_offset_table[C_VENVCONST_END];
void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{ {
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number] ] = f1; D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number] ] = f1;
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+1] = f2; D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+1] = f2;
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+2] = f3; D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+2] = f3;
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+3] = f4; D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+3] = f4;
D3D::gfxstate->vscbufchanged = true; D3D::gfxstate->vscbufchanged = true;
} }
void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float* f) void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float* f)
{ {
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4); memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4);
D3D::gfxstate->vscbufchanged = true; D3D::gfxstate->vscbufchanged = true;
} }
void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f) void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f)
{ {
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]], f+3*i, sizeof(float)*3); memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]], f+3*i, sizeof(float)*3);
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]+3] = 0.f; D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]+3] = 0.f;
} }
D3D::gfxstate->vscbufchanged = true; D3D::gfxstate->vscbufchanged = true;
} }
void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f) void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f)
{ {
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4*count); memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4*count);
D3D::gfxstate->vscbufchanged = true; D3D::gfxstate->vscbufchanged = true;
} }
// this class will load the precompiled shaders into our cache // this class will load the precompiled shaders into our cache
class VertexShaderCacheInserter : public LinearDiskCacheReader { class VertexShaderCacheInserter : public LinearDiskCacheReader {
public: public:
void Read(const u8* key, int key_size, const u8* value, int value_size) void Read(const u8* key, int key_size, const u8* value, int value_size)
{ {
VERTEXSHADERUID uid; VERTEXSHADERUID uid;
if (key_size != sizeof(uid)) if (key_size != sizeof(uid))
{ {
ERROR_LOG(VIDEO, "Wrong key size in vertex shader cache"); ERROR_LOG(VIDEO, "Wrong key size in vertex shader cache");
return; return;
} }
memcpy(&uid, key, key_size); memcpy(&uid, key, key_size);
D3DBlob* blob = new D3DBlob(value_size, value); D3DBlob* blob = new D3DBlob(value_size, value);
VertexShaderCache::InsertByteCode(uid, blob); VertexShaderCache::InsertByteCode(uid, blob);
blob->Release(); blob->Release();
} }
}; };
const char simple_shader_code[] = { const char simple_shader_code[] = {
"struct VSOUTPUT\n" "struct VSOUTPUT\n"
"{\n" "{\n"
"float4 vPosition : POSITION;\n" "float4 vPosition : POSITION;\n"
"float2 vTexCoord : TEXCOORD0;\n" "float2 vTexCoord : TEXCOORD0;\n"
"};\n" "};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0)\n" "VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0)\n"
"{\n" "{\n"
"VSOUTPUT OUT;\n" "VSOUTPUT OUT;\n"
"OUT.vPosition = inPosition;\n" "OUT.vPosition = inPosition;\n"
"OUT.vTexCoord = inTEX0;\n" "OUT.vTexCoord = inTEX0;\n"
"return OUT;\n" "return OUT;\n"
"}\n" "}\n"
}; };
const char clear_shader_code[] = { const char clear_shader_code[] = {
"struct VSOUTPUT\n" "struct VSOUTPUT\n"
"{\n" "{\n"
"float4 vPosition : POSITION;\n" "float4 vPosition : POSITION;\n"
"float4 vColor0 : COLOR0;\n" "float4 vColor0 : COLOR0;\n"
"};\n" "};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n" "VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n"
"{\n" "{\n"
"VSOUTPUT OUT;\n" "VSOUTPUT OUT;\n"
"OUT.vPosition = inPosition;\n" "OUT.vPosition = inPosition;\n"
"OUT.vColor0 = inColor0;\n" "OUT.vColor0 = inColor0;\n"
"return OUT;\n" "return OUT;\n"
"}\n" "}\n"
}; };
VertexShaderCache::VertexShaderCache() VertexShaderCache::VertexShaderCache()
{ {
const D3D11_INPUT_ELEMENT_DESC simpleelems[2] = const D3D11_INPUT_ELEMENT_DESC simpleelems[2] =
{ {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
}; };
const D3D11_INPUT_ELEMENT_DESC clearelems[2] = const D3D11_INPUT_ELEMENT_DESC clearelems[2] =
{ {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
}; };
D3DBlob* blob; D3DBlob* blob;
D3D::CompileVertexShader(simple_shader_code, sizeof(simple_shader_code), &blob); D3D::CompileVertexShader(simple_shader_code, sizeof(simple_shader_code), &blob);
D3D::device->CreateInputLayout(simpleelems, 2, blob->Data(), blob->Size(), &SimpleLayout); D3D::device->CreateInputLayout(simpleelems, 2, blob->Data(), blob->Size(), &SimpleLayout);
SimpleVertexShader = D3D::CreateVertexShaderFromByteCode(blob); SimpleVertexShader = D3D::CreateVertexShaderFromByteCode(blob);
if (SimpleLayout == NULL || SimpleVertexShader == NULL) PanicAlert("Failed to create simple vertex shader or input layout at %s %d\n", __FILE__, __LINE__); if (SimpleLayout == NULL || SimpleVertexShader == NULL) PanicAlert("Failed to create simple vertex shader or input layout at %s %d\n", __FILE__, __LINE__);
blob->Release(); blob->Release();
D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleVertexShader, "simple vertex shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleVertexShader, "simple vertex shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleLayout, "simple input layout"); D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleLayout, "simple input layout");
D3D::CompileVertexShader(clear_shader_code, sizeof(clear_shader_code), &blob); D3D::CompileVertexShader(clear_shader_code, sizeof(clear_shader_code), &blob);
D3D::device->CreateInputLayout(clearelems, 2, blob->Data(), blob->Size(), &ClearLayout); D3D::device->CreateInputLayout(clearelems, 2, blob->Data(), blob->Size(), &ClearLayout);
ClearVertexShader = D3D::CreateVertexShaderFromByteCode(blob); ClearVertexShader = D3D::CreateVertexShaderFromByteCode(blob);
if (ClearLayout == NULL || ClearVertexShader == NULL) PanicAlert("Failed to create clear vertex shader or input layout at %s %d\n", __FILE__, __LINE__); if (ClearLayout == NULL || ClearVertexShader == NULL) PanicAlert("Failed to create clear vertex shader or input layout at %s %d\n", __FILE__, __LINE__);
blob->Release(); blob->Release();
D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearVertexShader, "clear vertex shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearVertexShader, "clear vertex shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearLayout, "clear input layout"); D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearLayout, "clear input layout");
Clear(); Clear();
// these values are hardcoded, they depend on internal D3DCompile behavior // these values are hardcoded, they depend on internal D3DCompile behavior
// TODO: Do this with D3DReflect or something instead // TODO: Do this with D3DReflect or something instead
unsigned int k; unsigned int k;
for (k = 0;k < 6;k++) vs_constant_offset_table[C_POSNORMALMATRIX+k] = 0+4*k; for (k = 0;k < 6;k++) vs_constant_offset_table[C_POSNORMALMATRIX+k] = 0+4*k;
for (k = 0;k < 4;k++) vs_constant_offset_table[C_PROJECTION+k] = 24+4*k; for (k = 0;k < 4;k++) vs_constant_offset_table[C_PROJECTION+k] = 24+4*k;
for (k = 0;k < 4;k++) vs_constant_offset_table[C_MATERIALS+k] = 40+4*k; for (k = 0;k < 4;k++) vs_constant_offset_table[C_MATERIALS+k] = 40+4*k;
for (k = 0;k < 40;k++) vs_constant_offset_table[C_LIGHTS+k] = 56+4*k; for (k = 0;k < 40;k++) vs_constant_offset_table[C_LIGHTS+k] = 56+4*k;
for (k = 0;k < 24;k++) vs_constant_offset_table[C_TEXMATRICES+k] = 216+4*k; for (k = 0;k < 24;k++) vs_constant_offset_table[C_TEXMATRICES+k] = 216+4*k;
for (k = 0;k < 64;k++) vs_constant_offset_table[C_TRANSFORMMATRICES+k] = 312+4*k; for (k = 0;k < 64;k++) vs_constant_offset_table[C_TRANSFORMMATRICES+k] = 312+4*k;
for (k = 0;k < 32;k++) vs_constant_offset_table[C_NORMALMATRICES+k] = 568+4*k; for (k = 0;k < 32;k++) vs_constant_offset_table[C_NORMALMATRICES+k] = 568+4*k;
for (k = 0;k < 64;k++) vs_constant_offset_table[C_POSTTRANSFORMMATRICES+k] = 696+4*k; for (k = 0;k < 64;k++) vs_constant_offset_table[C_POSTTRANSFORMMATRICES+k] = 696+4*k;
for (k = 0;k < 4;k++) vs_constant_offset_table[C_DEPTHPARAMS+k] = 952+4*k; for (k = 0;k < 4;k++) vs_constant_offset_table[C_DEPTHPARAMS+k] = 952+4*k;
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
char cache_filename[MAX_PATH]; char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx11-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id); sprintf(cache_filename, "%sdx11-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
VertexShaderCacheInserter inserter; VertexShaderCacheInserter inserter;
g_vs_disk_cache.OpenAndRead(cache_filename, &inserter); g_vs_disk_cache.OpenAndRead(cache_filename, &inserter);
} }
void VertexShaderCache::Clear() void VertexShaderCache::Clear()
{ {
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter) for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter)
iter->second.Destroy(); iter->second.Destroy();
vshaders.clear(); vshaders.clear();
} }
VertexShaderCache::~VertexShaderCache() VertexShaderCache::~VertexShaderCache()
{ {
SAFE_RELEASE(SimpleVertexShader); SAFE_RELEASE(SimpleVertexShader);
SAFE_RELEASE(ClearVertexShader); SAFE_RELEASE(ClearVertexShader);
SAFE_RELEASE(SimpleLayout); SAFE_RELEASE(SimpleLayout);
SAFE_RELEASE(ClearLayout); SAFE_RELEASE(ClearLayout);
Clear(); Clear();
g_vs_disk_cache.Sync(); g_vs_disk_cache.Sync();
g_vs_disk_cache.Close(); g_vs_disk_cache.Close();
} }
bool VertexShaderCache::SetShader(u32 components) bool VertexShaderCache::SetShader(u32 components)
{ {
DVSTARTPROFILE(); DVSTARTPROFILE();
VERTEXSHADERUID uid; VERTEXSHADERUID uid;
GetVertexShaderId(&uid, components); GetVertexShaderId(&uid, components);
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount) if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
return (vshaders[uid].shader != NULL); return (vshaders[uid].shader != NULL);
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID)); memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
VSCache::iterator iter; VSCache::iterator iter;
iter = vshaders.find(uid); iter = vshaders.find(uid);
if (iter != vshaders.end()) if (iter != vshaders.end())
{ {
iter->second.frameCount = frameCount; iter->second.frameCount = frameCount;
const VSCacheEntry &entry = iter->second; const VSCacheEntry &entry = iter->second;
last_entry = &entry; last_entry = &entry;
if (entry.shader) D3D::gfxstate->SetVShader(entry.shader, iter->second.bytecode); if (entry.shader) D3D::gfxstate->SetVShader(entry.shader, iter->second.bytecode);
return (entry.shader != NULL); return (entry.shader != NULL);
} }
const char* code = GenerateVertexShaderCode(components, API_D3D11); const char* code = GenerateVertexShaderCode(components, API_D3D11);
D3DBlob* pbytecode = NULL; D3DBlob* pbytecode = NULL;
D3D::CompileVertexShader(code, (int)strlen(code), &pbytecode); D3D::CompileVertexShader(code, (int)strlen(code), &pbytecode);
if (pbytecode == NULL) if (pbytecode == NULL)
{ {
PanicAlert("Failed to compile Vertex Shader %s %d:\n\n%s", __FILE__, __LINE__, code); PanicAlert("Failed to compile Vertex Shader %s %d:\n\n%s", __FILE__, __LINE__, code);
return false; return false;
} }
g_vs_disk_cache.Append((u8*)&uid, sizeof(uid), (const u8*)pbytecode->Data(), pbytecode->Size()); g_vs_disk_cache.Append((u8*)&uid, sizeof(uid), (const u8*)pbytecode->Data(), pbytecode->Size());
g_vs_disk_cache.Sync(); g_vs_disk_cache.Sync();
bool result = InsertByteCode(uid, pbytecode); bool result = InsertByteCode(uid, pbytecode);
D3D::gfxstate->SetVShader(last_entry->shader, last_entry->bytecode); D3D::gfxstate->SetVShader(last_entry->shader, last_entry->bytecode);
pbytecode->Release(); pbytecode->Release();
return result; return result;
} }
bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, D3DBlob* bcodeblob) bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, D3DBlob* bcodeblob)
{ {
ID3D11VertexShader* shader = D3D::CreateVertexShaderFromByteCode(bcodeblob); ID3D11VertexShader* shader = D3D::CreateVertexShaderFromByteCode(bcodeblob);
if (shader == NULL) if (shader == NULL)
{ {
PanicAlert("Failed to create vertex shader from %p size %d at %s %d\n", bcodeblob->Data(), bcodeblob->Size(), __FILE__, __LINE__); PanicAlert("Failed to create vertex shader from %p size %d at %s %d\n", bcodeblob->Data(), bcodeblob->Size(), __FILE__, __LINE__);
return false; return false;
} }
// TODO: Somehow make the debug name a bit more specific // TODO: Somehow make the debug name a bit more specific
D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a vertex shader of VertexShaderCache"); D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a vertex shader of VertexShaderCache");
// Make an entry in the table // Make an entry in the table
VSCacheEntry entry; VSCacheEntry entry;
entry.shader = shader; entry.shader = shader;
entry.frameCount = frameCount; entry.frameCount = frameCount;
entry.SetByteCode(bcodeblob); entry.SetByteCode(bcodeblob);
vshaders[uid] = entry; vshaders[uid] = entry;
last_entry = &vshaders[uid]; last_entry = &vshaders[uid];
INCSTAT(stats.numVertexShadersCreated); INCSTAT(stats.numVertexShadersCreated);
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size()); SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
return true; return true;
} }
} }
@@ -1,80 +1,80 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _DX11_VERTEXSHADERCACHE_H #ifndef _DX11_VERTEXSHADERCACHE_H
#define _DX11_VERTEXSHADERCACHE_H #define _DX11_VERTEXSHADERCACHE_H
#include <map> #include <map>
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
#include "DX11_D3DBase.h" #include "DX11_D3DBase.h"
#include "../VertexShaderCache.h" #include "../VertexShaderCache.h"
namespace DX11 namespace DX11
{ {
class VertexShaderCache : public ::VertexShaderCacheBase class VertexShaderCache : public ::VertexShaderCacheBase
{ {
public: public:
VertexShaderCache(); VertexShaderCache();
~VertexShaderCache(); ~VertexShaderCache();
static void Clear(); static void Clear();
bool SetShader(u32 components); bool SetShader(u32 components);
static ID3D11VertexShader* GetSimpleVertexShader(); static ID3D11VertexShader* GetSimpleVertexShader();
static ID3D11VertexShader* GetClearVertexShader(); static ID3D11VertexShader* GetClearVertexShader();
static ID3D11InputLayout* GetSimpleInputLayout(); static ID3D11InputLayout* GetSimpleInputLayout();
static ID3D11InputLayout* GetClearInputLayout(); static ID3D11InputLayout* GetClearInputLayout();
static bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, D3DBlob* bcodeblob); static bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, D3DBlob* bcodeblob);
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4); void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
void SetVSConstant4fv(unsigned int const_number, const float* f); void SetVSConstant4fv(unsigned int const_number, const float* f);
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f); void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f);
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f); void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f);
private: private:
struct VSCacheEntry struct VSCacheEntry
{ {
ID3D11VertexShader* shader; ID3D11VertexShader* shader;
D3DBlob* bytecode; // needed to initialize the input layout D3DBlob* bytecode; // needed to initialize the input layout
int frameCount; int frameCount;
VSCacheEntry() : shader(NULL), bytecode(NULL), frameCount(0) {} VSCacheEntry() : shader(NULL), bytecode(NULL), frameCount(0) {}
void SetByteCode(D3DBlob* blob) void SetByteCode(D3DBlob* blob)
{ {
SAFE_RELEASE(bytecode); SAFE_RELEASE(bytecode);
bytecode = blob; bytecode = blob;
blob->AddRef(); blob->AddRef();
} }
void Destroy() void Destroy()
{ {
SAFE_RELEASE(shader); SAFE_RELEASE(shader);
SAFE_RELEASE(bytecode); SAFE_RELEASE(bytecode);
} }
}; };
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache; typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
static VSCache vshaders; static VSCache vshaders;
static const VSCacheEntry* last_entry; static const VSCacheEntry* last_entry;
}; };
} }
#endif // _VERTEXSHADERCACHE_H #endif // _VERTEXSHADERCACHE_H
File diff suppressed because it is too large Load Diff
@@ -1,165 +1,165 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _D3DBASE_H #ifndef _D3DBASE_H
#define _D3DBASE_H #define _D3DBASE_H
#include <vector> #include <vector>
#include <set> #include <set>
#include <d3dx9.h> #include <d3dx9.h>
#include "Common.h" #include "Common.h"
namespace DX9 namespace DX9
{ {
namespace D3D namespace D3D
{ {
#define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; } #define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; }
#define SAFE_DELETE(x) { delete (x); (x) = NULL; } #define SAFE_DELETE(x) { delete (x); (x) = NULL; }
// From http://developer.amd.com/gpu_assets/Advanced%20DX9%20Capabilities%20for%20ATI%20Radeon%20Cards.pdf // From http://developer.amd.com/gpu_assets/Advanced%20DX9%20Capabilities%20for%20ATI%20Radeon%20Cards.pdf
// Magic FourCC's to unlock undocumented D3D9 features: // Magic FourCC's to unlock undocumented D3D9 features:
// Z texture formats // Z texture formats
#define FOURCC_INTZ ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))) #define FOURCC_INTZ ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')))
#define FOURCC_RAWZ ((D3DFORMAT)(MAKEFOURCC('R','A','W','Z'))) #define FOURCC_RAWZ ((D3DFORMAT)(MAKEFOURCC('R','A','W','Z')))
#define FOURCC_DF24 ((D3DFORMAT)(MAKEFOURCC('D','F','2','4'))) #define FOURCC_DF24 ((D3DFORMAT)(MAKEFOURCC('D','F','2','4')))
#define FOURCC_DF16 ((D3DFORMAT)(MAKEFOURCC('D','F','1','6'))) #define FOURCC_DF16 ((D3DFORMAT)(MAKEFOURCC('D','F','1','6')))
// Depth buffer resolve: // Depth buffer resolve:
#define FOURCC_RESZ ((D3DFORMAT)(MAKEFOURCC('R','E','S','Z'))) #define FOURCC_RESZ ((D3DFORMAT)(MAKEFOURCC('R','E','S','Z')))
#define RESZ_CODE 0x7fa05000 #define RESZ_CODE 0x7fa05000
// Null render target to do Z-only shadow maps: (probably not useful for Dolphin) // Null render target to do Z-only shadow maps: (probably not useful for Dolphin)
#define FOURCC_NULL ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))) #define FOURCC_NULL ((D3DFORMAT)(MAKEFOURCC('N','U','L','L')))
bool IsATIDevice(); bool IsATIDevice();
HRESULT Init(); HRESULT Init();
HRESULT Create(int adapter, HWND wnd, int resolution, int aa_mode, bool auto_depth); HRESULT Create(int adapter, HWND wnd, int resolution, int aa_mode, bool auto_depth);
void Close(); void Close();
void Shutdown(); void Shutdown();
// Direct access to the device. // Direct access to the device.
extern LPDIRECT3DDEVICE9 dev; extern LPDIRECT3DDEVICE9 dev;
extern bool bFrameInProgress; extern bool bFrameInProgress;
void Reset(); void Reset();
bool BeginFrame(); bool BeginFrame();
void EndFrame(); void EndFrame();
void Present(); void Present();
bool CanUseINTZ(); bool CanUseINTZ();
int GetBackBufferWidth(); int GetBackBufferWidth();
int GetBackBufferHeight(); int GetBackBufferHeight();
LPDIRECT3DSURFACE9 GetBackBufferSurface(); LPDIRECT3DSURFACE9 GetBackBufferSurface();
LPDIRECT3DSURFACE9 GetBackBufferDepthSurface(); LPDIRECT3DSURFACE9 GetBackBufferDepthSurface();
LPDIRECT3DVERTEXBUFFER9 GetquadVB(); LPDIRECT3DVERTEXBUFFER9 GetquadVB();
LPDIRECT3DVERTEXDECLARATION9 GetBasicvertexDecl(); LPDIRECT3DVERTEXDECLARATION9 GetBasicvertexDecl();
const D3DCAPS9 &GetCaps(); const D3DCAPS9 &GetCaps();
const char *PixelShaderVersionString(); const char *PixelShaderVersionString();
const char *VertexShaderVersionString(); const char *VertexShaderVersionString();
void ShowD3DError(HRESULT err); void ShowD3DError(HRESULT err);
// The following are "filtered" versions of the corresponding D3Ddev-> functions. // The following are "filtered" versions of the corresponding D3Ddev-> functions.
void SetTexture(DWORD Stage, IDirect3DBaseTexture9 *pTexture); void SetTexture(DWORD Stage, IDirect3DBaseTexture9 *pTexture);
void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value); void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value);
void RefreshRenderState(D3DRENDERSTATETYPE State); void RefreshRenderState(D3DRENDERSTATETYPE State);
void ChangeRenderState(D3DRENDERSTATETYPE State, DWORD Value); void ChangeRenderState(D3DRENDERSTATETYPE State, DWORD Value);
void SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value); void SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
void RefreshTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type); void RefreshTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type);
void ChangeTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value); void ChangeTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value); void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
void RefreshSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type); void RefreshSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type);
void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value); void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
void RefreshVertexDeclaration(); void RefreshVertexDeclaration();
void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl); void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl);
void RefreshVertexShader(); void RefreshVertexShader();
void SetVertexShader(LPDIRECT3DVERTEXSHADER9 shader); void SetVertexShader(LPDIRECT3DVERTEXSHADER9 shader);
void RefreshPixelShader(); void RefreshPixelShader();
void SetPixelShader(LPDIRECT3DPIXELSHADER9 shader); void SetPixelShader(LPDIRECT3DPIXELSHADER9 shader);
void ApplyCachedState(); void ApplyCachedState();
// Utility functions for vendor specific hacks. So far, just the one. // Utility functions for vendor specific hacks. So far, just the one.
void EnableAlphaToCoverage(); void EnableAlphaToCoverage();
struct Resolution struct Resolution
{ {
char name[32]; char name[32];
int xres; int xres;
int yres; int yres;
std::set<D3DFORMAT> bitdepths; std::set<D3DFORMAT> bitdepths;
std::set<int> refreshes; std::set<int> refreshes;
}; };
struct AALevel struct AALevel
{ {
AALevel(const char *n, D3DMULTISAMPLE_TYPE m, int q) { AALevel(const char *n, D3DMULTISAMPLE_TYPE m, int q) {
strncpy(name, n, 32); strncpy(name, n, 32);
name[31] = '\0'; name[31] = '\0';
ms_setting = m; ms_setting = m;
qual_setting = q; qual_setting = q;
} }
char name[32]; char name[32];
D3DMULTISAMPLE_TYPE ms_setting; D3DMULTISAMPLE_TYPE ms_setting;
int qual_setting; int qual_setting;
}; };
struct Adapter struct Adapter
{ {
D3DADAPTER_IDENTIFIER9 ident; D3DADAPTER_IDENTIFIER9 ident;
std::vector<Resolution> resolutions; std::vector<Resolution> resolutions;
std::vector<AALevel> aa_levels; std::vector<AALevel> aa_levels;
bool supports_alpha_to_coverage; bool supports_alpha_to_coverage;
// Magic render targets, see the top of this file. // Magic render targets, see the top of this file.
bool supports_intz; bool supports_intz;
bool supports_rawz; bool supports_rawz;
bool supports_resz; bool supports_resz;
bool supports_null; bool supports_null;
}; };
const Adapter &GetAdapter(int i); const Adapter &GetAdapter(int i);
const Adapter &GetCurAdapter(); const Adapter &GetCurAdapter();
int GetNumAdapters(); int GetNumAdapters();
} // namespace } // namespace
// Used to not require the SDK and runtime versions to match: // Used to not require the SDK and runtime versions to match:
// Linking with d3dx9.lib makes the most recent d3dx9_xx.dll of the // Linking with d3dx9.lib makes the most recent d3dx9_xx.dll of the
// compiler's SDK an actually unnecessary requirement. // compiler's SDK an actually unnecessary requirement.
// Add any d3dx9 functions which you want to use here and load them in LoadD3DX9() // Add any d3dx9 functions which you want to use here and load them in LoadD3DX9()
typedef HRESULT (WINAPI* D3DXSAVESURFACETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DSURFACE9, CONST PALETTEENTRY*, CONST RECT*); typedef HRESULT (WINAPI* D3DXSAVESURFACETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DSURFACE9, CONST PALETTEENTRY*, CONST RECT*);
typedef HRESULT (WINAPI* D3DXSAVETEXTURETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DBASETEXTURE9, CONST PALETTEENTRY*); typedef HRESULT (WINAPI* D3DXSAVETEXTURETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DBASETEXTURE9, CONST PALETTEENTRY*);
typedef HRESULT (WINAPI* D3DXCOMPILESHADERTYPE)(LPCSTR, UINT, CONST D3DXMACRO*, LPD3DXINCLUDE, LPCSTR, LPCSTR, DWORD, LPD3DXBUFFER*, LPD3DXBUFFER*, LPD3DXCONSTANTTABLE*); typedef HRESULT (WINAPI* D3DXCOMPILESHADERTYPE)(LPCSTR, UINT, CONST D3DXMACRO*, LPD3DXINCLUDE, LPCSTR, LPCSTR, DWORD, LPD3DXBUFFER*, LPD3DXBUFFER*, LPD3DXCONSTANTTABLE*);
extern D3DXSAVESURFACETOFILEATYPE PD3DXSaveSurfaceToFileA; extern D3DXSAVESURFACETOFILEATYPE PD3DXSaveSurfaceToFileA;
extern D3DXSAVETEXTURETOFILEATYPE PD3DXSaveTextureToFileA; extern D3DXSAVETEXTURETOFILEATYPE PD3DXSaveTextureToFileA;
extern D3DXCOMPILESHADERTYPE PD3DXCompileShader; extern D3DXCOMPILESHADERTYPE PD3DXCompileShader;
} }
#endif #endif
@@ -1,150 +1,150 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <d3dx9.h> #include <d3dx9.h>
#include <string> #include <string>
#include "VideoConfig.h" #include "VideoConfig.h"
#include "DX9_D3DShader.h" #include "DX9_D3DShader.h"
namespace DX9 namespace DX9
{ {
namespace D3D namespace D3D
{ {
// Bytecode->shader. // Bytecode->shader.
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len) LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len)
{ {
LPDIRECT3DVERTEXSHADER9 v_shader; LPDIRECT3DVERTEXSHADER9 v_shader;
HRESULT hr = D3D::dev->CreateVertexShader((DWORD *)bytecode, &v_shader); HRESULT hr = D3D::dev->CreateVertexShader((DWORD *)bytecode, &v_shader);
if (FAILED(hr)) if (FAILED(hr))
v_shader = 0; v_shader = 0;
return v_shader; return v_shader;
} }
// Code->bytecode. // Code->bytecode.
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen) bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
{ {
//try to compile //try to compile
LPD3DXBUFFER shaderBuffer = 0; LPD3DXBUFFER shaderBuffer = 0;
LPD3DXBUFFER errorBuffer = 0; LPD3DXBUFFER errorBuffer = 0;
HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::VertexShaderVersionString(), HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::VertexShaderVersionString(),
0, &shaderBuffer, &errorBuffer, 0); 0, &shaderBuffer, &errorBuffer, 0);
if (FAILED(hr)) if (FAILED(hr))
{ {
//compilation error //compilation error
if (g_ActiveConfig.bShowShaderErrors) { if (g_ActiveConfig.bShowShaderErrors) {
std::string hello = (char*)errorBuffer->GetBufferPointer(); std::string hello = (char*)errorBuffer->GetBufferPointer();
hello += "\n\n"; hello += "\n\n";
hello += code; hello += code;
MessageBoxA(0, hello.c_str(), "Error compiling vertex shader", MB_ICONERROR); MessageBoxA(0, hello.c_str(), "Error compiling vertex shader", MB_ICONERROR);
} }
*bytecode = 0; *bytecode = 0;
*bytecodelen = 0; *bytecodelen = 0;
} }
else if (SUCCEEDED(hr)) else if (SUCCEEDED(hr))
{ {
*bytecodelen = shaderBuffer->GetBufferSize(); *bytecodelen = shaderBuffer->GetBufferSize();
*bytecode = new u8[*bytecodelen]; *bytecode = new u8[*bytecodelen];
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen); memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
} }
//cleanup //cleanup
if (shaderBuffer) if (shaderBuffer)
shaderBuffer->Release(); shaderBuffer->Release();
if (errorBuffer) if (errorBuffer)
errorBuffer->Release(); errorBuffer->Release();
return SUCCEEDED(hr) ? true : false; return SUCCEEDED(hr) ? true : false;
} }
// Bytecode->shader. // Bytecode->shader.
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len) LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len)
{ {
LPDIRECT3DPIXELSHADER9 p_shader; LPDIRECT3DPIXELSHADER9 p_shader;
HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)bytecode, &p_shader); HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)bytecode, &p_shader);
if (FAILED(hr)) if (FAILED(hr))
p_shader = 0; p_shader = 0;
return p_shader; return p_shader;
} }
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen) bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
{ {
LPD3DXBUFFER shaderBuffer = 0; LPD3DXBUFFER shaderBuffer = 0;
LPD3DXBUFFER errorBuffer = 0; LPD3DXBUFFER errorBuffer = 0;
// Someone: // Someone:
// For some reason, I had this kind of errors : "Shader uses texture addressing operations // For some reason, I had this kind of errors : "Shader uses texture addressing operations
// in a dependency chain that is too complex for the target shader model (ps_2_0) to handle." // in a dependency chain that is too complex for the target shader model (ps_2_0) to handle."
HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::PixelShaderVersionString(), HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::PixelShaderVersionString(),
0, &shaderBuffer, &errorBuffer, 0); 0, &shaderBuffer, &errorBuffer, 0);
if (FAILED(hr)) if (FAILED(hr))
{ {
if (g_ActiveConfig.bShowShaderErrors) { if (g_ActiveConfig.bShowShaderErrors) {
std::string hello = (char*)errorBuffer->GetBufferPointer(); std::string hello = (char*)errorBuffer->GetBufferPointer();
hello += "\n\n"; hello += "\n\n";
hello += code; hello += code;
MessageBoxA(0, hello.c_str(), "Error compiling pixel shader", MB_ICONERROR); MessageBoxA(0, hello.c_str(), "Error compiling pixel shader", MB_ICONERROR);
} }
*bytecode = 0; *bytecode = 0;
*bytecodelen = 0; *bytecodelen = 0;
} }
else if (SUCCEEDED(hr)) else if (SUCCEEDED(hr))
{ {
*bytecodelen = shaderBuffer->GetBufferSize(); *bytecodelen = shaderBuffer->GetBufferSize();
*bytecode = new u8[*bytecodelen]; *bytecode = new u8[*bytecodelen];
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen); memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
} }
//cleanup //cleanup
if (shaderBuffer) if (shaderBuffer)
shaderBuffer->Release(); shaderBuffer->Release();
if (errorBuffer) if (errorBuffer)
errorBuffer->Release(); errorBuffer->Release();
return SUCCEEDED(hr) ? true : false; return SUCCEEDED(hr) ? true : false;
} }
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len) { LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len) {
u8 *bytecode; u8 *bytecode;
int bytecodelen; int bytecodelen;
if (CompileVertexShader(code, len, &bytecode, &bytecodelen)) { if (CompileVertexShader(code, len, &bytecode, &bytecodelen)) {
LPDIRECT3DVERTEXSHADER9 v_shader = CreateVertexShaderFromByteCode(bytecode, len); LPDIRECT3DVERTEXSHADER9 v_shader = CreateVertexShaderFromByteCode(bytecode, len);
delete [] bytecode; delete [] bytecode;
return v_shader; return v_shader;
} else { } else {
return 0; return 0;
} }
} }
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len) { LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len) {
u8 *bytecode; u8 *bytecode;
int bytecodelen; int bytecodelen;
if (CompilePixelShader(code, len, &bytecode, &bytecodelen)) { if (CompilePixelShader(code, len, &bytecode, &bytecodelen)) {
LPDIRECT3DPIXELSHADER9 p_shader = CreatePixelShaderFromByteCode(bytecode, len); LPDIRECT3DPIXELSHADER9 p_shader = CreatePixelShaderFromByteCode(bytecode, len);
delete [] bytecode; delete [] bytecode;
return p_shader; return p_shader;
} else { } else {
return 0; return 0;
} }
} }
} // namespace } // namespace
} }
@@ -1,39 +1,39 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#pragma once #pragma once
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
namespace DX9 namespace DX9
{ {
namespace D3D namespace D3D
{ {
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len); LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len);
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len); LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len);
// The returned bytecode buffers should be delete[]-d. // The returned bytecode buffers should be delete[]-d.
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen); bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen); bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
// Utility functions // Utility functions
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len); LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len);
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len); LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len);
} }
} }
@@ -1,275 +1,275 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include "DX9_D3DTexture.h" #include "DX9_D3DTexture.h"
namespace DX9 namespace DX9
{ {
namespace D3D namespace D3D
{ {
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int levels) LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int levels)
{ {
u32* pBuffer = (u32*)buffer; u32* pBuffer = (u32*)buffer;
LPDIRECT3DTEXTURE9 pTexture; LPDIRECT3DTEXTURE9 pTexture;
// crazy bitmagic, sorry :) // crazy bitmagic, sorry :)
bool isPow2 = !((width&(width-1)) || (height&(height-1))); bool isPow2 = !((width&(width-1)) || (height&(height-1)));
bool bExpand = false; bool bExpand = false;
if (fmt == D3DFMT_A8P8) { if (fmt == D3DFMT_A8P8) {
fmt = D3DFMT_A8L8; fmt = D3DFMT_A8L8;
bExpand = true; bExpand = true;
} }
HRESULT hr; HRESULT hr;
// TODO(ector): Allow mipmaps for non-pow textures on newer cards? // TODO(ector): Allow mipmaps for non-pow textures on newer cards?
// TODO(ector): Use the game-specified mipmaps? // TODO(ector): Use the game-specified mipmaps?
if (levels > 0) if (levels > 0)
hr = dev->CreateTexture(width, height, levels, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL); hr = dev->CreateTexture(width, height, levels, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
else else
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL); hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
if (FAILED(hr)) if (FAILED(hr))
return 0; return 0;
int level = 0; int level = 0;
D3DLOCKED_RECT Lock; D3DLOCKED_RECT Lock;
pTexture->LockRect(level, &Lock, NULL, 0); pTexture->LockRect(level, &Lock, NULL, 0);
switch (fmt) switch (fmt)
{ {
case D3DFMT_L8: case D3DFMT_L8:
case D3DFMT_A8: case D3DFMT_A8:
case D3DFMT_A4L4: case D3DFMT_A4L4:
{ {
const u8 *pIn = buffer; const u8 *pIn = buffer;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch)); u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width); memcpy(pBits, pIn, width);
pIn += pitch; pIn += pitch;
} }
} }
break; break;
case D3DFMT_R5G6B5: case D3DFMT_R5G6B5:
{ {
const u16 *pIn = (u16*)buffer; const u16 *pIn = (u16*)buffer;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch)); u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 2); memcpy(pBits, pIn, width * 2);
pIn += pitch; pIn += pitch;
} }
} }
break; break;
case D3DFMT_A8L8: case D3DFMT_A8L8:
{ {
if (bExpand) { // I8 if (bExpand) { // I8
const u8 *pIn = buffer; const u8 *pIn = buffer;
// TODO(XK): Find a better way that does not involve either unpacking // TODO(XK): Find a better way that does not involve either unpacking
// or downsampling (i.e. A4L4) // or downsampling (i.e. A4L4)
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch)); u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
for(int i = 0; i < width * 2; i += 2) { for(int i = 0; i < width * 2; i += 2) {
pBits[i] = pIn[i / 2]; pBits[i] = pIn[i / 2];
pBits[i + 1] = pIn[i / 2]; pBits[i + 1] = pIn[i / 2];
} }
pIn += pitch; pIn += pitch;
} }
} else { // IA8 } else { // IA8
const u16 *pIn = (u16*)buffer; const u16 *pIn = (u16*)buffer;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch)); u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 2); memcpy(pBits, pIn, width * 2);
pIn += pitch; pIn += pitch;
} }
} }
} }
break; break;
case D3DFMT_A8R8G8B8: case D3DFMT_A8R8G8B8:
{ {
if(pitch * 4 == Lock.Pitch && !swap_r_b) if(pitch * 4 == Lock.Pitch && !swap_r_b)
{ {
memcpy(Lock.pBits,buffer,Lock.Pitch*height); memcpy(Lock.pBits,buffer,Lock.Pitch*height);
} }
else else
{ {
u32* pIn = pBuffer; u32* pIn = pBuffer;
if (!swap_r_b) { if (!swap_r_b) {
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch)); u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 4); memcpy(pBits, pIn, width * 4);
pIn += pitch; pIn += pitch;
} }
} else { } else {
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
u8 *pIn8 = (u8 *)pIn; u8 *pIn8 = (u8 *)pIn;
u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch)); u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
for (int x = 0; x < width * 4; x += 4) { for (int x = 0; x < width * 4; x += 4) {
pBits[x + 0] = pIn8[x + 2]; pBits[x + 0] = pIn8[x + 2];
pBits[x + 1] = pIn8[x + 1]; pBits[x + 1] = pIn8[x + 1];
pBits[x + 2] = pIn8[x + 0]; pBits[x + 2] = pIn8[x + 0];
pBits[x + 3] = pIn8[x + 3]; pBits[x + 3] = pIn8[x + 3];
} }
pIn += pitch; pIn += pitch;
} }
} }
} }
} }
break; break;
case D3DFMT_DXT1: case D3DFMT_DXT1:
memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8); memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
break; break;
default: default:
PanicAlert("D3D: Invalid texture format %i", fmt); PanicAlert("D3D: Invalid texture format %i", fmt);
} }
pTexture->UnlockRect(level); pTexture->UnlockRect(level);
return pTexture; return pTexture;
} }
LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt) LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt)
{ {
LPDIRECT3DTEXTURE9 pTexture; LPDIRECT3DTEXTURE9 pTexture;
// crazy bitmagic, sorry :) // crazy bitmagic, sorry :)
bool isPow2 = !((width&(width-1)) || (height&(height-1))); bool isPow2 = !((width&(width-1)) || (height&(height-1)));
bool bExpand = false; bool bExpand = false;
HRESULT hr; HRESULT hr;
// TODO(ector): Allow mipmaps for non-pow textures on newer cards? // TODO(ector): Allow mipmaps for non-pow textures on newer cards?
// TODO(ector): Use the game-specified mipmaps? // TODO(ector): Use the game-specified mipmaps?
if (!isPow2) if (!isPow2)
hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL); hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
else else
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL); hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
if (FAILED(hr)) if (FAILED(hr))
return 0; return 0;
return pTexture; return pTexture;
} }
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level) void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level)
{ {
u32* pBuffer = (u32*)buffer; u32* pBuffer = (u32*)buffer;
D3DLOCKED_RECT Lock; D3DLOCKED_RECT Lock;
pTexture->LockRect(level, &Lock, NULL, 0); pTexture->LockRect(level, &Lock, NULL, 0);
u32* pIn = pBuffer; u32* pIn = pBuffer;
bool bExpand = false; bool bExpand = false;
if (fmt == D3DFMT_A8P8) { if (fmt == D3DFMT_A8P8) {
fmt = D3DFMT_A8L8; fmt = D3DFMT_A8L8;
bExpand = true; bExpand = true;
} }
switch (fmt) switch (fmt)
{ {
case D3DFMT_A8R8G8B8: case D3DFMT_A8R8G8B8:
if(pitch * 4 == Lock.Pitch && !swap_r_b) if(pitch * 4 == Lock.Pitch && !swap_r_b)
{ {
memcpy(Lock.pBits, pBuffer, Lock.Pitch*height); memcpy(Lock.pBits, pBuffer, Lock.Pitch*height);
} }
else if (!swap_r_b) else if (!swap_r_b)
{ {
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch)); u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 4); memcpy(pBits, pIn, width * 4);
pIn += pitch; pIn += pitch;
} }
} }
else else
{ {
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
u8 *pIn8 = (u8 *)pIn; u8 *pIn8 = (u8 *)pIn;
u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch)); u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
for (int x = 0; x < width * 4; x += 4) for (int x = 0; x < width * 4; x += 4)
{ {
pBits[x + 0] = pIn8[x + 2]; pBits[x + 0] = pIn8[x + 2];
pBits[x + 1] = pIn8[x + 1]; pBits[x + 1] = pIn8[x + 1];
pBits[x + 2] = pIn8[x + 0]; pBits[x + 2] = pIn8[x + 0];
pBits[x + 3] = pIn8[x + 3]; pBits[x + 3] = pIn8[x + 3];
} }
pIn += pitch; pIn += pitch;
} }
} }
break; break;
case D3DFMT_L8: case D3DFMT_L8:
case D3DFMT_A8: case D3DFMT_A8:
case D3DFMT_A4L4: case D3DFMT_A4L4:
{ {
const u8 *pIn = buffer; const u8 *pIn = buffer;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch)); u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width); memcpy(pBits, pIn, width);
pIn += pitch; pIn += pitch;
} }
} }
break; break;
case D3DFMT_R5G6B5: case D3DFMT_R5G6B5:
{ {
const u16 *pIn = (u16*)buffer; const u16 *pIn = (u16*)buffer;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch)); u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 2); memcpy(pBits, pIn, width * 2);
pIn += pitch; pIn += pitch;
} }
} }
break; break;
case D3DFMT_A8L8: case D3DFMT_A8L8:
{ {
if (bExpand) { // I8 if (bExpand) { // I8
const u8 *pIn = buffer; const u8 *pIn = buffer;
// TODO(XK): Find a better way that does not involve either unpacking // TODO(XK): Find a better way that does not involve either unpacking
// or downsampling (i.e. A4L4) // or downsampling (i.e. A4L4)
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch)); u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
for(int i = 0; i < width * 2; i += 2) { for(int i = 0; i < width * 2; i += 2) {
pBits[i] = pIn[i / 2]; pBits[i] = pIn[i / 2];
pBits[i + 1] = pIn[i / 2]; pBits[i + 1] = pIn[i / 2];
} }
pIn += pitch; pIn += pitch;
} }
} else { // IA8 } else { // IA8
const u16 *pIn = (u16*)buffer; const u16 *pIn = (u16*)buffer;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch)); u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 2); memcpy(pBits, pIn, width * 2);
pIn += pitch; pIn += pitch;
} }
} }
} }
break; break;
case D3DFMT_DXT1: case D3DFMT_DXT1:
memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8); memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
break; break;
} }
pTexture->UnlockRect(level); pTexture->UnlockRect(level);
} }
} // namespace } // namespace
} }
@@ -1,34 +1,34 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#pragma once #pragma once
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
namespace DX9 namespace DX9
{ {
namespace D3D namespace D3D
{ {
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt = D3DFMT_A8R8G8B8, bool swap_r_b = false, int levels = 1); LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt = D3DFMT_A8R8G8B8, bool swap_r_b = false, int levels = 1);
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level = 0); void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level = 0);
LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height); LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height);
LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height); LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height);
LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt); LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt);
} }
} }
@@ -1,447 +1,447 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "Common.h"
#include "StringUtil.h" #include "StringUtil.h"
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include "DX9_D3DUtil.h" #include "DX9_D3DUtil.h"
#include "DX9_Render.h" #include "DX9_Render.h"
namespace DX9 namespace DX9
{ {
namespace D3D namespace D3D
{ {
CD3DFont font; CD3DFont font;
#define MAX_NUM_VERTICES 50*6 #define MAX_NUM_VERTICES 50*6
struct FONT2DVERTEX { struct FONT2DVERTEX {
float x,y,z; float x,y,z;
float rhw; float rhw;
u32 color; u32 color;
float tu, tv; float tu, tv;
}; };
#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1) #define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1) #define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1)
inline FONT2DVERTEX InitFont2DVertex(float x, float y, u32 color, float tu, float tv) inline FONT2DVERTEX InitFont2DVertex(float x, float y, u32 color, float tu, float tv)
{ {
FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv; FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv;
return v; return v;
} }
CD3DFont::CD3DFont() CD3DFont::CD3DFont()
{ {
m_pTexture = NULL; m_pTexture = NULL;
m_pVB = NULL; m_pVB = NULL;
} }
enum {m_dwTexWidth = 512, m_dwTexHeight = 512}; enum {m_dwTexWidth = 512, m_dwTexHeight = 512};
int CD3DFont::Init() int CD3DFont::Init()
{ {
// Create vertex buffer for the letters // Create vertex buffer for the letters
HRESULT hr; HRESULT hr;
if (FAILED(hr = dev->CreateVertexBuffer(MAX_NUM_VERTICES*sizeof(FONT2DVERTEX), if (FAILED(hr = dev->CreateVertexBuffer(MAX_NUM_VERTICES*sizeof(FONT2DVERTEX),
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &m_pVB, NULL))) D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &m_pVB, NULL)))
{ {
return hr; return hr;
} }
m_fTextScale = 1.0f; // Draw fonts into texture without scaling m_fTextScale = 1.0f; // Draw fonts into texture without scaling
// Prepare to create a bitmap // Prepare to create a bitmap
int *pBitmapBits; int *pBitmapBits;
BITMAPINFO bmi; BITMAPINFO bmi;
ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER)); ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = (int)m_dwTexWidth; bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
bmi.bmiHeader.biHeight = -(int)m_dwTexHeight; bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biBitCount = 32;
// Create a DC and a bitmap for the font // Create a DC and a bitmap for the font
HDC hDC = CreateCompatibleDC(NULL); HDC hDC = CreateCompatibleDC(NULL);
HBITMAP hbmBitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (VOID**)&pBitmapBits, NULL, 0); HBITMAP hbmBitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (VOID**)&pBitmapBits, NULL, 0);
SetMapMode(hDC, MM_TEXT); SetMapMode(hDC, MM_TEXT);
// Create a font. By specifying ANTIALIASED_QUALITY, we might get an // Create a font. By specifying ANTIALIASED_QUALITY, we might get an
// antialiased font, but this is not guaranteed. // antialiased font, but this is not guaranteed.
// We definitely don't want to get it cleartype'd, anyway. // We definitely don't want to get it cleartype'd, anyway.
int m_dwFontHeight = 24; int m_dwFontHeight = 24;
int nHeight = -MulDiv(m_dwFontHeight, int(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72); int nHeight = -MulDiv(m_dwFontHeight, int(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72);
int dwBold = FW_NORMAL; ///FW_BOLD int dwBold = FW_NORMAL; ///FW_BOLD
HFONT hFont = CreateFont(nHeight, 0, 0, 0, dwBold, 0, HFONT hFont = CreateFont(nHeight, 0, 0, 0, dwBold, 0,
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
VARIABLE_PITCH, _T("Tahoma")); VARIABLE_PITCH, _T("Tahoma"));
if (NULL == hFont) if (NULL == hFont)
return E_FAIL; return E_FAIL;
HGDIOBJ hOldbmBitmap = SelectObject(hDC, hbmBitmap); HGDIOBJ hOldbmBitmap = SelectObject(hDC, hbmBitmap);
HGDIOBJ hOldFont = SelectObject(hDC, hFont); HGDIOBJ hOldFont = SelectObject(hDC, hFont);
// Set text properties // Set text properties
SetTextColor(hDC, 0xFFFFFF); SetTextColor(hDC, 0xFFFFFF);
SetBkColor (hDC, 0); SetBkColor (hDC, 0);
SetTextAlign(hDC, TA_TOP); SetTextAlign(hDC, TA_TOP);
// Loop through all printable character and output them to the bitmap.. // Loop through all printable character and output them to the bitmap..
// Meanwhile, keep track of the corresponding tex coords for each character. // Meanwhile, keep track of the corresponding tex coords for each character.
int x = 0, y = 0; int x = 0, y = 0;
char str[2] = "\0"; char str[2] = "\0";
for (int c = 0; c < 127 - 32; c++) for (int c = 0; c < 127 - 32; c++)
{ {
str[0] = c + 32; str[0] = c + 32;
SIZE size; SIZE size;
GetTextExtentPoint32A(hDC, str, 1, &size); GetTextExtentPoint32A(hDC, str, 1, &size);
if ((int)(x+size.cx+1) > m_dwTexWidth) if ((int)(x+size.cx+1) > m_dwTexWidth)
{ {
x = 0; x = 0;
y += size.cy + 1; y += size.cy + 1;
} }
ExtTextOutA(hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL); ExtTextOutA(hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL);
m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth; m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth;
m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight; m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight;
m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth; m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth;
m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight; m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight;
x += size.cx + 3; //3 to work around annoying ij conflict (part of the j ends up with the i) x += size.cx + 3; //3 to work around annoying ij conflict (part of the j ends up with the i)
} }
// Create a new texture for the font // Create a new texture for the font
hr = dev->CreateTexture(m_dwTexWidth, m_dwTexHeight, 1, D3DUSAGE_DYNAMIC, hr = dev->CreateTexture(m_dwTexWidth, m_dwTexHeight, 1, D3DUSAGE_DYNAMIC,
D3DFMT_A4R4G4B4, D3DPOOL_DEFAULT, &m_pTexture, NULL); D3DFMT_A4R4G4B4, D3DPOOL_DEFAULT, &m_pTexture, NULL);
if (FAILED(hr)) if (FAILED(hr))
{ {
PanicAlert("Failed to create font texture"); PanicAlert("Failed to create font texture");
return hr; return hr;
} }
// Lock the surface and write the alpha values for the set pixels // Lock the surface and write the alpha values for the set pixels
D3DLOCKED_RECT d3dlr; D3DLOCKED_RECT d3dlr;
m_pTexture->LockRect(0, &d3dlr, 0, D3DLOCK_DISCARD); m_pTexture->LockRect(0, &d3dlr, 0, D3DLOCK_DISCARD);
int bAlpha; // 4-bit measure of pixel intensity int bAlpha; // 4-bit measure of pixel intensity
for (y = 0; y < m_dwTexHeight; y++) for (y = 0; y < m_dwTexHeight; y++)
{ {
u16 *pDst16 = (u16*)((u8 *)d3dlr.pBits + y * d3dlr.Pitch); u16 *pDst16 = (u16*)((u8 *)d3dlr.pBits + y * d3dlr.Pitch);
for (x = 0; x < m_dwTexWidth; x++) for (x = 0; x < m_dwTexWidth; x++)
{ {
bAlpha = ((pBitmapBits[m_dwTexWidth * y + x] & 0xff) >> 4); bAlpha = ((pBitmapBits[m_dwTexWidth * y + x] & 0xff) >> 4);
pDst16[x] = (bAlpha << 12) | 0x0fff; pDst16[x] = (bAlpha << 12) | 0x0fff;
} }
} }
// Done updating texture, so clean up used objects // Done updating texture, so clean up used objects
m_pTexture->UnlockRect(0); m_pTexture->UnlockRect(0);
SelectObject(hDC, hOldbmBitmap); SelectObject(hDC, hOldbmBitmap);
DeleteObject(hbmBitmap); DeleteObject(hbmBitmap);
SelectObject(hDC, hOldFont); SelectObject(hDC, hOldFont);
DeleteObject(hFont); DeleteObject(hFont);
return S_OK; return S_OK;
} }
int CD3DFont::Shutdown() int CD3DFont::Shutdown()
{ {
m_pVB->Release(); m_pVB->Release();
m_pVB = NULL; m_pVB = NULL;
m_pTexture->Release(); m_pTexture->Release();
m_pTexture = NULL; m_pTexture = NULL;
return S_OK; return S_OK;
} }
const int RS[6][2] = const int RS[6][2] =
{ {
{D3DRS_ALPHABLENDENABLE, TRUE}, {D3DRS_ALPHABLENDENABLE, TRUE},
{D3DRS_SRCBLEND, D3DBLEND_SRCALPHA}, {D3DRS_SRCBLEND, D3DBLEND_SRCALPHA},
{D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA}, {D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA},
{D3DRS_CULLMODE, D3DCULL_NONE}, {D3DRS_CULLMODE, D3DCULL_NONE},
{D3DRS_ZENABLE, FALSE}, {D3DRS_ZENABLE, FALSE},
{D3DRS_FOGENABLE, FALSE}, {D3DRS_FOGENABLE, FALSE},
}; };
const int TS[6][2] = const int TS[6][2] =
{ {
{D3DTSS_COLOROP, D3DTOP_MODULATE}, {D3DTSS_COLOROP, D3DTOP_MODULATE},
{D3DTSS_COLORARG1, D3DTA_TEXTURE}, {D3DTSS_COLORARG1, D3DTA_TEXTURE},
{D3DTSS_COLORARG2, D3DTA_DIFFUSE }, {D3DTSS_COLORARG2, D3DTA_DIFFUSE },
{D3DTSS_ALPHAOP, D3DTOP_MODULATE }, {D3DTSS_ALPHAOP, D3DTOP_MODULATE },
{D3DTSS_ALPHAARG1, D3DTA_TEXTURE }, {D3DTSS_ALPHAARG1, D3DTA_TEXTURE },
{D3DTSS_ALPHAARG2, D3DTA_DIFFUSE }, {D3DTSS_ALPHAARG2, D3DTA_DIFFUSE },
}; };
static LPDIRECT3DPIXELSHADER9 ps_old = NULL; static LPDIRECT3DPIXELSHADER9 ps_old = NULL;
static LPDIRECT3DVERTEXSHADER9 vs_old = NULL; static LPDIRECT3DVERTEXSHADER9 vs_old = NULL;
void RestoreShaders() void RestoreShaders()
{ {
D3D::SetTexture(0, 0); D3D::SetTexture(0, 0);
D3D::RefreshVertexDeclaration(); D3D::RefreshVertexDeclaration();
D3D::RefreshPixelShader(); D3D::RefreshPixelShader();
D3D::RefreshVertexShader(); D3D::RefreshVertexShader();
} }
void RestoreRenderStates() void RestoreRenderStates()
{ {
RestoreShaders(); RestoreShaders();
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
D3D::RefreshRenderState((_D3DRENDERSTATETYPE)RS[i][0]); D3D::RefreshRenderState((_D3DRENDERSTATETYPE)RS[i][0]);
D3D::RefreshTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0])); D3D::RefreshTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]));
} }
} }
void CD3DFont::SetRenderStates() void CD3DFont::SetRenderStates()
{ {
D3D::SetTexture(0, m_pTexture); D3D::SetTexture(0, m_pTexture);
dev->SetPixelShader(0); dev->SetPixelShader(0);
dev->SetVertexShader(0); dev->SetVertexShader(0);
dev->SetFVF(D3DFVF_FONT2DVERTEX); dev->SetFVF(D3DFVF_FONT2DVERTEX);
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
D3D::ChangeRenderState((_D3DRENDERSTATETYPE)RS[i][0], RS[i][1]); D3D::ChangeRenderState((_D3DRENDERSTATETYPE)RS[i][0], RS[i][1]);
D3D::ChangeTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1]); D3D::ChangeTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1]);
} }
} }
int CD3DFont::DrawTextScaled(float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const char* strText, bool center) int CD3DFont::DrawTextScaled(float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const char* strText, bool center)
{ {
if (!m_pVB) if (!m_pVB)
return 0; return 0;
SetRenderStates(); SetRenderStates();
dev->SetStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX)); dev->SetStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX));
float vpWidth = 1; float vpWidth = 1;
float vpHeight = 1; float vpHeight = 1;
float sx = x*vpWidth-0.5f; float sx = x*vpWidth-0.5f;
float sy = y*vpHeight-0.5f; float sy = y*vpHeight-0.5f;
float fStartX = sx; float fStartX = sx;
float invLineHeight = 1.0f / ((m_fTexCoords[0][3] - m_fTexCoords[0][1]) * m_dwTexHeight); float invLineHeight = 1.0f / ((m_fTexCoords[0][3] - m_fTexCoords[0][1]) * m_dwTexHeight);
// Fill vertex buffer // Fill vertex buffer
FONT2DVERTEX* pVertices; FONT2DVERTEX* pVertices;
int dwNumTriangles = 0L; int dwNumTriangles = 0L;
m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD); m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
const char *oldstrText=strText; const char *oldstrText=strText;
//First, let's measure the text //First, let's measure the text
float tw=0; float tw=0;
float mx=0; float mx=0;
float maxx=0; float maxx=0;
while (*strText) while (*strText)
{ {
char c = *strText++; char c = *strText++;
if (c == ('\n')) if (c == ('\n'))
mx = 0; mx = 0;
if (c < (' ')) if (c < (' '))
continue; continue;
float tx1 = m_fTexCoords[c-32][0]; float tx1 = m_fTexCoords[c-32][0];
float tx2 = m_fTexCoords[c-32][2]; float tx2 = m_fTexCoords[c-32][2];
float w = (tx2-tx1)*m_dwTexWidth; float w = (tx2-tx1)*m_dwTexWidth;
w *= (fXScale*vpHeight)*invLineHeight; w *= (fXScale*vpHeight)*invLineHeight;
mx += w + spacing*fXScale*vpWidth; mx += w + spacing*fXScale*vpWidth;
if (mx > maxx) maxx = mx; if (mx > maxx) maxx = mx;
} }
float offset = -maxx/2; float offset = -maxx/2;
strText = oldstrText; strText = oldstrText;
//Then let's draw it //Then let's draw it
if (center) if (center)
{ {
sx+=offset; sx+=offset;
fStartX+=offset; fStartX+=offset;
} }
float wScale = (fXScale*vpHeight)*invLineHeight; float wScale = (fXScale*vpHeight)*invLineHeight;
float hScale = (fYScale*vpHeight)*invLineHeight; float hScale = (fYScale*vpHeight)*invLineHeight;
while (*strText) while (*strText)
{ {
char c = *strText++; char c = *strText++;
if (c == ('\n')) if (c == ('\n'))
{ {
sx = fStartX; sx = fStartX;
sy += fYScale*vpHeight; sy += fYScale*vpHeight;
} }
if (c < (' ')) if (c < (' '))
continue; continue;
c-=32; c-=32;
float tx1 = m_fTexCoords[c][0]; float tx1 = m_fTexCoords[c][0];
float ty1 = m_fTexCoords[c][1]; float ty1 = m_fTexCoords[c][1];
float tx2 = m_fTexCoords[c][2]; float tx2 = m_fTexCoords[c][2];
float ty2 = m_fTexCoords[c][3]; float ty2 = m_fTexCoords[c][3];
float w = (tx2-tx1)*m_dwTexWidth; float w = (tx2-tx1)*m_dwTexWidth;
float h = (ty2-ty1)*m_dwTexHeight; float h = (ty2-ty1)*m_dwTexHeight;
w *= wScale; w *= wScale;
h *= hScale; h *= hScale;
FONT2DVERTEX v[6]; FONT2DVERTEX v[6];
v[0] = InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2); v[0] = InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2);
v[1] = InitFont2DVertex(sx, sy, dwColor, tx1, ty1); v[1] = InitFont2DVertex(sx, sy, dwColor, tx1, ty1);
v[2] = InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2); v[2] = InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2);
v[3] = InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1); v[3] = InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1);
v[4] = v[2]; v[4] = v[2];
v[5] = v[1]; v[5] = v[1];
memcpy(pVertices, v, 6*sizeof(FONT2DVERTEX)); memcpy(pVertices, v, 6*sizeof(FONT2DVERTEX));
pVertices+=6; pVertices+=6;
dwNumTriangles += 2; dwNumTriangles += 2;
if (dwNumTriangles * 3 > (MAX_NUM_VERTICES - 6)) if (dwNumTriangles * 3 > (MAX_NUM_VERTICES - 6))
{ {
// Unlock, render, and relock the vertex buffer // Unlock, render, and relock the vertex buffer
m_pVB->Unlock(); m_pVB->Unlock();
dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles); dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles);
m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD); m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
dwNumTriangles = 0; dwNumTriangles = 0;
} }
sx += w + spacing*fXScale*vpWidth; sx += w + spacing*fXScale*vpWidth;
} }
// Unlock and render the vertex buffer // Unlock and render the vertex buffer
m_pVB->Unlock(); m_pVB->Unlock();
if (dwNumTriangles > 0) if (dwNumTriangles > 0)
dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles); dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles);
RestoreRenderStates(); RestoreRenderStates();
return S_OK; return S_OK;
} }
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2) void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2)
{ {
struct Q2DVertex { float x,y,z,rhw;u32 color;float u,v,w,h; } coords[4] = { struct Q2DVertex { float x,y,z,rhw;u32 color;float u,v,w,h; } coords[4] = {
{x1-0.5f, y1-0.5f, 0, 1, color, u1, v1}, {x1-0.5f, y1-0.5f, 0, 1, color, u1, v1},
{x2-0.5f, y1-0.5f, 0, 1, color, u2, v1}, {x2-0.5f, y1-0.5f, 0, 1, color, u2, v1},
{x2-0.5f, y2-0.5f, 0, 1, color, u2, v2}, {x2-0.5f, y2-0.5f, 0, 1, color, u2, v2},
{x1-0.5f, y2-0.5f, 0, 1, color, u1, v2}, {x1-0.5f, y2-0.5f, 0, 1, color, u1, v2},
}; };
dev->SetPixelShader(0); dev->SetPixelShader(0);
dev->SetVertexShader(0); dev->SetVertexShader(0);
dev->SetVertexDeclaration(NULL); dev->SetVertexDeclaration(NULL);
dev->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); dev->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex)); dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
RestoreShaders(); RestoreShaders();
} }
void drawShadedTexQuad(IDirect3DTexture9 *texture, void drawShadedTexQuad(IDirect3DTexture9 *texture,
const RECT *rSource, const RECT *rSource,
int SourceWidth, int SourceWidth,
int SourceHeight, int SourceHeight,
int DestWidth, int DestWidth,
int DestHeight, int DestHeight,
IDirect3DPixelShader9 *PShader, IDirect3DPixelShader9 *PShader,
IDirect3DVertexShader9 *Vshader) IDirect3DVertexShader9 *Vshader)
{ {
float sw = 1.0f /(float) SourceWidth; float sw = 1.0f /(float) SourceWidth;
float sh = 1.0f /(float) SourceHeight; float sh = 1.0f /(float) SourceHeight;
float dw = 1.0f /(float) DestWidth; float dw = 1.0f /(float) DestWidth;
float dh = 1.0f /(float) DestHeight; float dh = 1.0f /(float) DestHeight;
float u1=((float)rSource->left) * sw; float u1=((float)rSource->left) * sw;
float u2=((float)rSource->right) * sw; float u2=((float)rSource->right) * sw;
float v1=((float)rSource->top) * sh; float v1=((float)rSource->top) * sh;
float v2=((float)rSource->bottom) * sh; float v2=((float)rSource->bottom) * sh;
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,L,T,R,B; } coords[4] = { struct Q2DVertex { float x,y,z,rhw,u,v,w,h,L,T,R,B; } coords[4] = {
{-1.0f - dw,-1.0f + dh, 0.0f,1.0f, u1, v2, sw, sh,u1,v1,u2,v2}, {-1.0f - dw,-1.0f + dh, 0.0f,1.0f, u1, v2, sw, sh,u1,v1,u2,v2},
{-1.0f - dw, 1.0f + dh, 0.0f,1.0f, u1, v1, sw, sh,u1,v1,u2,v2}, {-1.0f - dw, 1.0f + dh, 0.0f,1.0f, u1, v1, sw, sh,u1,v1,u2,v2},
{ 1.0f - dw,-1.0f + dh, 0.0f,1.0f, u2, v2, sw, sh,u1,v1,u2,v2}, { 1.0f - dw,-1.0f + dh, 0.0f,1.0f, u2, v2, sw, sh,u1,v1,u2,v2},
{ 1.0f - dw, 1.0f + dh, 0.0f,1.0f, u2, v1, sw, sh,u1,v1,u2,v2} { 1.0f - dw, 1.0f + dh, 0.0f,1.0f, u2, v1, sw, sh,u1,v1,u2,v2}
}; };
dev->SetVertexShader(Vshader); dev->SetVertexShader(Vshader);
dev->SetPixelShader(PShader); dev->SetPixelShader(PShader);
D3D::SetTexture(0, texture); D3D::SetTexture(0, texture);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2)); dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2));
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex)); dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
RestoreShaders(); RestoreShaders();
} }
void drawShadedTexSubQuad(IDirect3DTexture9 *texture, void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
const MathUtil::Rectangle<float> *rSource, const MathUtil::Rectangle<float> *rSource,
int SourceWidth, int SourceWidth,
int SourceHeight, int SourceHeight,
const MathUtil::Rectangle<float> *rDest, const MathUtil::Rectangle<float> *rDest,
int DestWidth, int DestWidth,
int DestHeight, int DestHeight,
IDirect3DPixelShader9 *PShader, IDirect3DPixelShader9 *PShader,
IDirect3DVertexShader9 *Vshader) IDirect3DVertexShader9 *Vshader)
{ {
float sw = 1.0f /(float) SourceWidth; float sw = 1.0f /(float) SourceWidth;
float sh = 1.0f /(float) SourceHeight; float sh = 1.0f /(float) SourceHeight;
float dw = 1.0f /(float) DestWidth; float dw = 1.0f /(float) DestWidth;
float dh = 1.0f /(float) DestHeight; float dh = 1.0f /(float) DestHeight;
float u1= rSource->left * sw; float u1= rSource->left * sw;
float u2= rSource->right * sw; float u2= rSource->right * sw;
float v1= rSource->top * sh; float v1= rSource->top * sh;
float v2= rSource->bottom * sh; float v2= rSource->bottom * sh;
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,L,T,R,B; } coords[4] = { struct Q2DVertex { float x,y,z,rhw,u,v,w,h,L,T,R,B; } coords[4] = {
{ rDest->left - dw , rDest->top + dh, 1.0f,1.0f, u1, v2, sw, sh,u1,v1,u2,v2}, { rDest->left - dw , rDest->top + dh, 1.0f,1.0f, u1, v2, sw, sh,u1,v1,u2,v2},
{ rDest->left - dw , rDest->bottom + dh, 1.0f,1.0f, u1, v1, sw, sh,u1,v1,u2,v2}, { rDest->left - dw , rDest->bottom + dh, 1.0f,1.0f, u1, v1, sw, sh,u1,v1,u2,v2},
{ rDest->right - dw , rDest->top + dh, 1.0f,1.0f, u2, v2, sw, sh,u1,v1,u2,v2}, { rDest->right - dw , rDest->top + dh, 1.0f,1.0f, u2, v2, sw, sh,u1,v1,u2,v2},
{ rDest->right - dw , rDest->bottom + dh, 1.0f,1.0f, u2, v1, sw, sh,u1,v1,u2,v2} { rDest->right - dw , rDest->bottom + dh, 1.0f,1.0f, u2, v1, sw, sh,u1,v1,u2,v2}
}; };
dev->SetVertexShader(Vshader); dev->SetVertexShader(Vshader);
dev->SetPixelShader(PShader); dev->SetPixelShader(PShader);
D3D::SetTexture(0, texture); D3D::SetTexture(0, texture);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2)); dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2));
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex)); dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
RestoreShaders(); RestoreShaders();
} }
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader) void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader)
{ {
struct Q2DVertex { float x,y,z,rhw;u32 color;} coords[4] = { struct Q2DVertex { float x,y,z,rhw;u32 color;} coords[4] = {
{-1.0f, 1.0f, z, 1.0f, Color}, {-1.0f, 1.0f, z, 1.0f, Color},
{ 1.0f, 1.0f, z, 1.0f, Color}, { 1.0f, 1.0f, z, 1.0f, Color},
{ 1.0f, -1.0f, z, 1.0f, Color}, { 1.0f, -1.0f, z, 1.0f, Color},
{-1.0f, -1.0f, z, 1.0f, Color} {-1.0f, -1.0f, z, 1.0f, Color}
}; };
dev->SetVertexShader(Vshader); dev->SetVertexShader(Vshader);
dev->SetPixelShader(PShader); dev->SetPixelShader(PShader);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_DIFFUSE); dev->SetFVF(D3DFVF_XYZW | D3DFVF_DIFFUSE);
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex)); dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
RestoreShaders(); RestoreShaders();
} }
} // namespace } // namespace
} }
@@ -1,88 +1,88 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#pragma once #pragma once
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include <math.h> #include <math.h>
#include <MathUtil.h> #include <MathUtil.h>
namespace DX9 namespace DX9
{ {
namespace D3D namespace D3D
{ {
// Font creation flags // Font creation flags
#define D3DFONT_BOLD 0x0001 #define D3DFONT_BOLD 0x0001
#define D3DFONT_ITALIC 0x0002 #define D3DFONT_ITALIC 0x0002
// Font rendering flags // Font rendering flags
#define D3DFONT_CENTERED 0x0001 #define D3DFONT_CENTERED 0x0001
//a cut-down variant of the DXSDK CD3DFont class //a cut-down variant of the DXSDK CD3DFont class
class CD3DFont class CD3DFont
{ {
LPDIRECT3DTEXTURE9 m_pTexture; // The d3d texture for this font LPDIRECT3DTEXTURE9 m_pTexture; // The d3d texture for this font
LPDIRECT3DVERTEXBUFFER9 m_pVB; // VertexBuffer for rendering text LPDIRECT3DVERTEXBUFFER9 m_pVB; // VertexBuffer for rendering text
//int m_dwTexWidth; // Texture dimensions //int m_dwTexWidth; // Texture dimensions
//int m_dwTexHeight; //int m_dwTexHeight;
float m_fTextScale; float m_fTextScale;
float m_fTexCoords[128-32][4]; float m_fTexCoords[128-32][4];
public: public:
CD3DFont(); CD3DFont();
// 2D (no longer 3D) text drawing function // 2D (no longer 3D) text drawing function
// Initializing and destroying device-dependent objects // Initializing and destroying device-dependent objects
void SetRenderStates(); void SetRenderStates();
int Init(); int Init();
int Shutdown(); int Shutdown();
int DrawTextScaled( float x, float y, int DrawTextScaled( float x, float y,
float fXScale, float fYScale, float fXScale, float fYScale,
float spacing, u32 dwColor, float spacing, u32 dwColor,
const char* strText, bool center=true ); const char* strText, bool center=true );
// Constructor / destructor // Constructor / destructor
//~CD3DFont(); //~CD3DFont();
}; };
extern CD3DFont font; extern CD3DFont font;
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1=0, float v1=0, float u2=1, float v2=1); void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1=0, float v1=0, float u2=1, float v2=1);
void drawShadedTexQuad(IDirect3DTexture9 *texture, void drawShadedTexQuad(IDirect3DTexture9 *texture,
const RECT *rSource, const RECT *rSource,
int SourceWidth, int SourceWidth,
int SourceHeight, int SourceHeight,
int DestWidth, int DestWidth,
int DestHeight, int DestHeight,
IDirect3DPixelShader9 *PShader, IDirect3DPixelShader9 *PShader,
IDirect3DVertexShader9 *Vshader); IDirect3DVertexShader9 *Vshader);
void drawShadedTexSubQuad(IDirect3DTexture9 *texture, void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
const MathUtil::Rectangle<float> *rSource, const MathUtil::Rectangle<float> *rSource,
int SourceWidth, int SourceWidth,
int SourceHeight, int SourceHeight,
const MathUtil::Rectangle<float> *rDest, const MathUtil::Rectangle<float> *rDest,
int DestWidth, int DestWidth,
int DestHeight, int DestHeight,
IDirect3DPixelShader9 *PShader, IDirect3DPixelShader9 *PShader,
IDirect3DVertexShader9 *Vshader); IDirect3DVertexShader9 *Vshader);
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader); void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader);
void SaveRenderStates(); void SaveRenderStates();
void RestoreRenderStates(); void RestoreRenderStates();
} }
} }
@@ -1,285 +1,285 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include "DX9_Render.h" #include "DX9_Render.h"
#include "DX9_FramebufferManager.h" #include "DX9_FramebufferManager.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "DX9_PixelShaderCache.h" #include "DX9_PixelShaderCache.h"
#include "DX9_VertexShaderCache.h" #include "DX9_VertexShaderCache.h"
#include "DX9_TextureConverter.h" #include "DX9_TextureConverter.h"
#include "../Main.h" #include "../Main.h"
#undef CHECK #undef CHECK
#define CHECK(hr, Message, ...) if (FAILED(hr)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); } #define CHECK(hr, Message, ...) if (FAILED(hr)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); }
namespace DX9 namespace DX9
{ {
XFBSource FramebufferManager::m_realXFBSource; XFBSource FramebufferManager::m_realXFBSource;
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_color_texture; LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_color_texture;
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_colorRead_texture; LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_colorRead_texture;
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_depth_texture; LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_depth_texture;
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_depthRead_texture; LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_depthRead_texture;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_surface; LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_surface;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_surface; LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_surface;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_ReadBuffer; LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_ReadBuffer;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_ReadBuffer; LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_ReadBuffer;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_OffScreenReadBuffer; LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_OffScreenReadBuffer;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_OffScreenReadBuffer; LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_OffScreenReadBuffer;
D3DFORMAT FramebufferManager::s_efb_color_surface_Format; D3DFORMAT FramebufferManager::s_efb_color_surface_Format;
D3DFORMAT FramebufferManager::s_efb_depth_surface_Format; D3DFORMAT FramebufferManager::s_efb_depth_surface_Format;
D3DFORMAT FramebufferManager::s_efb_depth_ReadBuffer_Format; D3DFORMAT FramebufferManager::s_efb_depth_ReadBuffer_Format;
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorRTSurface() LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorRTSurface()
{ {
return s_efb_color_surface; return s_efb_color_surface;
} }
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthRTSurface() LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthRTSurface()
{ {
return s_efb_depth_surface; return s_efb_depth_surface;
} }
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorOffScreenRTSurface() LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorOffScreenRTSurface()
{ {
return s_efb_color_OffScreenReadBuffer; return s_efb_color_OffScreenReadBuffer;
} }
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthOffScreenRTSurface() LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthOffScreenRTSurface()
{ {
return s_efb_depth_OffScreenReadBuffer; return s_efb_depth_OffScreenReadBuffer;
} }
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorReadSurface() LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorReadSurface()
{ {
return s_efb_color_ReadBuffer; return s_efb_color_ReadBuffer;
} }
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthReadSurface() LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthReadSurface()
{ {
return s_efb_depth_ReadBuffer; return s_efb_depth_ReadBuffer;
} }
D3DFORMAT FramebufferManager::GetEFBDepthRTSurfaceFormat() D3DFORMAT FramebufferManager::GetEFBDepthRTSurfaceFormat()
{ {
return s_efb_depth_surface_Format; return s_efb_depth_surface_Format;
} }
D3DFORMAT FramebufferManager::GetEFBDepthReadSurfaceFormat() D3DFORMAT FramebufferManager::GetEFBDepthReadSurfaceFormat()
{ {
return s_efb_depth_ReadBuffer_Format; return s_efb_depth_ReadBuffer_Format;
} }
D3DFORMAT FramebufferManager::GetEFBColorRTSurfaceFormat() D3DFORMAT FramebufferManager::GetEFBColorRTSurfaceFormat()
{ {
return s_efb_color_surface_Format; return s_efb_color_surface_Format;
} }
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc) LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
{ {
return s_efb_color_texture; return s_efb_color_texture;
} }
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBDepthTexture(const EFBRectangle &sourceRc) LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBDepthTexture(const EFBRectangle &sourceRc)
{ {
return s_efb_depth_texture; return s_efb_depth_texture;
} }
FramebufferManager::FramebufferManager() FramebufferManager::FramebufferManager()
{ {
s_efb_color_texture = NULL; s_efb_color_texture = NULL;
LPDIRECT3DTEXTURE9 s_efb_colorRead_texture = NULL; LPDIRECT3DTEXTURE9 s_efb_colorRead_texture = NULL;
LPDIRECT3DTEXTURE9 s_efb_depth_texture = NULL; LPDIRECT3DTEXTURE9 s_efb_depth_texture = NULL;
LPDIRECT3DTEXTURE9 s_efb_depthRead_texture = NULL; LPDIRECT3DTEXTURE9 s_efb_depthRead_texture = NULL;
LPDIRECT3DSURFACE9 s_efb_depth_surface = NULL; LPDIRECT3DSURFACE9 s_efb_depth_surface = NULL;
LPDIRECT3DSURFACE9 s_efb_color_surface = NULL; LPDIRECT3DSURFACE9 s_efb_color_surface = NULL;
LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer = NULL; LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer = NULL;
LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer = NULL; LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer = NULL;
LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer = NULL; LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer = NULL;
LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer = NULL; LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer = NULL;
D3DFORMAT s_efb_color_surface_Format = D3DFMT_FORCE_DWORD; D3DFORMAT s_efb_color_surface_Format = D3DFMT_FORCE_DWORD;
D3DFORMAT s_efb_depth_surface_Format = D3DFMT_FORCE_DWORD; D3DFORMAT s_efb_depth_surface_Format = D3DFMT_FORCE_DWORD;
D3DFORMAT s_efb_depth_ReadBuffer_Format = D3DFMT_FORCE_DWORD; D3DFORMAT s_efb_depth_ReadBuffer_Format = D3DFMT_FORCE_DWORD;
m_realXFBSource.texture = NULL; m_realXFBSource.texture = NULL;
// Simplest possible setup to start with. // Simplest possible setup to start with.
int target_width = Renderer::GetFullTargetWidth(); int target_width = Renderer::GetFullTargetWidth();
int target_height = Renderer::GetFullTargetHeight(); int target_height = Renderer::GetFullTargetHeight();
s_efb_color_surface_Format = D3DFMT_A8R8G8B8; s_efb_color_surface_Format = D3DFMT_A8R8G8B8;
// Get the framebuffer texture // Get the framebuffer texture
HRESULT hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format, HRESULT hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
D3DPOOL_DEFAULT, &s_efb_color_texture, NULL); D3DPOOL_DEFAULT, &s_efb_color_texture, NULL);
if(s_efb_color_texture) if(s_efb_color_texture)
{ {
hr = s_efb_color_texture->GetSurfaceLevel(0, &s_efb_color_surface); hr = s_efb_color_texture->GetSurfaceLevel(0, &s_efb_color_surface);
} }
CHECK(hr, "Create color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); CHECK(hr, "Create color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format, hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
D3DPOOL_DEFAULT, &s_efb_colorRead_texture, NULL); D3DPOOL_DEFAULT, &s_efb_colorRead_texture, NULL);
CHECK(hr, "Create Color Read Texture (hr=%#x)", hr); CHECK(hr, "Create Color Read Texture (hr=%#x)", hr);
if(s_efb_colorRead_texture) if(s_efb_colorRead_texture)
{ {
s_efb_colorRead_texture->GetSurfaceLevel(0, &s_efb_color_ReadBuffer); s_efb_colorRead_texture->GetSurfaceLevel(0, &s_efb_color_ReadBuffer);
} }
// Create an offscreen surface that we can lock to retrieve the data // Create an offscreen surface that we can lock to retrieve the data
hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, s_efb_color_surface_Format, D3DPOOL_SYSTEMMEM, &s_efb_color_OffScreenReadBuffer, NULL); hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, s_efb_color_surface_Format, D3DPOOL_SYSTEMMEM, &s_efb_color_OffScreenReadBuffer, NULL);
CHECK(hr, "Create offscreen color surface (hr=%#x)", hr); CHECK(hr, "Create offscreen color surface (hr=%#x)", hr);
// Select a Z-buffer format with hardware support // Select a Z-buffer format with hardware support
D3DFORMAT *DepthTexFormats = new D3DFORMAT[5]; D3DFORMAT *DepthTexFormats = new D3DFORMAT[5];
DepthTexFormats[0] = FOURCC_INTZ; DepthTexFormats[0] = FOURCC_INTZ;
DepthTexFormats[1] = FOURCC_DF24; DepthTexFormats[1] = FOURCC_DF24;
DepthTexFormats[2] = FOURCC_RAWZ; DepthTexFormats[2] = FOURCC_RAWZ;
DepthTexFormats[3] = FOURCC_DF16; DepthTexFormats[3] = FOURCC_DF16;
DepthTexFormats[4] = D3DFMT_D24X8; DepthTexFormats[4] = D3DFMT_D24X8;
for(int i = 0; i < 5; i++) for(int i = 0; i < 5; i++)
{ {
s_efb_depth_surface_Format = DepthTexFormats[i]; s_efb_depth_surface_Format = DepthTexFormats[i];
// Create the framebuffer depth texture // Create the framebuffer depth texture
hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_DEPTHSTENCIL, s_efb_depth_surface_Format, hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_DEPTHSTENCIL, s_efb_depth_surface_Format,
D3DPOOL_DEFAULT, &s_efb_depth_texture, NULL); D3DPOOL_DEFAULT, &s_efb_depth_texture, NULL);
if (!FAILED(hr)) if (!FAILED(hr))
break; break;
} }
CHECK(hr, "Framebuffer depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); CHECK(hr, "Framebuffer depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
// Get the Surface // Get the Surface
if(s_efb_depth_texture) if(s_efb_depth_texture)
{ {
s_efb_depth_texture->GetSurfaceLevel(0, &s_efb_depth_surface); s_efb_depth_texture->GetSurfaceLevel(0, &s_efb_depth_surface);
} }
// Create a 4x4 pixel texture to work as a buffer for peeking // Create a 4x4 pixel texture to work as a buffer for peeking
if(s_efb_depth_surface_Format == FOURCC_RAWZ || s_efb_depth_surface_Format == D3DFMT_D24X8) if(s_efb_depth_surface_Format == FOURCC_RAWZ || s_efb_depth_surface_Format == D3DFMT_D24X8)
{ {
DepthTexFormats[0] = D3DFMT_A8R8G8B8; DepthTexFormats[0] = D3DFMT_A8R8G8B8;
} }
else else
{ {
DepthTexFormats[0] = D3DFMT_R32F; DepthTexFormats[0] = D3DFMT_R32F;
} }
DepthTexFormats[1] = D3DFMT_A8R8G8B8; DepthTexFormats[1] = D3DFMT_A8R8G8B8;
for(int i = 0; i < 2; i++) for(int i = 0; i < 2; i++)
{ {
s_efb_depth_ReadBuffer_Format = DepthTexFormats[i]; s_efb_depth_ReadBuffer_Format = DepthTexFormats[i];
// Get the framebuffer Depth texture // Get the framebuffer Depth texture
hr = D3D::dev->CreateTexture(4, 4, 1, D3DUSAGE_RENDERTARGET, s_efb_depth_ReadBuffer_Format, hr = D3D::dev->CreateTexture(4, 4, 1, D3DUSAGE_RENDERTARGET, s_efb_depth_ReadBuffer_Format,
D3DPOOL_DEFAULT, &s_efb_depthRead_texture, NULL); D3DPOOL_DEFAULT, &s_efb_depthRead_texture, NULL);
if (!FAILED(hr)) if (!FAILED(hr))
break; break;
} }
CHECK(hr, "Create depth read texture (hr=%#x)", hr); CHECK(hr, "Create depth read texture (hr=%#x)", hr);
if(s_efb_depthRead_texture) if(s_efb_depthRead_texture)
{ {
s_efb_depthRead_texture->GetSurfaceLevel(0, &s_efb_depth_ReadBuffer); s_efb_depthRead_texture->GetSurfaceLevel(0, &s_efb_depth_ReadBuffer);
} }
// Create an offscreen surface that we can lock to retrieve the data // Create an offscreen surface that we can lock to retrieve the data
hr = D3D::dev->CreateOffscreenPlainSurface(4, 4, s_efb_depth_ReadBuffer_Format, D3DPOOL_SYSTEMMEM, &s_efb_depth_OffScreenReadBuffer, NULL); hr = D3D::dev->CreateOffscreenPlainSurface(4, 4, s_efb_depth_ReadBuffer_Format, D3DPOOL_SYSTEMMEM, &s_efb_depth_OffScreenReadBuffer, NULL);
CHECK(hr, "Create depth offscreen surface (hr=%#x)", hr); CHECK(hr, "Create depth offscreen surface (hr=%#x)", hr);
delete [] DepthTexFormats; delete [] DepthTexFormats;
} }
FramebufferManager::~FramebufferManager() FramebufferManager::~FramebufferManager()
{ {
SAFE_RELEASE(s_efb_depth_surface); SAFE_RELEASE(s_efb_depth_surface);
SAFE_RELEASE(s_efb_color_surface); SAFE_RELEASE(s_efb_color_surface);
SAFE_RELEASE(s_efb_color_ReadBuffer); SAFE_RELEASE(s_efb_color_ReadBuffer);
SAFE_RELEASE(s_efb_depth_ReadBuffer); SAFE_RELEASE(s_efb_depth_ReadBuffer);
SAFE_RELEASE(s_efb_color_OffScreenReadBuffer); SAFE_RELEASE(s_efb_color_OffScreenReadBuffer);
SAFE_RELEASE(s_efb_depth_OffScreenReadBuffer); SAFE_RELEASE(s_efb_depth_OffScreenReadBuffer);
SAFE_RELEASE(s_efb_color_texture); SAFE_RELEASE(s_efb_color_texture);
SAFE_RELEASE(s_efb_colorRead_texture); SAFE_RELEASE(s_efb_colorRead_texture);
SAFE_RELEASE(s_efb_depth_texture); SAFE_RELEASE(s_efb_depth_texture);
SAFE_RELEASE(s_efb_depthRead_texture); SAFE_RELEASE(s_efb_depthRead_texture);
if (m_realXFBSource.texture) if (m_realXFBSource.texture)
m_realXFBSource.texture->Release(); m_realXFBSource.texture->Release();
m_realXFBSource.texture = NULL; m_realXFBSource.texture = NULL;
} }
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{ {
// TODO: // TODO:
//u8* xfb_in_ram = Memory_GetPtr(xfbAddr); //u8* xfb_in_ram = Memory_GetPtr(xfbAddr);
//if (!xfb_in_ram) //if (!xfb_in_ram)
//{ //{
// WARN_LOG(VIDEO, "Tried to copy to invalid XFB address"); // WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
// return; // return;
//} //}
//TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc); //TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc);
//TextureConverter::EncodeToRamYUYV(GetEFBColorTexture(sourceRc), targetRc, xfb_in_ram, fbWidth, fbHeight); //TextureConverter::EncodeToRamYUYV(GetEFBColorTexture(sourceRc), targetRc, xfb_in_ram, fbWidth, fbHeight);
} }
const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount) const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{ {
return NULL; return NULL;
// TODO: // TODO:
//xfbCount = 1; //xfbCount = 1;
//m_realXFBSource.texWidth = fbWidth; //m_realXFBSource.texWidth = fbWidth;
//m_realXFBSource.texHeight = fbHeight; //m_realXFBSource.texHeight = fbHeight;
//m_realXFBSource.srcAddr = xfbAddr; //m_realXFBSource.srcAddr = xfbAddr;
//m_realXFBSource.srcWidth = fbWidth; //m_realXFBSource.srcWidth = fbWidth;
//m_realXFBSource.srcHeight = fbHeight; //m_realXFBSource.srcHeight = fbHeight;
//if (!m_realXFBSource.texture) //if (!m_realXFBSource.texture)
//{ //{
// D3D::dev->CreateTexture(fbWidth, fbHeight, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format, // D3D::dev->CreateTexture(fbWidth, fbHeight, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
// D3DPOOL_DEFAULT, &m_realXFBSource.texture, NULL); // D3DPOOL_DEFAULT, &m_realXFBSource.texture, NULL);
//} //}
//// Decode YUYV data from GameCube RAM //// Decode YUYV data from GameCube RAM
//TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture); //TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture);
//m_overlappingXFBArray[0] = &m_realXFBSource; //m_overlappingXFBArray[0] = &m_realXFBSource;
//return &m_overlappingXFBArray[0]; //return &m_overlappingXFBArray[0];
} }
XFBSourceBase *FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height) XFBSourceBase *FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
{ {
XFBSource* const xfbs = new XFBSource; XFBSource* const xfbs = new XFBSource;
D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format, D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
D3DPOOL_DEFAULT, &xfbs->texture, NULL); D3DPOOL_DEFAULT, &xfbs->texture, NULL);
return xfbs; return xfbs;
} }
XFBSource::~XFBSource() XFBSource::~XFBSource()
{ {
texture->Release(); texture->Release();
} }
void XFBSource::CopyEFB(const TargetRectangle& efbSource) void XFBSource::CopyEFB(const TargetRectangle& efbSource)
{ {
} }
} }
@@ -1,130 +1,130 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _FRAMEBUFFERMANAGER_D3D_H_ #ifndef _FRAMEBUFFERMANAGER_D3D_H_
#define _FRAMEBUFFERMANAGER_D3D_H_ #define _FRAMEBUFFERMANAGER_D3D_H_
#include <list> #include <list>
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include "../FramebufferManager.h" #include "../FramebufferManager.h"
// On the GameCube, the game sends a request for the graphics processor to // On the GameCube, the game sends a request for the graphics processor to
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM // transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
// called the XFB (External Framebuffer). The size and location of the XFB is // called the XFB (External Framebuffer). The size and location of the XFB is
// decided at the time of the copy, and the format is always YUYV. The video // decided at the time of the copy, and the format is always YUYV. The video
// interface is given a pointer to the XFB, which will be decoded and // interface is given a pointer to the XFB, which will be decoded and
// displayed on the TV. // displayed on the TV.
// //
// There are two ways for Dolphin to emulate this: // There are two ways for Dolphin to emulate this:
// //
// Real XFB mode: // Real XFB mode:
// //
// Dolphin will behave like the GameCube and encode the EFB to // Dolphin will behave like the GameCube and encode the EFB to
// a portion of GameCube RAM. The emulated video interface will decode the data // a portion of GameCube RAM. The emulated video interface will decode the data
// for output to the screen. // for output to the screen.
// //
// Advantages: Behaves exactly like the GameCube. // Advantages: Behaves exactly like the GameCube.
// Disadvantages: Resolution will be limited. // Disadvantages: Resolution will be limited.
// //
// Virtual XFB mode: // Virtual XFB mode:
// //
// When a request is made to copy the EFB to an XFB, Dolphin // When a request is made to copy the EFB to an XFB, Dolphin
// will remember the RAM location and size of the XFB in a Virtual XFB list. // will remember the RAM location and size of the XFB in a Virtual XFB list.
// The video interface will look up the XFB in the list and use the enhanced // The video interface will look up the XFB in the list and use the enhanced
// data stored there, if available. // data stored there, if available.
// //
// Advantages: Enables high resolution graphics, better than real hardware. // Advantages: Enables high resolution graphics, better than real hardware.
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is // Disadvantages: If the GameCube CPU writes directly to the XFB (which is
// possible but uncommon), the Virtual XFB will not capture this information. // possible but uncommon), the Virtual XFB will not capture this information.
// There may be multiple XFBs in GameCube RAM. This is the maximum number to // There may be multiple XFBs in GameCube RAM. This is the maximum number to
// virtualize. // virtualize.
namespace DX9 namespace DX9
{ {
const int MAX_VIRTUAL_XFB = 8; const int MAX_VIRTUAL_XFB = 8;
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper) inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
{ {
return !((aLower >= bUpper) || (bLower >= aUpper)); return !((aLower >= bUpper) || (bLower >= aUpper));
} }
struct XFBSource : public XFBSourceBase struct XFBSource : public XFBSourceBase
{ {
XFBSource() : texture(NULL) {} XFBSource() : texture(NULL) {}
~XFBSource(); ~XFBSource();
void CopyEFB(const TargetRectangle& efbSource); void CopyEFB(const TargetRectangle& efbSource);
LPDIRECT3DTEXTURE9 texture; LPDIRECT3DTEXTURE9 texture;
}; };
class FramebufferManager : public ::FramebufferManagerBase class FramebufferManager : public ::FramebufferManagerBase
{ {
public: public:
FramebufferManager(); FramebufferManager();
~FramebufferManager(); ~FramebufferManager();
void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc); void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
XFBSourceBase *CreateXFBSource(unsigned int target_width, unsigned int target_height); XFBSourceBase *CreateXFBSource(unsigned int target_width, unsigned int target_height);
static LPDIRECT3DTEXTURE9 GetEFBColorTexture(const EFBRectangle& sourceRc); static LPDIRECT3DTEXTURE9 GetEFBColorTexture(const EFBRectangle& sourceRc);
static LPDIRECT3DTEXTURE9 GetEFBDepthTexture(const EFBRectangle& sourceRc); static LPDIRECT3DTEXTURE9 GetEFBDepthTexture(const EFBRectangle& sourceRc);
static LPDIRECT3DSURFACE9 GetEFBColorRTSurface(); static LPDIRECT3DSURFACE9 GetEFBColorRTSurface();
static LPDIRECT3DSURFACE9 GetEFBDepthRTSurface(); static LPDIRECT3DSURFACE9 GetEFBDepthRTSurface();
static LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface(); static LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface();
static LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface(); static LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface();
static D3DFORMAT GetEFBDepthRTSurfaceFormat(); static D3DFORMAT GetEFBDepthRTSurfaceFormat();
static D3DFORMAT GetEFBColorRTSurfaceFormat(); static D3DFORMAT GetEFBColorRTSurfaceFormat();
static D3DFORMAT GetEFBDepthReadSurfaceFormat(); static D3DFORMAT GetEFBDepthReadSurfaceFormat();
static LPDIRECT3DSURFACE9 GetEFBColorReadSurface(); static LPDIRECT3DSURFACE9 GetEFBColorReadSurface();
static LPDIRECT3DSURFACE9 GetEFBDepthReadSurface(); static LPDIRECT3DSURFACE9 GetEFBDepthReadSurface();
private: private:
void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc); void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc); void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
const XFBSource** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount); const XFBSource** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
static XFBSource m_realXFBSource; // Only used in Real XFB mode static XFBSource m_realXFBSource; // Only used in Real XFB mode
const XFBSource* m_overlappingXFBArray[MAX_VIRTUAL_XFB]; const XFBSource* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
static LPDIRECT3DTEXTURE9 s_efb_color_texture;//Texture thats contains the color data of the render target static LPDIRECT3DTEXTURE9 s_efb_color_texture;//Texture thats contains the color data of the render target
static LPDIRECT3DTEXTURE9 s_efb_colorRead_texture;//1 pixel texture for temporal data store static LPDIRECT3DTEXTURE9 s_efb_colorRead_texture;//1 pixel texture for temporal data store
static LPDIRECT3DTEXTURE9 s_efb_depth_texture;//Texture thats contains the depth data of the render target static LPDIRECT3DTEXTURE9 s_efb_depth_texture;//Texture thats contains the depth data of the render target
static LPDIRECT3DTEXTURE9 s_efb_depthRead_texture;//4 pixel texture for temporal data store static LPDIRECT3DTEXTURE9 s_efb_depthRead_texture;//4 pixel texture for temporal data store
static LPDIRECT3DSURFACE9 s_efb_depth_surface;//Depth Surface static LPDIRECT3DSURFACE9 s_efb_depth_surface;//Depth Surface
static LPDIRECT3DSURFACE9 s_efb_color_surface;//Color Surface static LPDIRECT3DSURFACE9 s_efb_color_surface;//Color Surface
static LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer;//Surface 0 of s_efb_colorRead_texture static LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer;//Surface 0 of s_efb_colorRead_texture
static LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer;//Surface 0 of s_efb_depthRead_texture static LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer;//Surface 0 of s_efb_depthRead_texture
static LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data static LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
static LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data static LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
static D3DFORMAT s_efb_color_surface_Format;//Format of the color Surface static D3DFORMAT s_efb_color_surface_Format;//Format of the color Surface
static D3DFORMAT s_efb_depth_surface_Format;//Format of the Depth Surface static D3DFORMAT s_efb_depth_surface_Format;//Format of the Depth Surface
static D3DFORMAT s_efb_depth_ReadBuffer_Format;//Format of the Depth color Read Surface static D3DFORMAT s_efb_depth_ReadBuffer_Format;//Format of the Depth color Read Surface
}; };
} }
#endif #endif
@@ -1,178 +1,178 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include "Profiler.h" #include "Profiler.h"
#include "x64Emitter.h" #include "x64Emitter.h"
#include "ABI.h" #include "ABI.h"
#include "MemoryUtil.h" #include "MemoryUtil.h"
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
#include "CPMemory.h" #include "CPMemory.h"
#include "DX9_VertexManager.h" #include "DX9_VertexManager.h"
namespace DX9 namespace DX9
{ {
class D3DVertexFormat : public NativeVertexFormat class D3DVertexFormat : public NativeVertexFormat
{ {
LPDIRECT3DVERTEXDECLARATION9 d3d_decl; LPDIRECT3DVERTEXDECLARATION9 d3d_decl;
public: public:
D3DVertexFormat(); D3DVertexFormat();
~D3DVertexFormat(); ~D3DVertexFormat();
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl); virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
virtual void SetupVertexPointers() const; virtual void SetupVertexPointers() const;
}; };
NativeVertexFormat *VertexManager::CreateNativeVertexFormat() NativeVertexFormat *VertexManager::CreateNativeVertexFormat()
{ {
return new D3DVertexFormat(); return new D3DVertexFormat();
} }
D3DVertexFormat::D3DVertexFormat() : d3d_decl(NULL) D3DVertexFormat::D3DVertexFormat() : d3d_decl(NULL)
{ {
} }
D3DVertexFormat::~D3DVertexFormat() D3DVertexFormat::~D3DVertexFormat()
{ {
if (d3d_decl) if (d3d_decl)
{ {
d3d_decl->Release(); d3d_decl->Release();
d3d_decl = NULL; d3d_decl = NULL;
} }
} }
D3DDECLTYPE VarToD3D(VarType t, int size) D3DDECLTYPE VarToD3D(VarType t, int size)
{ {
if (t < 0 || t > 4) { if (t < 0 || t > 4) {
PanicAlert("VarToD3D: Invalid VarType %i", t); PanicAlert("VarToD3D: Invalid VarType %i", t);
} }
static const D3DDECLTYPE lookup1[5] = { static const D3DDECLTYPE lookup1[5] = {
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT1, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT1,
}; };
static const D3DDECLTYPE lookup2[5] = { static const D3DDECLTYPE lookup2[5] = {
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_SHORT2N, D3DDECLTYPE_USHORT2N, D3DDECLTYPE_FLOAT2, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_SHORT2N, D3DDECLTYPE_USHORT2N, D3DDECLTYPE_FLOAT2,
}; };
static const D3DDECLTYPE lookup3[5] = { static const D3DDECLTYPE lookup3[5] = {
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT3, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT3,
}; };
// Sadly, D3D9 has no SBYTE4N. D3D10 does, though. // Sadly, D3D9 has no SBYTE4N. D3D10 does, though.
static const D3DDECLTYPE lookup4[5] = { static const D3DDECLTYPE lookup4[5] = {
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UBYTE4N, D3DDECLTYPE_SHORT4N, D3DDECLTYPE_USHORT4N, D3DDECLTYPE_FLOAT4, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UBYTE4N, D3DDECLTYPE_SHORT4N, D3DDECLTYPE_USHORT4N, D3DDECLTYPE_FLOAT4,
}; };
D3DDECLTYPE retval = D3DDECLTYPE_UNUSED; D3DDECLTYPE retval = D3DDECLTYPE_UNUSED;
switch (size) { switch (size) {
case 1: retval = lookup1[t]; break; case 1: retval = lookup1[t]; break;
case 2: retval = lookup2[t]; break; case 2: retval = lookup2[t]; break;
case 3: retval = lookup3[t]; break; case 3: retval = lookup3[t]; break;
case 4: retval = lookup4[t]; break; case 4: retval = lookup4[t]; break;
default: PanicAlert("VarToD3D: size wrong (%i)", size); break; default: PanicAlert("VarToD3D: size wrong (%i)", size); break;
} }
if (retval == D3DDECLTYPE_UNUSED) { if (retval == D3DDECLTYPE_UNUSED) {
PanicAlert("VarToD3D: Invalid type/size combo %i , %i", (int)t, size); PanicAlert("VarToD3D: Invalid type/size combo %i , %i", (int)t, size);
} }
return retval; return retval;
} }
void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl) void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
{ {
vertex_stride = _vtx_decl.stride; vertex_stride = _vtx_decl.stride;
D3DVERTEXELEMENT9 *elems = new D3DVERTEXELEMENT9[32]; D3DVERTEXELEMENT9 *elems = new D3DVERTEXELEMENT9[32];
memset(elems, 0, sizeof(D3DVERTEXELEMENT9) * 32); memset(elems, 0, sizeof(D3DVERTEXELEMENT9) * 32);
// There's only one stream and it's 0, so the above memset takes care of that - no need to set Stream. // There's only one stream and it's 0, so the above memset takes care of that - no need to set Stream.
// Same for method. // Same for method.
// So, here we go. First position: // So, here we go. First position:
int elem_idx = 0; int elem_idx = 0;
elems[elem_idx].Offset = 0; // Positions are always first, at position 0. Always float3. elems[elem_idx].Offset = 0; // Positions are always first, at position 0. Always float3.
elems[elem_idx].Type = D3DDECLTYPE_FLOAT3; elems[elem_idx].Type = D3DDECLTYPE_FLOAT3;
elems[elem_idx].Usage = D3DDECLUSAGE_POSITION; elems[elem_idx].Usage = D3DDECLUSAGE_POSITION;
++elem_idx; ++elem_idx;
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
if (_vtx_decl.normal_offset[i] > 0) if (_vtx_decl.normal_offset[i] > 0)
{ {
elems[elem_idx].Offset = _vtx_decl.normal_offset[i]; elems[elem_idx].Offset = _vtx_decl.normal_offset[i];
elems[elem_idx].Type = VarToD3D(_vtx_decl.normal_gl_type, _vtx_decl.normal_gl_size); elems[elem_idx].Type = VarToD3D(_vtx_decl.normal_gl_type, _vtx_decl.normal_gl_size);
elems[elem_idx].Usage = D3DDECLUSAGE_NORMAL; elems[elem_idx].Usage = D3DDECLUSAGE_NORMAL;
elems[elem_idx].UsageIndex = i; elems[elem_idx].UsageIndex = i;
++elem_idx; ++elem_idx;
} }
} }
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
if (_vtx_decl.color_offset[i] > 0) if (_vtx_decl.color_offset[i] > 0)
{ {
elems[elem_idx].Offset = _vtx_decl.color_offset[i]; elems[elem_idx].Offset = _vtx_decl.color_offset[i];
elems[elem_idx].Type = VarToD3D(_vtx_decl.color_gl_type, 4); elems[elem_idx].Type = VarToD3D(_vtx_decl.color_gl_type, 4);
elems[elem_idx].Usage = D3DDECLUSAGE_COLOR; elems[elem_idx].Usage = D3DDECLUSAGE_COLOR;
elems[elem_idx].UsageIndex = i; elems[elem_idx].UsageIndex = i;
++elem_idx; ++elem_idx;
} }
} }
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
if (_vtx_decl.texcoord_offset[i] > 0) if (_vtx_decl.texcoord_offset[i] > 0)
{ {
elems[elem_idx].Offset = _vtx_decl.texcoord_offset[i]; elems[elem_idx].Offset = _vtx_decl.texcoord_offset[i];
elems[elem_idx].Type = VarToD3D(_vtx_decl.texcoord_gl_type[i], _vtx_decl.texcoord_size[i]); elems[elem_idx].Type = VarToD3D(_vtx_decl.texcoord_gl_type[i], _vtx_decl.texcoord_size[i]);
elems[elem_idx].Usage = D3DDECLUSAGE_TEXCOORD; elems[elem_idx].Usage = D3DDECLUSAGE_TEXCOORD;
elems[elem_idx].UsageIndex = i; elems[elem_idx].UsageIndex = i;
++elem_idx; ++elem_idx;
} }
} }
if (_vtx_decl.posmtx_offset != -1) if (_vtx_decl.posmtx_offset != -1)
{ {
elems[elem_idx].Offset = _vtx_decl.posmtx_offset; elems[elem_idx].Offset = _vtx_decl.posmtx_offset;
elems[elem_idx].Usage = D3DDECLUSAGE_BLENDINDICES; elems[elem_idx].Usage = D3DDECLUSAGE_BLENDINDICES;
elems[elem_idx].Type = D3DDECLTYPE_D3DCOLOR; elems[elem_idx].Type = D3DDECLTYPE_D3DCOLOR;
elems[elem_idx].UsageIndex = 0; elems[elem_idx].UsageIndex = 0;
++elem_idx; ++elem_idx;
} }
// End marker // End marker
elems[elem_idx].Stream = 0xff; elems[elem_idx].Stream = 0xff;
elems[elem_idx].Type = D3DDECLTYPE_UNUSED; elems[elem_idx].Type = D3DDECLTYPE_UNUSED;
++elem_idx; ++elem_idx;
if (FAILED(D3D::dev->CreateVertexDeclaration(elems, &d3d_decl))) if (FAILED(D3D::dev->CreateVertexDeclaration(elems, &d3d_decl)))
{ {
PanicAlert("Failed to create D3D vertex declaration!"); PanicAlert("Failed to create D3D vertex declaration!");
return; return;
} }
delete [] elems; delete [] elems;
} }
void D3DVertexFormat::SetupVertexPointers() const void D3DVertexFormat::SetupVertexPointers() const
{ {
if (d3d_decl) if (d3d_decl)
D3D::SetVertexDeclaration(d3d_decl); D3D::SetVertexDeclaration(d3d_decl);
else else
ERROR_LOG(VIDEO, "invalid d3d decl"); ERROR_LOG(VIDEO, "invalid d3d decl");
} }
} }
@@ -1,392 +1,392 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <map> #include <map>
#include <set> #include <set>
#include "Common.h" #include "Common.h"
#include "Hash.h" #include "Hash.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "LinearDiskCache.h" #include "LinearDiskCache.h"
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include "DX9_D3DShader.h" #include "DX9_D3DShader.h"
#include "Statistics.h" #include "Statistics.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "PixelShaderGen.h" #include "PixelShaderGen.h"
#include "PixelShaderManager.h" #include "PixelShaderManager.h"
#include "DX9_PixelShaderCache.h" #include "DX9_PixelShaderCache.h"
#include "VertexLoader.h" #include "VertexLoader.h"
#include "BPMemory.h" #include "BPMemory.h"
#include "XFMemory.h" #include "XFMemory.h"
#include "ImageWrite.h" #include "ImageWrite.h"
#include "../Main.h" #include "../Main.h"
//#include "Debugger/Debugger.h" //#include "Debugger/Debugger.h"
namespace DX9 namespace DX9
{ {
PixelShaderCache::PSCache PixelShaderCache::PixelShaders; PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
const PixelShaderCache::PSCacheEntry *PixelShaderCache::last_entry; const PixelShaderCache::PSCacheEntry *PixelShaderCache::last_entry;
static LinearDiskCache g_ps_disk_cache; static LinearDiskCache g_ps_disk_cache;
static std::set<u32> unique_shaders; static std::set<u32> unique_shaders;
#define MAX_SSAA_SHADERS 3 #define MAX_SSAA_SHADERS 3
static LPDIRECT3DPIXELSHADER9 s_ColorMatrixProgram[MAX_SSAA_SHADERS]; static LPDIRECT3DPIXELSHADER9 s_ColorMatrixProgram[MAX_SSAA_SHADERS];
static LPDIRECT3DPIXELSHADER9 s_ColorCopyProgram[MAX_SSAA_SHADERS]; static LPDIRECT3DPIXELSHADER9 s_ColorCopyProgram[MAX_SSAA_SHADERS];
static LPDIRECT3DPIXELSHADER9 s_DepthMatrixProgram[MAX_SSAA_SHADERS]; static LPDIRECT3DPIXELSHADER9 s_DepthMatrixProgram[MAX_SSAA_SHADERS];
static LPDIRECT3DPIXELSHADER9 s_ClearProgram = 0; static LPDIRECT3DPIXELSHADER9 s_ClearProgram = 0;
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorMatrixProgram(int SSAAMode) LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorMatrixProgram(int SSAAMode)
{ {
return s_ColorMatrixProgram[SSAAMode % MAX_SSAA_SHADERS]; return s_ColorMatrixProgram[SSAAMode % MAX_SSAA_SHADERS];
} }
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetDepthMatrixProgram(int SSAAMode) LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetDepthMatrixProgram(int SSAAMode)
{ {
return s_DepthMatrixProgram[SSAAMode % MAX_SSAA_SHADERS]; return s_DepthMatrixProgram[SSAAMode % MAX_SSAA_SHADERS];
} }
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorCopyProgram(int SSAAMode) LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorCopyProgram(int SSAAMode)
{ {
return s_ColorCopyProgram[SSAAMode % MAX_SSAA_SHADERS]; return s_ColorCopyProgram[SSAAMode % MAX_SSAA_SHADERS];
} }
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetClearProgram() LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetClearProgram()
{ {
return s_ClearProgram; return s_ClearProgram;
} }
void PixelShaderCache::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) void PixelShaderCache::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{ {
float f[4] = { f1, f2, f3, f4 }; float f[4] = { f1, f2, f3, f4 };
D3D::dev->SetPixelShaderConstantF(const_number, f, 1); D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
} }
void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float *f) void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float *f)
{ {
D3D::dev->SetPixelShaderConstantF(const_number, f, 1); D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
} }
void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f) void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
{ {
D3D::dev->SetPixelShaderConstantF(const_number, f, count); D3D::dev->SetPixelShaderConstantF(const_number, f, count);
} }
class PixelShaderCacheInserter : public LinearDiskCacheReader { class PixelShaderCacheInserter : public LinearDiskCacheReader {
public: public:
void Read(const u8 *key, int key_size, const u8 *value, int value_size) void Read(const u8 *key, int key_size, const u8 *value, int value_size)
{ {
PIXELSHADERUID uid; PIXELSHADERUID uid;
if (key_size != sizeof(uid)) { if (key_size != sizeof(uid)) {
ERROR_LOG(VIDEO, "Wrong key size in pixel shader cache"); ERROR_LOG(VIDEO, "Wrong key size in pixel shader cache");
return; return;
} }
memcpy(&uid, key, key_size); memcpy(&uid, key, key_size);
PixelShaderCache::InsertByteCode(uid, value, value_size, false); PixelShaderCache::InsertByteCode(uid, value, value_size, false);
} }
}; };
PixelShaderCache::PixelShaderCache() PixelShaderCache::PixelShaderCache()
{ {
//program used for clear screen //program used for clear screen
char pprog[3072]; char pprog[3072];
sprintf(pprog, "void main(\n" sprintf(pprog, "void main(\n"
"out float4 ocol0 : COLOR0,\n" "out float4 ocol0 : COLOR0,\n"
" in float4 incol0 : COLOR0){\n" " in float4 incol0 : COLOR0){\n"
"ocol0 = incol0;\n" "ocol0 = incol0;\n"
"}\n"); "}\n");
s_ClearProgram = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog)); s_ClearProgram = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//Used for Copy/resolve the color buffer //Used for Copy/resolve the color buffer
//1 Sample //1 Sample
sprintf(pprog, "uniform sampler samp0 : register(s0);\n" sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"void main(\n" "void main(\n"
"out float4 ocol0 : COLOR0,\n" "out float4 ocol0 : COLOR0,\n"
"in float2 uv0 : TEXCOORD0){\n" "in float2 uv0 : TEXCOORD0){\n"
"ocol0 = tex2D(samp0,uv0);\n" "ocol0 = tex2D(samp0,uv0);\n"
"}\n"); "}\n");
s_ColorCopyProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog)); s_ColorCopyProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//1 Samples SSAA //1 Samples SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n" sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"void main(\n" "void main(\n"
"out float4 ocol0 : COLOR0,\n" "out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n" "in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1){\n" "in float4 uv1 : TEXCOORD1){\n"
"ocol0 = tex2D(samp0,uv0.xy);\n" "ocol0 = tex2D(samp0,uv0.xy);\n"
"}\n"); "}\n");
s_ColorCopyProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog)); s_ColorCopyProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//4 Samples SSAA //4 Samples SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n" sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"void main(\n" "void main(\n"
"out float4 ocol0 : COLOR0,\n" "out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n" "in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1,\n" "in float4 uv1 : TEXCOORD1,\n"
"in float4 uv2 : TEXCOORD2,\n" "in float4 uv2 : TEXCOORD2,\n"
"in float4 uv3 : TEXCOORD3){\n" "in float4 uv3 : TEXCOORD3){\n"
"ocol0 = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25;\n" "ocol0 = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25;\n"
"}\n"); "}\n");
s_ColorCopyProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog)); s_ColorCopyProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//Color conversion Programs //Color conversion Programs
//1 sample //1 sample
sprintf(pprog, "uniform sampler samp0 : register(s0);\n" sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n" "uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n" "void main(\n"
"out float4 ocol0 : COLOR0,\n" "out float4 ocol0 : COLOR0,\n"
" in float2 uv0 : TEXCOORD0){\n" " in float2 uv0 : TEXCOORD0){\n"
"float4 texcol = tex2D(samp0,uv0);\n" "float4 texcol = tex2D(samp0,uv0);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n" "ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX); "}\n",C_COLORMATRIX);
s_ColorMatrixProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog)); s_ColorMatrixProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//1 samples SSAA //1 samples SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n" sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n" "uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n" "void main(\n"
"out float4 ocol0 : COLOR0,\n" "out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n" "in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1){\n" "in float4 uv1 : TEXCOORD1){\n"
"float4 texcol = tex2D(samp0,uv0.xy);\n" "float4 texcol = tex2D(samp0,uv0.xy);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n" "ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX); "}\n",C_COLORMATRIX);
s_ColorMatrixProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog)); s_ColorMatrixProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//4 samples SSAA //4 samples SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n" sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n" "uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n" "void main(\n"
"out float4 ocol0 : COLOR0,\n" "out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n" "in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1,\n" "in float4 uv1 : TEXCOORD1,\n"
"in float4 uv2 : TEXCOORD2,\n" "in float4 uv2 : TEXCOORD2,\n"
"in float4 uv3 : TEXCOORD3){\n" "in float4 uv3 : TEXCOORD3){\n"
"float4 texcol = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25f;\n" "float4 texcol = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25f;\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n" "ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX); "}\n",C_COLORMATRIX);
s_ColorMatrixProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog)); s_ColorMatrixProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//Depth copy programs //Depth copy programs
//1 sample //1 sample
sprintf(pprog, "uniform sampler samp0 : register(s0);\n" sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n" "uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n" "void main(\n"
"out float4 ocol0 : COLOR0,\n" "out float4 ocol0 : COLOR0,\n"
" in float2 uv0 : TEXCOORD0){\n" " in float2 uv0 : TEXCOORD0){\n"
"float4 texcol = tex2D(samp0,uv0);\n" "float4 texcol = tex2D(samp0,uv0);\n"
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n" "float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n" "texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n" "ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX); "}\n",C_COLORMATRIX);
s_DepthMatrixProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog)); s_DepthMatrixProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//1 sample SSAA //1 sample SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n" sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n" "uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n" "void main(\n"
"out float4 ocol0 : COLOR0,\n" "out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n" "in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1){\n" "in float4 uv1 : TEXCOORD1){\n"
"float4 texcol = tex2D(samp0,uv0.xy);\n" "float4 texcol = tex2D(samp0,uv0.xy);\n"
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n" "float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n" "texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n" "ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX); "}\n",C_COLORMATRIX);
s_DepthMatrixProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog)); s_DepthMatrixProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//4 sample SSAA //4 sample SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n" sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n" "uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n" "void main(\n"
"out float4 ocol0 : COLOR0,\n" "out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n" "in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1,\n" "in float4 uv1 : TEXCOORD1,\n"
"in float4 uv2 : TEXCOORD2,\n" "in float4 uv2 : TEXCOORD2,\n"
"in float4 uv3 : TEXCOORD3){\n" "in float4 uv3 : TEXCOORD3){\n"
"float4 texcol = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25f;\n" "float4 texcol = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25f;\n"
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n" "float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n" "texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n" "ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX); "}\n",C_COLORMATRIX);
s_DepthMatrixProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog)); s_DepthMatrixProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
Clear(); Clear();
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
SETSTAT(stats.numPixelShadersCreated, 0); SETSTAT(stats.numPixelShadersCreated, 0);
SETSTAT(stats.numPixelShadersAlive, 0); SETSTAT(stats.numPixelShadersAlive, 0);
char cache_filename[MAX_PATH]; char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx9-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id); sprintf(cache_filename, "%sdx9-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
PixelShaderCacheInserter inserter; PixelShaderCacheInserter inserter;
int read_items = g_ps_disk_cache.OpenAndRead(cache_filename, &inserter); int read_items = g_ps_disk_cache.OpenAndRead(cache_filename, &inserter);
} }
// ONLY to be used during shutdown. // ONLY to be used during shutdown.
void PixelShaderCache::Clear() void PixelShaderCache::Clear()
{ {
PSCache::iterator iter = PixelShaders.begin(); PSCache::iterator iter = PixelShaders.begin();
for (; iter != PixelShaders.end(); ++iter) for (; iter != PixelShaders.end(); ++iter)
iter->second.Destroy(); iter->second.Destroy();
PixelShaders.clear(); PixelShaders.clear();
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid)); memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
} }
PixelShaderCache::~PixelShaderCache() PixelShaderCache::~PixelShaderCache()
{ {
for(int i = 0;i < MAX_SSAA_SHADERS; i++) for(int i = 0;i < MAX_SSAA_SHADERS; i++)
{ {
if (s_ColorMatrixProgram[i]) s_ColorMatrixProgram[i]->Release(); if (s_ColorMatrixProgram[i]) s_ColorMatrixProgram[i]->Release();
s_ColorMatrixProgram[i] = NULL; s_ColorMatrixProgram[i] = NULL;
if (s_ColorCopyProgram[i]) s_ColorCopyProgram[i]->Release(); if (s_ColorCopyProgram[i]) s_ColorCopyProgram[i]->Release();
s_ColorCopyProgram[i] = NULL; s_ColorCopyProgram[i] = NULL;
if (s_DepthMatrixProgram[i]) s_DepthMatrixProgram[i]->Release(); if (s_DepthMatrixProgram[i]) s_DepthMatrixProgram[i]->Release();
s_DepthMatrixProgram[i] = NULL; s_DepthMatrixProgram[i] = NULL;
} }
if (s_ClearProgram) s_ClearProgram->Release(); if (s_ClearProgram) s_ClearProgram->Release();
s_ClearProgram = NULL; s_ClearProgram = NULL;
Clear(); Clear();
g_ps_disk_cache.Sync(); g_ps_disk_cache.Sync();
g_ps_disk_cache.Close(); g_ps_disk_cache.Close();
unique_shaders.clear(); unique_shaders.clear();
} }
bool PixelShaderCache::SetShader(bool dstAlpha) bool PixelShaderCache::SetShader(bool dstAlpha)
{ {
PIXELSHADERUID uid; PIXELSHADERUID uid;
GetPixelShaderId(&uid, dstAlpha); GetPixelShaderId(&uid, dstAlpha);
// Is the shader already set? // Is the shader already set?
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount) if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
{ {
PSCache::const_iterator iter = PixelShaders.find(uid); PSCache::const_iterator iter = PixelShaders.find(uid);
if (iter != PixelShaders.end() && iter->second.shader) if (iter != PixelShaders.end() && iter->second.shader)
return true; // Sure, we're done. return true; // Sure, we're done.
else else
return false; // ?? something is wrong. return false; // ?? something is wrong.
} }
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID)); memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
// Is the shader already in the cache? // Is the shader already in the cache?
PSCache::iterator iter; PSCache::iterator iter;
iter = PixelShaders.find(uid); iter = PixelShaders.find(uid);
if (iter != PixelShaders.end()) if (iter != PixelShaders.end())
{ {
iter->second.frameCount = frameCount; iter->second.frameCount = frameCount;
const PSCacheEntry &entry = iter->second; const PSCacheEntry &entry = iter->second;
last_entry = &entry; last_entry = &entry;
if (entry.shader) if (entry.shader)
{ {
D3D::SetPixelShader(entry.shader); D3D::SetPixelShader(entry.shader);
return true; return true;
} }
else else
return false; return false;
} }
// OK, need to generate and compile it. // OK, need to generate and compile it.
const char *code = GeneratePixelShaderCode(dstAlpha, API_D3D9); const char *code = GeneratePixelShaderCode(dstAlpha, API_D3D9);
u32 code_hash = HashAdler32((const u8 *)code, strlen(code)); u32 code_hash = HashAdler32((const u8 *)code, strlen(code));
unique_shaders.insert(code_hash); unique_shaders.insert(code_hash);
SETSTAT(stats.numUniquePixelShaders, unique_shaders.size()); SETSTAT(stats.numUniquePixelShaders, unique_shaders.size());
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) { if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
static int counter = 0; static int counter = 0;
char szTemp[MAX_PATH]; char szTemp[MAX_PATH];
sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++); sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
SaveData(szTemp, code); SaveData(szTemp, code);
} }
#endif #endif
u8 *bytecode = 0; u8 *bytecode = 0;
int bytecodelen = 0; int bytecodelen = 0;
if (!D3D::CompilePixelShader(code, (int)strlen(code), &bytecode, &bytecodelen)) { if (!D3D::CompilePixelShader(code, (int)strlen(code), &bytecode, &bytecodelen)) {
if (g_ActiveConfig.bShowShaderErrors) if (g_ActiveConfig.bShowShaderErrors)
{ {
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code); PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
static int counter = 0; static int counter = 0;
char szTemp[MAX_PATH]; char szTemp[MAX_PATH];
sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++); sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
SaveData(szTemp, code); SaveData(szTemp, code);
} }
return false; return false;
} }
// Here we have the UID and the byte code. Insert it into the disk cache. // Here we have the UID and the byte code. Insert it into the disk cache.
g_ps_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen); g_ps_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen);
g_ps_disk_cache.Sync(); g_ps_disk_cache.Sync();
// And insert it into the shader cache. // And insert it into the shader cache.
bool result = InsertByteCode(uid, bytecode, bytecodelen, true); bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
delete [] bytecode; delete [] bytecode;
return result; return result;
} }
bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) { bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) {
LPDIRECT3DPIXELSHADER9 shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen); LPDIRECT3DPIXELSHADER9 shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
// Make an entry in the table // Make an entry in the table
PSCacheEntry newentry; PSCacheEntry newentry;
newentry.shader = shader; newentry.shader = shader;
newentry.frameCount = frameCount; newentry.frameCount = frameCount;
PixelShaders[uid] = newentry; PixelShaders[uid] = newentry;
last_entry = &PixelShaders[uid]; last_entry = &PixelShaders[uid];
if (!shader) { if (!shader) {
// INCSTAT(stats.numPixelShadersFailed); // INCSTAT(stats.numPixelShadersFailed);
return false; return false;
} }
INCSTAT(stats.numPixelShadersCreated); INCSTAT(stats.numPixelShadersCreated);
SETSTAT(stats.numPixelShadersAlive, (int)PixelShaders.size()); SETSTAT(stats.numPixelShadersAlive, (int)PixelShaders.size());
if (activate) if (activate)
{ {
D3D::SetPixelShader(shader); D3D::SetPixelShader(shader);
} }
return true; return true;
} }
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
std::string PixelShaderCache::GetCurrentShaderCode() std::string PixelShaderCache::GetCurrentShaderCode()
{ {
if (last_entry) if (last_entry)
return last_entry->code; return last_entry->code;
else else
return "(no shader)\n"; return "(no shader)\n";
} }
#endif #endif
} }
@@ -1,89 +1,89 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _PIXELSHADERCACHE_H #ifndef _PIXELSHADERCACHE_H
#define _PIXELSHADERCACHE_H #define _PIXELSHADERCACHE_H
#include "Common.h" #include "Common.h"
#include "LinearDiskCache.h" #include "LinearDiskCache.h"
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include <map> #include <map>
#include "PixelShaderGen.h" #include "PixelShaderGen.h"
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
#include "../PixelShaderCache.h" #include "../PixelShaderCache.h"
namespace DX9 namespace DX9
{ {
typedef u32 tevhash; typedef u32 tevhash;
tevhash GetCurrentTEV(); tevhash GetCurrentTEV();
class PixelShaderCache : public ::PixelShaderCacheBase class PixelShaderCache : public ::PixelShaderCacheBase
{ {
private: private:
struct PSCacheEntry struct PSCacheEntry
{ {
LPDIRECT3DPIXELSHADER9 shader; LPDIRECT3DPIXELSHADER9 shader;
bool owns_shader; bool owns_shader;
int frameCount; int frameCount;
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
std::string code; std::string code;
#endif #endif
PSCacheEntry() : shader(NULL), owns_shader(true), frameCount(0) {} PSCacheEntry() : shader(NULL), owns_shader(true), frameCount(0) {}
void Destroy() void Destroy()
{ {
if (shader && owns_shader) if (shader && owns_shader)
shader->Release(); shader->Release();
shader = NULL; shader = NULL;
} }
}; };
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache; typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
static PSCache PixelShaders; static PSCache PixelShaders;
static const PSCacheEntry *last_entry; static const PSCacheEntry *last_entry;
static void Clear(); static void Clear();
public: public:
PixelShaderCache(); PixelShaderCache();
~PixelShaderCache(); ~PixelShaderCache();
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4); void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
void SetPSConstant4fv(unsigned int const_number, const float* f); void SetPSConstant4fv(unsigned int const_number, const float* f);
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float* f); void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float* f);
bool SetShader(bool dstAlpha); bool SetShader(bool dstAlpha);
static bool InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate); static bool InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
static LPDIRECT3DPIXELSHADER9 GetColorMatrixProgram(int SSAAMode); static LPDIRECT3DPIXELSHADER9 GetColorMatrixProgram(int SSAAMode);
static LPDIRECT3DPIXELSHADER9 GetColorCopyProgram(int SSAAMode); static LPDIRECT3DPIXELSHADER9 GetColorCopyProgram(int SSAAMode);
static LPDIRECT3DPIXELSHADER9 GetDepthMatrixProgram(int SSAAMode); static LPDIRECT3DPIXELSHADER9 GetDepthMatrixProgram(int SSAAMode);
static LPDIRECT3DPIXELSHADER9 GetClearProgram(); static LPDIRECT3DPIXELSHADER9 GetClearProgram();
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
static std::string GetCurrentShaderCode(); static std::string GetCurrentShaderCode();
#endif #endif
static LPDIRECT3DPIXELSHADER9 CompileCgShader(const char *pstrprogram); static LPDIRECT3DPIXELSHADER9 CompileCgShader(const char *pstrprogram);
}; };
} }
#endif // _PIXELSHADERCACHE_H #endif // _PIXELSHADERCACHE_H
File diff suppressed because it is too large Load Diff
@@ -1,58 +1,58 @@
#pragma once #pragma once
#include "MathUtil.h" #include "MathUtil.h"
#include "VideoCommon.h" #include "VideoCommon.h"
#include "Renderer.h" #include "Renderer.h"
#include "pluginspecs_video.h" #include "pluginspecs_video.h"
namespace DX9 namespace DX9
{ {
class Renderer : public ::RendererBase class Renderer : public ::RendererBase
{ {
public: public:
Renderer(); Renderer();
~Renderer(); ~Renderer();
void ResetAPIState(); void ResetAPIState();
void RestoreAPIState(); void RestoreAPIState();
static void SetupDeviceObjects(); static void SetupDeviceObjects();
static void TeardownDeviceObjects(); static void TeardownDeviceObjects();
void SetColorMask(); void SetColorMask();
void SetBlendMode(bool forceUpdate); void SetBlendMode(bool forceUpdate);
bool SetScissorRect(); bool SetScissorRect();
void SetGenerationMode(); void SetGenerationMode();
void SetDepthMode(); void SetDepthMode();
void SetLogicOpMode(); void SetLogicOpMode();
void SetSamplerState(int stage,int texindex); void SetSamplerState(int stage,int texindex);
void SetDitherMode(); void SetDitherMode();
void SetLineWidth(); void SetLineWidth();
u32 AccessEFB(EFBAccessType type, int x, int y); u32 AccessEFB(EFBAccessType type, int x, int y);
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z); void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
void UpdateViewport(); void UpdateViewport();
// virtual funcs used by RendererBase::Swap // virtual funcs used by RendererBase::Swap
void PrepareXFBCopy(const TargetRectangle &dst_rect); void PrepareXFBCopy(const TargetRectangle &dst_rect);
void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc, void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc); const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc);
void EndFrame(); void EndFrame();
void Present(); void Present();
bool CheckForResize(); bool CheckForResize();
void GetBackBufferSize(int* w, int* h); void GetBackBufferSize(int* w, int* h);
void RecreateFramebufferManger(); void RecreateFramebufferManger();
void BeginFrame(); void BeginFrame();
void Swap(u32, FieldType, u32, u32, const EFBRectangle&); void Swap(u32, FieldType, u32, u32, const EFBRectangle&);
private: private:
static bool IS_AMD; static bool IS_AMD;
}; };
} }
@@ -1,207 +1,207 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <d3dx9.h> #include <d3dx9.h>
#include "Statistics.h" #include "Statistics.h"
#include "MemoryUtil.h" #include "MemoryUtil.h"
#include "Hash.h" #include "Hash.h"
#include "CommonPaths.h" #include "CommonPaths.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include "DX9_D3DTexture.h" #include "DX9_D3DTexture.h"
#include "DX9_D3DUtil.h" #include "DX9_D3DUtil.h"
#include "DX9_FramebufferManager.h" #include "DX9_FramebufferManager.h"
#include "DX9_PixelShaderCache.h" #include "DX9_PixelShaderCache.h"
#include "PixelShaderManager.h" #include "PixelShaderManager.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "DX9_VertexShaderCache.h" #include "DX9_VertexShaderCache.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "DX9_Render.h" #include "DX9_Render.h"
#include "TextureDecoder.h" #include "TextureDecoder.h"
#include "DX9_TextureCache.h" #include "DX9_TextureCache.h"
#include "HiresTextures.h" #include "HiresTextures.h"
#include "DX9_TextureConverter.h" #include "DX9_TextureConverter.h"
#include "../Main.h" #include "../Main.h"
//#include "debugger/debugger.h" //#include "debugger/debugger.h"
namespace DX9 namespace DX9
{ {
TextureCache::TCacheEntry::TCacheEntry(LPDIRECT3DTEXTURE9 _texture) TextureCache::TCacheEntry::TCacheEntry(LPDIRECT3DTEXTURE9 _texture)
: texture(_texture), isDynamic(false) : texture(_texture), isDynamic(false)
{ {
} }
TextureCache::TCacheEntry::~TCacheEntry() TextureCache::TCacheEntry::~TCacheEntry()
{ {
texture->Release(); texture->Release();
} }
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int level) unsigned int expanded_width, unsigned int level)
{ {
D3D::ReplaceTexture2D(texture, temp, width, height, expanded_width, d3d_fmt, swap_r_b, level); D3D::ReplaceTexture2D(texture, temp, width, height, expanded_width, d3d_fmt, swap_r_b, level);
} }
void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf, void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect) unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect)
{ {
LPDIRECT3DSURFACE9 Rendersurf = NULL; LPDIRECT3DSURFACE9 Rendersurf = NULL;
texture->GetSurfaceLevel(0, &Rendersurf); texture->GetSurfaceLevel(0, &Rendersurf);
D3D::dev->SetDepthStencilSurface(NULL); D3D::dev->SetDepthStencilSurface(NULL);
D3D::dev->SetRenderTarget(0, Rendersurf); D3D::dev->SetRenderTarget(0, Rendersurf);
D3DVIEWPORT9 vp; D3DVIEWPORT9 vp;
// Stretch picture with increased internal resolution // Stretch picture with increased internal resolution
vp.X = 0; vp.X = 0;
vp.Y = 0; vp.Y = 0;
vp.Width = Scaledw; vp.Width = Scaledw;
vp.Height = Scaledh; vp.Height = Scaledh;
vp.MinZ = 0.0f; vp.MinZ = 0.0f;
vp.MaxZ = 1.0f; vp.MaxZ = 1.0f;
D3D::dev->SetViewport(&vp); D3D::dev->SetViewport(&vp);
RECT destrect; RECT destrect;
destrect.bottom = Scaledh; destrect.bottom = Scaledh;
destrect.left = 0; destrect.left = 0;
destrect.right = Scaledw; destrect.right = Scaledw;
destrect.top = 0; destrect.top = 0;
const float* const fConstAdd = colmat + 16; // fConstAdd is the last 4 floats of colmat const float* const fConstAdd = colmat + 16; // fConstAdd is the last 4 floats of colmat
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect); TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect);
RECT sourcerect; RECT sourcerect;
sourcerect.bottom = targetSource.bottom; sourcerect.bottom = targetSource.bottom;
sourcerect.left = targetSource.left; sourcerect.left = targetSource.left;
sourcerect.right = targetSource.right; sourcerect.right = targetSource.right;
sourcerect.top = targetSource.top; sourcerect.top = targetSource.top;
if (bFromZBuffer) if (bFromZBuffer)
{ {
if (bScaleByHalf || g_ActiveConfig.iMultisampleMode) if (bScaleByHalf || g_ActiveConfig.iMultisampleMode)
{ {
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
} }
else else
{ {
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
} }
} }
else else
{ {
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
} }
const LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ? const LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ?
FramebufferManager::GetEFBDepthTexture(source_rect) : FramebufferManager::GetEFBDepthTexture(source_rect) :
FramebufferManager::GetEFBColorTexture(source_rect); FramebufferManager::GetEFBColorTexture(source_rect);
D3DFORMAT bformat = FramebufferManager::GetEFBDepthRTSurfaceFormat(); D3DFORMAT bformat = FramebufferManager::GetEFBDepthRTSurfaceFormat();
int SSAAMode = g_ActiveConfig.iMultisampleMode; int SSAAMode = g_ActiveConfig.iMultisampleMode;
D3D::drawShadedTexQuad(read_texture, &sourcerect, D3D::drawShadedTexQuad(read_texture, &sourcerect,
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
Scaledw, Scaledh, Scaledw, Scaledh,
((bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8) && bFromZBuffer) ? ((bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8) && bFromZBuffer) ?
PixelShaderCache::GetDepthMatrixProgram(SSAAMode) : PixelShaderCache::GetDepthMatrixProgram(SSAAMode) :
PixelShaderCache::GetColorMatrixProgram(SSAAMode), PixelShaderCache::GetColorMatrixProgram(SSAAMode),
VertexShaderCache::GetSimpleVertexShader(SSAAMode)); VertexShaderCache::GetSimpleVertexShader(SSAAMode));
Rendersurf->Release(); Rendersurf->Release();
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER); D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
D3D::SetTexture(0,NULL); D3D::SetTexture(0,NULL);
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
} }
void TextureCache::TCacheEntry::Bind(unsigned int stage) void TextureCache::TCacheEntry::Bind(unsigned int stage)
{ {
D3D::SetTexture(stage, texture); D3D::SetTexture(stage, texture);
} }
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, unsigned int height, TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt) unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt)
{ {
D3DFORMAT d3d_fmt; D3DFORMAT d3d_fmt;
bool swap_r_b = false; bool swap_r_b = false;
switch (pcfmt) switch (pcfmt)
{ {
case PC_TEX_FMT_BGRA32: case PC_TEX_FMT_BGRA32:
d3d_fmt = D3DFMT_A8R8G8B8; d3d_fmt = D3DFMT_A8R8G8B8;
break; break;
case PC_TEX_FMT_RGBA32: case PC_TEX_FMT_RGBA32:
d3d_fmt = D3DFMT_A8R8G8B8; d3d_fmt = D3DFMT_A8R8G8B8;
swap_r_b = true; swap_r_b = true;
break; break;
case PC_TEX_FMT_RGB565: case PC_TEX_FMT_RGB565:
d3d_fmt = D3DFMT_R5G6B5; d3d_fmt = D3DFMT_R5G6B5;
break; break;
case PC_TEX_FMT_IA4_AS_IA8: case PC_TEX_FMT_IA4_AS_IA8:
d3d_fmt = D3DFMT_A8L8; d3d_fmt = D3DFMT_A8L8;
break; break;
case PC_TEX_FMT_I8: case PC_TEX_FMT_I8:
case PC_TEX_FMT_I4_AS_I8: case PC_TEX_FMT_I4_AS_I8:
// A hack which means the format is a packed // A hack which means the format is a packed
// 8-bit intensity texture. It is unpacked // 8-bit intensity texture. It is unpacked
// to A8L8 in D3DTexture.cpp // to A8L8 in D3DTexture.cpp
d3d_fmt = D3DFMT_A8P8; d3d_fmt = D3DFMT_A8P8;
break; break;
case PC_TEX_FMT_IA8: case PC_TEX_FMT_IA8:
d3d_fmt = D3DFMT_A8L8; d3d_fmt = D3DFMT_A8L8;
break; break;
case PC_TEX_FMT_DXT1: case PC_TEX_FMT_DXT1:
d3d_fmt = D3DFMT_DXT1; d3d_fmt = D3DFMT_DXT1;
break; break;
} }
TCacheEntry* entry = new TCacheEntry(D3D::CreateTexture2D(temp, width, height, expanded_width, d3d_fmt, swap_r_b, tex_levels)); TCacheEntry* entry = new TCacheEntry(D3D::CreateTexture2D(temp, width, height, expanded_width, d3d_fmt, swap_r_b, tex_levels));
entry->swap_r_b = swap_r_b; entry->swap_r_b = swap_r_b;
entry->d3d_fmt = d3d_fmt; entry->d3d_fmt = d3d_fmt;
return entry; return entry;
} }
TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h) TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h)
{ {
LPDIRECT3DTEXTURE9 texture; LPDIRECT3DTEXTURE9 texture;
D3D::dev->CreateTexture(scaled_tex_w, scaled_tex_h, 1, D3DUSAGE_RENDERTARGET, D3D::dev->CreateTexture(scaled_tex_w, scaled_tex_h, 1, D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0); D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
return new TCacheEntry(texture); return new TCacheEntry(texture);
} }
} }
@@ -1,67 +1,67 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _TEXTURECACHE_H #ifndef _TEXTURECACHE_H
#define _TEXTURECACHE_H #define _TEXTURECACHE_H
#include <map> #include <map>
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include "VideoCommon.h" #include "VideoCommon.h"
#include "BPMemory.h" #include "BPMemory.h"
#include "../TextureCache.h" #include "../TextureCache.h"
namespace DX9 namespace DX9
{ {
class TextureCache : public TextureCacheBase class TextureCache : public TextureCacheBase
{ {
public: public:
struct TCacheEntry : TCacheEntryBase struct TCacheEntry : TCacheEntryBase
{ {
LPDIRECT3DTEXTURE9 texture; LPDIRECT3DTEXTURE9 texture;
D3DFORMAT d3d_fmt; D3DFORMAT d3d_fmt;
bool swap_r_b; bool swap_r_b;
bool isDynamic; // mofified from cpu bool isDynamic; // mofified from cpu
TCacheEntry(LPDIRECT3DTEXTURE9 _texture); TCacheEntry(LPDIRECT3DTEXTURE9 _texture);
~TCacheEntry(); ~TCacheEntry();
void Load(unsigned int width, unsigned int height, void Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int levels); unsigned int expanded_width, unsigned int levels);
void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf, void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect); unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect);
void Bind(unsigned int stage); void Bind(unsigned int stage);
}; };
public: public:
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height, TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt); unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt);
TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h); TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h);
}; };
} }
#endif #endif
File diff suppressed because it is too large Load Diff
@@ -1,53 +1,53 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _TEXTURECONVERTER_H_ #ifndef _TEXTURECONVERTER_H_
#define _TEXTURECONVERTER_H_ #define _TEXTURECONVERTER_H_
#include "VideoCommon.h" #include "VideoCommon.h"
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include "DX9_D3DTexture.h" #include "DX9_D3DTexture.h"
#include "DX9_D3DUtil.h" #include "DX9_D3DUtil.h"
#include "DX9_D3DShader.h" #include "DX9_D3DShader.h"
namespace DX9 namespace DX9
{ {
// Converts textures between formats // Converts textures between formats
// TODO: support multiple texture formats // TODO: support multiple texture formats
namespace TextureConverter namespace TextureConverter
{ {
void Init(); void Init();
void Shutdown(); void Shutdown();
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc, void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,
u8* destAddr, int dstWidth, int dstHeight); u8* destAddr, int dstWidth, int dstHeight);
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture); void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture);
u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 SourceW, u32 SourceH,float MValueX,float MValueY,float Xstride, float Ystride , bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 SourceW, u32 SourceH,float MValueX,float MValueY,float Xstride, float Ystride , bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
} }
} }
#endif // _TEXTURECONVERTER_H_ #endif // _TEXTURECONVERTER_H_
@@ -1,135 +1,135 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "Common.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include "Fifo.h" #include "Fifo.h"
#include "Statistics.h" #include "Statistics.h"
#include "Profiler.h" #include "Profiler.h"
#include "DX9_VertexManager.h" #include "DX9_VertexManager.h"
#include "OpcodeDecoding.h" #include "OpcodeDecoding.h"
#include "IndexGenerator.h" #include "IndexGenerator.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "DX9_VertexShaderCache.h" #include "DX9_VertexShaderCache.h"
#include "PixelShaderManager.h" #include "PixelShaderManager.h"
#include "DX9_PixelShaderCache.h" #include "DX9_PixelShaderCache.h"
#include "NativeVertexFormat.h" #include "NativeVertexFormat.h"
#include "NativeVertexWriter.h" #include "NativeVertexWriter.h"
#include "DX9_TextureCache.h" #include "DX9_TextureCache.h"
#include "../Main.h" #include "../Main.h"
#include "BPStructs.h" #include "BPStructs.h"
#include "XFStructs.h" #include "XFStructs.h"
//#include "debugger/debugger.h" //#include "debugger/debugger.h"
namespace DX9 namespace DX9
{ {
using namespace D3D; using namespace D3D;
// internal state for loading vertices // internal state for loading vertices
extern NativeVertexFormat *g_nativeVertexFmt; extern NativeVertexFormat *g_nativeVertexFmt;
inline void DumpBadShaders() inline void DumpBadShaders()
{ {
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
std::string error_shaders; std::string error_shaders;
error_shaders.append(VertexShaderCache::GetCurrentShaderCode()); error_shaders.append(VertexShaderCache::GetCurrentShaderCode());
error_shaders.append(PixelShaderCache::GetCurrentShaderCode()); error_shaders.append(PixelShaderCache::GetCurrentShaderCode());
char filename[512] = "bad_shader_combo_0.txt"; char filename[512] = "bad_shader_combo_0.txt";
int which = 0; int which = 0;
while (File::Exists(filename)) while (File::Exists(filename))
{ {
which++; which++;
sprintf(filename, "bad_shader_combo_%i.txt", which); sprintf(filename, "bad_shader_combo_%i.txt", which);
} }
File::WriteStringToFile(true, error_shaders, filename); File::WriteStringToFile(true, error_shaders, filename);
PanicAlert("DrawIndexedPrimitiveUP failed. Shaders written to %s", filename); PanicAlert("DrawIndexedPrimitiveUP failed. Shaders written to %s", filename);
#endif #endif
} }
void VertexManager::Draw(u32 stride, bool alphapass) void VertexManager::Draw(u32 stride, bool alphapass)
{ {
if (alphapass) if (alphapass)
{ {
DWORD write = 0; DWORD write = 0;
if (false == g_pixel_shader_cache->SetShader(true)) if (false == g_pixel_shader_cache->SetShader(true))
{ {
//DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");}); //DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
//goto shader_fail; //goto shader_fail;
return; return;
} }
// update alpha only // update alpha only
D3D::ChangeRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA); D3D::ChangeRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA);
D3D::ChangeRenderState(D3DRS_ALPHABLENDENABLE, false); D3D::ChangeRenderState(D3DRS_ALPHABLENDENABLE, false);
} }
if (IndexGenerator::GetNumTriangles() > 0) if (IndexGenerator::GetNumTriangles() > 0)
{ {
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP( if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_TRIANGLELIST, D3DPT_TRIANGLELIST,
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumTriangles(), 0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumTriangles(),
TIBuffer, TIBuffer,
D3DFMT_INDEX16, D3DFMT_INDEX16,
LocalVBuffer, LocalVBuffer,
stride))) stride)))
{ {
DumpBadShaders(); DumpBadShaders();
} }
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
} }
if (IndexGenerator::GetNumLines() > 0) if (IndexGenerator::GetNumLines() > 0)
{ {
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP( if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_LINELIST, D3DPT_LINELIST,
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumLines(), 0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumLines(),
LIBuffer, LIBuffer,
D3DFMT_INDEX16, D3DFMT_INDEX16,
LocalVBuffer, LocalVBuffer,
stride))) stride)))
{ {
DumpBadShaders(); DumpBadShaders();
} }
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
} }
if (IndexGenerator::GetNumPoints() > 0) if (IndexGenerator::GetNumPoints() > 0)
{ {
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP( if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_POINTLIST, D3DPT_POINTLIST,
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumPoints(), 0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumPoints(),
PIBuffer, PIBuffer,
D3DFMT_INDEX16, D3DFMT_INDEX16,
LocalVBuffer, LocalVBuffer,
stride))) stride)))
{ {
DumpBadShaders(); DumpBadShaders();
} }
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
} }
if (alphapass) if (alphapass)
{ {
D3D::RefreshRenderState(D3DRS_COLORWRITEENABLE); D3D::RefreshRenderState(D3DRS_COLORWRITEENABLE);
D3D::RefreshRenderState(D3DRS_ALPHABLENDENABLE); D3D::RefreshRenderState(D3DRS_ALPHABLENDENABLE);
} }
} }
} // namespace } // namespace
@@ -1,39 +1,39 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _VERTEXMANAGER_H #ifndef _VERTEXMANAGER_H
#define _VERTEXMANAGER_H #define _VERTEXMANAGER_H
#include "CPMemory.h" #include "CPMemory.h"
#include "VertexLoader.h" #include "VertexLoader.h"
#include "../VertexManager.h" #include "../VertexManager.h"
namespace DX9 namespace DX9
{ {
class VertexManager : public ::VertexManagerBase class VertexManager : public ::VertexManagerBase
{ {
public: public:
void Draw(u32 stride, bool alphapass); void Draw(u32 stride, bool alphapass);
NativeVertexFormat* CreateNativeVertexFormat(); NativeVertexFormat* CreateNativeVertexFormat();
}; };
} }
#endif #endif
@@ -1,302 +1,302 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <map> #include <map>
#include "Common.h" #include "Common.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "LinearDiskCache.h" #include "LinearDiskCache.h"
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include "DX9_D3DShader.h" #include "DX9_D3DShader.h"
#include "Statistics.h" #include "Statistics.h"
#include "Profiler.h" #include "Profiler.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "DX9_VertexShaderCache.h" #include "DX9_VertexShaderCache.h"
#include "VertexLoader.h" #include "VertexLoader.h"
#include "BPMemory.h" #include "BPMemory.h"
#include "XFMemory.h" #include "XFMemory.h"
//#include "debugger/debugger.h" //#include "debugger/debugger.h"
#include "../Main.h" #include "../Main.h"
namespace DX9 namespace DX9
{ {
VertexShaderCache::VSCache VertexShaderCache::vshaders; VertexShaderCache::VSCache VertexShaderCache::vshaders;
const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry; const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry;
#define MAX_SSAA_SHADERS 3 #define MAX_SSAA_SHADERS 3
static LPDIRECT3DVERTEXSHADER9 SimpleVertexShader[MAX_SSAA_SHADERS]; static LPDIRECT3DVERTEXSHADER9 SimpleVertexShader[MAX_SSAA_SHADERS];
static LPDIRECT3DVERTEXSHADER9 ClearVertexShader; static LPDIRECT3DVERTEXSHADER9 ClearVertexShader;
LinearDiskCache g_vs_disk_cache; LinearDiskCache g_vs_disk_cache;
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetSimpleVertexShader(int level) LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetSimpleVertexShader(int level)
{ {
return SimpleVertexShader[level % MAX_SSAA_SHADERS]; return SimpleVertexShader[level % MAX_SSAA_SHADERS];
} }
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetClearVertexShader() LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetClearVertexShader()
{ {
return ClearVertexShader; return ClearVertexShader;
} }
void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{ {
const float f[4] = { f1, f2, f3, f4 }; const float f[4] = { f1, f2, f3, f4 };
D3D::dev->SetVertexShaderConstantF(const_number, f, 1); D3D::dev->SetVertexShaderConstantF(const_number, f, 1);
} }
void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float *f) void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float *f)
{ {
D3D::dev->SetVertexShaderConstantF(const_number, f, 1); D3D::dev->SetVertexShaderConstantF(const_number, f, 1);
} }
void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f) void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
{ {
float buf[4*C_VENVCONST_END]; float buf[4*C_VENVCONST_END];
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
buf[4*i ] = *f++; buf[4*i ] = *f++;
buf[4*i+1] = *f++; buf[4*i+1] = *f++;
buf[4*i+2] = *f++; buf[4*i+2] = *f++;
buf[4*i+3] = 0.f; buf[4*i+3] = 0.f;
} }
D3D::dev->SetVertexShaderConstantF(const_number, buf, count); D3D::dev->SetVertexShaderConstantF(const_number, buf, count);
} }
void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f) void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
{ {
D3D::dev->SetVertexShaderConstantF(const_number, f, count); D3D::dev->SetVertexShaderConstantF(const_number, f, count);
} }
class VertexShaderCacheInserter : public LinearDiskCacheReader { class VertexShaderCacheInserter : public LinearDiskCacheReader {
public: public:
void Read(const u8 *key, int key_size, const u8 *value, int value_size) void Read(const u8 *key, int key_size, const u8 *value, int value_size)
{ {
VERTEXSHADERUID uid; VERTEXSHADERUID uid;
if (key_size != sizeof(uid)) { if (key_size != sizeof(uid)) {
ERROR_LOG(VIDEO, "Wrong key size in vertex shader cache"); ERROR_LOG(VIDEO, "Wrong key size in vertex shader cache");
return; return;
} }
memcpy(&uid, key, key_size); memcpy(&uid, key, key_size);
VertexShaderCache::InsertByteCode(uid, value, value_size, false); VertexShaderCache::InsertByteCode(uid, value, value_size, false);
} }
}; };
VertexShaderCache::VertexShaderCache() VertexShaderCache::VertexShaderCache()
{ {
char* vProg = new char[2048]; char* vProg = new char[2048];
sprintf(vProg,"struct VSOUTPUT\n" sprintf(vProg,"struct VSOUTPUT\n"
"{\n" "{\n"
"float4 vPosition : POSITION;\n" "float4 vPosition : POSITION;\n"
"float2 vTexCoord : TEXCOORD0;\n" "float2 vTexCoord : TEXCOORD0;\n"
"};\n" "};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0)\n" "VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0)\n"
"{\n" "{\n"
"VSOUTPUT OUT;\n" "VSOUTPUT OUT;\n"
"OUT.vPosition = inPosition;\n" "OUT.vPosition = inPosition;\n"
"OUT.vTexCoord = inTEX0;\n" "OUT.vTexCoord = inTEX0;\n"
"return OUT;\n" "return OUT;\n"
"}\n"); "}\n");
SimpleVertexShader[0] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg)); SimpleVertexShader[0] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
sprintf(vProg,"struct VSOUTPUT\n" sprintf(vProg,"struct VSOUTPUT\n"
"{\n" "{\n"
"float4 vPosition : POSITION;\n" "float4 vPosition : POSITION;\n"
"float4 vColor0 : COLOR0;\n" "float4 vColor0 : COLOR0;\n"
"};\n" "};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n" "VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n"
"{\n" "{\n"
"VSOUTPUT OUT;\n" "VSOUTPUT OUT;\n"
"OUT.vPosition = inPosition;\n" "OUT.vPosition = inPosition;\n"
"OUT.vColor0 = inColor0;\n" "OUT.vColor0 = inColor0;\n"
"return OUT;\n" "return OUT;\n"
"}\n"); "}\n");
ClearVertexShader = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg)); ClearVertexShader = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
sprintf(vProg, "struct VSOUTPUT\n" sprintf(vProg, "struct VSOUTPUT\n"
"{\n" "{\n"
"float4 vPosition : POSITION;\n" "float4 vPosition : POSITION;\n"
"float4 vTexCoord : TEXCOORD0;\n" "float4 vTexCoord : TEXCOORD0;\n"
"float4 vTexCoord1 : TEXCOORD1;\n" "float4 vTexCoord1 : TEXCOORD1;\n"
"};\n" "};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float4 inTEX2 : TEXCOORD2)\n" "VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float4 inTEX2 : TEXCOORD2)\n"
"{\n" "{\n"
"VSOUTPUT OUT;" "VSOUTPUT OUT;"
"OUT.vPosition = inPosition;\n" "OUT.vPosition = inPosition;\n"
"OUT.vTexCoord = inTEX0.xyyx;\n" "OUT.vTexCoord = inTEX0.xyyx;\n"
"OUT.vTexCoord1 = inTEX2;\n" "OUT.vTexCoord1 = inTEX2;\n"
"return OUT;\n" "return OUT;\n"
"}\n"); "}\n");
SimpleVertexShader[1] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg)); SimpleVertexShader[1] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
sprintf(vProg, "struct VSOUTPUT\n" sprintf(vProg, "struct VSOUTPUT\n"
"{\n" "{\n"
"float4 vPosition : POSITION;\n" "float4 vPosition : POSITION;\n"
"float4 vTexCoord : TEXCOORD0;\n" "float4 vTexCoord : TEXCOORD0;\n"
"float4 vTexCoord1 : TEXCOORD1;\n" "float4 vTexCoord1 : TEXCOORD1;\n"
"float4 vTexCoord2 : TEXCOORD2;\n" "float4 vTexCoord2 : TEXCOORD2;\n"
"float4 vTexCoord3 : TEXCOORD3;\n" "float4 vTexCoord3 : TEXCOORD3;\n"
"};\n" "};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float4 inTEX2 : TEXCOORD2)\n" "VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float4 inTEX2 : TEXCOORD2)\n"
"{\n" "{\n"
"VSOUTPUT OUT;" "VSOUTPUT OUT;"
"OUT.vPosition = inPosition;\n" "OUT.vPosition = inPosition;\n"
"OUT.vTexCoord = inTEX0.xyyx;\n" "OUT.vTexCoord = inTEX0.xyyx;\n"
"OUT.vTexCoord1 = inTEX0.xyyx + (float4(-1.0f,-0.5f, 1.0f,-0.5f) * inTEX1.xyyx);\n" "OUT.vTexCoord1 = inTEX0.xyyx + (float4(-1.0f,-0.5f, 1.0f,-0.5f) * inTEX1.xyyx);\n"
"OUT.vTexCoord2 = inTEX0.xyyx + (float4( 1.0f, 0.5f,-1.0f, 0.5f) * inTEX1.xyyx);\n" "OUT.vTexCoord2 = inTEX0.xyyx + (float4( 1.0f, 0.5f,-1.0f, 0.5f) * inTEX1.xyyx);\n"
"OUT.vTexCoord3 = inTEX2;\n" "OUT.vTexCoord3 = inTEX2;\n"
"return OUT;\n" "return OUT;\n"
"}\n"); "}\n");
SimpleVertexShader[2] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg)); SimpleVertexShader[2] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
Clear(); Clear();
delete [] vProg; delete [] vProg;
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
SETSTAT(stats.numVertexShadersCreated, 0); SETSTAT(stats.numVertexShadersCreated, 0);
SETSTAT(stats.numVertexShadersAlive, 0); SETSTAT(stats.numVertexShadersAlive, 0);
char cache_filename[MAX_PATH]; char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx9-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id); sprintf(cache_filename, "%sdx9-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
VertexShaderCacheInserter inserter; VertexShaderCacheInserter inserter;
int read_items = g_vs_disk_cache.OpenAndRead(cache_filename, &inserter); int read_items = g_vs_disk_cache.OpenAndRead(cache_filename, &inserter);
} }
void VertexShaderCache::Clear() void VertexShaderCache::Clear()
{ {
VSCache::iterator VSCache::iterator
iter = vshaders.begin(), iter = vshaders.begin(),
vsend = vshaders.end(); vsend = vshaders.end();
for (; iter != vsend; ++iter) for (; iter != vsend; ++iter)
iter->second.Destroy(); iter->second.Destroy();
vshaders.clear(); vshaders.clear();
memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid)); memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid));
} }
VertexShaderCache::~VertexShaderCache() VertexShaderCache::~VertexShaderCache()
{ {
for (int i = 0; i < MAX_SSAA_SHADERS; i++) for (int i = 0; i < MAX_SSAA_SHADERS; i++)
{ {
if (SimpleVertexShader[i]) if (SimpleVertexShader[i])
SimpleVertexShader[i]->Release(); SimpleVertexShader[i]->Release();
SimpleVertexShader[i] = NULL; SimpleVertexShader[i] = NULL;
} }
if (ClearVertexShader) if (ClearVertexShader)
ClearVertexShader->Release(); ClearVertexShader->Release();
ClearVertexShader = NULL; ClearVertexShader = NULL;
g_vs_disk_cache.Sync(); g_vs_disk_cache.Sync();
g_vs_disk_cache.Close(); g_vs_disk_cache.Close();
} }
bool VertexShaderCache::SetShader(u32 components) bool VertexShaderCache::SetShader(u32 components)
{ {
DVSTARTPROFILE(); DVSTARTPROFILE();
VERTEXSHADERUID uid; VERTEXSHADERUID uid;
GetVertexShaderId(&uid, components); GetVertexShaderId(&uid, components);
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount) if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
{ {
if (vshaders[uid].shader) if (vshaders[uid].shader)
return true; return true;
else else
return false; return false;
} }
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID)); memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
VSCache::iterator iter; VSCache::iterator iter;
iter = vshaders.find(uid); iter = vshaders.find(uid);
if (iter != vshaders.end()) if (iter != vshaders.end())
{ {
iter->second.frameCount = frameCount; iter->second.frameCount = frameCount;
const VSCacheEntry &entry = iter->second; const VSCacheEntry &entry = iter->second;
last_entry = &entry; last_entry = &entry;
//DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); //DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
if (entry.shader) if (entry.shader)
{ {
D3D::SetVertexShader(entry.shader); D3D::SetVertexShader(entry.shader);
return true; return true;
} }
else else
return false; return false;
} }
const char *code = GenerateVertexShaderCode(components, API_D3D9); const char *code = GenerateVertexShaderCode(components, API_D3D9);
u8 *bytecode; u8 *bytecode;
int bytecodelen; int bytecodelen;
if (!D3D::CompileVertexShader(code, (int)strlen(code), &bytecode, &bytecodelen)) if (!D3D::CompileVertexShader(code, (int)strlen(code), &bytecode, &bytecodelen))
{ {
if (g_ActiveConfig.bShowShaderErrors) if (g_ActiveConfig.bShowShaderErrors)
{ {
PanicAlert("Failed to compile Vertex Shader:\n\n%s", code); PanicAlert("Failed to compile Vertex Shader:\n\n%s", code);
} }
return false; return false;
} }
g_vs_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen); g_vs_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen);
g_vs_disk_cache.Sync(); g_vs_disk_cache.Sync();
bool result = InsertByteCode(uid, bytecode, bytecodelen, true); bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
delete [] bytecode; delete [] bytecode;
return result; return result;
} }
bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) { bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) {
LPDIRECT3DVERTEXSHADER9 shader = D3D::CreateVertexShaderFromByteCode(bytecode, bytecodelen); LPDIRECT3DVERTEXSHADER9 shader = D3D::CreateVertexShaderFromByteCode(bytecode, bytecodelen);
// Make an entry in the table // Make an entry in the table
VSCacheEntry entry; VSCacheEntry entry;
entry.shader = shader; entry.shader = shader;
entry.frameCount = frameCount; entry.frameCount = frameCount;
vshaders[uid] = entry; vshaders[uid] = entry;
last_entry = &vshaders[uid]; last_entry = &vshaders[uid];
if (!shader) if (!shader)
return false; return false;
INCSTAT(stats.numVertexShadersCreated); INCSTAT(stats.numVertexShadersCreated);
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size()); SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
if (activate) if (activate)
{ {
D3D::SetVertexShader(shader); D3D::SetVertexShader(shader);
return true; return true;
} }
return false; return false;
} }
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
std::string VertexShaderCache::GetCurrentShaderCode() std::string VertexShaderCache::GetCurrentShaderCode()
{ {
return "(N/A)\n"; return "(N/A)\n";
} }
#endif #endif
} }
@@ -1,81 +1,81 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _VERTEXSHADERCACHE_H #ifndef _VERTEXSHADERCACHE_H
#define _VERTEXSHADERCACHE_H #define _VERTEXSHADERCACHE_H
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include <map> #include <map>
#include <string> #include <string>
#include "DX9_D3DBase.h" #include "DX9_D3DBase.h"
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
#include "../VertexShaderCache.h" #include "../VertexShaderCache.h"
namespace DX9 namespace DX9
{ {
class VertexShaderCache : public ::VertexShaderCacheBase class VertexShaderCache : public ::VertexShaderCacheBase
{ {
private: private:
struct VSCacheEntry struct VSCacheEntry
{ {
LPDIRECT3DVERTEXSHADER9 shader; LPDIRECT3DVERTEXSHADER9 shader;
int frameCount; int frameCount;
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
std::string code; std::string code;
#endif #endif
VSCacheEntry() : shader(NULL), frameCount(0) {} VSCacheEntry() : shader(NULL), frameCount(0) {}
void Destroy() void Destroy()
{ {
if (shader) if (shader)
shader->Release(); shader->Release();
shader = NULL; shader = NULL;
} }
}; };
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache; typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
static VSCache vshaders; static VSCache vshaders;
static const VSCacheEntry *last_entry; static const VSCacheEntry *last_entry;
static void Clear(); static void Clear();
public: public:
VertexShaderCache(); VertexShaderCache();
~VertexShaderCache(); ~VertexShaderCache();
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4); void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
void SetVSConstant4fv(unsigned int const_number, const float *f); void SetVSConstant4fv(unsigned int const_number, const float *f);
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f); void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f);
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f); void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
bool SetShader(u32 components); bool SetShader(u32 components);
static LPDIRECT3DVERTEXSHADER9 GetSimpleVertexShader(int level); static LPDIRECT3DVERTEXSHADER9 GetSimpleVertexShader(int level);
static LPDIRECT3DVERTEXSHADER9 GetClearVertexShader(); static LPDIRECT3DVERTEXSHADER9 GetClearVertexShader();
static bool InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate); static bool InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
static std::string GetCurrentShaderCode(); static std::string GetCurrentShaderCode();
#endif #endif
static LPDIRECT3DVERTEXSHADER9 CompileCgShader(const char *pstrprogram); static LPDIRECT3DVERTEXSHADER9 CompileCgShader(const char *pstrprogram);
}; };
} }
#endif // _VERTEXSHADERCACHE_H #endif // _VERTEXSHADERCACHE_H
+233 -233
View File
@@ -1,233 +1,233 @@
#include <windows.h> #include <windows.h>
// VideoCommon // VideoCommon
#include "VideoConfig.h" #include "VideoConfig.h"
#include "Fifo.h" #include "Fifo.h"
#include "EmuWindow.h" #include "EmuWindow.h"
int OSDChoice = 0 , OSDTime = 0, OSDInternalW = 0, OSDInternalH = 0; int OSDChoice = 0 , OSDTime = 0, OSDInternalW = 0, OSDInternalH = 0;
namespace EmuWindow namespace EmuWindow
{ {
HWND m_hWnd = NULL; HWND m_hWnd = NULL;
HWND m_hParent = NULL; HWND m_hParent = NULL;
HINSTANCE m_hInstance = NULL; HINSTANCE m_hInstance = NULL;
WNDCLASSEX wndClass; WNDCLASSEX wndClass;
const TCHAR m_szClassName[] = _T("DolphinEmuWnd"); const TCHAR m_szClassName[] = _T("DolphinEmuWnd");
int g_winstyle; int g_winstyle;
static volatile bool s_sizing; static volatile bool s_sizing;
bool IsSizing() bool IsSizing()
{ {
return s_sizing; return s_sizing;
} }
HWND GetWnd() HWND GetWnd()
{ {
return m_hWnd; return m_hWnd;
} }
HWND GetParentWnd() HWND GetParentWnd()
{ {
return m_hParent; return m_hParent;
} }
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// KeyDown events // KeyDown events
// ------------- // -------------
void OnKeyDown(WPARAM wParam) void OnKeyDown(WPARAM wParam)
{ {
switch (LOWORD( wParam )) switch (LOWORD( wParam ))
{ {
case '3': // OSD keys case '3': // OSD keys
case '4': case '4':
case '5': case '5':
case '6': case '6':
case '7': case '7':
if (g_Config.bOSDHotKey) if (g_Config.bOSDHotKey)
OSDMenu(wParam); OSDMenu(wParam);
break; break;
} }
} }
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
{ {
switch( iMsg ) switch( iMsg )
{ {
case WM_PAINT: case WM_PAINT:
{ {
HDC hdc; HDC hdc;
PAINTSTRUCT ps; PAINTSTRUCT ps;
hdc = BeginPaint(hWnd, &ps); hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps); EndPaint(hWnd, &ps);
} }
break; break;
case WM_ENTERSIZEMOVE: case WM_ENTERSIZEMOVE:
s_sizing = true; s_sizing = true;
break; break;
case WM_EXITSIZEMOVE: case WM_EXITSIZEMOVE:
s_sizing = false; s_sizing = false;
break; break;
/* Post thes mouse events to the main window, it's nessesary because in difference to the /* Post thes mouse events to the main window, it's nessesary because in difference to the
keyboard inputs these events only appear here, not in the parent window or any other WndProc()*/ keyboard inputs these events only appear here, not in the parent window or any other WndProc()*/
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
case WM_LBUTTONUP: case WM_LBUTTONUP:
case WM_LBUTTONDBLCLK: case WM_LBUTTONDBLCLK:
PostMessage(GetParentWnd(), iMsg, wParam, lParam); PostMessage(GetParentWnd(), iMsg, wParam, lParam);
break; break;
case WM_CLOSE: case WM_CLOSE:
// When the user closes the window, we post an event to the main window to call Stop() // When the user closes the window, we post an event to the main window to call Stop()
// Which then handles all the necessary steps to Shutdown the core + the plugins // Which then handles all the necessary steps to Shutdown the core + the plugins
if (m_hParent == NULL) if (m_hParent == NULL)
PostMessage(m_hParent, WM_USER, WM_USER_STOP, 0); PostMessage(m_hParent, WM_USER, WM_USER_STOP, 0);
break; break;
case WM_USER: case WM_USER:
if (wParam == WM_USER_KEYDOWN) if (wParam == WM_USER_KEYDOWN)
OnKeyDown(lParam); OnKeyDown(lParam);
else if (wParam == WIIMOTE_DISCONNECT) else if (wParam == WIIMOTE_DISCONNECT)
PostMessage(m_hParent, WM_USER, wParam, lParam); PostMessage(m_hParent, WM_USER, wParam, lParam);
break; break;
case WM_SYSCOMMAND: case WM_SYSCOMMAND:
switch (wParam) switch (wParam)
{ {
case SC_SCREENSAVE: case SC_SCREENSAVE:
case SC_MONITORPOWER: case SC_MONITORPOWER:
break; break;
default: default:
return DefWindowProc(hWnd, iMsg, wParam, lParam); return DefWindowProc(hWnd, iMsg, wParam, lParam);
} }
break; break;
case WM_SETCURSOR: case WM_SETCURSOR:
PostMessage(m_hParent, WM_USER, WM_USER_SETCURSOR, 0); PostMessage(m_hParent, WM_USER, WM_USER_SETCURSOR, 0);
return true; return true;
break; break;
default: default:
return DefWindowProc(hWnd, iMsg, wParam, lParam); return DefWindowProc(hWnd, iMsg, wParam, lParam);
} }
return 0; return 0;
} }
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// OSD Menu // OSD Menu
// ------------- // -------------
// Let's begin with 3 since 1 and 2 are default Wii keys // Let's begin with 3 since 1 and 2 are default Wii keys
// ------------- // -------------
void OSDMenu(WPARAM wParam) void OSDMenu(WPARAM wParam)
{ {
switch( LOWORD( wParam )) switch( LOWORD( wParam ))
{ {
//case '3': //case '3':
// OSDChoice = 1; // OSDChoice = 1;
// // Toggle native resolution // // Toggle native resolution
// OSDInternalW = D3D::GetBackBufferWidth(); // OSDInternalW = D3D::GetBackBufferWidth();
// OSDInternalH = D3D::GetBackBufferHeight(); // OSDInternalH = D3D::GetBackBufferHeight();
// break; // break;
case '4': case '4':
OSDChoice = 2; OSDChoice = 2;
// Toggle aspect ratio // Toggle aspect ratio
g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3; g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3;
break; break;
case '5': case '5':
OSDChoice = 3; OSDChoice = 3;
PanicAlert("Toggling EFB copy not implemented!\n"); PanicAlert("Toggling EFB copy not implemented!\n");
break; break;
case '6': case '6':
OSDChoice = 4; OSDChoice = 4;
g_Config.bDisableFog = !g_Config.bDisableFog; g_Config.bDisableFog = !g_Config.bDisableFog;
break; break;
case '7': case '7':
OSDChoice = 5; OSDChoice = 5;
g_Config.bDisableLighting = !g_Config.bDisableLighting; g_Config.bDisableLighting = !g_Config.bDisableLighting;
break; break;
} }
} }
HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title) HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title)
{ {
wndClass.cbSize = sizeof( wndClass ); wndClass.cbSize = sizeof( wndClass );
wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wndClass.lpfnWndProc = WndProc; wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0; wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0; wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance; wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wndClass.hCursor = NULL; wndClass.hCursor = NULL;
wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
wndClass.lpszMenuName = NULL; wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = m_szClassName; wndClass.lpszClassName = m_szClassName;
wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION ); wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
m_hInstance = hInstance; m_hInstance = hInstance;
RegisterClassEx( &wndClass ); RegisterClassEx( &wndClass );
m_hParent = parent; m_hParent = parent;
m_hWnd = CreateWindow(m_szClassName, title, WS_CHILD, m_hWnd = CreateWindow(m_szClassName, title, WS_CHILD,
0, 0, width, height, m_hParent, NULL, hInstance, NULL); 0, 0, width, height, m_hParent, NULL, hInstance, NULL);
return m_hWnd; return m_hWnd;
} }
void Show() void Show()
{ {
ShowWindow(m_hWnd, SW_SHOW); ShowWindow(m_hWnd, SW_SHOW);
BringWindowToTop(m_hWnd); BringWindowToTop(m_hWnd);
UpdateWindow(m_hWnd); UpdateWindow(m_hWnd);
SetFocus(m_hParent); SetFocus(m_hParent);
} }
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title) HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title)
{ {
// TODO: // TODO:
// 1. Remove redundant window manipulation, // 1. Remove redundant window manipulation,
// 2. Make DX11 in fullscreen can be overlapped by other dialogs // 2. Make DX11 in fullscreen can be overlapped by other dialogs
// 3. Request window sizes which actually make the client area map to a common resolution // 3. Request window sizes which actually make the client area map to a common resolution
HWND Ret; HWND Ret;
int x=0, y=0, width=640, height=480; int x=0, y=0, width=640, height=480;
g_VideoInitialize.pRequestWindowSize(x, y, width, height); g_VideoInitialize.pRequestWindowSize(x, y, width, height);
Ret = OpenWindow(hParent, hInstance, width, height, title); Ret = OpenWindow(hParent, hInstance, width, height, title);
if (Ret) if (Ret)
{ {
Show(); Show();
} }
return Ret; return Ret;
} }
void Close() void Close()
{ {
if (m_hParent == NULL) if (m_hParent == NULL)
DestroyWindow(m_hWnd); DestroyWindow(m_hWnd);
UnregisterClass(m_szClassName, m_hInstance); UnregisterClass(m_szClassName, m_hInstance);
} }
void SetSize(int width, int height) void SetSize(int width, int height)
{ {
RECT rc = {0, 0, width, height}; RECT rc = {0, 0, width, height};
DWORD style = GetWindowLong(m_hWnd, GWL_STYLE); DWORD style = GetWindowLong(m_hWnd, GWL_STYLE);
AdjustWindowRect(&rc, style, false); AdjustWindowRect(&rc, style, false);
int w = rc.right - rc.left; int w = rc.right - rc.left;
int h = rc.bottom - rc.top; int h = rc.bottom - rc.top;
rc.left = (1280 - w)/2; rc.left = (1280 - w)/2;
rc.right = rc.left + w; rc.right = rc.left + w;
rc.top = (1024 - h)/2; rc.top = (1024 - h)/2;
rc.bottom = rc.top + h; rc.bottom = rc.top + h;
MoveWindow(m_hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE); MoveWindow(m_hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE);
} }
} }
@@ -1,21 +1,21 @@
#ifndef _EMUWINDOW_H_ #ifndef _EMUWINDOW_H_
#define _EMUWINDOW_H_ #define _EMUWINDOW_H_
#include <windows.h> #include <windows.h>
namespace EmuWindow namespace EmuWindow
{ {
HWND GetWnd(); HWND GetWnd();
HWND GetParentWnd(); HWND GetParentWnd();
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR* title); HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR* title);
void Show(); void Show();
void Close(); void Close();
void SetSize(int displayWidth, int displayHeight); void SetSize(int displayWidth, int displayHeight);
bool IsSizing(); bool IsSizing();
void OSDMenu(WPARAM wParam); void OSDMenu(WPARAM wParam);
} }
#endif #endif
@@ -1,216 +1,216 @@
#include "FramebufferManager.h" #include "FramebufferManager.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "Renderer.h" #include "Renderer.h"
#include "Main.h" #include "Main.h"
FramebufferManagerBase::VirtualXFBListType FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode FramebufferManagerBase::VirtualXFBListType FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode
const XFBSourceBase* FramebufferManagerBase::m_overlappingXFBArray[]; const XFBSourceBase* FramebufferManagerBase::m_overlappingXFBArray[];
FramebufferManagerBase::~FramebufferManagerBase() FramebufferManagerBase::~FramebufferManagerBase()
{ {
VirtualXFBListType::iterator VirtualXFBListType::iterator
it = m_virtualXFBList.begin(), it = m_virtualXFBList.begin(),
vlend = m_virtualXFBList.end(); vlend = m_virtualXFBList.end();
for (; it != vlend; ++it) for (; it != vlend; ++it)
delete it->xfbSource; delete it->xfbSource;
} }
const XFBSourceBase** FramebufferManagerBase::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount) const XFBSourceBase** FramebufferManagerBase::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{ {
//if (g_ActiveConfig.bUseRealXFB) //if (g_ActiveConfig.bUseRealXFB)
// return getRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); // return getRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
//else //else
return getVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); return getVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
} }
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper) inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
{ {
return !((aLower >= bUpper) || (bLower >= aUpper)); return !((aLower >= bUpper) || (bLower >= aUpper));
} }
void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{ {
//if (g_ActiveConfig.bUseRealXFB) //if (g_ActiveConfig.bUseRealXFB)
// copyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc); // copyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
//else //else
copyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc); copyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
} }
void FramebufferManagerBase::replaceVirtualXFB() void FramebufferManagerBase::replaceVirtualXFB()
{ {
VirtualXFBListType::iterator VirtualXFBListType::iterator
it = m_virtualXFBList.begin(), it = m_virtualXFBList.begin(),
vlend = m_virtualXFBList.end(); vlend = m_virtualXFBList.end();
VirtualXFB *vxfb = &*it; VirtualXFB *vxfb = &*it;
const s32 srcLower = vxfb->xfbAddr; const s32 srcLower = vxfb->xfbAddr;
const s32 srcUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight; const s32 srcUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
const s32 lineSize = 2 * vxfb->xfbWidth; const s32 lineSize = 2 * vxfb->xfbWidth;
while (++it != vlend) while (++it != vlend)
{ {
vxfb = &*it; vxfb = &*it;
const s32 dstLower = vxfb->xfbAddr; const s32 dstLower = vxfb->xfbAddr;
const s32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight; const s32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
if (dstLower >= srcLower && dstUpper <= srcUpper) if (dstLower >= srcLower && dstUpper <= srcUpper)
{ {
// invalidate the data // invalidate the data
vxfb->xfbAddr = 0; vxfb->xfbAddr = 0;
vxfb->xfbHeight = 0; vxfb->xfbHeight = 0;
vxfb->xfbWidth = 0; vxfb->xfbWidth = 0;
} }
else if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper)) else if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
{ {
const s32 upperOverlap = (srcUpper - dstLower) / lineSize; const s32 upperOverlap = (srcUpper - dstLower) / lineSize;
const s32 lowerOverlap = (dstUpper - srcLower) / lineSize; const s32 lowerOverlap = (dstUpper - srcLower) / lineSize;
if (upperOverlap > 0 && lowerOverlap < 0) if (upperOverlap > 0 && lowerOverlap < 0)
{ {
vxfb->xfbAddr += lineSize * upperOverlap; vxfb->xfbAddr += lineSize * upperOverlap;
vxfb->xfbHeight -= upperOverlap; vxfb->xfbHeight -= upperOverlap;
} }
else if (lowerOverlap > 0) else if (lowerOverlap > 0)
{ {
vxfb->xfbHeight -= lowerOverlap; vxfb->xfbHeight -= lowerOverlap;
} }
} }
} }
} }
FramebufferManagerBase::VirtualXFBListType::iterator FramebufferManagerBase::VirtualXFBListType::iterator
FramebufferManagerBase::findVirtualXFB(u32 xfbAddr, u32 width, u32 height) FramebufferManagerBase::findVirtualXFB(u32 xfbAddr, u32 width, u32 height)
{ {
const u32 srcLower = xfbAddr; const u32 srcLower = xfbAddr;
const u32 srcUpper = xfbAddr + 2 * width * height; const u32 srcUpper = xfbAddr + 2 * width * height;
VirtualXFBListType::iterator VirtualXFBListType::iterator
it = m_virtualXFBList.begin(), it = m_virtualXFBList.begin(),
vlend = m_virtualXFBList.end(); vlend = m_virtualXFBList.end();
for (; it != vlend; ++it) for (; it != vlend; ++it)
{ {
const VirtualXFB &vxfb = *it; const VirtualXFB &vxfb = *it;
const u32 dstLower = vxfb.xfbAddr; const u32 dstLower = vxfb.xfbAddr;
const u32 dstUpper = vxfb.xfbAddr + 2 * vxfb.xfbWidth * vxfb.xfbHeight; const u32 dstUpper = vxfb.xfbAddr + 2 * vxfb.xfbWidth * vxfb.xfbHeight;
if (dstLower >= srcLower && dstUpper <= srcUpper) if (dstLower >= srcLower && dstUpper <= srcUpper)
return it; return it;
} }
// That address is not in the Virtual XFB list. // That address is not in the Virtual XFB list.
return m_virtualXFBList.end(); return m_virtualXFBList.end();
} }
void FramebufferManagerBase::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) void FramebufferManagerBase::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{ {
const VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, fbWidth, fbHeight); const VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, fbWidth, fbHeight);
VirtualXFB *vxfb = NULL; VirtualXFB *vxfb = NULL;
if (m_virtualXFBList.end() == it) if (m_virtualXFBList.end() == it)
{ {
if (m_virtualXFBList.size() >= MAX_VIRTUAL_XFB) if (m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
{ {
PanicAlert("Requested creating a new virtual XFB although the maximum number has already been reached! Report this to the devs"); PanicAlert("Requested creating a new virtual XFB although the maximum number has already been reached! Report this to the devs");
return; return;
// TODO, possible alternative to failing: just delete the oldest virtual XFB: // TODO, possible alternative to failing: just delete the oldest virtual XFB:
// delete m_virtualXFBList.back().xfbSource; // delete m_virtualXFBList.back().xfbSource;
// m_virtualXFBList.pop_back(); // m_virtualXFBList.pop_back();
} }
else else
{ {
// create a new Virtual XFB and place it at the front of the list // create a new Virtual XFB and place it at the front of the list
VirtualXFB v; VirtualXFB v;
m_virtualXFBList.push_front(v); m_virtualXFBList.push_front(v);
vxfb = &m_virtualXFBList.front(); vxfb = &m_virtualXFBList.front();
} }
} }
else else
{ {
vxfb = &*it; vxfb = &*it;
delete vxfb->xfbSource; delete vxfb->xfbSource;
} }
vxfb->xfbAddr = xfbAddr; vxfb->xfbAddr = xfbAddr;
vxfb->xfbWidth = fbWidth; vxfb->xfbWidth = fbWidth;
vxfb->xfbHeight = fbHeight; vxfb->xfbHeight = fbHeight;
const float scaleX = RendererBase::GetXFBScaleX(); const float scaleX = RendererBase::GetXFBScaleX();
const float scaleY = RendererBase::GetXFBScaleY(); const float scaleY = RendererBase::GetXFBScaleY();
TargetRectangle targetSource; TargetRectangle targetSource;
targetSource.top = (int)(sourceRc.top * scaleY); targetSource.top = (int)(sourceRc.top * scaleY);
targetSource.bottom = (int)(sourceRc.bottom * scaleY); targetSource.bottom = (int)(sourceRc.bottom * scaleY);
targetSource.left = (int)(sourceRc.left * scaleX); targetSource.left = (int)(sourceRc.left * scaleX);
targetSource.right = (int)(sourceRc.right * scaleX); targetSource.right = (int)(sourceRc.right * scaleX);
const unsigned int target_width = targetSource.right - targetSource.left; const unsigned int target_width = targetSource.right - targetSource.left;
const unsigned int target_height = targetSource.bottom - targetSource.top; const unsigned int target_height = targetSource.bottom - targetSource.top;
vxfb->xfbSource = g_framebuffer_manager->CreateXFBSource(target_width, target_height); vxfb->xfbSource = g_framebuffer_manager->CreateXFBSource(target_width, target_height);
if (NULL == vxfb->xfbSource) if (NULL == vxfb->xfbSource)
{ {
PanicAlert("Failed to create virtual XFB"); PanicAlert("Failed to create virtual XFB");
return; return;
} }
// why do both of these have a height/width/addr ? // why do both of these have a height/width/addr ?
vxfb->xfbSource->srcAddr = xfbAddr; vxfb->xfbSource->srcAddr = xfbAddr;
vxfb->xfbSource->srcWidth = fbWidth; vxfb->xfbSource->srcWidth = fbWidth;
vxfb->xfbSource->srcHeight = fbHeight; vxfb->xfbSource->srcHeight = fbHeight;
vxfb->xfbSource->texWidth = target_width; vxfb->xfbSource->texWidth = target_width;
vxfb->xfbSource->texHeight = target_height; vxfb->xfbSource->texHeight = target_height;
if (m_virtualXFBList.end() != it) if (m_virtualXFBList.end() != it)
{ {
// move this Virtual XFB to the front of the list. // move this Virtual XFB to the front of the list.
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it); m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it);
// keep stale XFB data from being used // keep stale XFB data from being used
replaceVirtualXFB(); replaceVirtualXFB();
} }
g_renderer->ResetAPIState(); // reset any game specific settings g_renderer->ResetAPIState(); // reset any game specific settings
vxfb->xfbSource->CopyEFB(RendererBase::ConvertEFBRectangle(sourceRc)); vxfb->xfbSource->CopyEFB(RendererBase::ConvertEFBRectangle(sourceRc));
g_renderer->RestoreAPIState(); g_renderer->RestoreAPIState();
} }
const XFBSourceBase** FramebufferManagerBase::getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount) const XFBSourceBase** FramebufferManagerBase::getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{ {
xfbCount = 0; xfbCount = 0;
if (0 == m_virtualXFBList.size()) // no Virtual XFBs available if (0 == m_virtualXFBList.size()) // no Virtual XFBs available
return NULL; return NULL;
u32 srcLower = xfbAddr; u32 srcLower = xfbAddr;
u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight; u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight;
VirtualXFBListType::reverse_iterator VirtualXFBListType::reverse_iterator
it = m_virtualXFBList.rbegin(), it = m_virtualXFBList.rbegin(),
vlend = m_virtualXFBList.rend(); vlend = m_virtualXFBList.rend();
for (; it != vlend; ++it) for (; it != vlend; ++it)
{ {
VirtualXFB* vxfb = &*it; VirtualXFB* vxfb = &*it;
u32 dstLower = vxfb->xfbAddr; u32 dstLower = vxfb->xfbAddr;
u32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight; u32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper)) if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
{ {
m_overlappingXFBArray[xfbCount] = vxfb->xfbSource; m_overlappingXFBArray[xfbCount] = vxfb->xfbSource;
xfbCount++; xfbCount++;
} }
} }
return &m_overlappingXFBArray[0]; return &m_overlappingXFBArray[0];
} }
@@ -1,71 +1,71 @@
#ifndef _FRAMEBUFFERMANAGER_H_ #ifndef _FRAMEBUFFERMANAGER_H_
#define _FRAMEBUFFERMANAGER_H_ #define _FRAMEBUFFERMANAGER_H_
#include <list> #include <list>
#include "CommonTypes.h" #include "CommonTypes.h"
#include "VideoCommon.h" #include "VideoCommon.h"
struct XFBSourceBase struct XFBSourceBase
{ {
u32 srcAddr; u32 srcAddr;
u32 srcWidth; u32 srcWidth;
u32 srcHeight; u32 srcHeight;
unsigned int texWidth; unsigned int texWidth;
unsigned int texHeight; unsigned int texHeight;
virtual void CopyEFB(const TargetRectangle& efbSource) = 0; virtual void CopyEFB(const TargetRectangle& efbSource) = 0;
virtual ~XFBSourceBase() {} virtual ~XFBSourceBase() {}
protected: protected:
XFBSourceBase() : srcAddr(0), srcWidth(0), srcHeight(0), texWidth(0), texHeight(0) {} XFBSourceBase() : srcAddr(0), srcWidth(0), srcHeight(0), texWidth(0), texHeight(0) {}
}; };
class FramebufferManagerBase class FramebufferManagerBase
{ {
public: public:
enum enum
{ {
MAX_VIRTUAL_XFB = 8, MAX_VIRTUAL_XFB = 8,
}; };
virtual ~FramebufferManagerBase(); virtual ~FramebufferManagerBase();
//virtual void Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples) = 0; //virtual void Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples) = 0;
//virtual void Shutdown() = 0; //virtual void Shutdown() = 0;
static void replaceVirtualXFB(); static void replaceVirtualXFB();
static void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc); static void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
static const XFBSourceBase** GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount); static const XFBSourceBase** GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
static const XFBSourceBase** getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount); static const XFBSourceBase** getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
//protected: //protected:
struct VirtualXFB struct VirtualXFB
{ {
// Address and size in GameCube RAM // Address and size in GameCube RAM
u32 xfbAddr; u32 xfbAddr;
u32 xfbWidth; u32 xfbWidth;
u32 xfbHeight; u32 xfbHeight;
XFBSourceBase *xfbSource; XFBSourceBase *xfbSource;
}; };
virtual XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height) = 0; virtual XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height) = 0;
typedef std::list<VirtualXFB> VirtualXFBListType; typedef std::list<VirtualXFB> VirtualXFBListType;
static VirtualXFBListType m_virtualXFBList; // used in virtual XFB mode static VirtualXFBListType m_virtualXFBList; // used in virtual XFB mode
static VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height); static VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height);
static void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc); static void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
static const XFBSourceBase* m_overlappingXFBArray[MAX_VIRTUAL_XFB]; static const XFBSourceBase* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
}; };
#endif #endif
File diff suppressed because it is too large Load Diff
+57 -57
View File
@@ -1,57 +1,57 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _MAIN_H_ #ifndef _MAIN_H_
#define _MAIN_H_ #define _MAIN_H_
#include "PluginSpecs_Video.h" #include "PluginSpecs_Video.h"
#include "Renderer.h" #include "Renderer.h"
#include "TextureCache.h" #include "TextureCache.h"
#include "VertexManager.h" #include "VertexManager.h"
#include "PixelShaderCache.h" #include "PixelShaderCache.h"
#include "VertexShaderCache.h" #include "VertexShaderCache.h"
#include "FramebufferManager.h" #include "FramebufferManager.h"
extern SVideoInitialize g_VideoInitialize; extern SVideoInitialize g_VideoInitialize;
extern volatile u32 s_swapRequested; extern volatile u32 s_swapRequested;
extern PLUGIN_GLOBALS *g_globals; extern PLUGIN_GLOBALS *g_globals;
extern RendererBase *g_renderer; extern RendererBase *g_renderer;
extern TextureCacheBase *g_texture_cache; extern TextureCacheBase *g_texture_cache;
extern VertexManagerBase *g_vertex_manager; extern VertexManagerBase *g_vertex_manager;
extern VertexShaderCacheBase* g_vertex_shader_cache; extern VertexShaderCacheBase* g_vertex_shader_cache;
extern PixelShaderCacheBase* g_pixel_shader_cache; extern PixelShaderCacheBase* g_pixel_shader_cache;
extern FramebufferManagerBase* g_framebuffer_manager; extern FramebufferManagerBase* g_framebuffer_manager;
extern int frameCount; extern int frameCount;
void VideoFifo_CheckEFBAccess(); void VideoFifo_CheckEFBAccess();
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight); void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
enum enum
{ {
GFXAPI_SOFTWARE, GFXAPI_SOFTWARE,
GFXAPI_OPENGL, GFXAPI_OPENGL,
GFXAPI_D3D9, GFXAPI_D3D9,
GFXAPI_D3D11, GFXAPI_D3D11,
}; };
extern const char* const g_gfxapi_names[]; extern const char* const g_gfxapi_names[];
extern int g_gfxapi; extern int g_gfxapi;
#endif #endif
@@ -1,385 +1,385 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// OGL // OGL
#include "OGL_Render.h" #include "OGL_Render.h"
#include "OGL_XFB.h" #include "OGL_XFB.h"
#include "OGL_FramebufferManager.h" #include "OGL_FramebufferManager.h"
#include "OGL_TextureConverter.h" #include "OGL_TextureConverter.h"
namespace OGL namespace OGL
{ {
extern bool s_bHaveFramebufferBlit; // comes from Render.cpp extern bool s_bHaveFramebufferBlit; // comes from Render.cpp
int FramebufferManager::m_targetWidth; int FramebufferManager::m_targetWidth;
int FramebufferManager::m_targetHeight; int FramebufferManager::m_targetHeight;
int FramebufferManager::m_msaaSamples; int FramebufferManager::m_msaaSamples;
int FramebufferManager::m_msaaCoverageSamples; int FramebufferManager::m_msaaCoverageSamples;
GLuint FramebufferManager::m_efbFramebuffer; GLuint FramebufferManager::m_efbFramebuffer;
GLuint FramebufferManager::m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise GLuint FramebufferManager::m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
GLuint FramebufferManager::m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise GLuint FramebufferManager::m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
// Only used in MSAA mode. // Only used in MSAA mode.
GLuint FramebufferManager::m_resolvedFramebuffer; GLuint FramebufferManager::m_resolvedFramebuffer;
GLuint FramebufferManager::m_resolvedColorTexture; GLuint FramebufferManager::m_resolvedColorTexture;
GLuint FramebufferManager::m_resolvedDepthTexture; GLuint FramebufferManager::m_resolvedDepthTexture;
GLuint FramebufferManager::m_xfbFramebuffer; // Only used in MSAA mode GLuint FramebufferManager::m_xfbFramebuffer; // Only used in MSAA mode
XFBSource FramebufferManager::m_realXFBSource; // Only used in Real XFB mode XFBSource FramebufferManager::m_realXFBSource; // Only used in Real XFB mode
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples) FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
{ {
// m_efbFramebuffer(0), // m_efbFramebuffer(0),
// m_efbColor(0), // m_efbColor(0),
// m_efbDepth(0), // m_efbDepth(0),
// m_resolvedFramebuffer(0), // m_resolvedFramebuffer(0),
// m_resolvedColorTexture(0), // m_resolvedColorTexture(0),
// m_resolvedDepthTexture(0), // m_resolvedDepthTexture(0),
// m_xfbFramebuffer(0) // m_xfbFramebuffer(0)
m_targetWidth = targetWidth; m_targetWidth = targetWidth;
m_targetHeight = targetHeight; m_targetHeight = targetHeight;
m_msaaSamples = msaaSamples; m_msaaSamples = msaaSamples;
m_msaaCoverageSamples = msaaCoverageSamples; m_msaaCoverageSamples = msaaCoverageSamples;
// The EFB can be set to different pixel formats by the game through the // The EFB can be set to different pixel formats by the game through the
// BPMEM_ZCOMPARE register (which should probably have a different name). // BPMEM_ZCOMPARE register (which should probably have a different name).
// They are: // They are:
// - 24-bit RGB (8-bit components) with 24-bit Z // - 24-bit RGB (8-bit components) with 24-bit Z
// - 24-bit RGBA (6-bit components) with 24-bit Z // - 24-bit RGBA (6-bit components) with 24-bit Z
// - Multisampled 16-bit RGB (5-6-5 format) with 16-bit Z // - Multisampled 16-bit RGB (5-6-5 format) with 16-bit Z
// We only use one EFB format here: 32-bit ARGB with 24-bit Z. // We only use one EFB format here: 32-bit ARGB with 24-bit Z.
// Multisampling depends on user settings. // Multisampling depends on user settings.
// The distinction becomes important for certain operations, i.e. the // The distinction becomes important for certain operations, i.e. the
// alpha channel should be ignored if the EFB does not have one. // alpha channel should be ignored if the EFB does not have one.
// Create EFB target. // Create EFB target.
glGenFramebuffersEXT(1, &m_efbFramebuffer); glGenFramebuffersEXT(1, &m_efbFramebuffer);
if (m_msaaSamples <= 1) if (m_msaaSamples <= 1)
{ {
// EFB targets will be textures in non-MSAA mode. // EFB targets will be textures in non-MSAA mode.
GLuint glObj[2]; GLuint glObj[2];
glGenTextures(2, glObj); glGenTextures(2, glObj);
m_efbColor = glObj[0]; m_efbColor = glObj[0];
m_efbDepth = glObj[1]; m_efbDepth = glObj[1];
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbColor); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbColor);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbDepth); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbDepth);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
// Bind target textures to the EFB framebuffer. // Bind target textures to the EFB framebuffer.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbColor, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbColor, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0);
GL_REPORT_FBO_ERROR(); GL_REPORT_FBO_ERROR();
} }
else else
{ {
// EFB targets will be renderbuffers in MSAA mode (required by OpenGL). // EFB targets will be renderbuffers in MSAA mode (required by OpenGL).
// Resolve targets will be created to transfer EFB to RAM textures. // Resolve targets will be created to transfer EFB to RAM textures.
// XFB framebuffer will be created to transfer EFB to XFB texture. // XFB framebuffer will be created to transfer EFB to XFB texture.
// Create EFB target renderbuffers. // Create EFB target renderbuffers.
GLuint glObj[2]; GLuint glObj[2];
glGenRenderbuffersEXT(2, glObj); glGenRenderbuffersEXT(2, glObj);
m_efbColor = glObj[0]; m_efbColor = glObj[0];
m_efbDepth = glObj[1]; m_efbDepth = glObj[1];
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor);
if (m_msaaCoverageSamples) if (m_msaaCoverageSamples)
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight); glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
else else
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth);
if (m_msaaCoverageSamples) if (m_msaaCoverageSamples)
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight); glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
else else
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
// Bind target renderbuffers to EFB framebuffer. // Bind target renderbuffers to EFB framebuffer.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_efbColor); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_efbColor);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_efbDepth); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_efbDepth);
GL_REPORT_FBO_ERROR(); GL_REPORT_FBO_ERROR();
// Create resolved targets for transferring multisampled EFB to texture. // Create resolved targets for transferring multisampled EFB to texture.
glGenFramebuffersEXT(1, &m_resolvedFramebuffer); glGenFramebuffersEXT(1, &m_resolvedFramebuffer);
glGenTextures(2, glObj); glGenTextures(2, glObj);
m_resolvedColorTexture = glObj[0]; m_resolvedColorTexture = glObj[0];
m_resolvedDepthTexture = glObj[1]; m_resolvedDepthTexture = glObj[1];
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
// Bind resolved textures to resolved framebuffer. // Bind resolved textures to resolved framebuffer.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_resolvedFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0);
GL_REPORT_FBO_ERROR(); GL_REPORT_FBO_ERROR();
// Return to EFB framebuffer. // Return to EFB framebuffer.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
} }
// Create XFB framebuffer; targets will be created elsewhere. // Create XFB framebuffer; targets will be created elsewhere.
glGenFramebuffersEXT(1, &m_xfbFramebuffer); glGenFramebuffersEXT(1, &m_xfbFramebuffer);
// EFB framebuffer is currently bound. // EFB framebuffer is currently bound.
} }
FramebufferManager::~FramebufferManager() FramebufferManager::~FramebufferManager()
{ {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
GLuint glObj[3]; GLuint glObj[3];
// Note: OpenGL deletion functions silently ignore parameters of "0". // Note: OpenGL deletion functions silently ignore parameters of "0".
glObj[0] = m_efbFramebuffer; glObj[0] = m_efbFramebuffer;
glObj[1] = m_resolvedFramebuffer; glObj[1] = m_resolvedFramebuffer;
glObj[2] = m_xfbFramebuffer; glObj[2] = m_xfbFramebuffer;
glDeleteFramebuffersEXT(3, glObj); glDeleteFramebuffersEXT(3, glObj);
m_efbFramebuffer = 0; m_efbFramebuffer = 0;
m_xfbFramebuffer = 0; m_xfbFramebuffer = 0;
glObj[0] = m_resolvedColorTexture; glObj[0] = m_resolvedColorTexture;
glObj[1] = m_resolvedDepthTexture; glObj[1] = m_resolvedDepthTexture;
glObj[2] = m_realXFBSource.texture; glObj[2] = m_realXFBSource.texture;
glDeleteTextures(3, glObj); glDeleteTextures(3, glObj);
m_resolvedColorTexture = 0; m_resolvedColorTexture = 0;
m_resolvedDepthTexture = 0; m_resolvedDepthTexture = 0;
m_realXFBSource.texture = 0; m_realXFBSource.texture = 0;
glObj[0] = m_efbColor; glObj[0] = m_efbColor;
glObj[1] = m_efbDepth; glObj[1] = m_efbDepth;
if (m_msaaSamples <= 1) if (m_msaaSamples <= 1)
glDeleteTextures(2, glObj); glDeleteTextures(2, glObj);
else else
glDeleteRenderbuffersEXT(2, glObj); glDeleteRenderbuffersEXT(2, glObj);
m_efbColor = 0; m_efbColor = 0;
m_efbDepth = 0; m_efbDepth = 0;
} }
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height) XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
{ {
XFBSource* const xfbs = new XFBSource; XFBSource* const xfbs = new XFBSource;
glGenTextures(1, &xfbs->texture); glGenTextures(1, &xfbs->texture);
return xfbs; return xfbs;
} }
void XFBSource::CopyEFB(const TargetRectangle& efbSource) void XFBSource::CopyEFB(const TargetRectangle& efbSource)
{ {
// Copy EFB to XFB texture // Copy EFB to XFB texture
#if 0 #if 0
if (m_msaaSamples <= 1) if (m_msaaSamples <= 1)
#else #else
if (!s_bHaveFramebufferBlit) if (!s_bHaveFramebufferBlit)
#endif #endif
{ {
// Just copy the EFB directly. // Just copy the EFB directly.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::m_efbFramebuffer);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, texWidth, texHeight, 0); glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, texWidth, texHeight, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
} }
else else
{ {
// OpenGL cannot copy directly from a multisampled framebuffer, so use // OpenGL cannot copy directly from a multisampled framebuffer, so use
// EXT_framebuffer_blit. // EXT_framebuffer_blit.
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::m_efbFramebuffer); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::m_efbFramebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, FramebufferManager::m_xfbFramebuffer); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, FramebufferManager::m_xfbFramebuffer);
// Bind texture. // Bind texture.
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB, texture, 0); GL_TEXTURE_RECTANGLE_ARB, texture, 0);
GL_REPORT_FBO_ERROR(); GL_REPORT_FBO_ERROR();
glBlitFramebufferEXT(0, 0, texWidth, texHeight, 0, 0, texWidth, glBlitFramebufferEXT(0, 0, texWidth, texHeight, 0, 0, texWidth,
texHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); texHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// Unbind texture. // Unbind texture.
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0); glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
// Return to EFB. // Return to EFB.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::m_efbFramebuffer);
} }
} }
GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc) GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
{ {
if (m_msaaSamples <= 1) if (m_msaaSamples <= 1)
{ {
return m_efbColor; return m_efbColor;
} }
else else
{ {
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is // Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
// required. // required.
TargetRectangle targetRc = RendererBase::ConvertEFBRectangle(sourceRc); TargetRectangle targetRc = RendererBase::ConvertEFBRectangle(sourceRc);
targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight); targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight);
// Resolve. // Resolve.
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
glBlitFramebufferEXT( glBlitFramebufferEXT(
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom, targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom, targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
GL_COLOR_BUFFER_BIT, GL_NEAREST GL_COLOR_BUFFER_BIT, GL_NEAREST
); );
// Return to EFB. // Return to EFB.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
return m_resolvedColorTexture; return m_resolvedColorTexture;
} }
} }
GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc) GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc)
{ {
if (m_msaaSamples <= 1) if (m_msaaSamples <= 1)
{ {
return m_efbDepth; return m_efbDepth;
} }
else else
{ {
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is // Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
// required. // required.
TargetRectangle targetRc = RendererBase::ConvertEFBRectangle(sourceRc); TargetRectangle targetRc = RendererBase::ConvertEFBRectangle(sourceRc);
targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight); targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight);
// Resolve. // Resolve.
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
glBlitFramebufferEXT( glBlitFramebufferEXT(
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom, targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom, targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
GL_DEPTH_BUFFER_BIT, GL_NEAREST GL_DEPTH_BUFFER_BIT, GL_NEAREST
); );
// Return to EFB. // Return to EFB.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
return m_resolvedDepthTexture; return m_resolvedDepthTexture;
} }
} }
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{ {
u8* pXFB = Memory_GetPtr(xfbAddr); u8* pXFB = Memory_GetPtr(xfbAddr);
if (!pXFB) if (!pXFB)
{ {
WARN_LOG(VIDEO, "Tried to copy to invalid XFB address"); WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
return; return;
} }
XFB_Write(pXFB, sourceRc, fbWidth, fbHeight); XFB_Write(pXFB, sourceRc, fbWidth, fbHeight);
} }
const XFBSourceBase** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount) const XFBSourceBase** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{ {
xfbCount = 1; xfbCount = 1;
m_realXFBSource.texWidth = MAX_XFB_WIDTH; m_realXFBSource.texWidth = MAX_XFB_WIDTH;
m_realXFBSource.texHeight = MAX_XFB_HEIGHT; m_realXFBSource.texHeight = MAX_XFB_HEIGHT;
m_realXFBSource.srcAddr = xfbAddr; m_realXFBSource.srcAddr = xfbAddr;
m_realXFBSource.srcWidth = fbWidth; m_realXFBSource.srcWidth = fbWidth;
m_realXFBSource.srcHeight = fbHeight; m_realXFBSource.srcHeight = fbHeight;
// OpenGL texture coordinates originate at the lower left, which is why // OpenGL texture coordinates originate at the lower left, which is why
// sourceRc.top = fbHeight and sourceRc.bottom = 0. // sourceRc.top = fbHeight and sourceRc.bottom = 0.
m_realXFBSource.sourceRc.left = 0; m_realXFBSource.sourceRc.left = 0;
m_realXFBSource.sourceRc.top = fbHeight; m_realXFBSource.sourceRc.top = fbHeight;
m_realXFBSource.sourceRc.right = fbWidth; m_realXFBSource.sourceRc.right = fbWidth;
m_realXFBSource.sourceRc.bottom = 0; m_realXFBSource.sourceRc.bottom = 0;
if (!m_realXFBSource.texture) if (!m_realXFBSource.texture)
{ {
glGenTextures(1, &m_realXFBSource.texture); glGenTextures(1, &m_realXFBSource.texture);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_realXFBSource.texture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_realXFBSource.texture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, MAX_XFB_WIDTH, MAX_XFB_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, MAX_XFB_WIDTH, MAX_XFB_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
} }
// Decode YUYV data from GameCube RAM // Decode YUYV data from GameCube RAM
TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture); TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture);
m_overlappingXFBArray[0] = &m_realXFBSource; m_overlappingXFBArray[0] = &m_realXFBSource;
return &m_overlappingXFBArray[0]; return &m_overlappingXFBArray[0];
} }
void FramebufferManager::SetFramebuffer(GLuint fb) void FramebufferManager::SetFramebuffer(GLuint fb)
{ {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb != 0 ? fb : GetEFBFramebuffer()); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb != 0 ? fb : GetEFBFramebuffer());
} }
// Apply AA if enabled // Apply AA if enabled
GLuint FramebufferManager::ResolveAndGetRenderTarget(const EFBRectangle &source_rect) GLuint FramebufferManager::ResolveAndGetRenderTarget(const EFBRectangle &source_rect)
{ {
return GetEFBColorTexture(source_rect); return GetEFBColorTexture(source_rect);
} }
GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_rect) GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_rect)
{ {
return GetEFBDepthTexture(source_rect); return GetEFBDepthTexture(source_rect);
} }
} }
@@ -1,135 +1,135 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _OGL_FRAMEBUFFERMANAGER_H_ #ifndef _OGL_FRAMEBUFFERMANAGER_H_
#define _OGL_FRAMEBUFFERMANAGER_H_ #define _OGL_FRAMEBUFFERMANAGER_H_
#include <list> #include <list>
#include "OGL_GLUtil.h" #include "OGL_GLUtil.h"
#include "../FramebufferManager.h" #include "../FramebufferManager.h"
namespace OGL namespace OGL
{ {
// On the GameCube, the game sends a request for the graphics processor to // On the GameCube, the game sends a request for the graphics processor to
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM // transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
// called the XFB (External Framebuffer). The size and location of the XFB is // called the XFB (External Framebuffer). The size and location of the XFB is
// decided at the time of the copy, and the format is always YUYV. The video // decided at the time of the copy, and the format is always YUYV. The video
// interface is given a pointer to the XFB, which will be decoded and // interface is given a pointer to the XFB, which will be decoded and
// displayed on the TV. // displayed on the TV.
// //
// There are two ways for Dolphin to emulate this: // There are two ways for Dolphin to emulate this:
// //
// Real XFB mode: // Real XFB mode:
// //
// Dolphin will behave like the GameCube and encode the EFB to // Dolphin will behave like the GameCube and encode the EFB to
// a portion of GameCube RAM. The emulated video interface will decode the data // a portion of GameCube RAM. The emulated video interface will decode the data
// for output to the screen. // for output to the screen.
// //
// Advantages: Behaves exactly like the GameCube. // Advantages: Behaves exactly like the GameCube.
// Disadvantages: Resolution will be limited. // Disadvantages: Resolution will be limited.
// //
// Virtual XFB mode: // Virtual XFB mode:
// //
// When a request is made to copy the EFB to an XFB, Dolphin // When a request is made to copy the EFB to an XFB, Dolphin
// will remember the RAM location and size of the XFB in a Virtual XFB list. // will remember the RAM location and size of the XFB in a Virtual XFB list.
// The video interface will look up the XFB in the list and use the enhanced // The video interface will look up the XFB in the list and use the enhanced
// data stored there, if available. // data stored there, if available.
// //
// Advantages: Enables high resolution graphics, better than real hardware. // Advantages: Enables high resolution graphics, better than real hardware.
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is // Disadvantages: If the GameCube CPU writes directly to the XFB (which is
// possible but uncommon), the Virtual XFB will not capture this information. // possible but uncommon), the Virtual XFB will not capture this information.
// There may be multiple XFBs in GameCube RAM. This is the maximum number to // There may be multiple XFBs in GameCube RAM. This is the maximum number to
// virtualize. // virtualize.
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper) inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
{ {
return !((aLower >= bUpper) || (bLower >= aUpper)); return !((aLower >= bUpper) || (bLower >= aUpper));
} }
struct XFBSource : XFBSourceBase struct XFBSource : XFBSourceBase
{ {
XFBSource() : texture(0) {} XFBSource() : texture(0) {}
void CopyEFB(const TargetRectangle& efbSource); void CopyEFB(const TargetRectangle& efbSource);
GLuint texture; GLuint texture;
TargetRectangle sourceRc; TargetRectangle sourceRc;
}; };
class FramebufferManager : public ::FramebufferManagerBase class FramebufferManager : public ::FramebufferManagerBase
{ {
friend struct XFBSource; friend struct XFBSource;
public: public:
FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples); FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples);
~FramebufferManager(); ~FramebufferManager();
// To get the EFB in texture form, these functions may have to transfer // To get the EFB in texture form, these functions may have to transfer
// the EFB to a resolved texture first. // the EFB to a resolved texture first.
static GLuint GetEFBColorTexture(const EFBRectangle& sourceRc); static GLuint GetEFBColorTexture(const EFBRectangle& sourceRc);
static GLuint GetEFBDepthTexture(const EFBRectangle& sourceRc); static GLuint GetEFBDepthTexture(const EFBRectangle& sourceRc);
static GLuint GetEFBFramebuffer() { return m_efbFramebuffer; } static GLuint GetEFBFramebuffer() { return m_efbFramebuffer; }
// Resolved framebuffer is only used in MSAA mode. // Resolved framebuffer is only used in MSAA mode.
static GLuint GetResolvedFramebuffer() { return m_resolvedFramebuffer; } static GLuint GetResolvedFramebuffer() { return m_resolvedFramebuffer; }
static void SetFramebuffer(GLuint fb); static void SetFramebuffer(GLuint fb);
// If in MSAA mode, this will perform a resolve of the specified rectangle, and return the resolve target as a texture ID. // If in MSAA mode, this will perform a resolve of the specified rectangle, and return the resolve target as a texture ID.
// Thus, this call may be expensive. Don't repeat it unnecessarily. // Thus, this call may be expensive. Don't repeat it unnecessarily.
// If not in MSAA mode, will just return the render target texture ID. // If not in MSAA mode, will just return the render target texture ID.
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to. // After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
static GLuint ResolveAndGetRenderTarget(const EFBRectangle &rect); static GLuint ResolveAndGetRenderTarget(const EFBRectangle &rect);
// Same as above but for the depth Target. // Same as above but for the depth Target.
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to. // After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
static GLuint ResolveAndGetDepthTarget(const EFBRectangle &rect); static GLuint ResolveAndGetDepthTarget(const EFBRectangle &rect);
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height); XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
protected: protected:
static GLuint m_efbFramebuffer; static GLuint m_efbFramebuffer;
static GLuint m_xfbFramebuffer; // Only used in MSAA mode static GLuint m_xfbFramebuffer; // Only used in MSAA mode
private: private:
static void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc); static void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
static const XFBSourceBase** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount); static const XFBSourceBase** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
static int m_targetWidth; static int m_targetWidth;
static int m_targetHeight; static int m_targetHeight;
static int m_msaaSamples; static int m_msaaSamples;
static int m_msaaCoverageSamples; static int m_msaaCoverageSamples;
static GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise static GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
static GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise static GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
// Only used in MSAA mode. // Only used in MSAA mode.
static GLuint m_resolvedFramebuffer; static GLuint m_resolvedFramebuffer;
static GLuint m_resolvedColorTexture; static GLuint m_resolvedColorTexture;
static GLuint m_resolvedDepthTexture; static GLuint m_resolvedDepthTexture;
static XFBSource m_realXFBSource; // Only used in Real XFB mode static XFBSource m_realXFBSource; // Only used in Real XFB mode
}; };
} }
#endif #endif
File diff suppressed because it is too large Load Diff
@@ -1,145 +1,145 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _GLINIT_H_ #ifndef _GLINIT_H_
#define _GLINIT_H_ #define _GLINIT_H_
// Common // Common
#include "MathUtil.h" #include "MathUtil.h"
// VideoCommon // VideoCommon
#include "VideoConfig.h" #include "VideoConfig.h"
#include "pluginspecs_video.h" #include "pluginspecs_video.h"
#ifdef _WIN32 #ifdef _WIN32
#define GLEW_STATIC #define GLEW_STATIC
#include <GL/glew.h> #include <GL/glew.h>
#include <GL/wglew.h> #include <GL/wglew.h>
#else // linux and apple basic definitions #else // linux and apple basic definitions
#if defined(USE_WX) && USE_WX #if defined(USE_WX) && USE_WX
#include <GL/glew.h> #include <GL/glew.h>
#include "wx/wx.h" #include "wx/wx.h"
#include "wx/glcanvas.h" #include "wx/glcanvas.h"
#elif defined(HAVE_X11) && HAVE_X11 #elif defined(HAVE_X11) && HAVE_X11
#include <GL/glxew.h> #include <GL/glxew.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/keysym.h> #include <X11/keysym.h>
#include "Thread.h" #include "Thread.h"
#elif defined(__APPLE__) #elif defined(__APPLE__)
#include <GL/glew.h> #include <GL/glew.h>
#include "cocoaGL.h" #include "cocoaGL.h"
#endif // end USE_WX #endif // end USE_WX
#if defined(__APPLE__) #if defined(__APPLE__)
#include <OpenGL/gl.h> #include <OpenGL/gl.h>
#else #else
#include <GL/gl.h> #include <GL/gl.h>
#endif #endif
#endif // linux basic definitions #endif // linux basic definitions
#ifndef GL_DEPTH24_STENCIL8_EXT // allows FBOs to support stencils #ifndef GL_DEPTH24_STENCIL8_EXT // allows FBOs to support stencils
#define GL_DEPTH_STENCIL_EXT 0x84F9 #define GL_DEPTH_STENCIL_EXT 0x84F9
#define GL_UNSIGNED_INT_24_8_EXT 0x84FA #define GL_UNSIGNED_INT_24_8_EXT 0x84FA
#define GL_DEPTH24_STENCIL8_EXT 0x88F0 #define GL_DEPTH24_STENCIL8_EXT 0x88F0
#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 #define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
#endif #endif
#ifndef _WIN32 #ifndef _WIN32
#include <sys/types.h> #include <sys/types.h>
typedef struct { typedef struct {
#if defined(USE_WX) && USE_WX #if defined(USE_WX) && USE_WX
wxGLCanvas *glCanvas; wxGLCanvas *glCanvas;
wxPanel *panel; wxPanel *panel;
wxGLContext *glCtxt; wxGLContext *glCtxt;
#elif defined(__APPLE__) #elif defined(__APPLE__)
NSWindow *cocoaWin; NSWindow *cocoaWin;
NSOpenGLContext *cocoaCtx; NSOpenGLContext *cocoaCtx;
#elif defined(HAVE_X11) && HAVE_X11 #elif defined(HAVE_X11) && HAVE_X11
int screen; int screen;
Window win; Window win;
Window parent; Window parent;
Display *dpy; Display *dpy;
XVisualInfo *vi; XVisualInfo *vi;
GLXContext ctx; GLXContext ctx;
XSetWindowAttributes attr; XSetWindowAttributes attr;
Common::Thread *xEventThread; Common::Thread *xEventThread;
int x, y; int x, y;
#endif #endif
unsigned int width, height; unsigned int width, height;
} GLWindow; } GLWindow;
extern GLWindow GLWin; extern GLWindow GLWin;
#endif #endif
// Public OpenGL util // Public OpenGL util
//#if defined __APPLE__ || defined __linux__ || defined _WIN32 //#if defined __APPLE__ || defined __linux__ || defined _WIN32
//#include <Cg/cg.h> //#include <Cg/cg.h>
//#include <Cg/cgGL.h> //#include <Cg/cgGL.h>
//#define HAVE_CG 1 //#define HAVE_CG 1
//extern CGcontext g_cgcontext; //extern CGcontext g_cgcontext;
//extern CGprofile g_cgvProf, g_cgfProf; //extern CGprofile g_cgvProf, g_cgfProf;
//#endif //#endif
namespace OGL namespace OGL
{ {
// Initialization / upkeep // Initialization / upkeep
bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _width, int _height); bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _width, int _height);
void OpenGL_Shutdown(); void OpenGL_Shutdown();
void OpenGL_Update(); void OpenGL_Update();
bool OpenGL_MakeCurrent(); bool OpenGL_MakeCurrent();
void OpenGL_SwapBuffers(); void OpenGL_SwapBuffers();
// Get status // Get status
u32 OpenGL_GetBackbufferWidth(); u32 OpenGL_GetBackbufferWidth();
u32 OpenGL_GetBackbufferHeight(); u32 OpenGL_GetBackbufferHeight();
// Set things // Set things
void OpenGL_SetWindowText(const char *text); void OpenGL_SetWindowText(const char *text);
// Error reporting - use the convenient macros. // Error reporting - use the convenient macros.
void OpenGL_ReportARBProgramError(); void OpenGL_ReportARBProgramError();
GLuint OpenGL_ReportGLError(const char *function, const char *file, int line); GLuint OpenGL_ReportGLError(const char *function, const char *file, int line);
bool OpenGL_ReportFBOError(const char *function, const char *file, int line); bool OpenGL_ReportFBOError(const char *function, const char *file, int line);
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
#define GL_REPORT_ERROR() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__) #define GL_REPORT_ERROR() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__)
#define GL_REPORT_ERRORD() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__) #define GL_REPORT_ERRORD() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__)
#define GL_REPORT_FBO_ERROR() OpenGL_ReportFBOError(__FUNCTION__, __FILE__, __LINE__) #define GL_REPORT_FBO_ERROR() OpenGL_ReportFBOError(__FUNCTION__, __FILE__, __LINE__)
#define GL_REPORT_PROGRAM_ERROR() OpenGL_ReportARBProgramError() #define GL_REPORT_PROGRAM_ERROR() OpenGL_ReportARBProgramError()
#else #else
#define GL_REPORT_ERROR() GL_NO_ERROR #define GL_REPORT_ERROR() GL_NO_ERROR
#define GL_REPORT_ERRORD() (void)GL_NO_ERROR #define GL_REPORT_ERRORD() (void)GL_NO_ERROR
#define GL_REPORT_FBO_ERROR() (void)true #define GL_REPORT_FBO_ERROR() (void)true
#define GL_REPORT_PROGRAM_ERROR() (void)0 #define GL_REPORT_PROGRAM_ERROR() (void)0
#endif #endif
} }
#endif // _GLINIT_H_ #endif // _GLINIT_H_
@@ -1,178 +1,178 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _OGL_GLWINDOW_H_ #ifndef _OGL_GLWINDOW_H_
#define _OGL_GLWINDOW_H_ #define _OGL_GLWINDOW_H_
#include <vector> #include <vector>
#include "Common.h" #include "Common.h"
#include "OGL_Globals.h" #include "OGL_Globals.h"
#include "pluginspecs_video.h" #include "pluginspecs_video.h"
#ifdef _WIN32 #ifdef _WIN32
#define GLEW_STATIC #define GLEW_STATIC
#include <GLew/glew.h> #include <GLew/glew.h>
#include <GLew/wglew.h> #include <GLew/wglew.h>
#include <GLew/gl.h> #include <GLew/gl.h>
#include <GLew/glext.h> #include <GLew/glext.h>
#else #else
#include <GL/glew.h> #include <GL/glew.h>
#endif #endif
#if defined(__APPLE__) #if defined(__APPLE__)
#include <OpenGL/gl.h> #include <OpenGL/gl.h>
#else #else
#include <GL/gl.h> #include <GL/gl.h>
#endif #endif
namespace OGL namespace OGL
{ {
enum OGL_Props enum OGL_Props
{ {
OGL_FULLSCREEN, OGL_FULLSCREEN,
OGL_KEEPRATIO, OGL_KEEPRATIO,
OGL_HIDECURSOR, OGL_HIDECURSOR,
OGL_PROP_COUNT OGL_PROP_COUNT
}; };
struct res struct res
{ {
u32 x; u32 x;
u32 y; u32 y;
}; };
class GLWindow class GLWindow
{ {
private: private:
// TODO: what is xmax and ymax? do we need [xy]render? // TODO: what is xmax and ymax? do we need [xy]render?
u32 xWin, yWin; // Windows' size u32 xWin, yWin; // Windows' size
int xOffset, yOffset; // Offset in window int xOffset, yOffset; // Offset in window
float xMax, yMax; // ??? float xMax, yMax; // ???
u32 xRender, yRender; // Render area u32 xRender, yRender; // Render area
bool properties[OGL_PROP_COUNT]; bool properties[OGL_PROP_COUNT];
protected: protected:
EventHandler* eventHandler; EventHandler* eventHandler;
res origRes, currFullRes, currWinRes; res origRes, currFullRes, currWinRes;
static std::vector<res> fullResolutions; static std::vector<res> fullResolutions;
virtual void SetRender(u32 x, u32 y) virtual void SetRender(u32 x, u32 y)
{ {
xRender = x; xRender = x;
yRender = y; yRender = y;
} }
static const std::vector<res>& getFsResolutions() static const std::vector<res>& getFsResolutions()
{ {
return fullResolutions; return fullResolutions;
} }
static void addFSResolution(res fsr) static void addFSResolution(res fsr)
{ {
fullResolutions.push_back(fsr); fullResolutions.push_back(fsr);
} }
public: public:
virtual void SwapBuffers() {}; virtual void SwapBuffers() {};
virtual void SetWindowText(const char *text) {}; virtual void SetWindowText(const char *text) {};
virtual bool PeekMessages() {return false;}; virtual bool PeekMessages() {return false;};
virtual void Update() {}; virtual void Update() {};
virtual bool MakeCurrent() {return false;}; virtual bool MakeCurrent() {return false;};
virtual void updateDim() virtual void updateDim()
{ {
if (GetProperty(OGL_FULLSCREEN)) if (GetProperty(OGL_FULLSCREEN))
SetWinSize(currFullRes.x, currFullRes.y); SetWinSize(currFullRes.x, currFullRes.y);
else else
// Set the windowed resolution // Set the windowed resolution
SetWinSize(currWinRes.x, currWinRes.y); SetWinSize(currWinRes.x, currWinRes.y);
float FactorX = 640.0f / (float)GetXwin(); float FactorX = 640.0f / (float)GetXwin();
float FactorY = 480.0f / (float)GetYwin(); float FactorY = 480.0f / (float)GetYwin();
//float Max = (FactorX < FactorY) ? FactorX : FactorY; //float Max = (FactorX < FactorY) ? FactorX : FactorY;
SetMax(1.0f / FactorX, 1.0f / FactorY); SetMax(1.0f / FactorX, 1.0f / FactorY);
SetOffset(0,0); SetOffset(0,0);
} }
void SetEventHandler(EventHandler *eh) { eventHandler = eh;} void SetEventHandler(EventHandler *eh) { eventHandler = eh;}
bool GetProperty(OGL_Props prop) {return properties[prop];} bool GetProperty(OGL_Props prop) {return properties[prop];}
virtual bool SetProperty(OGL_Props prop, bool value) virtual bool SetProperty(OGL_Props prop, bool value)
{return properties[prop] = value;} {return properties[prop] = value;}
u32 GetXrender() {return xRender;} u32 GetXrender() {return xRender;}
u32 GetYrender() {return yRender;} u32 GetYrender() {return yRender;}
u32 GetXwin() {return xWin;} u32 GetXwin() {return xWin;}
u32 GetYwin() {return yWin;} u32 GetYwin() {return yWin;}
void SetWinSize(u32 x, u32 y) void SetWinSize(u32 x, u32 y)
{ {
xWin = x; xWin = x;
yWin = y; yWin = y;
} }
int GetYoff() {return yOffset;} int GetYoff() {return yOffset;}
int GetXoff() {return xOffset;} int GetXoff() {return xOffset;}
void SetOffset(int x, int y) void SetOffset(int x, int y)
{ {
yOffset = y; yOffset = y;
xOffset = x; xOffset = x;
} }
void SetMax(float x, float y) void SetMax(float x, float y)
{ {
yMax = y; yMax = y;
xMax = x; xMax = x;
} }
float GetXmax() {return xMax;} float GetXmax() {return xMax;}
float GetYmax() {return yMax;} float GetYmax() {return yMax;}
static bool valid() { return false;} static bool valid() { return false;}
GLWindow() GLWindow()
{ {
// Load defaults // Load defaults
sscanf(g_Config.iFSResolution, "%dx%d", sscanf(g_Config.iFSResolution, "%dx%d",
&currFullRes.x, &currFullRes.y); &currFullRes.x, &currFullRes.y);
sscanf(g_Config.iInternalRes, "%dx%d", sscanf(g_Config.iInternalRes, "%dx%d",
&currWinRes.x, &currWinRes.y); &currWinRes.x, &currWinRes.y);
SetProperty(OGL_FULLSCREEN, g_Config.bFullscreen); SetProperty(OGL_FULLSCREEN, g_Config.bFullscreen);
// What does this do? // What does this do?
SetProperty(OGL_KEEPRATIO, g_Config.bKeepAR43); SetProperty(OGL_KEEPRATIO, g_Config.bKeepAR43);
SetProperty(OGL_HIDECURSOR, g_Config.bHideCursor); SetProperty(OGL_HIDECURSOR, g_Config.bHideCursor);
updateDim(); updateDim();
} }
// setResolution // setResolution
// resolution iter // resolution iter
}; };
} }
#endif // _GLWINDOW_H_ #endif // _GLWINDOW_H_
@@ -1,310 +1,310 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Common // Common
#include "x64Emitter.h" #include "x64Emitter.h"
#include "ABI.h" #include "ABI.h"
#include "MemoryUtil.h" #include "MemoryUtil.h"
// VideoCommon // VideoCommon
#include "Profiler.h" #include "Profiler.h"
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
#include "NativeVertexFormat.h" #include "NativeVertexFormat.h"
#include "NativeVertexWriter.h" #include "NativeVertexWriter.h"
#include "CPMemory.h" #include "CPMemory.h"
// OGL // OGL
#include "OGL_GLUtil.h" #include "OGL_GLUtil.h"
#include "OGL_VertexManager.h" #include "OGL_VertexManager.h"
#include "../Main.h" #include "../Main.h"
namespace OGL namespace OGL
{ {
#define COMPILED_CODE_SIZE 4096 #define COMPILED_CODE_SIZE 4096
u32 s_prevcomponents; // previous state set u32 s_prevcomponents; // previous state set
/* /*
#ifdef _WIN32 #ifdef _WIN32
#ifdef _M_IX86 #ifdef _M_IX86
#define USE_JIT #define USE_JIT
#endif #endif
#endif #endif
*/ */
// Note the use of CallCdeclFunction3I etc. // Note the use of CallCdeclFunction3I etc.
// This is a horrible hack that is necessary because in 64-bit mode, Opengl32.dll is based way, way above the 32-bit // This is a horrible hack that is necessary because in 64-bit mode, Opengl32.dll is based way, way above the 32-bit
// address space that is within reach of a CALL, and just doing &fn gives us these high uncallable addresses. So we // address space that is within reach of a CALL, and just doing &fn gives us these high uncallable addresses. So we
// want to grab the function pointers from the import table instead. // want to grab the function pointers from the import table instead.
// This problem does not apply to glew functions, only core opengl32 functions. // This problem does not apply to glew functions, only core opengl32 functions.
// Here's some global state. We only use this to keep track of what we've sent to the OpenGL state // Here's some global state. We only use this to keep track of what we've sent to the OpenGL state
// machine. // machine.
#ifdef USE_JIT #ifdef USE_JIT
DECLARE_IMPORT(glNormalPointer); DECLARE_IMPORT(glNormalPointer);
DECLARE_IMPORT(glVertexPointer); DECLARE_IMPORT(glVertexPointer);
DECLARE_IMPORT(glColorPointer); DECLARE_IMPORT(glColorPointer);
DECLARE_IMPORT(glTexCoordPointer); DECLARE_IMPORT(glTexCoordPointer);
#endif #endif
class GLVertexFormat : public NativeVertexFormat class GLVertexFormat : public NativeVertexFormat
{ {
u8 *m_compiledCode; u8 *m_compiledCode;
PortableVertexDeclaration vtx_decl; PortableVertexDeclaration vtx_decl;
public: public:
GLVertexFormat(); GLVertexFormat();
~GLVertexFormat(); ~GLVertexFormat();
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl); virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
virtual void SetupVertexPointers() const; virtual void SetupVertexPointers() const;
virtual void EnableComponents(u32 components); virtual void EnableComponents(u32 components);
}; };
NativeVertexFormat* VertexManager::CreateNativeVertexFormat() NativeVertexFormat* VertexManager::CreateNativeVertexFormat()
{ {
return new GLVertexFormat; return new GLVertexFormat;
} }
GLVertexFormat::GLVertexFormat() GLVertexFormat::GLVertexFormat()
{ {
#ifdef USE_JIT #ifdef USE_JIT
m_compiledCode = (u8 *)AllocateExecutableMemory(COMPILED_CODE_SIZE, false); m_compiledCode = (u8 *)AllocateExecutableMemory(COMPILED_CODE_SIZE, false);
if (m_compiledCode) if (m_compiledCode)
memset(m_compiledCode, 0, COMPILED_CODE_SIZE); memset(m_compiledCode, 0, COMPILED_CODE_SIZE);
#endif #endif
} }
GLVertexFormat::~GLVertexFormat() GLVertexFormat::~GLVertexFormat()
{ {
#ifdef USE_JIT #ifdef USE_JIT
FreeMemoryPages(m_compiledCode, COMPILED_CODE_SIZE); FreeMemoryPages(m_compiledCode, COMPILED_CODE_SIZE);
m_compiledCode = 0; m_compiledCode = 0;
#endif #endif
} }
inline GLuint VarToGL(VarType t) inline GLuint VarToGL(VarType t)
{ {
static const GLuint lookup[5] = { static const GLuint lookup[5] = {
GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT
}; };
return lookup[t]; return lookup[t];
} }
void GLVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl) void GLVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
{ {
vertex_stride = _vtx_decl.stride; vertex_stride = _vtx_decl.stride;
using namespace Gen; using namespace Gen;
// We will not allow vertex components causing uneven strides. // We will not allow vertex components causing uneven strides.
if (_vtx_decl.stride & 3) if (_vtx_decl.stride & 3)
PanicAlert("Uneven vertex stride: %i", _vtx_decl.stride); PanicAlert("Uneven vertex stride: %i", _vtx_decl.stride);
#ifdef USE_JIT #ifdef USE_JIT
Gen::XEmitter emit(m_compiledCode); Gen::XEmitter emit(m_compiledCode);
// Alright, we have our vertex declaration. Compile some crazy code to set it quickly using GL. // Alright, we have our vertex declaration. Compile some crazy code to set it quickly using GL.
emit.ABI_EmitPrologue(6); emit.ABI_EmitPrologue(6);
emit.CallCdeclFunction4_I(glVertexPointer, 3, GL_FLOAT, _vtx_decl.stride, 0); emit.CallCdeclFunction4_I(glVertexPointer, 3, GL_FLOAT, _vtx_decl.stride, 0);
if (_vtx_decl.num_normals >= 1) if (_vtx_decl.num_normals >= 1)
{ {
emit.CallCdeclFunction3_I(glNormalPointer, VarToGL(_vtx_decl.normal_gl_type), _vtx_decl.stride, _vtx_decl.normal_offset[0]); emit.CallCdeclFunction3_I(glNormalPointer, VarToGL(_vtx_decl.normal_gl_type), _vtx_decl.stride, _vtx_decl.normal_offset[0]);
if (_vtx_decl.num_normals == 3) { if (_vtx_decl.num_normals == 3) {
emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM1_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[1]); emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM1_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[1]);
emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM2_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[2]); emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM2_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[2]);
} }
} }
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
if (_vtx_decl.color_offset[i] != -1) if (_vtx_decl.color_offset[i] != -1)
{ {
if (i == 0) if (i == 0)
emit.CallCdeclFunction4_I(glColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]); emit.CallCdeclFunction4_I(glColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]);
else else
emit.CallCdeclFunction4((void *)glSecondaryColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]); emit.CallCdeclFunction4((void *)glSecondaryColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]);
} }
} }
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
if (_vtx_decl.texcoord_offset[i] != -1) if (_vtx_decl.texcoord_offset[i] != -1)
{ {
int id = GL_TEXTURE0 + i; int id = GL_TEXTURE0 + i;
#ifdef _M_X64 #ifdef _M_X64
#ifdef _MSC_VER #ifdef _MSC_VER
emit.MOV(32, R(RCX), Imm32(id)); emit.MOV(32, R(RCX), Imm32(id));
#else #else
emit.MOV(32, R(RDI), Imm32(id)); emit.MOV(32, R(RDI), Imm32(id));
#endif #endif
#else #else
emit.ABI_AlignStack(1 * 4); emit.ABI_AlignStack(1 * 4);
emit.PUSH(32, Imm32(id)); emit.PUSH(32, Imm32(id));
#endif #endif
emit.CALL((void *)glClientActiveTexture); emit.CALL((void *)glClientActiveTexture);
#ifndef _M_X64 #ifndef _M_X64
#ifdef _WIN32 #ifdef _WIN32
// don't inc stack on windows, stdcall // don't inc stack on windows, stdcall
#else #else
emit.ABI_RestoreStack(1 * 4); emit.ABI_RestoreStack(1 * 4);
#endif #endif
#endif #endif
emit.CallCdeclFunction4_I( emit.CallCdeclFunction4_I(
glTexCoordPointer, _vtx_decl.texcoord_size[i], VarToGL(_vtx_decl.texcoord_gl_type[i]), glTexCoordPointer, _vtx_decl.texcoord_size[i], VarToGL(_vtx_decl.texcoord_gl_type[i]),
_vtx_decl.stride, _vtx_decl.texcoord_offset[i]); _vtx_decl.stride, _vtx_decl.texcoord_offset[i]);
} }
} }
if (_vtx_decl.posmtx_offset != -1) if (_vtx_decl.posmtx_offset != -1)
emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, _vtx_decl.stride, _vtx_decl.posmtx_offset); emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, _vtx_decl.stride, _vtx_decl.posmtx_offset);
emit.ABI_EmitEpilogue(6); emit.ABI_EmitEpilogue(6);
if (emit.GetCodePtr() - (u8*)m_compiledCode > COMPILED_CODE_SIZE) if (emit.GetCodePtr() - (u8*)m_compiledCode > COMPILED_CODE_SIZE)
Crash(); Crash();
#endif #endif
this->vtx_decl = _vtx_decl; this->vtx_decl = _vtx_decl;
} }
void GLVertexFormat::SetupVertexPointers() const { void GLVertexFormat::SetupVertexPointers() const {
// Cast a pointer to compiled code to a pointer to a function taking no parameters, through a (void *) cast first to // Cast a pointer to compiled code to a pointer to a function taking no parameters, through a (void *) cast first to
// get around type checking errors, and call it. // get around type checking errors, and call it.
#ifdef USE_JIT #ifdef USE_JIT
((void (*)())(void*)m_compiledCode)(); ((void (*)())(void*)m_compiledCode)();
#else #else
glVertexPointer(3, GL_FLOAT, vtx_decl.stride, ::VertexManager::s_pBaseBufferPointer); glVertexPointer(3, GL_FLOAT, vtx_decl.stride, ::VertexManager::s_pBaseBufferPointer);
if (vtx_decl.num_normals >= 1) { if (vtx_decl.num_normals >= 1) {
glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[0])); glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[0]));
if (vtx_decl.num_normals == 3) { if (vtx_decl.num_normals == 3) {
glVertexAttribPointer(SHADER_NORM1_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[1])); glVertexAttribPointer(SHADER_NORM1_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[1]));
glVertexAttribPointer(SHADER_NORM2_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[2])); glVertexAttribPointer(SHADER_NORM2_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[2]));
} }
} }
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
if (vtx_decl.color_offset[i] != -1) { if (vtx_decl.color_offset[i] != -1) {
if (i == 0) if (i == 0)
glColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i])); glColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i]));
else { else {
glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i])); glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i]));
} }
} }
} }
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if (vtx_decl.texcoord_offset[i] != -1) { if (vtx_decl.texcoord_offset[i] != -1) {
int id = GL_TEXTURE0 + i; int id = GL_TEXTURE0 + i;
glClientActiveTexture(id); glClientActiveTexture(id);
glTexCoordPointer(vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]), glTexCoordPointer(vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]),
vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.texcoord_offset[i])); vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.texcoord_offset[i]));
} }
} }
if (vtx_decl.posmtx_offset != -1) { if (vtx_decl.posmtx_offset != -1) {
glVertexAttribPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.posmtx_offset)); glVertexAttribPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (void *)(::VertexManager::s_pBaseBufferPointer + vtx_decl.posmtx_offset));
} }
#endif #endif
} }
void GLVertexFormat::EnableComponents(u32 components) void GLVertexFormat::EnableComponents(u32 components)
{ {
if (s_prevcomponents != components) if (s_prevcomponents != components)
{ {
g_vertex_manager->Flush(); g_vertex_manager->Flush();
// matrices // matrices
if ((components & VB_HAS_POSMTXIDX) != (s_prevcomponents & VB_HAS_POSMTXIDX)) if ((components & VB_HAS_POSMTXIDX) != (s_prevcomponents & VB_HAS_POSMTXIDX))
{ {
if (components & VB_HAS_POSMTXIDX) if (components & VB_HAS_POSMTXIDX)
glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB); glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB);
else else
glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB); glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB);
} }
// normals // normals
if ((components & VB_HAS_NRM0) != (s_prevcomponents & VB_HAS_NRM0)) if ((components & VB_HAS_NRM0) != (s_prevcomponents & VB_HAS_NRM0))
{ {
if (components & VB_HAS_NRM0) if (components & VB_HAS_NRM0)
glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_NORMAL_ARRAY);
else else
glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_NORMAL_ARRAY);
} }
if ((components & VB_HAS_NRM1) != (s_prevcomponents & VB_HAS_NRM1)) if ((components & VB_HAS_NRM1) != (s_prevcomponents & VB_HAS_NRM1))
{ {
if (components & VB_HAS_NRM1) { if (components & VB_HAS_NRM1) {
glEnableVertexAttribArray(SHADER_NORM1_ATTRIB); glEnableVertexAttribArray(SHADER_NORM1_ATTRIB);
glEnableVertexAttribArray(SHADER_NORM2_ATTRIB); glEnableVertexAttribArray(SHADER_NORM2_ATTRIB);
} }
else { else {
glDisableVertexAttribArray(SHADER_NORM1_ATTRIB); glDisableVertexAttribArray(SHADER_NORM1_ATTRIB);
glDisableVertexAttribArray(SHADER_NORM2_ATTRIB); glDisableVertexAttribArray(SHADER_NORM2_ATTRIB);
} }
} }
// color // color
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
{ {
if ((components & (VB_HAS_COL0 << i)) != (s_prevcomponents & (VB_HAS_COL0 << i))) if ((components & (VB_HAS_COL0 << i)) != (s_prevcomponents & (VB_HAS_COL0 << i)))
{ {
if (components & (VB_HAS_COL0 << i)) if (components & (VB_HAS_COL0 << i))
glEnableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY); glEnableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY);
else else
glDisableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY); glDisableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY);
} }
} }
// tex // tex
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
{ {
if (!g_ActiveConfig.bDisableTexturing) if (!g_ActiveConfig.bDisableTexturing)
{ {
if ((components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i))) if ((components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i)))
{ {
glClientActiveTexture(GL_TEXTURE0 + i); glClientActiveTexture(GL_TEXTURE0 + i);
if (components & (VB_HAS_UV0 << i)) if (components & (VB_HAS_UV0 << i))
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
else else
glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
} }
} }
else else
{ {
glClientActiveTexture(GL_TEXTURE0 + i); glClientActiveTexture(GL_TEXTURE0 + i);
glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
} }
} }
// Disable Lighting // Disable Lighting
// TODO - Is this a good spot for this code? // TODO - Is this a good spot for this code?
if (g_ActiveConfig.bDisableLighting) if (g_ActiveConfig.bDisableLighting)
{ {
for (int i = 0; i < xfregs.nNumChans; i++) for (int i = 0; i < xfregs.nNumChans; i++)
{ {
xfregs.colChans[i].alpha.enablelighting = false; xfregs.colChans[i].alpha.enablelighting = false;
xfregs.colChans[i].color.enablelighting = false; xfregs.colChans[i].color.enablelighting = false;
} }
} }
s_prevcomponents = components; s_prevcomponents = components;
} }
} }
} }
@@ -1,340 +1,340 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <cmath> #include <cmath>
// Common // Common
#include "Common.h" #include "Common.h"
#include "FileUtil.h" #include "FileUtil.h"
// VideoCommon // VideoCommon
#include "Profiler.h" #include "Profiler.h"
#include "Statistics.h" #include "Statistics.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "ImageWrite.h" #include "ImageWrite.h"
#include "PixelShaderManager.h" #include "PixelShaderManager.h"
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
// OGL // OGL
#include "OGL_Render.h" #include "OGL_Render.h"
#include "OGL_GLUtil.h" #include "OGL_GLUtil.h"
#include "OGL_PixelShaderCache.h" #include "OGL_PixelShaderCache.h"
#include "../Main.h" #include "../Main.h"
namespace OGL namespace OGL
{ {
static int s_nMaxPixelInstructions; static int s_nMaxPixelInstructions;
static GLuint s_ColorMatrixProgram = 0; static GLuint s_ColorMatrixProgram = 0;
static GLuint s_DepthMatrixProgram = 0; static GLuint s_DepthMatrixProgram = 0;
PixelShaderCache::PSCache PixelShaderCache::pshaders; PixelShaderCache::PSCache PixelShaderCache::pshaders;
PIXELSHADERUID PixelShaderCache::s_curuid; PIXELSHADERUID PixelShaderCache::s_curuid;
bool PixelShaderCache::s_displayCompileAlert; bool PixelShaderCache::s_displayCompileAlert;
GLuint PixelShaderCache::CurrentShader; GLuint PixelShaderCache::CurrentShader;
bool PixelShaderCache::ShaderEnabled; bool PixelShaderCache::ShaderEnabled;
static FRAGMENTSHADER* pShaderLast = NULL; static FRAGMENTSHADER* pShaderLast = NULL;
void PixelShaderCache::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) void PixelShaderCache::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{ {
float f[4] = { f1, f2, f3, f4 }; float f[4] = { f1, f2, f3, f4 };
glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f); glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
//SetPSConstant4fv(const_number, f); //SetPSConstant4fv(const_number, f);
} }
void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float *f) void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float *f)
{ {
glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f); glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
} }
void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f) void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
{ {
for (unsigned int i = 0; i < count; ++i, f+=4, ++const_number) for (unsigned int i = 0; i < count; ++i, f+=4, ++const_number)
glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f); glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
//SetPSConstant4fv(const_number, f); //SetPSConstant4fv(const_number, f);
} }
PixelShaderCache::PixelShaderCache() PixelShaderCache::PixelShaderCache()
{ {
glEnable(GL_FRAGMENT_PROGRAM_ARB); glEnable(GL_FRAGMENT_PROGRAM_ARB);
ShaderEnabled = true; ShaderEnabled = true;
CurrentShader = 0; CurrentShader = 0;
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid)); memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
s_displayCompileAlert = true; s_displayCompileAlert = true;
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions); glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions);
#if CG_VERSION_NUM == 2100 #if CG_VERSION_NUM == 2100
if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL) if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
{ {
s_nMaxPixelInstructions = 4096; s_nMaxPixelInstructions = 4096;
} }
#endif #endif
int maxinst, maxattribs; int maxinst, maxattribs;
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&maxinst); glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&maxinst);
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, (GLint *)&maxattribs); glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, (GLint *)&maxattribs);
INFO_LOG(VIDEO, "pixel max_alu=%d, max_inst=%d, max_attrib=%d", s_nMaxPixelInstructions, maxinst, maxattribs); INFO_LOG(VIDEO, "pixel max_alu=%d, max_inst=%d, max_attrib=%d", s_nMaxPixelInstructions, maxinst, maxattribs);
char pmatrixprog[1024]; char pmatrixprog[1024];
sprintf(pmatrixprog, "!!ARBfp1.0" sprintf(pmatrixprog, "!!ARBfp1.0"
"TEMP R0;\n" "TEMP R0;\n"
"TEMP R1;\n" "TEMP R1;\n"
"TEX R0, fragment.texcoord[0], texture[0], RECT;\n" "TEX R0, fragment.texcoord[0], texture[0], RECT;\n"
"DP4 R1.w, R0, program.env[%d];\n" "DP4 R1.w, R0, program.env[%d];\n"
"DP4 R1.z, R0, program.env[%d];\n" "DP4 R1.z, R0, program.env[%d];\n"
"DP4 R1.x, R0, program.env[%d];\n" "DP4 R1.x, R0, program.env[%d];\n"
"DP4 R1.y, R0, program.env[%d];\n" "DP4 R1.y, R0, program.env[%d];\n"
"ADD result.color, R1, program.env[%d];\n" "ADD result.color, R1, program.env[%d];\n"
"END\n", C_COLORMATRIX+3, C_COLORMATRIX+2, C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+4); "END\n", C_COLORMATRIX+3, C_COLORMATRIX+2, C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+4);
glGenProgramsARB(1, &s_ColorMatrixProgram); glGenProgramsARB(1, &s_ColorMatrixProgram);
SetCurrentShader(s_ColorMatrixProgram); SetCurrentShader(s_ColorMatrixProgram);
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog);
GLenum err = GL_REPORT_ERROR(); GLenum err = GL_REPORT_ERROR();
if (err != GL_NO_ERROR) { if (err != GL_NO_ERROR) {
ERROR_LOG(VIDEO, "Failed to create color matrix fragment program"); ERROR_LOG(VIDEO, "Failed to create color matrix fragment program");
glDeleteProgramsARB(1, &s_ColorMatrixProgram); glDeleteProgramsARB(1, &s_ColorMatrixProgram);
s_ColorMatrixProgram = 0; s_ColorMatrixProgram = 0;
} }
sprintf(pmatrixprog, "!!ARBfp1.0" sprintf(pmatrixprog, "!!ARBfp1.0"
"TEMP R0;\n" "TEMP R0;\n"
"TEMP R1;\n" "TEMP R1;\n"
"TEMP R2;\n" "TEMP R2;\n"
"PARAM K0 = { 65535.0, 255.0,1.0,16777215.0};\n" "PARAM K0 = { 65535.0, 255.0,1.0,16777215.0};\n"
"PARAM K1 = { 0.999999940395355224609375, 1.0000000596046483281045155587504,0.0,0.0};\n" "PARAM K1 = { 0.999999940395355224609375, 1.0000000596046483281045155587504,0.0,0.0};\n"
"TEX R2, fragment.texcoord[0], texture[0], RECT;\n" "TEX R2, fragment.texcoord[0], texture[0], RECT;\n"
"MUL R0, R2.x, K1.x;\n" "MUL R0, R2.x, K1.x;\n"
"MUL R0, R0.x, K0;\n" "MUL R0, R0.x, K0;\n"
"FRC R0, R0;\n" "FRC R0, R0;\n"
"MUL R0, R0, K1.y;\n" "MUL R0, R0, K1.y;\n"
"DP4 R1.x, R0, program.env[%d];\n" "DP4 R1.x, R0, program.env[%d];\n"
"DP4 R1.y, R0, program.env[%d];\n" "DP4 R1.y, R0, program.env[%d];\n"
"DP4 R1.z, R0, program.env[%d];\n" "DP4 R1.z, R0, program.env[%d];\n"
"DP4 R1.w, R0, program.env[%d];\n" "DP4 R1.w, R0, program.env[%d];\n"
"ADD result.color, R1, program.env[%d];\n" "ADD result.color, R1, program.env[%d];\n"
"END\n", C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+2, C_COLORMATRIX+3, C_COLORMATRIX+4); "END\n", C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+2, C_COLORMATRIX+3, C_COLORMATRIX+4);
glGenProgramsARB(1, &s_DepthMatrixProgram); glGenProgramsARB(1, &s_DepthMatrixProgram);
SetCurrentShader(s_DepthMatrixProgram); SetCurrentShader(s_DepthMatrixProgram);
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog);
err = GL_REPORT_ERROR(); err = GL_REPORT_ERROR();
if (err != GL_NO_ERROR) { if (err != GL_NO_ERROR) {
ERROR_LOG(VIDEO, "Failed to create depth matrix fragment program"); ERROR_LOG(VIDEO, "Failed to create depth matrix fragment program");
glDeleteProgramsARB(1, &s_DepthMatrixProgram); glDeleteProgramsARB(1, &s_DepthMatrixProgram);
s_DepthMatrixProgram = 0; s_DepthMatrixProgram = 0;
} }
} }
PixelShaderCache::~PixelShaderCache() PixelShaderCache::~PixelShaderCache()
{ {
glDeleteProgramsARB(1, &s_ColorMatrixProgram); glDeleteProgramsARB(1, &s_ColorMatrixProgram);
s_ColorMatrixProgram = 0; s_ColorMatrixProgram = 0;
glDeleteProgramsARB(1, &s_DepthMatrixProgram); glDeleteProgramsARB(1, &s_DepthMatrixProgram);
s_DepthMatrixProgram = 0; s_DepthMatrixProgram = 0;
PSCache::iterator iter = pshaders.begin(); PSCache::iterator iter = pshaders.begin();
for (; iter != pshaders.end(); iter++) for (; iter != pshaders.end(); iter++)
iter->second.Destroy(); iter->second.Destroy();
pshaders.clear(); pshaders.clear();
} }
GLuint PixelShaderCache::GetColorMatrixProgram() GLuint PixelShaderCache::GetColorMatrixProgram()
{ {
return s_ColorMatrixProgram; return s_ColorMatrixProgram;
} }
GLuint PixelShaderCache::GetDepthMatrixProgram() GLuint PixelShaderCache::GetDepthMatrixProgram()
{ {
return s_DepthMatrixProgram; return s_DepthMatrixProgram;
} }
bool PixelShaderCache::SetShader(bool dstAlphaEnable) bool PixelShaderCache::SetShader(bool dstAlphaEnable)
{ {
const FRAGMENTSHADER* const ps = GetShader(dstAlphaEnable); const FRAGMENTSHADER* const ps = GetShader(dstAlphaEnable);
if (ps) if (ps)
{ {
SetCurrentShader(ps->glprogid); SetCurrentShader(ps->glprogid);
return true; return true;
} }
else else
return false; return false;
} }
FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable) FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
{ {
DVSTARTPROFILE(); DVSTARTPROFILE();
PIXELSHADERUID uid; PIXELSHADERUID uid;
GetPixelShaderId(&uid, dstAlphaEnable ? 1 : 0); GetPixelShaderId(&uid, dstAlphaEnable ? 1 : 0);
if (uid == last_pixel_shader_uid && pshaders[uid].frameCount == frameCount) if (uid == last_pixel_shader_uid && pshaders[uid].frameCount == frameCount)
{ {
return pShaderLast; return pShaderLast;
} }
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID)); memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
PSCache::iterator iter = pshaders.find(uid); PSCache::iterator iter = pshaders.find(uid);
if (iter != pshaders.end()) { if (iter != pshaders.end()) {
iter->second.frameCount = frameCount; iter->second.frameCount = frameCount;
PSCacheEntry &entry = iter->second; PSCacheEntry &entry = iter->second;
if (&entry.shader != pShaderLast) if (&entry.shader != pShaderLast)
{ {
pShaderLast = &entry.shader; pShaderLast = &entry.shader;
} }
return pShaderLast; return pShaderLast;
} }
//Make an entry in the table //Make an entry in the table
PSCacheEntry& newentry = pshaders[uid]; PSCacheEntry& newentry = pshaders[uid];
newentry.frameCount = frameCount; newentry.frameCount = frameCount;
pShaderLast = &newentry.shader; pShaderLast = &newentry.shader;
const char *code = GeneratePixelShaderCode(dstAlphaEnable,API_OPENGL); const char *code = GeneratePixelShaderCode(dstAlphaEnable,API_OPENGL);
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) { if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
static int counter = 0; static int counter = 0;
char szTemp[MAX_PATH]; char szTemp[MAX_PATH];
sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++); sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
SaveData(szTemp, code); SaveData(szTemp, code);
} }
#endif #endif
// printf("Compiling pixel shader. size = %i\n", strlen(code)); // printf("Compiling pixel shader. size = %i\n", strlen(code));
if (!code || !CompilePixelShader(newentry.shader, code)) { if (!code || !CompilePixelShader(newentry.shader, code)) {
ERROR_LOG(VIDEO, "failed to create pixel shader"); ERROR_LOG(VIDEO, "failed to create pixel shader");
static int counter = 0; static int counter = 0;
char szTemp[MAX_PATH]; char szTemp[MAX_PATH];
sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++); sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
SaveData(szTemp, code); SaveData(szTemp, code);
return NULL; return NULL;
} }
INCSTAT(stats.numPixelShadersCreated); INCSTAT(stats.numPixelShadersCreated);
SETSTAT(stats.numPixelShadersAlive, pshaders.size()); SETSTAT(stats.numPixelShadersAlive, pshaders.size());
return pShaderLast; return pShaderLast;
} }
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram) bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
{ {
GLenum err = GL_REPORT_ERROR(); GLenum err = GL_REPORT_ERROR();
if (err != GL_NO_ERROR) if (err != GL_NO_ERROR)
{ {
ERROR_LOG(VIDEO, "glError %08x before PS!", err); ERROR_LOG(VIDEO, "glError %08x before PS!", err);
} }
#if defined HAVE_CG && HAVE_CG #if defined HAVE_CG && HAVE_CG
char stropt[128]; char stropt[128];
sprintf(stropt, "MaxLocalParams=32,NumInstructionSlots=%d", s_nMaxPixelInstructions); sprintf(stropt, "MaxLocalParams=32,NumInstructionSlots=%d", s_nMaxPixelInstructions);
const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL}; const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts); CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts);
// handle errors // handle errors
if (!cgIsProgram(tempprog)) { if (!cgIsProgram(tempprog)) {
cgDestroyProgram(tempprog); cgDestroyProgram(tempprog);
ERROR_LOG(VIDEO, "Failed to compile ps %s:", cgGetLastListing(g_cgcontext)); ERROR_LOG(VIDEO, "Failed to compile ps %s:", cgGetLastListing(g_cgcontext));
ERROR_LOG(VIDEO, pstrprogram); ERROR_LOG(VIDEO, pstrprogram);
return false; return false;
} }
// handle warnings // handle warnings
if (cgGetError() != CG_NO_ERROR) if (cgGetError() != CG_NO_ERROR)
{ {
WARN_LOG(VIDEO, "Warnings on compile ps %s:", cgGetLastListing(g_cgcontext)); WARN_LOG(VIDEO, "Warnings on compile ps %s:", cgGetLastListing(g_cgcontext));
WARN_LOG(VIDEO, pstrprogram); WARN_LOG(VIDEO, pstrprogram);
} }
// This looks evil - we modify the program through the const char * we got from cgGetProgramString! // This looks evil - we modify the program through the const char * we got from cgGetProgramString!
// It SHOULD not have any nasty side effects though - but you never know... // It SHOULD not have any nasty side effects though - but you never know...
char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM); char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
char *plocal = strstr(pcompiledprog, "program.local"); char *plocal = strstr(pcompiledprog, "program.local");
while (plocal != NULL) { while (plocal != NULL) {
const char *penv = " program.env"; const char *penv = " program.env";
memcpy(plocal, penv, 13); memcpy(plocal, penv, 13);
plocal = strstr(plocal+13, "program.local"); plocal = strstr(plocal+13, "program.local");
} }
glGenProgramsARB(1, &ps.glprogid); glGenProgramsARB(1, &ps.glprogid);
SetCurrentShader(ps.glprogid); SetCurrentShader(ps.glprogid);
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
err = GL_REPORT_ERROR(); err = GL_REPORT_ERROR();
if (err != GL_NO_ERROR) if (err != GL_NO_ERROR)
{ {
GLint error_pos, native_limit; GLint error_pos, native_limit;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos); glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native_limit); glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native_limit);
// Error occur // Error occur
if (error_pos != -1) { if (error_pos != -1) {
const char *program_error = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB); const char *program_error = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);
char line[256]; char line[256];
strncpy(line, (const char *)pcompiledprog + error_pos, 255); strncpy(line, (const char *)pcompiledprog + error_pos, 255);
line[255] = 0; line[255] = 0;
ERROR_LOG(VIDEO, "Error at %i: %s", error_pos, program_error); ERROR_LOG(VIDEO, "Error at %i: %s", error_pos, program_error);
ERROR_LOG(VIDEO, "Line dump: \n%s", line); ERROR_LOG(VIDEO, "Line dump: \n%s", line);
} else if (native_limit != -1) { } else if (native_limit != -1) {
ERROR_LOG(VIDEO, "Hit limit? %i", native_limit); ERROR_LOG(VIDEO, "Hit limit? %i", native_limit);
// TODO // TODO
} }
ERROR_LOG(VIDEO, pstrprogram); ERROR_LOG(VIDEO, pstrprogram);
ERROR_LOG(VIDEO, pcompiledprog); ERROR_LOG(VIDEO, pcompiledprog);
} }
cgDestroyProgram(tempprog); cgDestroyProgram(tempprog);
#endif #endif
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
ps.strprog = pstrprogram; ps.strprog = pstrprogram;
#endif #endif
return true; return true;
} }
//Disable Fragment programs and reset the selected Program //Disable Fragment programs and reset the selected Program
void PixelShaderCache::DisableShader() void PixelShaderCache::DisableShader()
{ {
if(ShaderEnabled) if(ShaderEnabled)
{ {
glDisable(GL_FRAGMENT_PROGRAM_ARB); glDisable(GL_FRAGMENT_PROGRAM_ARB);
ShaderEnabled = false; ShaderEnabled = false;
} }
} }
//bind a program if is diferent from the binded oone //bind a program if is diferent from the binded oone
void PixelShaderCache::SetCurrentShader(GLuint Shader) void PixelShaderCache::SetCurrentShader(GLuint Shader)
{ {
if(!ShaderEnabled) if(!ShaderEnabled)
{ {
glEnable(GL_FRAGMENT_PROGRAM_ARB); glEnable(GL_FRAGMENT_PROGRAM_ARB);
ShaderEnabled = true; ShaderEnabled = true;
} }
if(CurrentShader != Shader) if(CurrentShader != Shader)
{ {
if(Shader != 0) if(Shader != 0)
CurrentShader = Shader; CurrentShader = Shader;
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, CurrentShader); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, CurrentShader);
} }
} }
} }
@@ -1,96 +1,96 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _OGL_PIXELSHADERCACHE_H_ #ifndef _OGL_PIXELSHADERCACHE_H_
#define _OGL_PIXELSHADERCACHE_H_ #define _OGL_PIXELSHADERCACHE_H_
#include <map> #include <map>
#include <string> #include <string>
// VideoCommon // VideoCommon
#include "BPMemory.h" #include "BPMemory.h"
#include "PixelShaderGen.h" #include "PixelShaderGen.h"
#include "../PixelShaderCache.h" #include "../PixelShaderCache.h"
namespace OGL namespace OGL
{ {
struct FRAGMENTSHADER struct FRAGMENTSHADER
{ {
FRAGMENTSHADER() : glprogid(0) { } FRAGMENTSHADER() : glprogid(0) { }
void Destroy() void Destroy()
{ {
if (glprogid) if (glprogid)
{ {
glDeleteProgramsARB(1, &glprogid); glDeleteProgramsARB(1, &glprogid);
glprogid = 0; glprogid = 0;
} }
} }
GLuint glprogid; // opengl program id GLuint glprogid; // opengl program id
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
std::string strprog; std::string strprog;
#endif #endif
}; };
class PixelShaderCache : public ::PixelShaderCacheBase class PixelShaderCache : public ::PixelShaderCacheBase
{ {
struct PSCacheEntry struct PSCacheEntry
{ {
FRAGMENTSHADER shader; FRAGMENTSHADER shader;
int frameCount; int frameCount;
PSCacheEntry() : frameCount(0) {} PSCacheEntry() : frameCount(0) {}
void Destroy() void Destroy()
{ {
shader.Destroy(); shader.Destroy();
} }
}; };
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache; typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
static PSCache pshaders; static PSCache pshaders;
static PIXELSHADERUID s_curuid; // the current pixel shader uid (progressively changed as memory is written) static PIXELSHADERUID s_curuid; // the current pixel shader uid (progressively changed as memory is written)
static bool s_displayCompileAlert; static bool s_displayCompileAlert;
static GLuint CurrentShader; static GLuint CurrentShader;
static bool ShaderEnabled; static bool ShaderEnabled;
public: public:
PixelShaderCache(); PixelShaderCache();
~PixelShaderCache(); ~PixelShaderCache();
static FRAGMENTSHADER* GetShader(bool dstAlphaEnable); static FRAGMENTSHADER* GetShader(bool dstAlphaEnable);
static bool CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram); static bool CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram);
static GLuint GetColorMatrixProgram(); static GLuint GetColorMatrixProgram();
static GLuint GetDepthMatrixProgram(); static GLuint GetDepthMatrixProgram();
bool SetShader(bool dstAlphaEnable); bool SetShader(bool dstAlphaEnable);
static void SetCurrentShader(GLuint Shader); static void SetCurrentShader(GLuint Shader);
static void DisableShader(); static void DisableShader();
void Clear() {} void Clear() {}
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4); void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
void SetPSConstant4fv(unsigned int const_number, const float *f); void SetPSConstant4fv(unsigned int const_number, const float *f);
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f); void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
}; };
} }
#endif // _PIXELSHADERCACHE_H_ #endif // _PIXELSHADERCACHE_H_
@@ -1,97 +1,97 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Common // Common
#include "FileUtil.h" #include "FileUtil.h"
// VideoCommon // VideoCommon
#include "VideoCommon.h" #include "VideoCommon.h"
#include "VideoConfig.h" #include "VideoConfig.h"
// OGL // OGL
#include "OGL_GLUtil.h" #include "OGL_GLUtil.h"
#include "OGL_PostProcessing.h" #include "OGL_PostProcessing.h"
#include "OGL_PixelShaderCache.h" #include "OGL_PixelShaderCache.h"
namespace OGL namespace OGL
{ {
namespace PostProcessing namespace PostProcessing
{ {
static std::string s_currentShader; static std::string s_currentShader;
static FRAGMENTSHADER s_shader; static FRAGMENTSHADER s_shader;
void Init() void Init()
{ {
s_currentShader = ""; s_currentShader = "";
} }
void Shutdown() void Shutdown()
{ {
s_shader.Destroy(); s_shader.Destroy();
} }
void ReloadShader() void ReloadShader()
{ {
s_currentShader = ""; s_currentShader = "";
} }
bool ApplyShader() bool ApplyShader()
{ {
if (s_currentShader != std::string(File::GetUserPath(D_SHADERS_IDX)) + g_ActiveConfig.sPostProcessingShader + ".txt") if (s_currentShader != std::string(File::GetUserPath(D_SHADERS_IDX)) + g_ActiveConfig.sPostProcessingShader + ".txt")
{ {
// Set immediately to prevent endless recompiles on failure. // Set immediately to prevent endless recompiles on failure.
if (!g_ActiveConfig.sPostProcessingShader.empty()) if (!g_ActiveConfig.sPostProcessingShader.empty())
s_currentShader = std::string(File::GetUserPath(D_SHADERS_IDX)) + g_ActiveConfig.sPostProcessingShader + ".txt"; s_currentShader = std::string(File::GetUserPath(D_SHADERS_IDX)) + g_ActiveConfig.sPostProcessingShader + ".txt";
else else
s_currentShader.clear(); s_currentShader.clear();
s_shader.Destroy(); s_shader.Destroy();
if (!s_currentShader.empty()) if (!s_currentShader.empty())
{ {
std::string code; std::string code;
if (File::ReadFileToString(true, s_currentShader.c_str(), code)) if (File::ReadFileToString(true, s_currentShader.c_str(), code))
{ {
if (!PixelShaderCache::CompilePixelShader(s_shader, code.c_str())) if (!PixelShaderCache::CompilePixelShader(s_shader, code.c_str()))
{ {
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str()); ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
} }
} }
else else
{ {
ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str()); ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str());
} }
} }
} }
if (s_shader.glprogid != 0) if (s_shader.glprogid != 0)
{ {
PixelShaderCache::SetCurrentShader(s_shader.glprogid); PixelShaderCache::SetCurrentShader(s_shader.glprogid);
return true; return true;
} }
else else
{ {
PixelShaderCache::DisableShader(); PixelShaderCache::DisableShader();
return false; return false;
} }
} }
} // namespace } // namespace
} }
@@ -1,42 +1,42 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _OGL_POSTPROCESSING_H_ #ifndef _OGL_POSTPROCESSING_H_
#define _OGL_POSTPROCESSING_H_ #define _OGL_POSTPROCESSING_H_
#include "VideoCommon.h" #include "VideoCommon.h"
#include "OGL_GLUtil.h" #include "OGL_GLUtil.h"
namespace OGL namespace OGL
{ {
namespace PostProcessing namespace PostProcessing
{ {
void Init(); void Init();
void Shutdown(); void Shutdown();
void ReloadShader(); void ReloadShader();
// Returns false if no shader was applied. // Returns false if no shader was applied.
bool ApplyShader(); bool ApplyShader();
} // namespace } // namespace
} }
#endif // _POSTPROCESSING_H_ #endif // _POSTPROCESSING_H_
@@ -1,226 +1,226 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <string.h> #include <string.h>
#include "OGL_GLUtil.h" #include "OGL_GLUtil.h"
#include "OGL_RasterFont.h" #include "OGL_RasterFont.h"
// globals // globals
namespace OGL namespace OGL
{ {
GLubyte rasters[][13] = { GLubyte rasters[][13] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, {0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
{0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18}, {0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18},
{0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70}, {0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70},
{0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38}, {0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e},
{0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c}, {0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c},
{0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30}, {0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30},
{0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00},
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03}, {0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03},
{0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c}, {0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c},
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18}, {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e}, {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e}, {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e},
{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c}, {0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff}, {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06}, {0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06},
{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60}, {0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60},
{0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e}, {0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e},
{0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18}, {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18},
{0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, {0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
{0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, {0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc}, {0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff}, {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e}, {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e},
{0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06}, {0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06},
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3}, {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3}, {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3},
{0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3}, {0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e}, {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e},
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
{0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c}, {0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c},
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e}, {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff}, {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, {0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff}, {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff},
{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c}, {0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c},
{0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60}, {0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60},
{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c}, {0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18},
{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70},
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, {0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03}, {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03},
{0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e}, {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e},
{0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, {0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0}, {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00}, {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00},
{0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00}, {0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00},
{0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0}, {0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78}, {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78},
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
{0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00}, {0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00},
{0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00}, {0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00}, {0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00},
{0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
{0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, {0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f}, {0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f},
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
{0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0}, {0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00} {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
}; };
RasterFont::RasterFont() RasterFont::RasterFont()
{ {
// set GL modes // set GL modes
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// create the raster font // create the raster font
fontOffset = glGenLists(128); fontOffset = glGenLists(128);
for (int i = 32; i < 127; i++) { for (int i = 32; i < 127; i++) {
glNewList(i + fontOffset, GL_COMPILE); glNewList(i + fontOffset, GL_COMPILE);
glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]); glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
glEndList(); glEndList();
} }
temp_buffer = new char[TEMP_BUFFER_SIZE]; temp_buffer = new char[TEMP_BUFFER_SIZE];
} }
RasterFont::~RasterFont() RasterFont::~RasterFont()
{ {
glDeleteLists(fontOffset, 128); glDeleteLists(fontOffset, 128);
delete [] temp_buffer; delete [] temp_buffer;
} }
void RasterFont::printString(const char *s, double x, double y, double z) void RasterFont::printString(const char *s, double x, double y, double z)
{ {
int length = (int)strlen(s); int length = (int)strlen(s);
if (!length) if (!length)
return; return;
if (length >= TEMP_BUFFER_SIZE) if (length >= TEMP_BUFFER_SIZE)
length = TEMP_BUFFER_SIZE - 1; length = TEMP_BUFFER_SIZE - 1;
// Sanitize string to avoid GL errors. // Sanitize string to avoid GL errors.
char *s2 = temp_buffer; char *s2 = temp_buffer;
memcpy(s2, s, length); memcpy(s2, s, length);
s2[length] = 0; s2[length] = 0;
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
if (s2[i] < 32 || s2[i] > 126) if (s2[i] < 32 || s2[i] > 126)
s2[i] = '!'; s2[i] = '!';
// go to the right spot // go to the right spot
glRasterPos3d(x, y, z); glRasterPos3d(x, y, z);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
glPushAttrib (GL_LIST_BIT); glPushAttrib (GL_LIST_BIT);
glListBase(fontOffset); glListBase(fontOffset);
glCallLists((GLsizei)strlen(s2), GL_UNSIGNED_BYTE, (GLubyte *) s2); glCallLists((GLsizei)strlen(s2), GL_UNSIGNED_BYTE, (GLubyte *) s2);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
glPopAttrib(); glPopAttrib();
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
} }
void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z) void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z)
{ {
int length = (int)strlen(s); int length = (int)strlen(s);
int x = (int)(screen_width/2.0 - (length/2.0)*char_width); int x = (int)(screen_width/2.0 - (length/2.0)*char_width);
printString(s, x, y, z); printString(s, x, y, z);
} }
void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight) void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight)
{ {
double x = start_x; double x = start_x;
double y = start_y; double y = start_y;
char temp[1024]; char temp[1024];
char *t = temp; char *t = temp;
while (*text) while (*text)
{ {
if (*text == '\n') if (*text == '\n')
{ {
*t = 0; *t = 0;
printString(temp, x, y, z); printString(temp, x, y, z);
y -= char_height * 2.0f / bbHeight; y -= char_height * 2.0f / bbHeight;
x = start_x; x = start_x;
t = temp; t = temp;
} }
else if (*text == '\r') else if (*text == '\r')
{ {
t = temp; t = temp;
} }
else if (*text == '\t') else if (*text == '\t')
{ {
//todo: add tabs every something like 4*char_width //todo: add tabs every something like 4*char_width
*t = 0; *t = 0;
int cpos = (int)strlen(temp); int cpos = (int)strlen(temp);
int newpos = (cpos + 4) & (~3); int newpos = (cpos + 4) & (~3);
printString(temp, x, y, z); printString(temp, x, y, z);
x = start_x + (char_width*newpos) * 2.0f / bbWidth; x = start_x + (char_width*newpos) * 2.0f / bbWidth;
t = temp; t = temp;
*t++ = ' '; *t++ = ' ';
} }
else else
*t++ = *text; *t++ = *text;
text++; text++;
} }
// ???? // ????
if (t != text) if (t != text)
{ {
*t = 0; *t = 0;
printString(temp, x, y, z); printString(temp, x, y, z);
} }
} }
} }
@@ -1,51 +1,51 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _OGL_RASTERFONT_H_ #ifndef _OGL_RASTERFONT_H_
#define _OGL_RASTERFONT_H_ #define _OGL_RASTERFONT_H_
namespace OGL namespace OGL
{ {
class RasterFont { class RasterFont {
public: public:
RasterFont(); RasterFont();
~RasterFont(void); ~RasterFont(void);
static int debug; static int debug;
// some useful constants // some useful constants
enum enum
{ {
char_width = 10, char_width = 10,
char_height = 15, char_height = 15,
}; };
// and the happy helper functions // and the happy helper functions
void printString(const char *s, double x, double y, double z=0.0); void printString(const char *s, double x, double y, double z=0.0);
void printCenteredString(const char *s, double y, int screen_width, double z=0.0); void printCenteredString(const char *s, double y, int screen_width, double z=0.0);
void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight); void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight);
private: private:
int fontOffset; int fontOffset;
char *temp_buffer; char *temp_buffer;
enum {TEMP_BUFFER_SIZE = 64 * 1024}; enum {TEMP_BUFFER_SIZE = 64 * 1024};
}; };
} }
#endif // _RASTERFONT_H_ #endif // _RASTERFONT_H_
File diff suppressed because it is too large Load Diff
@@ -1,61 +1,61 @@
#ifndef _OGL_RENDER_H_ #ifndef _OGL_RENDER_H_
#define _OGL_RENDER_H_ #define _OGL_RENDER_H_
#include "MathUtil.h" #include "MathUtil.h"
#include "VideoCommon.h" #include "VideoCommon.h"
#include "Renderer.h" #include "Renderer.h"
#include "pluginspecs_video.h" #include "pluginspecs_video.h"
namespace OGL namespace OGL
{ {
extern int OSDChoice; extern int OSDChoice;
class Renderer : public ::RendererBase class Renderer : public ::RendererBase
{ {
public: public:
Renderer(); Renderer();
~Renderer(); ~Renderer();
// What's the real difference between these? Too similar names. // What's the real difference between these? Too similar names.
void ResetAPIState(); void ResetAPIState();
void RestoreAPIState(); void RestoreAPIState();
void SetColorMask(); void SetColorMask();
void SetBlendMode(bool forceUpdate); void SetBlendMode(bool forceUpdate);
bool SetScissorRect(); bool SetScissorRect();
void SetGenerationMode(); void SetGenerationMode();
void SetDepthMode(); void SetDepthMode();
void SetLogicOpMode(); void SetLogicOpMode();
void SetDitherMode(); void SetDitherMode();
void SetLineWidth(); void SetLineWidth();
// Live resolution change // Live resolution change
bool Allow2x(); bool Allow2x();
bool AllowCustom(); bool AllowCustom();
u32 AccessEFB(EFBAccessType type, int x, int y); u32 AccessEFB(EFBAccessType type, int x, int y);
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z); void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
void UpdateViewport(); void UpdateViewport();
// virtual funcs used by RendererBase::Swap // virtual funcs used by RendererBase::Swap
void PrepareXFBCopy(const TargetRectangle &dst_rect); void PrepareXFBCopy(const TargetRectangle &dst_rect);
void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc, void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc); const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc);
void EndFrame(); void EndFrame();
void Present(); void Present();
bool CheckForResize(); bool CheckForResize();
void GetBackBufferSize(int* w, int* h); void GetBackBufferSize(int* w, int* h);
void RecreateFramebufferManger(); void RecreateFramebufferManger();
void BeginFrame(); void BeginFrame();
private: private:
}; };
} }
#endif #endif
@@ -1,339 +1,339 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <vector> #include <vector>
#include <cmath> #include <cmath>
#include <fstream> #include <fstream>
#ifdef _WIN32 #ifdef _WIN32
#define _interlockedbittestandset workaround_ms_header_bug_platform_sdk6_set #define _interlockedbittestandset workaround_ms_header_bug_platform_sdk6_set
#define _interlockedbittestandreset workaround_ms_header_bug_platform_sdk6_reset #define _interlockedbittestandreset workaround_ms_header_bug_platform_sdk6_reset
#define _interlockedbittestandset64 workaround_ms_header_bug_platform_sdk6_set64 #define _interlockedbittestandset64 workaround_ms_header_bug_platform_sdk6_set64
#define _interlockedbittestandreset64 workaround_ms_header_bug_platform_sdk6_reset64 #define _interlockedbittestandreset64 workaround_ms_header_bug_platform_sdk6_reset64
#include <intrin.h> #include <intrin.h>
#undef _interlockedbittestandset #undef _interlockedbittestandset
#undef _interlockedbittestandreset #undef _interlockedbittestandreset
#undef _interlockedbittestandset64 #undef _interlockedbittestandset64
#undef _interlockedbittestandreset64 #undef _interlockedbittestandreset64
#endif #endif
// Common // Common
#include "CommonPaths.h" #include "CommonPaths.h"
#include "StringUtil.h" #include "StringUtil.h"
#include "MemoryUtil.h" #include "MemoryUtil.h"
#include "FileUtil.h" #include "FileUtil.h"
// VideoCommon // VideoCommon
#include "VideoConfig.h" #include "VideoConfig.h"
#include "Hash.h" #include "Hash.h"
#include "Statistics.h" #include "Statistics.h"
#include "Profiler.h" #include "Profiler.h"
#include "ImageWrite.h" #include "ImageWrite.h"
#include "BPStructs.h" #include "BPStructs.h"
#include "TextureDecoder.h" #include "TextureDecoder.h"
#include "PixelShaderManager.h" #include "PixelShaderManager.h"
#include "HiresTextures.h" #include "HiresTextures.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
// OGL // OGL
#include "OGL_TextureCache.h" #include "OGL_TextureCache.h"
#include "OGL_PixelShaderCache.h" #include "OGL_PixelShaderCache.h"
#include "OGL_TextureConverter.h" #include "OGL_TextureConverter.h"
#include "OGL_FramebufferManager.h" #include "OGL_FramebufferManager.h"
#include "../Main.h" #include "../Main.h"
namespace OGL namespace OGL
{ {
static u32 s_TempFramebuffer = 0; static u32 s_TempFramebuffer = 0;
static const GLint c_MinLinearFilter[8] = { static const GLint c_MinLinearFilter[8] = {
GL_NEAREST, GL_NEAREST,
GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_NEAREST,
GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_LINEAR,
GL_NEAREST, GL_NEAREST,
GL_LINEAR, GL_LINEAR,
GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST,
GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR,
GL_LINEAR, GL_LINEAR,
}; };
static const GLint c_WrapSettings[4] = { static const GLint c_WrapSettings[4] = {
GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE,
GL_REPEAT, GL_REPEAT,
GL_MIRRORED_REPEAT, GL_MIRRORED_REPEAT,
GL_REPEAT, GL_REPEAT,
}; };
TextureCache::TCacheEntry::~TCacheEntry() TextureCache::TCacheEntry::~TCacheEntry()
{ {
if (texture) if (texture)
{ {
glDeleteTextures(1, &texture); glDeleteTextures(1, &texture);
texture = 0; texture = 0;
} }
} }
TextureCache::TCacheEntry::TCacheEntry() TextureCache::TCacheEntry::TCacheEntry()
{ {
glGenTextures(1, &texture); glGenTextures(1, &texture);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
} }
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int level) unsigned int expanded_width, unsigned int level)
{ {
if (bHaveMipMaps) if (bHaveMipMaps)
{ {
if (pcfmt != PC_TEX_FMT_DXT1) if (pcfmt != PC_TEX_FMT_DXT1)
{ {
if (expanded_width != (int)width) if (expanded_width != (int)width)
glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width); glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, TextureCache::temp); glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, TextureCache::temp);
if (expanded_width != (int)width) if (expanded_width != (int)width)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
} }
else else
{ {
// TODO: // TODO:
//glCompressedTexImage2D(target, level, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, width, height, 0, expanded_width*expanded_height/2, temp); //glCompressedTexImage2D(target, level, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, width, height, 0, expanded_width*expanded_height/2, temp);
} }
} }
else else
{ {
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, width, height, 0, gl_format, gl_type, TextureCache::temp); glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, width, height, 0, gl_format, gl_type, TextureCache::temp);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
} }
} }
void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf, void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect) unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect)
{ {
glBindTexture(GL_TEXTURE_2D, texture); glBindTexture(GL_TEXTURE_2D, texture);
// Make sure to resolve anything we need to read from. // Make sure to resolve anything we need to read from.
const GLuint read_texture = bFromZBuffer ? FramebufferManager::ResolveAndGetDepthTarget(source_rect) : FramebufferManager::ResolveAndGetRenderTarget(source_rect); const GLuint read_texture = bFromZBuffer ? FramebufferManager::ResolveAndGetDepthTarget(source_rect) : FramebufferManager::ResolveAndGetRenderTarget(source_rect);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
if (s_TempFramebuffer == 0) if (s_TempFramebuffer == 0)
glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer); glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer);
FramebufferManager::SetFramebuffer(s_TempFramebuffer); FramebufferManager::SetFramebuffer(s_TempFramebuffer);
// Bind texture to temporary framebuffer // Bind texture to temporary framebuffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture, 0);
GL_REPORT_FBO_ERROR(); GL_REPORT_FBO_ERROR();
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_RECTANGLE_ARB); glEnable(GL_TEXTURE_RECTANGLE_ARB);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture);
glViewport(0, 0, Scaledw, Scaledh); glViewport(0, 0, Scaledw, Scaledh);
PixelShaderCache::SetCurrentShader(bFromZBuffer ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram()); PixelShaderCache::SetCurrentShader(bFromZBuffer ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram());
const float* const fConstAdd = colmat + 16; // fConstAdd is the last 4 floats of colmat const float* const fConstAdd = colmat + 16; // fConstAdd is the last 4 floats of colmat
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(source_rect); TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(source_rect);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.bottom); glVertex2f(-1, 1); glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.bottom); glVertex2f(-1, 1);
glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.top ); glVertex2f(-1, -1); glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.top ); glVertex2f(-1, -1);
glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.top ); glVertex2f( 1, -1); glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.top ); glVertex2f( 1, -1);
glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.bottom); glVertex2f( 1, 1); glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.bottom); glVertex2f( 1, 1);
glEnd(); glEnd();
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
// Unbind texture from temporary framebuffer // Unbind texture from temporary framebuffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
// TODO: these good here? // TODO: these good here?
FramebufferManager::SetFramebuffer(0); FramebufferManager::SetFramebuffer(0);
VertexShaderManager::SetViewportChanged(); VertexShaderManager::SetViewportChanged();
DisableStage(0); DisableStage(0);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
// TODO: do this? // TODO: do this?
//glBindTexture(GL_TEXTURE_2D, 0); //glBindTexture(GL_TEXTURE_2D, 0);
} }
void TextureCache::TCacheEntry::Bind(unsigned int stage) void TextureCache::TCacheEntry::Bind(unsigned int stage)
{ {
glBindTexture(GL_TEXTURE_2D, texture); glBindTexture(GL_TEXTURE_2D, texture);
} }
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
unsigned int height, unsigned int expanded_width, unsigned int height, unsigned int expanded_width,
unsigned int tex_levels, PC_TexFormat pcfmt) unsigned int tex_levels, PC_TexFormat pcfmt)
{ {
TCacheEntry &entry = *new TCacheEntry; TCacheEntry &entry = *new TCacheEntry;
int gl_format = 0; int gl_format = 0;
int gl_iformat = 0; int gl_iformat = 0;
int gl_type = 0; int gl_type = 0;
if (pcfmt != PC_TEX_FMT_DXT1) if (pcfmt != PC_TEX_FMT_DXT1)
{ {
switch (pcfmt) switch (pcfmt)
{ {
default: default:
case PC_TEX_FMT_NONE: case PC_TEX_FMT_NONE:
PanicAlert("Invalid PC texture format %i", pcfmt); PanicAlert("Invalid PC texture format %i", pcfmt);
case PC_TEX_FMT_BGRA32: case PC_TEX_FMT_BGRA32:
gl_format = GL_BGRA; gl_format = GL_BGRA;
gl_iformat = 4; gl_iformat = 4;
gl_type = GL_UNSIGNED_BYTE; gl_type = GL_UNSIGNED_BYTE;
break; break;
case PC_TEX_FMT_RGBA32: case PC_TEX_FMT_RGBA32:
gl_format = GL_RGBA; gl_format = GL_RGBA;
gl_iformat = 4; gl_iformat = 4;
gl_type = GL_UNSIGNED_BYTE; gl_type = GL_UNSIGNED_BYTE;
break; break;
case PC_TEX_FMT_I4_AS_I8: case PC_TEX_FMT_I4_AS_I8:
gl_format = GL_LUMINANCE; gl_format = GL_LUMINANCE;
gl_iformat = GL_INTENSITY4; gl_iformat = GL_INTENSITY4;
gl_type = GL_UNSIGNED_BYTE; gl_type = GL_UNSIGNED_BYTE;
break; break;
case PC_TEX_FMT_IA4_AS_IA8: case PC_TEX_FMT_IA4_AS_IA8:
gl_format = GL_LUMINANCE_ALPHA; gl_format = GL_LUMINANCE_ALPHA;
gl_iformat = GL_LUMINANCE4_ALPHA4; gl_iformat = GL_LUMINANCE4_ALPHA4;
gl_type = GL_UNSIGNED_BYTE; gl_type = GL_UNSIGNED_BYTE;
break; break;
case PC_TEX_FMT_I8: case PC_TEX_FMT_I8:
gl_format = GL_LUMINANCE; gl_format = GL_LUMINANCE;
gl_iformat = GL_INTENSITY8; gl_iformat = GL_INTENSITY8;
gl_type = GL_UNSIGNED_BYTE; gl_type = GL_UNSIGNED_BYTE;
break; break;
case PC_TEX_FMT_IA8: case PC_TEX_FMT_IA8:
gl_format = GL_LUMINANCE_ALPHA; gl_format = GL_LUMINANCE_ALPHA;
gl_iformat = GL_LUMINANCE8_ALPHA8; gl_iformat = GL_LUMINANCE8_ALPHA8;
gl_type = GL_UNSIGNED_BYTE; gl_type = GL_UNSIGNED_BYTE;
break; break;
case PC_TEX_FMT_RGB565: case PC_TEX_FMT_RGB565:
gl_format = GL_RGB; gl_format = GL_RGB;
gl_iformat = GL_RGB; gl_iformat = GL_RGB;
gl_type = GL_UNSIGNED_SHORT_5_6_5; gl_type = GL_UNSIGNED_SHORT_5_6_5;
break; break;
} }
} }
entry.gl_format = gl_format; entry.gl_format = gl_format;
entry.gl_iformat = gl_iformat; entry.gl_iformat = gl_iformat;
entry.gl_type = gl_type; entry.gl_type = gl_type;
// ok? // ok?
//Load(width, height, expanded_width, level); //Load(width, height, expanded_width, level);
return &entry; return &entry;
} }
TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h) TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h)
{ {
TCacheEntry &entry = *new TCacheEntry; TCacheEntry &entry = *new TCacheEntry;
entry.isDynamic = false; entry.isDynamic = false;
glBindTexture(GL_TEXTURE_2D, entry.texture); glBindTexture(GL_TEXTURE_2D, entry.texture);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
const GLenum gl_format = GL_RGBA, const GLenum gl_format = GL_RGBA,
gl_iformat = 4, gl_iformat = 4,
gl_type = GL_UNSIGNED_BYTE; gl_type = GL_UNSIGNED_BYTE;
glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, scaled_tex_w, scaled_tex_w, 0, gl_format, gl_type, NULL); glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, scaled_tex_w, scaled_tex_w, 0, gl_format, gl_type, NULL);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (GL_REPORT_ERROR() != GL_NO_ERROR) if (GL_REPORT_ERROR() != GL_NO_ERROR)
{ {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
} }
return &entry; return &entry;
} }
void TextureCache::TCacheEntry::SetTextureParameters(TexMode0 &newmode, TexMode1 &newmode1) void TextureCache::TCacheEntry::SetTextureParameters(TexMode0 &newmode, TexMode1 &newmode1)
{ {
mode = newmode; mode = newmode;
//mode1 = newmode1; //mode1 = newmode1;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
(newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
if (bHaveMipMaps) if (bHaveMipMaps)
{ {
if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4) if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
mode.min_filter += 4; // take equivalent forced linear mode.min_filter += 4; // take equivalent forced linear
int filt = newmode.min_filter; int filt = newmode.min_filter;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod >> 4); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod >> 4);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod >> 4); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod >> 4);
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (newmode.lod_bias/32.0f)); glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (newmode.lod_bias/32.0f));
} }
else else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
(g_ActiveConfig.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST); (g_ActiveConfig.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]);
if (g_Config.iMaxAnisotropy >= 1) if (g_Config.iMaxAnisotropy >= 1)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_ActiveConfig.iMaxAnisotropy)); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_ActiveConfig.iMaxAnisotropy));
} }
TextureCache::~TextureCache() TextureCache::~TextureCache()
{ {
if (s_TempFramebuffer) if (s_TempFramebuffer)
{ {
glDeleteFramebuffersEXT(1, (GLuint *)&s_TempFramebuffer); glDeleteFramebuffersEXT(1, (GLuint *)&s_TempFramebuffer);
s_TempFramebuffer = 0; s_TempFramebuffer = 0;
} }
} }
void TextureCache::DisableStage(int stage) void TextureCache::DisableStage(int stage)
{ {
glActiveTexture(GL_TEXTURE0 + stage); glActiveTexture(GL_TEXTURE0 + stage);
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_RECTANGLE_ARB); glDisable(GL_TEXTURE_RECTANGLE_ARB);
} }
} }
@@ -1,80 +1,80 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _OGL_TEXTURECACHE_H_ #ifndef _OGL_TEXTURECACHE_H_
#define _OGL_TEXTURECACHE_H_ #define _OGL_TEXTURECACHE_H_
#include "VideoCommon.h" #include "VideoCommon.h"
#include "BPMemory.h" #include "BPMemory.h"
#include "OGL_GLUtil.h" #include "OGL_GLUtil.h"
#include "../TextureCache.h" #include "../TextureCache.h"
namespace OGL namespace OGL
{ {
class TextureCache : public ::TextureCacheBase class TextureCache : public ::TextureCacheBase
{ {
public: public:
struct TCacheEntry : TCacheEntryBase struct TCacheEntry : TCacheEntryBase
{ {
GLuint texture; GLuint texture;
bool isDynamic; bool isDynamic;
bool bHaveMipMaps; bool bHaveMipMaps;
PC_TexFormat pcfmt; PC_TexFormat pcfmt;
int gl_format; int gl_format;
int gl_iformat; int gl_iformat;
int gl_type; int gl_type;
TexMode0 mode; // current filter and clamp modes that texture is set to TexMode0 mode; // current filter and clamp modes that texture is set to
TexMode1 mode1; // current filter and clamp modes that texture is set to TexMode1 mode1; // current filter and clamp modes that texture is set to
void SetTextureParameters(TexMode0 &newmode, TexMode1 &newmode1); void SetTextureParameters(TexMode0 &newmode, TexMode1 &newmode1);
TCacheEntry(); TCacheEntry();
~TCacheEntry(); ~TCacheEntry();
void Load(unsigned int width, unsigned int height, void Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int level); unsigned int expanded_width, unsigned int level);
void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf, void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect); unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect);
void Bind(unsigned int stage); void Bind(unsigned int stage);
}; };
~TextureCache(); ~TextureCache();
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height, TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt); unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt);
TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h); TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h);
void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, unsigned int bScaleByHalf, const EFBRectangle &source); void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, unsigned int bScaleByHalf, const EFBRectangle &source);
static void DisableStage(int stage); // sets active texture static void DisableStage(int stage); // sets active texture
}; };
//bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height); //bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height);
} }
#endif // _TEXTUREMNGR_H_ #endif // _TEXTUREMNGR_H_
@@ -1,486 +1,486 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Fast image conversion using OpenGL shaders. // Fast image conversion using OpenGL shaders.
// This kind of stuff would be a LOT nicer with OpenCL. // This kind of stuff would be a LOT nicer with OpenCL.
#include <math.h> #include <math.h>
// Common // Common
#include "FileUtil.h" #include "FileUtil.h"
// VideoCommon // VideoCommon
#include "TextureConversionShader.h" #include "TextureConversionShader.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "ImageWrite.h" #include "ImageWrite.h"
// OGL // OGL
#include "OGL_Render.h" #include "OGL_Render.h"
#include "OGL_TextureConverter.h" #include "OGL_TextureConverter.h"
#include "OGL_TextureCache.h" #include "OGL_TextureCache.h"
#include "OGL_PixelShaderCache.h" #include "OGL_PixelShaderCache.h"
#include "OGL_FramebufferManager.h" #include "OGL_FramebufferManager.h"
#include "../Main.h" #include "../Main.h"
namespace OGL namespace OGL
{ {
namespace TextureConverter namespace TextureConverter
{ {
static GLuint s_texConvFrameBuffer = 0; static GLuint s_texConvFrameBuffer = 0;
static GLuint s_srcTexture = 0; // for decoding from RAM static GLuint s_srcTexture = 0; // for decoding from RAM
static GLuint s_srcTextureWidth = 0; static GLuint s_srcTextureWidth = 0;
static GLuint s_srcTextureHeight = 0; static GLuint s_srcTextureHeight = 0;
static GLuint s_dstRenderBuffer = 0; // for encoding to RAM static GLuint s_dstRenderBuffer = 0; // for encoding to RAM
const int renderBufferWidth = 1024; const int renderBufferWidth = 1024;
const int renderBufferHeight = 1024; const int renderBufferHeight = 1024;
static FRAGMENTSHADER s_rgbToYuyvProgram; static FRAGMENTSHADER s_rgbToYuyvProgram;
static FRAGMENTSHADER s_yuyvToRgbProgram; static FRAGMENTSHADER s_yuyvToRgbProgram;
// Not all slots are taken - but who cares. // Not all slots are taken - but who cares.
const u32 NUM_ENCODING_PROGRAMS = 64; const u32 NUM_ENCODING_PROGRAMS = 64;
static FRAGMENTSHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS]; static FRAGMENTSHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS];
void CreateRgbToYuyvProgram() void CreateRgbToYuyvProgram()
{ {
// Output is BGRA because that is slightly faster than RGBA. // Output is BGRA because that is slightly faster than RGBA.
const char *FProgram = const char *FProgram =
"uniform samplerRECT samp0 : register(s0);\n" "uniform samplerRECT samp0 : register(s0);\n"
"void main(\n" "void main(\n"
" out float4 ocol0 : COLOR0,\n" " out float4 ocol0 : COLOR0,\n"
" in float2 uv0 : TEXCOORD0)\n" " in float2 uv0 : TEXCOORD0)\n"
"{\n" "{\n"
" float2 uv1 = float2(uv0.x + 1.0f, uv0.y);\n" " float2 uv1 = float2(uv0.x + 1.0f, uv0.y);\n"
" float3 c0 = texRECT(samp0, uv0).rgb;\n" " float3 c0 = texRECT(samp0, uv0).rgb;\n"
" float3 c1 = texRECT(samp0, uv1).rgb;\n" " float3 c1 = texRECT(samp0, uv1).rgb;\n"
" float3 y_const = float3(0.257f,0.504f,0.098f);\n" " float3 y_const = float3(0.257f,0.504f,0.098f);\n"
" float3 u_const = float3(-0.148f,-0.291f,0.439f);\n" " float3 u_const = float3(-0.148f,-0.291f,0.439f);\n"
" float3 v_const = float3(0.439f,-0.368f,-0.071f);\n" " float3 v_const = float3(0.439f,-0.368f,-0.071f);\n"
" float4 const3 = float4(0.0625f,0.5f,0.0625f,0.5f);\n" " float4 const3 = float4(0.0625f,0.5f,0.0625f,0.5f);\n"
" float3 c01 = (c0 + c1) * 0.5f;\n" " float3 c01 = (c0 + c1) * 0.5f;\n"
" ocol0 = float4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + const3;\n" " ocol0 = float4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + const3;\n"
"}\n"; "}\n";
if (!PixelShaderCache::CompilePixelShader(s_rgbToYuyvProgram, FProgram)) { if (!PixelShaderCache::CompilePixelShader(s_rgbToYuyvProgram, FProgram)) {
ERROR_LOG(VIDEO, "Failed to create RGB to YUYV fragment program"); ERROR_LOG(VIDEO, "Failed to create RGB to YUYV fragment program");
} }
} }
void CreateYuyvToRgbProgram() void CreateYuyvToRgbProgram()
{ {
const char *FProgram = const char *FProgram =
"uniform samplerRECT samp0 : register(s0);\n" "uniform samplerRECT samp0 : register(s0);\n"
"void main(\n" "void main(\n"
" out float4 ocol0 : COLOR0,\n" " out float4 ocol0 : COLOR0,\n"
" in float2 uv0 : TEXCOORD0)\n" " in float2 uv0 : TEXCOORD0)\n"
"{\n" "{\n"
" float4 c0 = texRECT(samp0, uv0).rgba;\n" " float4 c0 = texRECT(samp0, uv0).rgba;\n"
" float f = step(0.5, frac(uv0.x));\n" " float f = step(0.5, frac(uv0.x));\n"
" float y = lerp(c0.b, c0.r, f);\n" " float y = lerp(c0.b, c0.r, f);\n"
" float yComp = 1.164f * (y - 0.0625f);\n" " float yComp = 1.164f * (y - 0.0625f);\n"
" float uComp = c0.g - 0.5f;\n" " float uComp = c0.g - 0.5f;\n"
" float vComp = c0.a - 0.5f;\n" " float vComp = c0.a - 0.5f;\n"
" ocol0 = float4(yComp + (1.596f * vComp),\n" " ocol0 = float4(yComp + (1.596f * vComp),\n"
" yComp - (0.813f * vComp) - (0.391f * uComp),\n" " yComp - (0.813f * vComp) - (0.391f * uComp),\n"
" yComp + (2.018f * uComp),\n" " yComp + (2.018f * uComp),\n"
" 1.0f);\n" " 1.0f);\n"
"}\n"; "}\n";
if (!PixelShaderCache::CompilePixelShader(s_yuyvToRgbProgram, FProgram)) { if (!PixelShaderCache::CompilePixelShader(s_yuyvToRgbProgram, FProgram)) {
ERROR_LOG(VIDEO, "Failed to create YUYV to RGB fragment program"); ERROR_LOG(VIDEO, "Failed to create YUYV to RGB fragment program");
} }
} }
FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format) FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format)
{ {
if (format > NUM_ENCODING_PROGRAMS) if (format > NUM_ENCODING_PROGRAMS)
{ {
PanicAlert("Unknown texture copy format: 0x%x\n", format); PanicAlert("Unknown texture copy format: 0x%x\n", format);
return s_encodingPrograms[0]; return s_encodingPrograms[0];
} }
if (s_encodingPrograms[format].glprogid == 0) if (s_encodingPrograms[format].glprogid == 0)
{ {
const char* shader = TextureConversionShader::GenerateEncodingShader(format,API_OPENGL); const char* shader = TextureConversionShader::GenerateEncodingShader(format,API_OPENGL);
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader) { if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader) {
static int counter = 0; static int counter = 0;
char szTemp[MAX_PATH]; char szTemp[MAX_PATH];
sprintf(szTemp, "%senc_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++); sprintf(szTemp, "%senc_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
SaveData(szTemp, shader); SaveData(szTemp, shader);
} }
#endif #endif
if (!PixelShaderCache::CompilePixelShader(s_encodingPrograms[format], shader)) { if (!PixelShaderCache::CompilePixelShader(s_encodingPrograms[format], shader)) {
ERROR_LOG(VIDEO, "Failed to create encoding fragment program"); ERROR_LOG(VIDEO, "Failed to create encoding fragment program");
} }
} }
return s_encodingPrograms[format]; return s_encodingPrograms[format];
} }
void Init() void Init()
{ {
glGenFramebuffersEXT(1, &s_texConvFrameBuffer); glGenFramebuffersEXT(1, &s_texConvFrameBuffer);
glGenRenderbuffersEXT(1, &s_dstRenderBuffer); glGenRenderbuffersEXT(1, &s_dstRenderBuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, renderBufferWidth, renderBufferHeight); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, renderBufferWidth, renderBufferHeight);
glGenTextures(1, &s_srcTexture); glGenTextures(1, &s_srcTexture);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
CreateRgbToYuyvProgram(); CreateRgbToYuyvProgram();
CreateYuyvToRgbProgram(); CreateYuyvToRgbProgram();
} }
void Shutdown() void Shutdown()
{ {
glDeleteTextures(1, &s_srcTexture); glDeleteTextures(1, &s_srcTexture);
glDeleteRenderbuffersEXT(1, &s_dstRenderBuffer); glDeleteRenderbuffersEXT(1, &s_dstRenderBuffer);
glDeleteFramebuffersEXT(1, &s_texConvFrameBuffer); glDeleteFramebuffersEXT(1, &s_texConvFrameBuffer);
s_rgbToYuyvProgram.Destroy(); s_rgbToYuyvProgram.Destroy();
s_yuyvToRgbProgram.Destroy(); s_yuyvToRgbProgram.Destroy();
for (unsigned int i = 0; i < NUM_ENCODING_PROGRAMS; i++) for (unsigned int i = 0; i < NUM_ENCODING_PROGRAMS; i++)
s_encodingPrograms[i].Destroy(); s_encodingPrograms[i].Destroy();
s_srcTexture = 0; s_srcTexture = 0;
s_dstRenderBuffer = 0; s_dstRenderBuffer = 0;
s_texConvFrameBuffer = 0; s_texConvFrameBuffer = 0;
} }
void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const TargetRectangle& sourceRc, void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const TargetRectangle& sourceRc,
u8* destAddr, int dstWidth, int dstHeight, int readStride, bool toTexture, bool linearFilter) u8* destAddr, int dstWidth, int dstHeight, int readStride, bool toTexture, bool linearFilter)
{ {
// switch to texture converter frame buffer // switch to texture converter frame buffer
// attach render buffer as color destination // attach render buffer as color destination
FramebufferManager::SetFramebuffer(s_texConvFrameBuffer); FramebufferManager::SetFramebuffer(s_texConvFrameBuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, s_dstRenderBuffer); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
for (int i = 1; i < 8; ++i) for (int i = 1; i < 8; ++i)
TextureCache::DisableStage(i); TextureCache::DisableStage(i);
// set source texture // set source texture
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_RECTANGLE_ARB); glEnable(GL_TEXTURE_RECTANGLE_ARB);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture);
if (linearFilter) if (linearFilter)
{ {
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} }
else else
{ {
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
} }
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
glViewport(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight); glViewport(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight);
PixelShaderCache::SetCurrentShader(shader.glprogid); PixelShaderCache::SetCurrentShader(shader.glprogid);
// Draw... // Draw...
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2f((float)sourceRc.left, (float)sourceRc.top); glVertex2f(-1,-1); glTexCoord2f((float)sourceRc.left, (float)sourceRc.top); glVertex2f(-1,-1);
glTexCoord2f((float)sourceRc.left, (float)sourceRc.bottom); glVertex2f(-1,1); glTexCoord2f((float)sourceRc.left, (float)sourceRc.bottom); glVertex2f(-1,1);
glTexCoord2f((float)sourceRc.right, (float)sourceRc.bottom); glVertex2f(1,1); glTexCoord2f((float)sourceRc.right, (float)sourceRc.bottom); glVertex2f(1,1);
glTexCoord2f((float)sourceRc.right, (float)sourceRc.top); glVertex2f(1,-1); glTexCoord2f((float)sourceRc.right, (float)sourceRc.top); glVertex2f(1,-1);
glEnd(); glEnd();
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
// .. and then readback the results. // .. and then readback the results.
// TODO: make this less slow. // TODO: make this less slow.
int writeStride = bpmem.copyMipMapStrideChannels * 32; int writeStride = bpmem.copyMipMapStrideChannels * 32;
if (writeStride != readStride && toTexture) if (writeStride != readStride && toTexture)
{ {
// writing to a texture of a different size // writing to a texture of a different size
int readHeight = readStride / dstWidth; int readHeight = readStride / dstWidth;
readHeight /= 4; // 4 bytes per pixel readHeight /= 4; // 4 bytes per pixel
int readStart = 0; int readStart = 0;
int readLoops = dstHeight / readHeight; int readLoops = dstHeight / readHeight;
for (int i = 0; i < readLoops; i++) for (int i = 0; i < readLoops; i++)
{ {
glReadPixels(0, readStart, (GLsizei)dstWidth, (GLsizei)readHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr); glReadPixels(0, readStart, (GLsizei)dstWidth, (GLsizei)readHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr);
readStart += readHeight; readStart += readHeight;
destAddr += writeStride; destAddr += writeStride;
} }
} }
else else
glReadPixels(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr); glReadPixels(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
} }
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
{ {
u32 format = copyfmt; u32 format = copyfmt;
if (bFromZBuffer) if (bFromZBuffer)
{ {
format |= _GX_TF_ZTF; format |= _GX_TF_ZTF;
if (copyfmt == 11) if (copyfmt == 11)
format = GX_TF_Z16; format = GX_TF_Z16;
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8) else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
format |= _GX_TF_CTF; format |= _GX_TF_CTF;
} }
else else
if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt)) if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt))
format |= _GX_TF_CTF; format |= _GX_TF_CTF;
FRAGMENTSHADER& texconv_shader = GetOrCreateEncodingShader(format); FRAGMENTSHADER& texconv_shader = GetOrCreateEncodingShader(format);
if (texconv_shader.glprogid == 0) if (texconv_shader.glprogid == 0)
return; return;
u8 *dest_ptr = Memory_GetPtr(address); u8 *dest_ptr = Memory_GetPtr(address);
GLuint source_texture = bFromZBuffer ? FramebufferManager::ResolveAndGetDepthTarget(source) : FramebufferManager::ResolveAndGetRenderTarget(source); GLuint source_texture = bFromZBuffer ? FramebufferManager::ResolveAndGetDepthTarget(source) : FramebufferManager::ResolveAndGetRenderTarget(source);
int width = (source.right - source.left) >> bScaleByHalf; int width = (source.right - source.left) >> bScaleByHalf;
int height = (source.bottom - source.top) >> bScaleByHalf; int height = (source.bottom - source.top) >> bScaleByHalf;
int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format); int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format);
// Invalidate any existing texture covering this memory range. // Invalidate any existing texture covering this memory range.
// TODO - don't delete the texture if it already exists, just replace the contents. // TODO - don't delete the texture if it already exists, just replace the contents.
TextureCache::InvalidateRange(address, size_in_bytes); TextureCache::InvalidateRange(address, size_in_bytes);
u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1; u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1;
u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1; u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1;
u16 samples = TextureConversionShader::GetEncodedSampleCount(format); u16 samples = TextureConversionShader::GetEncodedSampleCount(format);
// only copy on cache line boundaries // only copy on cache line boundaries
// extra pixels are copied but not displayed in the resulting texture // extra pixels are copied but not displayed in the resulting texture
s32 expandedWidth = (width + blkW) & (~blkW); s32 expandedWidth = (width + blkW) & (~blkW);
s32 expandedHeight = (height + blkH) & (~blkH); s32 expandedHeight = (height + blkH) & (~blkH);
float MValueX = Renderer::GetTargetScaleX(); float MValueX = Renderer::GetTargetScaleX();
float MValueY = Renderer::GetTargetScaleY(); float MValueY = Renderer::GetTargetScaleY();
float top = (EFB_HEIGHT - source.top - expandedHeight) * MValueY ; float top = (EFB_HEIGHT - source.top - expandedHeight) * MValueY ;
float sampleStride = bScaleByHalf?2.0f:1.0f; float sampleStride = bScaleByHalf?2.0f:1.0f;
TextureConversionShader::SetShaderParameters((float)expandedWidth, TextureConversionShader::SetShaderParameters((float)expandedWidth,
expandedHeight * MValueY, expandedHeight * MValueY,
source.left * MValueX, source.left * MValueX,
top, top,
sampleStride * MValueX, sampleStride * MValueX,
sampleStride * MValueY); sampleStride * MValueY);
TargetRectangle scaledSource; TargetRectangle scaledSource;
scaledSource.top = 0; scaledSource.top = 0;
scaledSource.bottom = expandedHeight; scaledSource.bottom = expandedHeight;
scaledSource.left = 0; scaledSource.left = 0;
scaledSource.right = expandedWidth / samples; scaledSource.right = expandedWidth / samples;
int cacheBytes = 32; int cacheBytes = 32;
if ((format & 0x0f) == 6) if ((format & 0x0f) == 6)
cacheBytes = 64; cacheBytes = 64;
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
g_renderer->ResetAPIState(); g_renderer->ResetAPIState();
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0); EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0);
FramebufferManager::SetFramebuffer(0); FramebufferManager::SetFramebuffer(0);
VertexShaderManager::SetViewportChanged(); VertexShaderManager::SetViewportChanged();
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
TextureCache::DisableStage(0); TextureCache::DisableStage(0);
g_renderer->RestoreAPIState(); g_renderer->RestoreAPIState();
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
} }
u64 EncodeToRamFromTexture(u32 address,GLuint source_texture,float MValueX,float MValueY,bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) u64 EncodeToRamFromTexture(u32 address,GLuint source_texture,float MValueX,float MValueY,bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
{ {
u32 format = copyfmt; u32 format = copyfmt;
if (bFromZBuffer) if (bFromZBuffer)
{ {
format |= _GX_TF_ZTF; format |= _GX_TF_ZTF;
if (copyfmt == 11) if (copyfmt == 11)
format = GX_TF_Z16; format = GX_TF_Z16;
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8) else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
format |= _GX_TF_CTF; format |= _GX_TF_CTF;
} }
else else
if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt)) if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt))
format |= _GX_TF_CTF; format |= _GX_TF_CTF;
FRAGMENTSHADER& texconv_shader = GetOrCreateEncodingShader(format); FRAGMENTSHADER& texconv_shader = GetOrCreateEncodingShader(format);
if (texconv_shader.glprogid == 0) if (texconv_shader.glprogid == 0)
return 0; return 0;
u8 *dest_ptr = Memory_GetPtr(address); u8 *dest_ptr = Memory_GetPtr(address);
int width = (source.right - source.left) >> bScaleByHalf; int width = (source.right - source.left) >> bScaleByHalf;
int height = (source.bottom - source.top) >> bScaleByHalf; int height = (source.bottom - source.top) >> bScaleByHalf;
int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format); int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format);
u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1; u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1;
u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1; u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1;
u16 samples = TextureConversionShader::GetEncodedSampleCount(format); u16 samples = TextureConversionShader::GetEncodedSampleCount(format);
// only copy on cache line boundaries // only copy on cache line boundaries
// extra pixels are copied but not displayed in the resulting texture // extra pixels are copied but not displayed in the resulting texture
s32 expandedWidth = (width + blkW) & (~blkW); s32 expandedWidth = (width + blkW) & (~blkW);
s32 expandedHeight = (height + blkH) & (~blkH); s32 expandedHeight = (height + blkH) & (~blkH);
float sampleStride = bScaleByHalf?2.0f:1.0f; float sampleStride = bScaleByHalf?2.0f:1.0f;
float top = (EFB_HEIGHT - source.top - expandedHeight) * MValueY ; float top = (EFB_HEIGHT - source.top - expandedHeight) * MValueY ;
TextureConversionShader::SetShaderParameters((float)expandedWidth, TextureConversionShader::SetShaderParameters((float)expandedWidth,
expandedHeight * MValueY, expandedHeight * MValueY,
source.left * MValueX, source.left * MValueX,
top, top,
sampleStride * MValueX, sampleStride * MValueX,
sampleStride * MValueY); sampleStride * MValueY);
TargetRectangle scaledSource; TargetRectangle scaledSource;
scaledSource.top = 0; scaledSource.top = 0;
scaledSource.bottom = expandedHeight; scaledSource.bottom = expandedHeight;
scaledSource.left = 0; scaledSource.left = 0;
scaledSource.right = expandedWidth / samples; scaledSource.right = expandedWidth / samples;
int cacheBytes = 32; int cacheBytes = 32;
if ((format & 0x0f) == 6) if ((format & 0x0f) == 6)
cacheBytes = 64; cacheBytes = 64;
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0 && !bFromZBuffer); EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0 && !bFromZBuffer);
g_texture_cache->MakeRangeDynamic(address,size_in_bytes); g_texture_cache->MakeRangeDynamic(address,size_in_bytes);
return GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples); return GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples);
} }
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
u8* destAddr, int dstWidth, int dstHeight) u8* destAddr, int dstWidth, int dstHeight)
{ {
g_renderer->ResetAPIState(); g_renderer->ResetAPIState();
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false); EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
FramebufferManager::SetFramebuffer(0); FramebufferManager::SetFramebuffer(0);
VertexShaderManager::SetViewportChanged(); VertexShaderManager::SetViewportChanged();
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
TextureCache::DisableStage(0); TextureCache::DisableStage(0);
g_renderer->RestoreAPIState(); g_renderer->RestoreAPIState();
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
} }
// Should be scale free. // Should be scale free.
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture) void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture)
{ {
u8* srcAddr = Memory_GetPtr(xfbAddr); u8* srcAddr = Memory_GetPtr(xfbAddr);
if (!srcAddr) if (!srcAddr)
{ {
WARN_LOG(VIDEO, "Tried to decode from invalid memory address"); WARN_LOG(VIDEO, "Tried to decode from invalid memory address");
return; return;
} }
g_renderer->ResetAPIState(); g_renderer->ResetAPIState();
int srcFmtWidth = srcWidth / 2; int srcFmtWidth = srcWidth / 2;
// swich to texture converter frame buffer // swich to texture converter frame buffer
// attach destTexture as color destination // attach destTexture as color destination
FramebufferManager::SetFramebuffer(s_texConvFrameBuffer); FramebufferManager::SetFramebuffer(s_texConvFrameBuffer);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destTexture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destTexture);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destTexture, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destTexture, 0);
GL_REPORT_FBO_ERROR(); GL_REPORT_FBO_ERROR();
for (int i = 1; i < 8; ++i) for (int i = 1; i < 8; ++i)
TextureCache::DisableStage(i); TextureCache::DisableStage(i);
// activate source texture // activate source texture
// set srcAddr as data for source texture // set srcAddr as data for source texture
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_RECTANGLE_ARB); glEnable(GL_TEXTURE_RECTANGLE_ARB);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture);
// TODO: make this less slow. (How?) // TODO: make this less slow. (How?)
if((GLsizei)s_srcTextureWidth == (GLsizei)srcFmtWidth && (GLsizei)s_srcTextureHeight == (GLsizei)srcHeight) if((GLsizei)s_srcTextureWidth == (GLsizei)srcFmtWidth && (GLsizei)s_srcTextureHeight == (GLsizei)srcHeight)
{ {
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,0,0,s_srcTextureWidth, s_srcTextureHeight, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr); glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,0,0,s_srcTextureWidth, s_srcTextureHeight, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
} }
else else
{ {
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)srcFmtWidth, (GLsizei)srcHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)srcFmtWidth, (GLsizei)srcHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
s_srcTextureWidth = (GLsizei)srcFmtWidth; s_srcTextureWidth = (GLsizei)srcFmtWidth;
s_srcTextureHeight = (GLsizei)srcHeight; s_srcTextureHeight = (GLsizei)srcHeight;
} }
glViewport(0, 0, srcWidth, srcHeight); glViewport(0, 0, srcWidth, srcHeight);
PixelShaderCache::SetCurrentShader(s_yuyvToRgbProgram.glprogid); PixelShaderCache::SetCurrentShader(s_yuyvToRgbProgram.glprogid);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2f((float)srcFmtWidth, (float)srcHeight); glTexCoord2f((float)srcFmtWidth, (float)srcHeight);
glVertex2f(1, -1); glVertex2f(1, -1);
glTexCoord2f((float)srcFmtWidth, 0); glTexCoord2f((float)srcFmtWidth, 0);
glVertex2f(1, 1); glVertex2f(1, 1);
glTexCoord2f(0, 0); glTexCoord2f(0, 0);
glVertex2f(-1, 1); glVertex2f(-1, 1);
glTexCoord2f(0, (float)srcHeight); glTexCoord2f(0, (float)srcHeight);
glVertex2f(-1, -1); glVertex2f(-1, -1);
glEnd(); glEnd();
// reset state // reset state
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
TextureCache::DisableStage(0); TextureCache::DisableStage(0);
VertexShaderManager::SetViewportChanged(); VertexShaderManager::SetViewportChanged();
FramebufferManager::SetFramebuffer(0); FramebufferManager::SetFramebuffer(0);
g_renderer->RestoreAPIState(); g_renderer->RestoreAPIState();
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
} }
} // namespace } // namespace
} }
@@ -1,50 +1,50 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _OGL_TEXTURECONVERTER_H_ #ifndef _OGL_TEXTURECONVERTER_H_
#define _OGL_TEXTURECONVERTER_H_ #define _OGL_TEXTURECONVERTER_H_
#include "VideoCommon.h" #include "VideoCommon.h"
#include "OGL_GLUtil.h" #include "OGL_GLUtil.h"
namespace OGL namespace OGL
{ {
// Converts textures between formats // Converts textures between formats
// TODO: support multiple texture formats // TODO: support multiple texture formats
namespace TextureConverter namespace TextureConverter
{ {
void Init(); void Init();
void Shutdown(); void Shutdown();
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
u8* destAddr, int dstWidth, int dstHeight); u8* destAddr, int dstWidth, int dstHeight);
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture); void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);
u64 EncodeToRamFromTexture(u32 address,GLuint source_texture,float MValueX,float MValueY, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); u64 EncodeToRamFromTexture(u32 address,GLuint source_texture,float MValueX,float MValueY, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
} }
} }
#endif // _TEXTURECONVERTER_H_ #endif // _TEXTURECONVERTER_H_
@@ -1,113 +1,113 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <fstream> #include <fstream>
#include <vector> #include <vector>
// Common // Common
#include "MemoryUtil.h" #include "MemoryUtil.h"
#include "FileUtil.h" #include "FileUtil.h"
// VideoCommon // VideoCommon
#include "Fifo.h" #include "Fifo.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "Statistics.h" #include "Statistics.h"
#include "Profiler.h" #include "Profiler.h"
#include "ImageWrite.h" #include "ImageWrite.h"
#include "BPMemory.h" #include "BPMemory.h"
#include "IndexGenerator.h" #include "IndexGenerator.h"
#include "OpcodeDecoding.h" #include "OpcodeDecoding.h"
#include "PixelShaderManager.h" #include "PixelShaderManager.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
#include "VertexLoader.h" #include "VertexLoader.h"
// OGL // OGL
#include "OGL_Render.h" #include "OGL_Render.h"
#include "OGL_TextureCache.h" #include "OGL_TextureCache.h"
#include "OGL_PixelShaderCache.h" #include "OGL_PixelShaderCache.h"
#include "OGL_VertexShaderCache.h" #include "OGL_VertexShaderCache.h"
#include "OGL_VertexManager.h" #include "OGL_VertexManager.h"
#include "../Main.h" #include "../Main.h"
namespace OGL namespace OGL
{ {
enum enum
{ {
MAXVBUFFERSIZE = 0x1FFFF, MAXVBUFFERSIZE = 0x1FFFF,
MAXIBUFFERSIZE = 0xFFFF, MAXIBUFFERSIZE = 0xFFFF,
MAXVBOBUFFERCOUNT = 0x8, MAXVBOBUFFERCOUNT = 0x8,
}; };
//static GLuint s_vboBuffers[MAXVBOBUFFERCOUNT] = {0}; //static GLuint s_vboBuffers[MAXVBOBUFFERCOUNT] = {0};
//static int s_nCurVBOIndex = 0; // current free buffer //static int s_nCurVBOIndex = 0; // current free buffer
VertexManager::VertexManager() VertexManager::VertexManager()
{ {
lastPrimitive = GX_DRAW_NONE; lastPrimitive = GX_DRAW_NONE;
//s_nCurVBOIndex = 0; //s_nCurVBOIndex = 0;
//glGenBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers); //glGenBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers);
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
g_nativeVertexFmt = NULL; g_nativeVertexFmt = NULL;
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
} }
VertexManager::~VertexManager() VertexManager::~VertexManager()
{ {
//glDeleteBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers); //glDeleteBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers);
//s_nCurVBOIndex = 0; //s_nCurVBOIndex = 0;
} }
void VertexManager::Draw(u32 /*stride*/, bool alphapass) void VertexManager::Draw(u32 /*stride*/, bool alphapass)
{ {
if (alphapass) if (alphapass)
{ {
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glDisable(GL_BLEND); glDisable(GL_BLEND);
} }
if (IndexGenerator::GetNumTriangles() > 0) if (IndexGenerator::GetNumTriangles() > 0)
{ {
glDrawElements(GL_TRIANGLES, IndexGenerator::GetTriangleindexLen(), GL_UNSIGNED_SHORT, TIBuffer); glDrawElements(GL_TRIANGLES, IndexGenerator::GetTriangleindexLen(), GL_UNSIGNED_SHORT, TIBuffer);
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
} }
if (IndexGenerator::GetNumLines() > 0) if (IndexGenerator::GetNumLines() > 0)
{ {
glDrawElements(GL_LINES, IndexGenerator::GetLineindexLen(), GL_UNSIGNED_SHORT, LIBuffer); glDrawElements(GL_LINES, IndexGenerator::GetLineindexLen(), GL_UNSIGNED_SHORT, LIBuffer);
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
} }
if (IndexGenerator::GetNumPoints() > 0) if (IndexGenerator::GetNumPoints() > 0)
{ {
glDrawElements(GL_POINTS, IndexGenerator::GetPointindexLen(), GL_UNSIGNED_SHORT, PIBuffer); glDrawElements(GL_POINTS, IndexGenerator::GetPointindexLen(), GL_UNSIGNED_SHORT, PIBuffer);
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
} }
if (alphapass) if (alphapass)
{ {
// restore color mask // restore color mask
g_renderer->SetColorMask(); g_renderer->SetColorMask();
if (bpmem.blendmode.blendenable || bpmem.blendmode.subtract) if (bpmem.blendmode.blendenable || bpmem.blendmode.subtract)
glEnable(GL_BLEND); glEnable(GL_BLEND);
} }
} }
} }
@@ -1,44 +1,44 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _OGL_VERTEXMANAGER_H_ #ifndef _OGL_VERTEXMANAGER_H_
#define _OGL_VERTEXMANAGER_H_ #define _OGL_VERTEXMANAGER_H_
#include "CPMemory.h" #include "CPMemory.h"
#include "NativeVertexWriter.h" #include "NativeVertexWriter.h"
#include "../VertexManager.h" #include "../VertexManager.h"
namespace OGL namespace OGL
{ {
// Handles the OpenGL details of drawing lots of vertices quickly. // Handles the OpenGL details of drawing lots of vertices quickly.
// Other functionality is moving out. // Other functionality is moving out.
class VertexManager : public ::VertexManagerBase class VertexManager : public ::VertexManagerBase
{ {
public: public:
VertexManager(); VertexManager();
~VertexManager(); ~VertexManager();
void Draw(u32 stride, bool alphapass); void Draw(u32 stride, bool alphapass);
NativeVertexFormat* CreateNativeVertexFormat(); NativeVertexFormat* CreateNativeVertexFormat();
}; };
} }
#endif // _VERTEXMANAGER_H_ #endif // _VERTEXMANAGER_H_
@@ -1,255 +1,255 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <math.h> #include <math.h>
// Common // Common
#include "FileUtil.h" #include "FileUtil.h"
// VideoCommon // VideoCommon
#include "Profiler.h" #include "Profiler.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "Statistics.h" #include "Statistics.h"
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "VertexLoader.h" #include "VertexLoader.h"
#include "XFMemory.h" #include "XFMemory.h"
#include "ImageWrite.h" #include "ImageWrite.h"
// OGL // OGL
#include "OGL_Render.h" #include "OGL_Render.h"
#include "OGL_VertexShaderCache.h" #include "OGL_VertexShaderCache.h"
#include "OGL_GLUtil.h" #include "OGL_GLUtil.h"
#include "OGL_VertexManager.h" #include "OGL_VertexManager.h"
#include "../Main.h" #include "../Main.h"
namespace OGL namespace OGL
{ {
VertexShaderCache::VSCache VertexShaderCache::vshaders; VertexShaderCache::VSCache VertexShaderCache::vshaders;
bool VertexShaderCache::s_displayCompileAlert; bool VertexShaderCache::s_displayCompileAlert;
GLuint VertexShaderCache::CurrentShader; GLuint VertexShaderCache::CurrentShader;
bool VertexShaderCache::ShaderEnabled; bool VertexShaderCache::ShaderEnabled;
static VERTEXSHADER *pShaderLast = NULL; static VERTEXSHADER *pShaderLast = NULL;
static int s_nMaxVertexInstructions; static int s_nMaxVertexInstructions;
void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{ {
float f[4] = { f1, f2, f3, f4 }; float f[4] = { f1, f2, f3, f4 };
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f); glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f);
} }
void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float *f) void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float *f)
{ {
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f); glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f);
} }
void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f) void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
{ {
for (unsigned int i = 0; i < count; i++,f+=4) for (unsigned int i = 0; i < count; i++,f+=4)
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, f); glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, f);
} }
void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f) void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
{ {
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
float buf[4]; float buf[4];
buf[0] = *f++; buf[0] = *f++;
buf[1] = *f++; buf[1] = *f++;
buf[2] = *f++; buf[2] = *f++;
buf[3] = 0.f; buf[3] = 0.f;
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, buf); glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, buf);
} }
} }
VertexShaderCache::VertexShaderCache() VertexShaderCache::VertexShaderCache()
{ {
glEnable(GL_VERTEX_PROGRAM_ARB); glEnable(GL_VERTEX_PROGRAM_ARB);
ShaderEnabled = true; ShaderEnabled = true;
CurrentShader = 0; CurrentShader = 0;
memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid)); memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid));
s_displayCompileAlert = true; s_displayCompileAlert = true;
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions);
#if CG_VERSION_NUM == 2100 #if CG_VERSION_NUM == 2100
if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL) if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
{ {
s_nMaxVertexInstructions = 4096; s_nMaxVertexInstructions = 4096;
} }
#endif #endif
} }
VertexShaderCache::~VertexShaderCache() VertexShaderCache::~VertexShaderCache()
{ {
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); iter++) for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); iter++)
iter->second.Destroy(); iter->second.Destroy();
vshaders.clear(); vshaders.clear();
} }
bool VertexShaderCache::SetShader(u32 components) bool VertexShaderCache::SetShader(u32 components)
{ {
const VERTEXSHADER* const vs = GetShader(components); const VERTEXSHADER* const vs = GetShader(components);
if (vs) if (vs)
{ {
SetCurrentShader(vs->glprogid); SetCurrentShader(vs->glprogid);
return true; return true;
} }
else else
return false; return false;
} }
VERTEXSHADER* VertexShaderCache::GetShader(u32 components) VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
{ {
DVSTARTPROFILE(); DVSTARTPROFILE();
VERTEXSHADERUID uid; VERTEXSHADERUID uid;
GetVertexShaderId(&uid, components); GetVertexShaderId(&uid, components);
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount) if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
{ {
return pShaderLast; return pShaderLast;
} }
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID)); memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
VSCache::iterator iter = vshaders.find(uid); VSCache::iterator iter = vshaders.find(uid);
if (iter != vshaders.end()) { if (iter != vshaders.end()) {
iter->second.frameCount = frameCount; iter->second.frameCount = frameCount;
VSCacheEntry &entry = iter->second; VSCacheEntry &entry = iter->second;
if (&entry.shader != pShaderLast) { if (&entry.shader != pShaderLast) {
pShaderLast = &entry.shader; pShaderLast = &entry.shader;
} }
return pShaderLast; return pShaderLast;
} }
//Make an entry in the table //Make an entry in the table
VSCacheEntry& entry = vshaders[uid]; VSCacheEntry& entry = vshaders[uid];
entry.frameCount = frameCount; entry.frameCount = frameCount;
pShaderLast = &entry.shader; pShaderLast = &entry.shader;
const char *code = GenerateVertexShaderCode(components, API_OPENGL); const char *code = GenerateVertexShaderCode(components, API_OPENGL);
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) { if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
static int counter = 0; static int counter = 0;
char szTemp[MAX_PATH]; char szTemp[MAX_PATH];
sprintf(szTemp, "%svs_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++); sprintf(szTemp, "%svs_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
SaveData(szTemp, code); SaveData(szTemp, code);
} }
#endif #endif
if (!code || !VertexShaderCache::CompileVertexShader(entry.shader, code)) { if (!code || !VertexShaderCache::CompileVertexShader(entry.shader, code)) {
ERROR_LOG(VIDEO, "failed to create vertex shader"); ERROR_LOG(VIDEO, "failed to create vertex shader");
return NULL; return NULL;
} }
INCSTAT(stats.numVertexShadersCreated); INCSTAT(stats.numVertexShadersCreated);
SETSTAT(stats.numVertexShadersAlive, vshaders.size()); SETSTAT(stats.numVertexShadersAlive, vshaders.size());
return pShaderLast; return pShaderLast;
} }
bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram) bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
{ {
// Reset GL error before compiling shaders. Yeah, we need to investigate the causes of these. // Reset GL error before compiling shaders. Yeah, we need to investigate the causes of these.
GLenum err = GL_REPORT_ERROR(); GLenum err = GL_REPORT_ERROR();
if (err != GL_NO_ERROR) if (err != GL_NO_ERROR)
{ {
ERROR_LOG(VIDEO, "glError %08x before VS!", err); ERROR_LOG(VIDEO, "glError %08x before VS!", err);
} }
#if defined HAVE_CG && HAVE_CG #if defined HAVE_CG && HAVE_CG
char stropt[64]; char stropt[64];
sprintf(stropt, "MaxLocalParams=256,MaxInstructions=%d", s_nMaxVertexInstructions); sprintf(stropt, "MaxLocalParams=256,MaxInstructions=%d", s_nMaxVertexInstructions);
const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL}; const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgvProf, "main", opts); CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgvProf, "main", opts);
if (!cgIsProgram(tempprog)) { if (!cgIsProgram(tempprog)) {
if (s_displayCompileAlert) { if (s_displayCompileAlert) {
PanicAlert("Failed to create vertex shader"); PanicAlert("Failed to create vertex shader");
s_displayCompileAlert = false; s_displayCompileAlert = false;
} }
cgDestroyProgram(tempprog); cgDestroyProgram(tempprog);
ERROR_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext)); ERROR_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
ERROR_LOG(VIDEO, pstrprogram); ERROR_LOG(VIDEO, pstrprogram);
return false; return false;
} }
if (cgGetError() != CG_NO_ERROR) if (cgGetError() != CG_NO_ERROR)
{ {
WARN_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext)); WARN_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
WARN_LOG(VIDEO, pstrprogram); WARN_LOG(VIDEO, pstrprogram);
} }
// This looks evil - we modify the program through the const char * we got from cgGetProgramString! // This looks evil - we modify the program through the const char * we got from cgGetProgramString!
// It SHOULD not have any nasty side effects though - but you never know... // It SHOULD not have any nasty side effects though - but you never know...
char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM); char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
char *plocal = strstr(pcompiledprog, "program.local"); char *plocal = strstr(pcompiledprog, "program.local");
while (plocal != NULL) { while (plocal != NULL) {
const char* penv = " program.env"; const char* penv = " program.env";
memcpy(plocal, penv, 13); memcpy(plocal, penv, 13);
plocal = strstr(plocal + 13, "program.local"); plocal = strstr(plocal + 13, "program.local");
} }
glGenProgramsARB(1, &vs.glprogid); glGenProgramsARB(1, &vs.glprogid);
SetCurrentShader(vs.glprogid); SetCurrentShader(vs.glprogid);
glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog); glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
err = GL_REPORT_ERROR(); err = GL_REPORT_ERROR();
if (err != GL_NO_ERROR) { if (err != GL_NO_ERROR) {
ERROR_LOG(VIDEO, pstrprogram); ERROR_LOG(VIDEO, pstrprogram);
ERROR_LOG(VIDEO, pcompiledprog); ERROR_LOG(VIDEO, pcompiledprog);
} }
cgDestroyProgram(tempprog); cgDestroyProgram(tempprog);
#endif #endif
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
vs.strprog = pstrprogram; vs.strprog = pstrprogram;
#endif #endif
return true; return true;
} }
void VertexShaderCache::DisableShader() void VertexShaderCache::DisableShader()
{ {
if (ShaderEnabled) if (ShaderEnabled)
{ {
glDisable(GL_VERTEX_PROGRAM_ARB); glDisable(GL_VERTEX_PROGRAM_ARB);
ShaderEnabled = false; ShaderEnabled = false;
} }
} }
void VertexShaderCache::SetCurrentShader(GLuint Shader) void VertexShaderCache::SetCurrentShader(GLuint Shader)
{ {
if (!ShaderEnabled) if (!ShaderEnabled)
{ {
glEnable(GL_VERTEX_PROGRAM_ARB); glEnable(GL_VERTEX_PROGRAM_ARB);
ShaderEnabled= true; ShaderEnabled= true;
} }
if (CurrentShader != Shader) if (CurrentShader != Shader)
{ {
if(Shader != 0) if(Shader != 0)
CurrentShader = Shader; CurrentShader = Shader;
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader); glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
} }
} }
} }
@@ -1,89 +1,89 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _OGL_VERTEXSHADERCACHE_H_ #ifndef _OGL_VERTEXSHADERCACHE_H_
#define _OGL_VERTEXSHADERCACHE_H_ #define _OGL_VERTEXSHADERCACHE_H_
#include <map> #include <map>
#include <string> #include <string>
// VideoCommon // VideoCommon
#include "BPMemory.h" #include "BPMemory.h"
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
// OGL // OGL
#include "OGL_GLUtil.h" #include "OGL_GLUtil.h"
#include "../VertexShaderCache.h" #include "../VertexShaderCache.h"
namespace OGL namespace OGL
{ {
struct VERTEXSHADER struct VERTEXSHADER
{ {
VERTEXSHADER() : glprogid(0) {} VERTEXSHADER() : glprogid(0) {}
GLuint glprogid; // opengl program id GLuint glprogid; // opengl program id
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
std::string strprog; std::string strprog;
#endif #endif
}; };
class VertexShaderCache : public ::VertexShaderCacheBase class VertexShaderCache : public ::VertexShaderCacheBase
{ {
struct VSCacheEntry struct VSCacheEntry
{ {
VERTEXSHADER shader; VERTEXSHADER shader;
int frameCount; int frameCount;
VSCacheEntry() : frameCount(0) {} VSCacheEntry() : frameCount(0) {}
void Destroy() { void Destroy() {
// printf("Destroying vs %i\n", shader.glprogid); // printf("Destroying vs %i\n", shader.glprogid);
glDeleteProgramsARB(1, &shader.glprogid); glDeleteProgramsARB(1, &shader.glprogid);
shader.glprogid = 0; shader.glprogid = 0;
} }
}; };
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache; typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
static VSCache vshaders; static VSCache vshaders;
static bool s_displayCompileAlert; static bool s_displayCompileAlert;
static GLuint CurrentShader; static GLuint CurrentShader;
static bool ShaderEnabled; static bool ShaderEnabled;
public: public:
VertexShaderCache(); VertexShaderCache();
~VertexShaderCache(); ~VertexShaderCache();
bool SetShader(u32 components); bool SetShader(u32 components);
static VERTEXSHADER* GetShader(u32 components); static VERTEXSHADER* GetShader(u32 components);
static bool CompileVertexShader(VERTEXSHADER& ps, const char* pstrprogram); static bool CompileVertexShader(VERTEXSHADER& ps, const char* pstrprogram);
static void SetCurrentShader(GLuint Shader); static void SetCurrentShader(GLuint Shader);
static void DisableShader(); static void DisableShader();
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4); void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
void SetVSConstant4fv(unsigned int const_number, const float* f); void SetVSConstant4fv(unsigned int const_number, const float* f);
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f); void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f);
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f); void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f);
}; };
} }
#endif // _VERTEXSHADERCACHE_H_ #endif // _VERTEXSHADERCACHE_H_
@@ -1,42 +1,42 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// ---------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------
// This file handles the External Frame Buffer (XFB). The XFB is a storage point when the picture is resized // This file handles the External Frame Buffer (XFB). The XFB is a storage point when the picture is resized
// by the system to the correct display format for output to the TV. In most cases its function can be // by the system to the correct display format for output to the TV. In most cases its function can be
// supplemented by the equivalent adjustments in glScissor and glViewport (or their DirectX equivalents). But // supplemented by the equivalent adjustments in glScissor and glViewport (or their DirectX equivalents). But
// for some homebrew games these functions are necessary because the homebrew game communicate directly with // for some homebrew games these functions are necessary because the homebrew game communicate directly with
// them. // them.
// ---------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------
// OGL // OGL
#include "OGL_Render.h" #include "OGL_Render.h"
#include "OGL_TextureConverter.h" #include "OGL_TextureConverter.h"
#include "OGL_FramebufferManager.h" #include "OGL_FramebufferManager.h"
#include "OGL_XFB.h" #include "OGL_XFB.h"
namespace OGL namespace OGL
{ {
void XFB_Write(u8 *xfb_in_ram, const EFBRectangle& sourceRc, u32 dstWd, u32 dstHt) void XFB_Write(u8 *xfb_in_ram, const EFBRectangle& sourceRc, u32 dstWd, u32 dstHt)
{ {
TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc); TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc);
TextureConverter::EncodeToRamYUYV(FramebufferManager::ResolveAndGetRenderTarget(sourceRc), targetRc, xfb_in_ram, dstWd, dstHt); TextureConverter::EncodeToRamYUYV(FramebufferManager::ResolveAndGetRenderTarget(sourceRc), targetRc, xfb_in_ram, dstWd, dstHt);
} }
} }
@@ -1,31 +1,31 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _OGL_XFB_H_ #ifndef _OGL_XFB_H_
#define _OGL_XFB_H_ #define _OGL_XFB_H_
#include "OGL_GLUtil.h" #include "OGL_GLUtil.h"
namespace OGL namespace OGL
{ {
// write the EFB to the XFB // write the EFB to the XFB
void XFB_Write(u8 *xfb_in_ram, const EFBRectangle& sourceRc, u32 dstWd, u32 dstHt); void XFB_Write(u8 *xfb_in_ram, const EFBRectangle& sourceRc, u32 dstWd, u32 dstHt);
} }
#endif // _XFB_H_ #endif // _XFB_H_
@@ -1,20 +1,20 @@
#include "PixelShaderManager.h" #include "PixelShaderManager.h"
#include "Main.h" #include "Main.h"
#include "PixelShaderCache.h" #include "PixelShaderCache.h"
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{ {
g_pixel_shader_cache->SetPSConstant4f(const_number, f1, f2, f3, f4); g_pixel_shader_cache->SetPSConstant4f(const_number, f1, f2, f3, f4);
} }
void SetPSConstant4fv(unsigned int const_number, const float *f) void SetPSConstant4fv(unsigned int const_number, const float *f)
{ {
g_pixel_shader_cache->SetPSConstant4fv(const_number, f); g_pixel_shader_cache->SetPSConstant4fv(const_number, f);
} }
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f) void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
{ {
g_pixel_shader_cache->SetMultiPSConstant4fv(const_number, count, f); g_pixel_shader_cache->SetMultiPSConstant4fv(const_number, count, f);
} }
@@ -1,20 +1,20 @@
#ifndef _PIXELSHADERCACHE_H_ #ifndef _PIXELSHADERCACHE_H_
#define _PIXELSHADERCACHE_H_ #define _PIXELSHADERCACHE_H_
class PixelShaderCacheBase class PixelShaderCacheBase
{ {
public: public:
virtual ~PixelShaderCacheBase() {} virtual ~PixelShaderCacheBase() {}
virtual bool SetShader(bool dstAlphaEnable) = 0; virtual bool SetShader(bool dstAlphaEnable) = 0;
virtual void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) = 0; virtual void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) = 0;
virtual void SetPSConstant4fv(unsigned int const_number, const float *f) = 0; virtual void SetPSConstant4fv(unsigned int const_number, const float *f) = 0;
virtual void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f) = 0; virtual void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f) = 0;
protected: protected:
}; };
#endif #endif
+390 -390
View File
@@ -1,390 +1,390 @@
#include <math.h> #include <math.h>
#include "Common.h" #include "Common.h"
#include "Timer.h" #include "Timer.h"
#include "Render.h" #include "Render.h"
#include "BPMemory.h" #include "BPMemory.h"
#include "Atomic.h" #include "Atomic.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "FramebufferManager.h" #include "FramebufferManager.h"
#include "Fifo.h" #include "Fifo.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "DLCache.h" #include "DLCache.h"
#include "OnScreenDisplay.h" #include "OnScreenDisplay.h"
#include "Statistics.h" #include "Statistics.h"
#include "Renderer.h" #include "Renderer.h"
#include "Main.h" #include "Main.h"
int RendererBase::s_target_width; int RendererBase::s_target_width;
int RendererBase::s_target_height; int RendererBase::s_target_height;
int RendererBase::s_Fulltarget_width; int RendererBase::s_Fulltarget_width;
int RendererBase::s_Fulltarget_height; int RendererBase::s_Fulltarget_height;
int RendererBase::s_backbuffer_width; int RendererBase::s_backbuffer_width;
int RendererBase::s_backbuffer_height; int RendererBase::s_backbuffer_height;
int RendererBase::s_XFB_width; int RendererBase::s_XFB_width;
int RendererBase::s_XFB_height; int RendererBase::s_XFB_height;
float RendererBase::xScale; float RendererBase::xScale;
float RendererBase::yScale; float RendererBase::yScale;
int RendererBase::s_fps; int RendererBase::s_fps;
u32 RendererBase::s_blendMode; u32 RendererBase::s_blendMode;
bool RendererBase::XFBWrited; bool RendererBase::XFBWrited;
float RendererBase::EFBxScale; float RendererBase::EFBxScale;
float RendererBase::EFByScale; float RendererBase::EFByScale;
volatile u32 RendererBase::s_swapRequested; volatile u32 RendererBase::s_swapRequested;
//void VideoConfig::UpdateProjectionHack() //void VideoConfig::UpdateProjectionHack()
//{ //{
// return; // return;
// //::UpdateProjectionHack(g_Config.iPhackvalue); // //::UpdateProjectionHack(g_Config.iPhackvalue);
//} //}
RendererBase::RendererBase() RendererBase::RendererBase()
{ {
UpdateActiveConfig(); UpdateActiveConfig();
s_blendMode = 0; s_blendMode = 0;
s_XFB_width = MAX_XFB_WIDTH; s_XFB_width = MAX_XFB_WIDTH;
s_XFB_height = MAX_XFB_HEIGHT; s_XFB_height = MAX_XFB_HEIGHT;
} }
// can maybe reuse this func in Renderer::Swap to eliminate redundant code // can maybe reuse this func in Renderer::Swap to eliminate redundant code
void RendererBase::FramebufferSize(int w, int h) void RendererBase::FramebufferSize(int w, int h)
{ {
TargetRectangle dst_rect; TargetRectangle dst_rect;
ComputeDrawRectangle(w, h, false, &dst_rect); ComputeDrawRectangle(w, h, false, &dst_rect);
xScale = (float)(dst_rect.right - dst_rect.left) / (float)s_XFB_width; xScale = (float)(dst_rect.right - dst_rect.left) / (float)s_XFB_width;
yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height; yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height;
// TODO: why these, prolly can remove them // TODO: why these, prolly can remove them
const int s_LastAA = g_ActiveConfig.iMultisampleMode; const int s_LastAA = g_ActiveConfig.iMultisampleMode;
const int s_LastEFBScale = g_ActiveConfig.iEFBScale; const int s_LastEFBScale = g_ActiveConfig.iEFBScale;
switch (s_LastEFBScale) switch (s_LastEFBScale)
{ {
case 0: case 0:
EFBxScale = xScale; EFBxScale = xScale;
EFByScale = yScale; EFByScale = yScale;
break; break;
case 1: case 1:
EFBxScale = ceilf(xScale); EFBxScale = ceilf(xScale);
EFByScale = ceilf(yScale); EFByScale = ceilf(yScale);
break; break;
default: default:
EFByScale = EFBxScale = (g_ActiveConfig.iEFBScale - 1); EFByScale = EFBxScale = (g_ActiveConfig.iEFBScale - 1);
break; break;
}; };
const float SupersampleCoeficient = s_LastAA + 1; const float SupersampleCoeficient = s_LastAA + 1;
EFBxScale *= SupersampleCoeficient; EFBxScale *= SupersampleCoeficient;
EFByScale *= SupersampleCoeficient; EFByScale *= SupersampleCoeficient;
s_target_width = (int)(EFB_WIDTH * EFBxScale); s_target_width = (int)(EFB_WIDTH * EFBxScale);
s_target_height = (int)(EFB_HEIGHT * EFByScale); s_target_height = (int)(EFB_HEIGHT * EFByScale);
// TODO: set anything else? // TODO: set anything else?
s_Fulltarget_width = s_target_width; s_Fulltarget_width = s_target_width;
s_Fulltarget_height = s_target_height; s_Fulltarget_height = s_target_height;
} }
void UpdateViewport() void UpdateViewport()
{ {
g_renderer->UpdateViewport(); g_renderer->UpdateViewport();
} }
void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{ {
RendererBase::RenderToXFB(xfbAddr, fbWidth, fbHeight, sourceRc); RendererBase::RenderToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
} }
// whats this for? // whats this for?
bool IsD3D() bool IsD3D()
{ {
//PanicAlert("IsD3D!"); //PanicAlert("IsD3D!");
// TODO: temporary // TODO: temporary
return true; return true;
} }
void Renderer::RenderText(const char *pstr, int left, int top, u32 color) void Renderer::RenderText(const char *pstr, int left, int top, u32 color)
{ {
} }
void RendererBase::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) void RendererBase::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{ {
if (!fbWidth || !fbHeight) if (!fbWidth || !fbHeight)
return; return;
VideoFifo_CheckEFBAccess(); VideoFifo_CheckEFBAccess();
VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight); VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight);
XFBWrited = true; XFBWrited = true;
// XXX: Without the VI, how would we know what kind of field this is? So // XXX: Without the VI, how would we know what kind of field this is? So
// just use progressive. // just use progressive.
if (g_ActiveConfig.bUseXFB) if (g_ActiveConfig.bUseXFB)
{ {
g_framebuffer_manager->CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc); g_framebuffer_manager->CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
} }
else else
{ {
g_renderer->Swap(xfbAddr, FIELD_PROGRESSIVE, fbWidth, fbHeight, sourceRc); g_renderer->Swap(xfbAddr, FIELD_PROGRESSIVE, fbWidth, fbHeight, sourceRc);
Common::AtomicStoreRelease(s_swapRequested, FALSE); Common::AtomicStoreRelease(s_swapRequested, FALSE);
} }
} }
TargetRectangle RendererBase::ConvertEFBRectangle(const EFBRectangle& rc) TargetRectangle RendererBase::ConvertEFBRectangle(const EFBRectangle& rc)
{ {
int Xstride = (s_Fulltarget_width - s_target_width) / 2; int Xstride = (s_Fulltarget_width - s_target_width) / 2;
int Ystride = (s_Fulltarget_height - s_target_height) / 2; int Ystride = (s_Fulltarget_height - s_target_height) / 2;
TargetRectangle result; TargetRectangle result;
result.left = (int)(rc.left * EFBxScale) + Xstride; result.left = (int)(rc.left * EFBxScale) + Xstride;
result.top = (int)(rc.top * EFByScale) + Ystride; result.top = (int)(rc.top * EFByScale) + Ystride;
result.right = (int)(rc.right * EFBxScale) + Xstride; result.right = (int)(rc.right * EFBxScale) + Xstride;
result.bottom = (int)(rc.bottom * EFByScale) + Ystride; result.bottom = (int)(rc.bottom * EFByScale) + Ystride;
return result; return result;
} }
bool RendererBase::SetScissorRect(EFBRectangle &rc) bool RendererBase::SetScissorRect(EFBRectangle &rc)
{ {
int xoff = bpmem.scissorOffset.x * 2 - 342; int xoff = bpmem.scissorOffset.x * 2 - 342;
int yoff = bpmem.scissorOffset.y * 2 - 342; int yoff = bpmem.scissorOffset.y * 2 - 342;
rc.left = bpmem.scissorTL.x - xoff - 342; rc.left = bpmem.scissorTL.x - xoff - 342;
rc.top = bpmem.scissorTL.y - yoff - 342; rc.top = bpmem.scissorTL.y - yoff - 342;
rc.right = bpmem.scissorBR.x - xoff - 341; rc.right = bpmem.scissorBR.x - xoff - 341;
rc.bottom = bpmem.scissorBR.y - yoff - 341; rc.bottom = bpmem.scissorBR.y - yoff - 341;
int Xstride = (s_Fulltarget_width - s_target_width) / 2; int Xstride = (s_Fulltarget_width - s_target_width) / 2;
int Ystride = (s_Fulltarget_height - s_target_height) / 2; int Ystride = (s_Fulltarget_height - s_target_height) / 2;
rc.left = (int)(rc.left * EFBxScale); rc.left = (int)(rc.left * EFBxScale);
rc.top = (int)(rc.top * EFByScale); rc.top = (int)(rc.top * EFByScale);
rc.right = (int)(rc.right * EFBxScale); rc.right = (int)(rc.right * EFBxScale);
rc.bottom = (int)(rc.bottom * EFByScale); rc.bottom = (int)(rc.bottom * EFByScale);
if (rc.left < 0) rc.left = 0; if (rc.left < 0) rc.left = 0;
if (rc.right < 0) rc.right = 0; if (rc.right < 0) rc.right = 0;
if (rc.left > s_target_width) rc.left = s_target_width; if (rc.left > s_target_width) rc.left = s_target_width;
if (rc.right > s_target_width) rc.right = s_target_width; if (rc.right > s_target_width) rc.right = s_target_width;
if (rc.top < 0) rc.top = 0; if (rc.top < 0) rc.top = 0;
if (rc.bottom < 0) rc.bottom = 0; if (rc.bottom < 0) rc.bottom = 0;
if (rc.top > s_target_height) rc.top = s_target_height; if (rc.top > s_target_height) rc.top = s_target_height;
if (rc.bottom > s_target_height) rc.bottom = s_target_height; if (rc.bottom > s_target_height) rc.bottom = s_target_height;
rc.left += Xstride; rc.left += Xstride;
rc.top += Ystride; rc.top += Ystride;
rc.right += Xstride; rc.right += Xstride;
rc.bottom += Ystride; rc.bottom += Ystride;
if (rc.left > rc.right) if (rc.left > rc.right)
{ {
int temp = rc.right; int temp = rc.right;
rc.right = rc.left; rc.right = rc.left;
rc.left = temp; rc.left = temp;
} }
if (rc.top > rc.bottom) if (rc.top > rc.bottom)
{ {
int temp = rc.bottom; int temp = rc.bottom;
rc.bottom = rc.top; rc.bottom = rc.top;
rc.top = temp; rc.top = temp;
} }
return (rc.right >= rc.left && rc.bottom >= rc.top); return (rc.right >= rc.left && rc.bottom >= rc.top);
} }
void RendererBase::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight, const EFBRectangle& rc) void RendererBase::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight, const EFBRectangle& rc)
{ {
if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.bUseRealXFB) || !fbWidth || !fbHeight) if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.bUseRealXFB) || !fbWidth || !fbHeight)
{ {
g_VideoInitialize.pCopiedToXFB(false); g_VideoInitialize.pCopiedToXFB(false);
return; return;
} }
// this function is called after the XFB field is changed, not after // this function is called after the XFB field is changed, not after
// EFB is copied to XFB. In this way, flickering is reduced in games // EFB is copied to XFB. In this way, flickering is reduced in games
// and seems to also give more FPS in ZTP // and seems to also give more FPS in ZTP
if (field == FIELD_LOWER) if (field == FIELD_LOWER)
xfbAddr -= fbWidth * 2; xfbAddr -= fbWidth * 2;
u32 xfbCount = 0; u32 xfbCount = 0;
const XFBSourceBase** xfbSourceList = g_framebuffer_manager->GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); const XFBSourceBase** xfbSourceList = g_framebuffer_manager->GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
{ {
g_VideoInitialize.pCopiedToXFB(false); g_VideoInitialize.pCopiedToXFB(false);
return; return;
} }
g_renderer->ResetAPIState(); g_renderer->ResetAPIState();
// prepare copying the XFBs to our backbuffer // prepare copying the XFBs to our backbuffer
TargetRectangle dst_rect; TargetRectangle dst_rect;
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect); ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
g_renderer->PrepareXFBCopy(dst_rect); g_renderer->PrepareXFBCopy(dst_rect);
if (g_ActiveConfig.bUseXFB) if (g_ActiveConfig.bUseXFB)
{ {
const XFBSourceBase* xfbSource; const XFBSourceBase* xfbSource;
// draw each xfb source // draw each xfb source
for (u32 i = 0; i < xfbCount; ++i) for (u32 i = 0; i < xfbCount; ++i)
{ {
xfbSource = xfbSourceList[i]; xfbSource = xfbSourceList[i];
TargetRectangle sourceRc; TargetRectangle sourceRc;
//if (g_ActiveConfig.bAutoScale) //if (g_ActiveConfig.bAutoScale)
//{ //{
// sourceRc = xfbSource->sourceRc; // sourceRc = xfbSource->sourceRc;
//} //}
//else //else
//{ //{
sourceRc.left = 0; sourceRc.left = 0;
sourceRc.top = 0; sourceRc.top = 0;
sourceRc.right = xfbSource->texWidth; sourceRc.right = xfbSource->texWidth;
sourceRc.bottom = xfbSource->texHeight; sourceRc.bottom = xfbSource->texHeight;
//} //}
MathUtil::Rectangle<float> drawRc; MathUtil::Rectangle<float> drawRc;
if (g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) if (g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
{ {
// use virtual xfb with offset // use virtual xfb with offset
int xfbHeight = xfbSource->srcHeight; int xfbHeight = xfbSource->srcHeight;
int xfbWidth = xfbSource->srcWidth; int xfbWidth = xfbSource->srcWidth;
int hOffset = ((s32)xfbSource->srcAddr - (s32)xfbAddr) / ((s32)fbWidth * 2); int hOffset = ((s32)xfbSource->srcAddr - (s32)xfbAddr) / ((s32)fbWidth * 2);
drawRc.bottom = 1.0f - 2.0f * ((hOffset) / (float)fbHeight); drawRc.bottom = 1.0f - 2.0f * ((hOffset) / (float)fbHeight);
drawRc.top = 1.0f - 2.0f * ((hOffset + xfbHeight) / (float)fbHeight); drawRc.top = 1.0f - 2.0f * ((hOffset + xfbHeight) / (float)fbHeight);
drawRc.left = -(xfbWidth / (float)fbWidth); drawRc.left = -(xfbWidth / (float)fbWidth);
drawRc.right = (xfbWidth / (float)fbWidth); drawRc.right = (xfbWidth / (float)fbWidth);
if (!g_ActiveConfig.bAutoScale) if (!g_ActiveConfig.bAutoScale)
{ {
// scale draw area for a 1 to 1 pixel mapping with the draw target // scale draw area for a 1 to 1 pixel mapping with the draw target
float vScale = (float)fbHeight / (float)s_backbuffer_height; float vScale = (float)fbHeight / (float)s_backbuffer_height;
float hScale = (float)fbWidth / (float)s_backbuffer_width; float hScale = (float)fbWidth / (float)s_backbuffer_width;
drawRc.top *= vScale; drawRc.top *= vScale;
drawRc.bottom *= vScale; drawRc.bottom *= vScale;
drawRc.left *= hScale; drawRc.left *= hScale;
drawRc.right *= hScale; drawRc.right *= hScale;
} }
} }
else else
{ {
drawRc.top = -1; drawRc.top = -1;
drawRc.bottom = 1; drawRc.bottom = 1;
drawRc.left = -1; drawRc.left = -1;
drawRc.right = 1; drawRc.right = 1;
} }
g_renderer->Draw(xfbSource, sourceRc, drawRc, rc); g_renderer->Draw(xfbSource, sourceRc, drawRc, rc);
} }
} }
else else
{ {
// TODO: organize drawRc stuff // TODO: organize drawRc stuff
MathUtil::Rectangle<float> drawRc; MathUtil::Rectangle<float> drawRc;
drawRc.top = -1; drawRc.top = -1;
drawRc.bottom = 1; drawRc.bottom = 1;
drawRc.left = -1; drawRc.left = -1;
drawRc.right = 1; drawRc.right = 1;
const TargetRectangle targetRc = ConvertEFBRectangle(rc); const TargetRectangle targetRc = ConvertEFBRectangle(rc);
g_renderer->Draw(NULL, targetRc, drawRc, rc); g_renderer->Draw(NULL, targetRc, drawRc, rc);
} }
// done with drawing the game stuff, good moment to save a screenshot // done with drawing the game stuff, good moment to save a screenshot
// TODO: screenshot code // TODO: screenshot code
// //
// finally present some information // finally present some information
// TODO: debug text, fps, etc... // TODO: debug text, fps, etc...
// //
OSD::DrawMessages(); OSD::DrawMessages();
g_renderer->EndFrame(); g_renderer->EndFrame();
++frameCount; ++frameCount;
DLCache::ProgressiveCleanup(); DLCache::ProgressiveCleanup();
g_texture_cache->Cleanup(); g_texture_cache->Cleanup();
// check for configuration changes // check for configuration changes
const int last_efbscale = g_ActiveConfig.iEFBScale; const int last_efbscale = g_ActiveConfig.iEFBScale;
//const int last_aa = g_ActiveConfig.iMultisampleMode; //const int last_aa = g_ActiveConfig.iMultisampleMode;
UpdateActiveConfig(); UpdateActiveConfig();
bool window_resized = g_renderer->CheckForResize(); bool window_resized = g_renderer->CheckForResize();
bool xfbchanged = false; bool xfbchanged = false;
if (s_XFB_width != fbWidth || s_XFB_height != fbHeight) if (s_XFB_width != fbWidth || s_XFB_height != fbHeight)
{ {
xfbchanged = true; xfbchanged = true;
s_XFB_width = fbWidth; s_XFB_width = fbWidth;
s_XFB_height = fbHeight; s_XFB_height = fbHeight;
if (s_XFB_width < 1) s_XFB_width = MAX_XFB_WIDTH; if (s_XFB_width < 1) s_XFB_width = MAX_XFB_WIDTH;
if (s_XFB_width > MAX_XFB_WIDTH) s_XFB_width = MAX_XFB_WIDTH; if (s_XFB_width > MAX_XFB_WIDTH) s_XFB_width = MAX_XFB_WIDTH;
if (s_XFB_height < 1) s_XFB_height = MAX_XFB_HEIGHT; if (s_XFB_height < 1) s_XFB_height = MAX_XFB_HEIGHT;
if (s_XFB_height > MAX_XFB_HEIGHT) s_XFB_height = MAX_XFB_HEIGHT; if (s_XFB_height > MAX_XFB_HEIGHT) s_XFB_height = MAX_XFB_HEIGHT;
} }
// update FPS counter // update FPS counter
// TODO: make this better // TODO: make this better
static int fpscount = 0; static int fpscount = 0;
static unsigned long lasttime = 0; static unsigned long lasttime = 0;
if (Common::Timer::GetTimeMs() - lasttime >= 1000) if (Common::Timer::GetTimeMs() - lasttime >= 1000)
{ {
lasttime = Common::Timer::GetTimeMs(); lasttime = Common::Timer::GetTimeMs();
s_fps = fpscount; s_fps = fpscount;
fpscount = 0; fpscount = 0;
} }
if (XFBWrited) if (XFBWrited)
++fpscount; ++fpscount;
// set default viewport and scissor, for the clear to work correctly // set default viewport and scissor, for the clear to work correctly
stats.ResetFrame(); stats.ResetFrame();
// done. Show our work ;) // done. Show our work ;)
g_renderer->Present(); g_renderer->Present();
// resize the back buffers NOW to avoid flickering when resizing windows // resize the back buffers NOW to avoid flickering when resizing windows
if (xfbchanged || window_resized || last_efbscale != g_ActiveConfig.iEFBScale) if (xfbchanged || window_resized || last_efbscale != g_ActiveConfig.iEFBScale)
{ {
g_renderer->GetBackBufferSize(&s_backbuffer_width, &s_backbuffer_height); g_renderer->GetBackBufferSize(&s_backbuffer_width, &s_backbuffer_height);
FramebufferSize(s_backbuffer_width, s_backbuffer_height); FramebufferSize(s_backbuffer_width, s_backbuffer_height);
g_renderer->RecreateFramebufferManger(); g_renderer->RecreateFramebufferManger();
} }
// begin next frame // begin next frame
g_renderer->RestoreAPIState(); g_renderer->RestoreAPIState();
g_renderer->BeginFrame(); g_renderer->BeginFrame();
g_renderer->UpdateViewport(); g_renderer->UpdateViewport();
VertexShaderManager::SetViewportChanged(); VertexShaderManager::SetViewportChanged();
g_VideoInitialize.pCopiedToXFB(XFBWrited || g_ActiveConfig.bUseRealXFB); g_VideoInitialize.pCopiedToXFB(XFBWrited || g_ActiveConfig.bUseRealXFB);
XFBWrited = false; XFBWrited = false;
} }
+99 -99
View File
@@ -1,99 +1,99 @@
#ifndef _RENDER_H_ #ifndef _RENDER_H_
#define _RENDER_H_ #define _RENDER_H_
#include "VideoCommon.h" #include "VideoCommon.h"
#include "CommonTypes.h" #include "CommonTypes.h"
#include "FramebufferManager.h" #include "FramebufferManager.h"
class RendererBase class RendererBase
{ {
public: public:
RendererBase(); RendererBase();
virtual ~RendererBase() {} virtual ~RendererBase() {}
static void FramebufferSize(int w, int h); static void FramebufferSize(int w, int h);
static void RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc); static void RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
virtual u32 AccessEFB(EFBAccessType type, int x, int y) = 0; virtual u32 AccessEFB(EFBAccessType type, int x, int y) = 0;
static void Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc); static void Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc);
// virtual funcs used in Swap() // virtual funcs used in Swap()
virtual void PrepareXFBCopy(const TargetRectangle &dst_rect) = 0; virtual void PrepareXFBCopy(const TargetRectangle &dst_rect) = 0;
virtual void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc, virtual void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc) = 0; const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc) = 0;
virtual void EndFrame() = 0; virtual void EndFrame() = 0;
virtual void Present() = 0; virtual void Present() = 0;
virtual bool CheckForResize() = 0; virtual bool CheckForResize() = 0;
virtual void GetBackBufferSize(int* w, int* h) = 0; virtual void GetBackBufferSize(int* w, int* h) = 0;
virtual void RecreateFramebufferManger() = 0; virtual void RecreateFramebufferManger() = 0;
virtual void BeginFrame() = 0; virtual void BeginFrame() = 0;
// hmm // hmm
virtual bool SetScissorRect() = 0; virtual bool SetScissorRect() = 0;
static bool SetScissorRect(EFBRectangle &rc); static bool SetScissorRect(EFBRectangle &rc);
static TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc); static TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc);
virtual void UpdateViewport() = 0; virtual void UpdateViewport() = 0;
virtual void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) = 0; virtual void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) = 0;
virtual void ResetAPIState() = 0; virtual void ResetAPIState() = 0;
virtual void RestoreAPIState() = 0; virtual void RestoreAPIState() = 0;
static int GetTargetWidth() { return s_target_width; } static int GetTargetWidth() { return s_target_width; }
static int GetTargetHeight() { return s_target_height; } static int GetTargetHeight() { return s_target_height; }
static int GetFullTargetWidth() { return s_Fulltarget_width; } static int GetFullTargetWidth() { return s_Fulltarget_width; }
static int GetFullTargetHeight() { return s_Fulltarget_height; } static int GetFullTargetHeight() { return s_Fulltarget_height; }
static float GetTargetScaleX() { return EFBxScale; } static float GetTargetScaleX() { return EFBxScale; }
static float GetTargetScaleY() { return EFByScale; } static float GetTargetScaleY() { return EFByScale; }
static int GetFrameBufferWidth() { return s_backbuffer_width; } static int GetFrameBufferWidth() { return s_backbuffer_width; }
static int GetFrameBufferHeight() { return s_backbuffer_height; } static int GetFrameBufferHeight() { return s_backbuffer_height; }
static float GetXFBScaleX() { return xScale; } static float GetXFBScaleX() { return xScale; }
static float GetXFBScaleY() { return yScale; } static float GetXFBScaleY() { return yScale; }
virtual void SetColorMask() {} virtual void SetColorMask() {}
virtual void SetBlendMode(bool forceUpdate) {} virtual void SetBlendMode(bool forceUpdate) {}
virtual void SetSamplerState(int stage, int texindex) {} virtual void SetSamplerState(int stage, int texindex) {}
virtual void SetDitherMode() {} virtual void SetDitherMode() {}
virtual void SetLineWidth() {} virtual void SetLineWidth() {}
virtual void SetInterlacingMode() {} virtual void SetInterlacingMode() {}
virtual void SetGenerationMode() = 0; virtual void SetGenerationMode() = 0;
virtual void SetDepthMode() = 0; virtual void SetDepthMode() = 0;
virtual void SetLogicOpMode() = 0; virtual void SetLogicOpMode() = 0;
protected: protected:
// TODO: are all of these needed? // TODO: are all of these needed?
static int s_target_width; static int s_target_width;
static int s_target_height; static int s_target_height;
static int s_Fulltarget_width; static int s_Fulltarget_width;
static int s_Fulltarget_height; static int s_Fulltarget_height;
static int s_backbuffer_width; static int s_backbuffer_width;
static int s_backbuffer_height; static int s_backbuffer_height;
// //
static int s_fps; static int s_fps;
static u32 s_blendMode; static u32 s_blendMode;
static bool XFBWrited; static bool XFBWrited;
// these go with the settings in the GUI 1x,2x,3x,etc // these go with the settings in the GUI 1x,2x,3x,etc
static float EFBxScale; static float EFBxScale;
static float EFByScale; static float EFByScale;
// these seem be the fractional value // these seem be the fractional value
// TODO: are these ones needed? // TODO: are these ones needed?
static float xScale; static float xScale;
static float yScale; static float yScale;
static int s_XFB_width; static int s_XFB_width;
static int s_XFB_height; static int s_XFB_height;
static volatile u32 s_swapRequested; static volatile u32 s_swapRequested;
}; };
#endif #endif
File diff suppressed because it is too large Load Diff
@@ -1,80 +1,80 @@
#ifndef _TEXTURECACHE_H_ #ifndef _TEXTURECACHE_H_
#define _TEXTURECACHE_H_ #define _TEXTURECACHE_H_
#include <map> #include <map>
#include "CommonTypes.h" #include "CommonTypes.h"
#include "VideoCommon.h" #include "VideoCommon.h"
#include "TextureDecoder.h" #include "TextureDecoder.h"
unsigned int GetPow2(unsigned int val); unsigned int GetPow2(unsigned int val);
class TextureCacheBase class TextureCacheBase
{ {
public: public:
struct TCacheEntryBase struct TCacheEntryBase
{ {
u32 addr; u32 addr;
u32 size_in_bytes; u32 size_in_bytes;
u64 hash; u64 hash;
u32 paletteHash; u32 paletteHash;
u32 oldpixel; u32 oldpixel;
int frameCount; int frameCount;
unsigned int w, h, fmt, MipLevels; unsigned int w, h, fmt, MipLevels;
int Scaledw, Scaledh; int Scaledw, Scaledh;
bool isRenderTarget; bool isRenderTarget;
bool isNonPow2; bool isNonPow2;
TCacheEntryBase() : addr(0), size_in_bytes(0), hash(0), paletteHash(0), oldpixel(0), TCacheEntryBase() : addr(0), size_in_bytes(0), hash(0), paletteHash(0), oldpixel(0),
frameCount(0), w(0), h(0), fmt(0), MipLevels(0), Scaledw(0), Scaledh(0), frameCount(0), w(0), h(0), fmt(0), MipLevels(0), Scaledw(0), Scaledh(0),
isRenderTarget(false), isNonPow2(true) {} isRenderTarget(false), isNonPow2(true) {}
virtual ~TCacheEntryBase(); virtual ~TCacheEntryBase();
virtual void Load(unsigned int width, unsigned int height, virtual void Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int levels) = 0; unsigned int expanded_width, unsigned int levels) = 0;
virtual void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf, virtual void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect) = 0; unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect) = 0;
virtual void Bind(unsigned int stage) = 0; virtual void Bind(unsigned int stage) = 0;
bool IntersectsMemoryRange(u32 range_address, u32 range_size) const; bool IntersectsMemoryRange(u32 range_address, u32 range_size) const;
}; };
friend struct TCacheEntryBase; friend struct TCacheEntryBase;
TextureCacheBase(); TextureCacheBase();
virtual ~TextureCacheBase(); virtual ~TextureCacheBase();
static void Cleanup(); static void Cleanup();
static void Invalidate(bool shutdown); static void Invalidate(bool shutdown);
static void InvalidateRange(u32 start_address, u32 size); static void InvalidateRange(u32 start_address, u32 size);
// TODO: make these 2 static? // TODO: make these 2 static?
TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width, TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width,
unsigned int height, unsigned int tex_format, unsigned int tlutaddr, unsigned int height, unsigned int tex_format, unsigned int tlutaddr,
unsigned int tlutfmt, bool UseNativeMips, unsigned int maxlevel); unsigned int tlutfmt, bool UseNativeMips, unsigned int maxlevel);
void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
u32 copyfmt, bool bScaleByHalf, const EFBRectangle &source_rect); u32 copyfmt, bool bScaleByHalf, const EFBRectangle &source_rect);
virtual TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height, virtual TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt) = 0; unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt) = 0;
virtual TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h) = 0; virtual TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h) = 0;
static void ClearRenderTargets(); static void ClearRenderTargets();
static void MakeRangeDynamic(u32 start_address, u32 size); static void MakeRangeDynamic(u32 start_address, u32 size);
protected: protected:
typedef std::map<u32, TCacheEntryBase*> TexCache; typedef std::map<u32, TCacheEntryBase*> TexCache;
static TexCache textures; static TexCache textures;
static u8 *temp; static u8 *temp;
}; };
#endif #endif
@@ -1,268 +1,268 @@
// VideoCommon // VideoCommon
#include "CommonTypes.h" #include "CommonTypes.h"
#include "OpcodeDecoding.h" #include "OpcodeDecoding.h"
#include "IndexGenerator.h" #include "IndexGenerator.h"
#include "Statistics.h" #include "Statistics.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "PixelShaderManager.h" #include "PixelShaderManager.h"
#include "NativeVertexFormat.h" #include "NativeVertexFormat.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "Profiler.h" #include "Profiler.h"
// //
#include "TextureCache.h" #include "TextureCache.h"
#include "VertexManager.h" #include "VertexManager.h"
#include "Main.h" #include "Main.h"
u16* VertexManagerBase::TIBuffer; u16* VertexManagerBase::TIBuffer;
u16* VertexManagerBase::LIBuffer; u16* VertexManagerBase::LIBuffer;
u16* VertexManagerBase::PIBuffer; u16* VertexManagerBase::PIBuffer;
bool VertexManagerBase::Flushed; bool VertexManagerBase::Flushed;
int VertexManagerBase::lastPrimitive; int VertexManagerBase::lastPrimitive;
u8* VertexManagerBase::LocalVBuffer; u8* VertexManagerBase::LocalVBuffer;
// TODO: put this in .h perhaps // TODO: put this in .h perhaps
extern NativeVertexFormat* g_nativeVertexFmt; extern NativeVertexFormat* g_nativeVertexFmt;
NativeVertexFormat* NativeVertexFormat::Create() NativeVertexFormat* NativeVertexFormat::Create()
{ {
return g_vertex_manager->CreateNativeVertexFormat(); return g_vertex_manager->CreateNativeVertexFormat();
} }
void VertexManagerBase::ResetBuffer() void VertexManagerBase::ResetBuffer()
{ {
s_pCurBufferPointer = LocalVBuffer; s_pCurBufferPointer = LocalVBuffer;
} }
VertexManagerBase::VertexManagerBase() VertexManagerBase::VertexManagerBase()
{ {
LocalVBuffer = new u8[MAXVBUFFERSIZE]; LocalVBuffer = new u8[MAXVBUFFERSIZE];
TIBuffer = new u16[MAXIBUFFERSIZE]; TIBuffer = new u16[MAXIBUFFERSIZE];
LIBuffer = new u16[MAXIBUFFERSIZE]; LIBuffer = new u16[MAXIBUFFERSIZE];
PIBuffer = new u16[MAXIBUFFERSIZE]; PIBuffer = new u16[MAXIBUFFERSIZE];
s_pCurBufferPointer = LocalVBuffer; s_pCurBufferPointer = LocalVBuffer;
s_pBaseBufferPointer = LocalVBuffer; s_pBaseBufferPointer = LocalVBuffer;
Flushed = false; Flushed = false;
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer); IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
} }
VertexManagerBase::~VertexManagerBase() VertexManagerBase::~VertexManagerBase()
{ {
delete[] LocalVBuffer; delete[] LocalVBuffer;
delete[] TIBuffer; delete[] TIBuffer;
delete[] LIBuffer; delete[] LIBuffer;
delete[] PIBuffer; delete[] PIBuffer;
// most likely not needed // most likely not needed
ResetBuffer(); ResetBuffer();
} }
void VertexManagerBase::AddIndices(int _primitive, int _numVertices) void VertexManagerBase::AddIndices(int _primitive, int _numVertices)
{ {
switch (_primitive) switch (_primitive)
{ {
case GX_DRAW_QUADS: case GX_DRAW_QUADS:
IndexGenerator::AddQuads(_numVertices); IndexGenerator::AddQuads(_numVertices);
break; break;
case GX_DRAW_TRIANGLES: case GX_DRAW_TRIANGLES:
IndexGenerator::AddList(_numVertices); IndexGenerator::AddList(_numVertices);
break; break;
case GX_DRAW_TRIANGLE_STRIP: case GX_DRAW_TRIANGLE_STRIP:
IndexGenerator::AddStrip(_numVertices); IndexGenerator::AddStrip(_numVertices);
break; break;
case GX_DRAW_TRIANGLE_FAN: case GX_DRAW_TRIANGLE_FAN:
IndexGenerator::AddFan(_numVertices); IndexGenerator::AddFan(_numVertices);
break; break;
case GX_DRAW_LINE_STRIP: case GX_DRAW_LINE_STRIP:
IndexGenerator::AddLineStrip(_numVertices); IndexGenerator::AddLineStrip(_numVertices);
break; break;
case GX_DRAW_LINES: case GX_DRAW_LINES:
IndexGenerator::AddLineList(_numVertices); IndexGenerator::AddLineList(_numVertices);
break; break;
case GX_DRAW_POINTS: case GX_DRAW_POINTS:
IndexGenerator::AddPoints(_numVertices); IndexGenerator::AddPoints(_numVertices);
break; break;
} }
} }
int VertexManager::GetRemainingSize() int VertexManager::GetRemainingSize()
{ {
return VertexManagerBase::GetRemainingSize(); return VertexManagerBase::GetRemainingSize();
} }
int VertexManagerBase::GetRemainingSize() int VertexManagerBase::GetRemainingSize()
{ {
return MAXVBUFFERSIZE - (int)(s_pCurBufferPointer - LocalVBuffer); return MAXVBUFFERSIZE - (int)(s_pCurBufferPointer - LocalVBuffer);
return 0; return 0;
} }
int VertexManagerBase::GetRemainingVertices(int primitive) int VertexManagerBase::GetRemainingVertices(int primitive)
{ {
switch (primitive) switch (primitive)
{ {
case GX_DRAW_QUADS: case GX_DRAW_QUADS:
case GX_DRAW_TRIANGLES: case GX_DRAW_TRIANGLES:
case GX_DRAW_TRIANGLE_STRIP: case GX_DRAW_TRIANGLE_STRIP:
case GX_DRAW_TRIANGLE_FAN: case GX_DRAW_TRIANGLE_FAN:
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3; return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3;
break; break;
case GX_DRAW_LINE_STRIP: case GX_DRAW_LINE_STRIP:
case GX_DRAW_LINES: case GX_DRAW_LINES:
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2; return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2;
break; break;
case GX_DRAW_POINTS: case GX_DRAW_POINTS:
return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen()); return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen());
break; break;
default: default:
return 0; return 0;
break; break;
} }
} }
void VertexManager::AddVertices(int _primitive, int _numVertices) void VertexManager::AddVertices(int _primitive, int _numVertices)
{ {
VertexManagerBase::AddVertices(_primitive, _numVertices); VertexManagerBase::AddVertices(_primitive, _numVertices);
} }
void VertexManagerBase::AddVertices(int _primitive, int _numVertices) void VertexManagerBase::AddVertices(int _primitive, int _numVertices)
{ {
if (_numVertices <= 0) if (_numVertices <= 0)
return; return;
switch (_primitive) switch (_primitive)
{ {
case GX_DRAW_QUADS: case GX_DRAW_QUADS:
case GX_DRAW_TRIANGLES: case GX_DRAW_TRIANGLES:
case GX_DRAW_TRIANGLE_STRIP: case GX_DRAW_TRIANGLE_STRIP:
case GX_DRAW_TRIANGLE_FAN: case GX_DRAW_TRIANGLE_FAN:
if (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen() < 3 * _numVertices) if (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen() < 3 * _numVertices)
g_vertex_manager->Flush(); g_vertex_manager->Flush();
break; break;
case GX_DRAW_LINE_STRIP: case GX_DRAW_LINE_STRIP:
case GX_DRAW_LINES: case GX_DRAW_LINES:
if (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen() < 2 * _numVertices) if (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen() < 2 * _numVertices)
g_vertex_manager->Flush(); g_vertex_manager->Flush();
break; break;
case GX_DRAW_POINTS: case GX_DRAW_POINTS:
if (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen() < _numVertices) if (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen() < _numVertices)
g_vertex_manager->Flush(); g_vertex_manager->Flush();
break; break;
default: default:
return; return;
break; break;
} }
if (Flushed) if (Flushed)
{ {
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer); IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
Flushed = false; Flushed = false;
} }
lastPrimitive = _primitive; lastPrimitive = _primitive;
ADDSTAT(stats.thisFrame.numPrims, _numVertices); ADDSTAT(stats.thisFrame.numPrims, _numVertices);
INCSTAT(stats.thisFrame.numPrimitiveJoins); INCSTAT(stats.thisFrame.numPrimitiveJoins);
AddIndices(_primitive, _numVertices); AddIndices(_primitive, _numVertices);
} }
void VertexManager::Flush() void VertexManager::Flush()
{ {
VertexManagerBase::Flush(); VertexManagerBase::Flush();
} }
void VertexManagerBase::Flush() void VertexManagerBase::Flush()
{ {
if (LocalVBuffer == s_pCurBufferPointer) if (LocalVBuffer == s_pCurBufferPointer)
return; return;
if (Flushed) if (Flushed)
return; return;
Flushed = true; Flushed = true;
VideoFifo_CheckEFBAccess(); VideoFifo_CheckEFBAccess();
DVSTARTPROFILE(); DVSTARTPROFILE();
u32 usedtextures = 0; u32 usedtextures = 0;
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i)
{ {
if (bpmem.tevorders[i/2].getEnable(i & 1)) if (bpmem.tevorders[i/2].getEnable(i & 1))
usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1); usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1);
} }
if (bpmem.genMode.numindstages > 0) if (bpmem.genMode.numindstages > 0)
for (unsigned int i = 0; i < bpmem.genMode.numtevstages + 1; ++i) for (unsigned int i = 0; i < bpmem.genMode.numtevstages + 1; ++i)
if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages)
usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt); usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt);
for (unsigned int i = 0; i < 8; ++i) for (unsigned int i = 0; i < 8; ++i)
{ {
if (usedtextures & (1 << i)) if (usedtextures & (1 << i))
{ {
g_renderer->SetSamplerState(i & 3, i >> 2); g_renderer->SetSamplerState(i & 3, i >> 2);
FourTexUnits &tex = bpmem.tex[i >> 2]; FourTexUnits &tex = bpmem.tex[i >> 2];
TextureCacheBase::TCacheEntryBase* tentry = g_texture_cache->Load(i, TextureCacheBase::TCacheEntryBase* tentry = g_texture_cache->Load(i,
(tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5, (tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5,
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1, 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.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
tex.texTlut[i&3].tlut_format, 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) && g_ActiveConfig.bUseNativeMips,
(tex.texMode1[i&3].max_lod >> 4)); (tex.texMode1[i&3].max_lod >> 4));
if (tentry) if (tentry)
PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0); PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0);
else else
ERROR_LOG(VIDEO, "error loading texture"); ERROR_LOG(VIDEO, "error loading texture");
} }
} }
VertexShaderManager::SetConstants(); VertexShaderManager::SetConstants();
PixelShaderManager::SetConstants(); PixelShaderManager::SetConstants();
if (false == g_pixel_shader_cache->SetShader(false)) if (false == g_pixel_shader_cache->SetShader(false))
goto shader_fail; goto shader_fail;
if (false == g_vertex_shader_cache->SetShader(g_nativeVertexFmt->m_components)) if (false == g_vertex_shader_cache->SetShader(g_nativeVertexFmt->m_components))
goto shader_fail; goto shader_fail;
const unsigned int stride = g_nativeVertexFmt->GetVertexStride(); const unsigned int stride = g_nativeVertexFmt->GetVertexStride();
g_nativeVertexFmt->SetupVertexPointers(); g_nativeVertexFmt->SetupVertexPointers();
// TODO: // TODO:
g_vertex_manager->Draw(stride, false); g_vertex_manager->Draw(stride, false);
if (false == g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate) if (false == g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate)
{ {
if (false == g_pixel_shader_cache->SetShader(true)) if (false == g_pixel_shader_cache->SetShader(true))
goto shader_fail; goto shader_fail;
// update alpha only // update alpha only
g_vertex_manager->Draw(stride, true); g_vertex_manager->Draw(stride, true);
} }
//IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer); //IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
shader_fail: shader_fail:
ResetBuffer(); ResetBuffer();
} }
@@ -1,47 +1,47 @@
#ifndef _VERTExMANAGER_H_ #ifndef _VERTExMANAGER_H_
#define _VERTExMANAGER_H_ #define _VERTExMANAGER_H_
#include "NativeVertexFormat.h" #include "NativeVertexFormat.h"
#include "NativeVertexWriter.h" #include "NativeVertexWriter.h"
#include "BPMemory.h" #include "BPMemory.h"
enum enum
{ {
MAXVBUFFERSIZE = 0x50000, MAXVBUFFERSIZE = 0x50000,
MAXIBUFFERSIZE = 0x10000, MAXIBUFFERSIZE = 0x10000,
}; };
using VertexManager::s_pBaseBufferPointer; using VertexManager::s_pBaseBufferPointer;
using VertexManager::s_pCurBufferPointer; using VertexManager::s_pCurBufferPointer;
extern NativeVertexFormat *g_nativeVertexFmt; extern NativeVertexFormat *g_nativeVertexFmt;
class VertexManagerBase class VertexManagerBase
{ {
public: public:
VertexManagerBase(); VertexManagerBase();
virtual ~VertexManagerBase(); virtual ~VertexManagerBase();
static void Flush(); static void Flush();
virtual void Draw(u32 stride, bool alphapass) = 0; virtual void Draw(u32 stride, bool alphapass) = 0;
virtual NativeVertexFormat* CreateNativeVertexFormat() = 0; virtual NativeVertexFormat* CreateNativeVertexFormat() = 0;
static void AddIndices(int _primitive, int _numVertices); static void AddIndices(int _primitive, int _numVertices);
static int GetRemainingSize(); static int GetRemainingSize();
static int GetRemainingVertices(int primitive); static int GetRemainingVertices(int primitive);
static void AddVertices(int _primitive, int _numVertices); static void AddVertices(int _primitive, int _numVertices);
static void ResetBuffer(); static void ResetBuffer();
protected: protected:
static u16* TIBuffer; static u16* TIBuffer;
static u16* LIBuffer; static u16* LIBuffer;
static u16* PIBuffer; static u16* PIBuffer;
static bool Flushed; static bool Flushed;
static int lastPrimitive; static int lastPrimitive;
static u8* LocalVBuffer; static u8* LocalVBuffer;
}; };
#endif #endif
@@ -1,25 +1,25 @@
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "Main.h" #include "Main.h"
#include "VertexShaderCache.h" #include "VertexShaderCache.h"
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{ {
g_vertex_shader_cache->SetVSConstant4f(const_number, f1, f2, f3, f4); g_vertex_shader_cache->SetVSConstant4f(const_number, f1, f2, f3, f4);
} }
void SetVSConstant4fv(unsigned int const_number, const float* f) void SetVSConstant4fv(unsigned int const_number, const float* f)
{ {
g_vertex_shader_cache->SetVSConstant4fv(const_number, f); g_vertex_shader_cache->SetVSConstant4fv(const_number, f);
} }
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f) void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f)
{ {
g_vertex_shader_cache->SetMultiVSConstant3fv(const_number, count, f); g_vertex_shader_cache->SetMultiVSConstant3fv(const_number, count, f);
} }
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f) void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f)
{ {
g_vertex_shader_cache->SetMultiVSConstant4fv(const_number, count, f); g_vertex_shader_cache->SetMultiVSConstant4fv(const_number, count, f);
} }
@@ -1,18 +1,18 @@
#ifndef _VERTEXSHADERCACHE_H_ #ifndef _VERTEXSHADERCACHE_H_
#define _VERTEXSHADERCACHE_H_ #define _VERTEXSHADERCACHE_H_
class VertexShaderCacheBase class VertexShaderCacheBase
{ {
public: public:
virtual ~VertexShaderCacheBase() {} virtual ~VertexShaderCacheBase() {}
virtual bool SetShader(u32 components) = 0; virtual bool SetShader(u32 components) = 0;
virtual void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) = 0; virtual void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) = 0;
virtual void SetVSConstant4fv(unsigned int const_number, const float* f) = 0; virtual void SetVSConstant4fv(unsigned int const_number, const float* f) = 0;
virtual void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f) = 0; virtual void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f) = 0;
virtual void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f) = 0; virtual void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f) = 0;
}; };
#endif #endif
@@ -1,245 +1,245 @@
#include "VideoConfigDiag.h" #include "VideoConfigDiag.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "Main.h" #include "Main.h"
#define _connect_macro_(b, f, c, s) (b)->Connect(wxID_ANY, (c), wxCommandEventHandler( f ), (wxObject*)0, (wxEvtHandler*)s) #define _connect_macro_(b, f, c, s) (b)->Connect(wxID_ANY, (c), wxCommandEventHandler( f ), (wxObject*)0, (wxEvtHandler*)s)
// template instantiation // template instantiation
template class BoolSetting<wxCheckBox>; template class BoolSetting<wxCheckBox>;
template class BoolSetting<wxRadioButton>; template class BoolSetting<wxRadioButton>;
typedef BoolSetting<wxCheckBox> SettingCheckBox; typedef BoolSetting<wxCheckBox> SettingCheckBox;
typedef BoolSetting<wxRadioButton> SettingRadioButton; typedef BoolSetting<wxRadioButton> SettingRadioButton;
SettingCheckBox::BoolSetting(wxWindow* parent, const wxString& label, bool &setting, bool reverse, long style) SettingCheckBox::BoolSetting(wxWindow* parent, const wxString& label, bool &setting, bool reverse, long style)
: wxCheckBox(parent, -1, label, wxDefaultPosition, wxDefaultSize, style) : wxCheckBox(parent, -1, label, wxDefaultPosition, wxDefaultSize, style)
, m_setting(setting) , m_setting(setting)
, m_reverse(reverse) , m_reverse(reverse)
{ {
SetValue(m_setting ^ m_reverse); SetValue(m_setting ^ m_reverse);
_connect_macro_(this, BoolSetting<W>::UpdateValue, wxEVT_COMMAND_CHECKBOX_CLICKED, this); _connect_macro_(this, BoolSetting<W>::UpdateValue, wxEVT_COMMAND_CHECKBOX_CLICKED, this);
} }
SettingRadioButton::BoolSetting(wxWindow* parent, const wxString& label, bool &setting, bool reverse, long style) SettingRadioButton::BoolSetting(wxWindow* parent, const wxString& label, bool &setting, bool reverse, long style)
: wxRadioButton(parent, -1, label, wxDefaultPosition, wxDefaultSize, style) : wxRadioButton(parent, -1, label, wxDefaultPosition, wxDefaultSize, style)
, m_setting(setting) , m_setting(setting)
, m_reverse(reverse) , m_reverse(reverse)
{ {
SetValue(m_setting ^ m_reverse); SetValue(m_setting ^ m_reverse);
_connect_macro_(this, BoolSetting<W>::UpdateValue, wxEVT_COMMAND_RADIOBUTTON_SELECTED, this); _connect_macro_(this, BoolSetting<W>::UpdateValue, wxEVT_COMMAND_RADIOBUTTON_SELECTED, this);
} }
template <typename W> template <typename W>
void BoolSetting<W>::UpdateValue(wxCommandEvent& ev) void BoolSetting<W>::UpdateValue(wxCommandEvent& ev)
{ {
m_setting = (ev.GetInt() != 0) ^ m_reverse; m_setting = (ev.GetInt() != 0) ^ m_reverse;
} }
SettingChoice::SettingChoice(wxWindow* parent, int &setting, int num, const wxString choices[]) SettingChoice::SettingChoice(wxWindow* parent, int &setting, int num, const wxString choices[])
: wxChoice(parent, -1, wxDefaultPosition, wxDefaultSize, num, choices) : wxChoice(parent, -1, wxDefaultPosition, wxDefaultSize, num, choices)
, m_setting(setting) , m_setting(setting)
{ {
Select(m_setting); Select(m_setting);
_connect_macro_(this, SettingChoice::UpdateValue, wxEVT_COMMAND_CHOICE_SELECTED, this); _connect_macro_(this, SettingChoice::UpdateValue, wxEVT_COMMAND_CHOICE_SELECTED, this);
} }
void SettingChoice::UpdateValue(wxCommandEvent& ev) void SettingChoice::UpdateValue(wxCommandEvent& ev)
{ {
m_setting = ev.GetInt(); m_setting = ev.GetInt();
} }
void VideoConfigDiag::CloseDiag(wxCommandEvent&) void VideoConfigDiag::CloseDiag(wxCommandEvent&)
{ {
Close(); Close();
} }
VideoConfigDiag::VideoConfigDiag(wxWindow* parent) VideoConfigDiag::VideoConfigDiag(wxWindow* parent)
: wxDialog(parent, -1, wxT("Dolphin Graphics Configuration"), wxDefaultPosition, wxDefaultSize) : wxDialog(parent, -1, wxT("Dolphin Graphics Configuration"), wxDefaultPosition, wxDefaultSize)
{ {
VideoConfig &vconfig = g_Config; VideoConfig &vconfig = g_Config;
wxNotebook* const notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize); wxNotebook* const notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize);
// -- GENERAL -- // -- GENERAL --
{ {
wxPanel* const page_general = new wxPanel(notebook, -1, wxDefaultPosition); wxPanel* const page_general = new wxPanel(notebook, -1, wxDefaultPosition);
notebook->AddPage(page_general, wxT("General")); notebook->AddPage(page_general, wxT("General"));
wxBoxSizer* const szr_general = new wxBoxSizer(wxVERTICAL); wxBoxSizer* const szr_general = new wxBoxSizer(wxVERTICAL);
// - basic // - basic
{ {
wxStaticBoxSizer* const group_basic = new wxStaticBoxSizer(wxVERTICAL, page_general, wxT("Basic")); wxStaticBoxSizer* const group_basic = new wxStaticBoxSizer(wxVERTICAL, page_general, wxT("Basic"));
szr_general->Add(group_basic, 0, wxEXPAND | wxALL, 5); szr_general->Add(group_basic, 0, wxEXPAND | wxALL, 5);
wxFlexGridSizer* const szr_basic = new wxFlexGridSizer(2, 5, 5); wxFlexGridSizer* const szr_basic = new wxFlexGridSizer(2, 5, 5);
group_basic->Add(szr_basic, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); group_basic->Add(szr_basic, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
// graphics api // graphics api
{ {
const wxString gfxapi_choices[] = { wxT("Software [not present]"), const wxString gfxapi_choices[] = { wxT("Software [not present]"),
wxT("OpenGL [broken]"), wxT("Direct3D 9 [broken]"), wxT("Direct3D 11") }; wxT("OpenGL [broken]"), wxT("Direct3D 9 [broken]"), wxT("Direct3D 11") };
szr_basic->Add(new wxStaticText(page_general, -1, wxT("Graphics API:")), 1, wxALIGN_CENTER_VERTICAL, 0); szr_basic->Add(new wxStaticText(page_general, -1, wxT("Graphics API:")), 1, wxALIGN_CENTER_VERTICAL, 0);
wxChoice* const choice_gfxapi = new SettingChoice(page_general, wxChoice* const choice_gfxapi = new SettingChoice(page_general,
g_gfxapi, sizeof(gfxapi_choices)/sizeof(*gfxapi_choices), gfxapi_choices); g_gfxapi, sizeof(gfxapi_choices)/sizeof(*gfxapi_choices), gfxapi_choices);
szr_basic->Add(choice_gfxapi, 1, 0, 0); szr_basic->Add(choice_gfxapi, 1, 0, 0);
} }
// for D3D only // for D3D only
// adapter // adapter
{ {
//szr_basic->Add(new wxStaticText(page_general, -1, wxT("Adapter:")), 1, wxALIGN_CENTER_VERTICAL, 5); //szr_basic->Add(new wxStaticText(page_general, -1, wxT("Adapter:")), 1, wxALIGN_CENTER_VERTICAL, 5);
//wxChoice* const choice_adapter = new SettingChoice(page_general, vconfig.iAdapter); //wxChoice* const choice_adapter = new SettingChoice(page_general, vconfig.iAdapter);
//szr_basic->Add(choice_adapter, 1, 0, 0); //szr_basic->Add(choice_adapter, 1, 0, 0);
} }
// aspect-ratio // aspect-ratio
{ {
const wxString ar_choices[] = { wxT("Auto [recommended]"), const wxString ar_choices[] = { wxT("Auto [recommended]"),
wxT("Force 16:9"), wxT("Force 4:3"), wxT("Strech to Window") }; wxT("Force 16:9"), wxT("Force 4:3"), wxT("Strech to Window") };
szr_basic->Add(new wxStaticText(page_general, -1, wxT("Aspect ratio:")), 1, wxALIGN_CENTER_VERTICAL, 0); szr_basic->Add(new wxStaticText(page_general, -1, wxT("Aspect ratio:")), 1, wxALIGN_CENTER_VERTICAL, 0);
wxChoice* const choice_aspect = new SettingChoice(page_general, wxChoice* const choice_aspect = new SettingChoice(page_general,
vconfig.iAspectRatio, sizeof(ar_choices)/sizeof(*ar_choices), ar_choices); vconfig.iAspectRatio, sizeof(ar_choices)/sizeof(*ar_choices), ar_choices);
szr_basic->Add(choice_aspect, 1, 0, 0); szr_basic->Add(choice_aspect, 1, 0, 0);
} }
// widescreen hack // widescreen hack
{ {
szr_basic->AddStretchSpacer(1); szr_basic->AddStretchSpacer(1);
szr_basic->Add(new SettingCheckBox(page_general, wxT("Widescreen Hack"), vconfig.bWidescreenHack), 1, 0, 0); szr_basic->Add(new SettingCheckBox(page_general, wxT("Widescreen Hack"), vconfig.bWidescreenHack), 1, 0, 0);
szr_basic->AddStretchSpacer(1); szr_basic->AddStretchSpacer(1);
szr_basic->Add(new SettingCheckBox(page_general, wxT("V-Sync"), vconfig.bVSync), 1, 0, 0); szr_basic->Add(new SettingCheckBox(page_general, wxT("V-Sync"), vconfig.bVSync), 1, 0, 0);
} }
// - EFB // - EFB
{ {
wxStaticBoxSizer* const group_efb = new wxStaticBoxSizer(wxVERTICAL, page_general, wxT("EFB")); wxStaticBoxSizer* const group_efb = new wxStaticBoxSizer(wxVERTICAL, page_general, wxT("EFB"));
szr_general->Add(group_efb, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); szr_general->Add(group_efb, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
group_efb->Add(new SettingCheckBox(page_general, wxT("Enable CPU Access"), vconfig.bEFBAccessEnable), 0, wxBOTTOM | wxLEFT, 5); group_efb->Add(new SettingCheckBox(page_general, wxT("Enable CPU Access"), vconfig.bEFBAccessEnable), 0, wxBOTTOM | wxLEFT, 5);
// EFB scale // EFB scale
{ {
// TODO: give this a label // TODO: give this a label
const wxString efbscale_choices[] = { wxT("Fractional"), wxT("Integral [recommended]"), const wxString efbscale_choices[] = { wxT("Fractional"), wxT("Integral [recommended]"),
wxT("1x"), wxT("2x"), wxT("3x")/*, wxT("4x")*/ }; wxT("1x"), wxT("2x"), wxT("3x")/*, wxT("4x")*/ };
wxChoice *const choice_efbscale = new SettingChoice(page_general, wxChoice *const choice_efbscale = new SettingChoice(page_general,
vconfig.iEFBScale, sizeof(efbscale_choices)/sizeof(*efbscale_choices), efbscale_choices); vconfig.iEFBScale, sizeof(efbscale_choices)/sizeof(*efbscale_choices), efbscale_choices);
group_efb->Add(choice_efbscale, 0, wxBOTTOM | wxLEFT, 5); group_efb->Add(choice_efbscale, 0, wxBOTTOM | wxLEFT, 5);
} }
// EFB copy // EFB copy
wxStaticBoxSizer* const group_efbcopy = new wxStaticBoxSizer(wxHORIZONTAL, page_general, wxT("Copy")); wxStaticBoxSizer* const group_efbcopy = new wxStaticBoxSizer(wxHORIZONTAL, page_general, wxT("Copy"));
group_efb->Add(group_efbcopy, 0, wxEXPAND | wxBOTTOM, 5); group_efb->Add(group_efbcopy, 0, wxEXPAND | wxBOTTOM, 5);
group_efbcopy->Add(new SettingCheckBox(page_general, wxT("Enable"), vconfig.bEFBCopyDisable, true), 0, wxLEFT | wxRIGHT | wxBOTTOM, 5); group_efbcopy->Add(new SettingCheckBox(page_general, wxT("Enable"), vconfig.bEFBCopyDisable, true), 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);
group_efbcopy->AddStretchSpacer(1); group_efbcopy->AddStretchSpacer(1);
group_efbcopy->Add(new SettingRadioButton(page_general, wxT("Texture"), vconfig.bCopyEFBToTexture, false, wxRB_GROUP), 0, wxRIGHT, 5); group_efbcopy->Add(new SettingRadioButton(page_general, wxT("Texture"), vconfig.bCopyEFBToTexture, false, wxRB_GROUP), 0, wxRIGHT, 5);
group_efbcopy->Add(new SettingRadioButton(page_general, wxT("RAM"), vconfig.bCopyEFBToTexture, true), 0, wxRIGHT, 5); group_efbcopy->Add(new SettingRadioButton(page_general, wxT("RAM"), vconfig.bCopyEFBToTexture, true), 0, wxRIGHT, 5);
} }
// - safe texture cache // - safe texture cache
{ {
wxStaticBoxSizer* const group_safetex = new wxStaticBoxSizer(wxHORIZONTAL, page_general, wxT("Safe Texture Cache")); wxStaticBoxSizer* const group_safetex = new wxStaticBoxSizer(wxHORIZONTAL, page_general, wxT("Safe Texture Cache"));
szr_general->Add(group_safetex, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); szr_general->Add(group_safetex, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
// safe texture cache // safe texture cache
group_safetex->Add(new SettingCheckBox(page_general, wxT("Enable"), vconfig.bSafeTextureCache), 0, wxLEFT | wxRIGHT | wxBOTTOM, 5); group_safetex->Add(new SettingCheckBox(page_general, wxT("Enable"), vconfig.bSafeTextureCache), 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);
group_safetex->AddStretchSpacer(1); group_safetex->AddStretchSpacer(1);
// TODO: make these radio buttons functional // TODO: make these radio buttons functional
//group_safetex->Add(new wxRadioButton(page_general, -1, wxT("Safe"), //group_safetex->Add(new wxRadioButton(page_general, -1, wxT("Safe"),
// wxDefaultPosition, wxDefaultSize, wxRB_GROUP), 0, wxRIGHT, 5); // wxDefaultPosition, wxDefaultSize, wxRB_GROUP), 0, wxRIGHT, 5);
//group_safetex->Add(new wxRadioButton(page_general, -1, wxT("Normal")), 0, wxRIGHT, 5); //group_safetex->Add(new wxRadioButton(page_general, -1, wxT("Normal")), 0, wxRIGHT, 5);
//group_safetex->Add(new wxRadioButton(page_general, -1, wxT("Fast")), 0, wxRIGHT, 5); //group_safetex->Add(new wxRadioButton(page_general, -1, wxT("Fast")), 0, wxRIGHT, 5);
} }
} }
page_general->SetSizerAndFit(szr_general); page_general->SetSizerAndFit(szr_general);
} }
// -- ADVANCED -- // -- ADVANCED --
{ {
wxPanel* const page_advanced = new wxPanel(notebook, -1, wxDefaultPosition); wxPanel* const page_advanced = new wxPanel(notebook, -1, wxDefaultPosition);
notebook->AddPage(page_advanced, wxT("Advanced")); notebook->AddPage(page_advanced, wxT("Advanced"));
wxBoxSizer* const szr_advanced = new wxBoxSizer(wxVERTICAL); wxBoxSizer* const szr_advanced = new wxBoxSizer(wxVERTICAL);
// - rendering // - rendering
{ {
wxStaticBoxSizer* const group_rendering = new wxStaticBoxSizer(wxVERTICAL, page_advanced, wxT("Rendering")); wxStaticBoxSizer* const group_rendering = new wxStaticBoxSizer(wxVERTICAL, page_advanced, wxT("Rendering"));
szr_advanced->Add(group_rendering, 0, wxEXPAND | wxALL, 5); szr_advanced->Add(group_rendering, 0, wxEXPAND | wxALL, 5);
wxGridSizer* const szr_rendering = new wxGridSizer(2, 5, 5); wxGridSizer* const szr_rendering = new wxGridSizer(2, 5, 5);
group_rendering->Add(szr_rendering, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); group_rendering->Add(szr_rendering, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Enable Wireframe"), vconfig.bWireFrame)); szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Enable Wireframe"), vconfig.bWireFrame));
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Lighting"), vconfig.bDisableLighting)); szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Lighting"), vconfig.bDisableLighting));
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Textures"), vconfig.bDisableTexturing)); szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Textures"), vconfig.bDisableTexturing));
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Fog"), vconfig.bDisableFog)); szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Fog"), vconfig.bDisableFog));
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Dest. Alpha Pass"), vconfig.bDstAlphaPass)); szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Dest. Alpha Pass"), vconfig.bDstAlphaPass));
} }
// - info // - info
{ {
wxStaticBoxSizer* const group_info = new wxStaticBoxSizer(wxVERTICAL, page_advanced, wxT("Overlay Information")); wxStaticBoxSizer* const group_info = new wxStaticBoxSizer(wxVERTICAL, page_advanced, wxT("Overlay Information"));
szr_advanced->Add(group_info, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); szr_advanced->Add(group_info, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
wxGridSizer* const szr_info = new wxGridSizer(2, 5, 5); wxGridSizer* const szr_info = new wxGridSizer(2, 5, 5);
group_info->Add(szr_info, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); group_info->Add(szr_info, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
szr_info->Add(new SettingCheckBox(page_advanced, wxT("Show FPS"), vconfig.bShowFPS)); szr_info->Add(new SettingCheckBox(page_advanced, wxT("Show FPS"), vconfig.bShowFPS));
szr_info->Add(new SettingCheckBox(page_advanced, wxT("Various Statistics"), vconfig.bOverlayStats)); szr_info->Add(new SettingCheckBox(page_advanced, wxT("Various Statistics"), vconfig.bOverlayStats));
szr_info->Add(new SettingCheckBox(page_advanced, wxT("Projection Stats"), vconfig.bOverlayProjStats)); szr_info->Add(new SettingCheckBox(page_advanced, wxT("Projection Stats"), vconfig.bOverlayProjStats));
szr_info->Add(new SettingCheckBox(page_advanced, wxT("Texture Format"), vconfig.bTexFmtOverlayEnable)); szr_info->Add(new SettingCheckBox(page_advanced, wxT("Texture Format"), vconfig.bTexFmtOverlayEnable));
szr_info->Add(new SettingCheckBox(page_advanced, wxT("EFB Copy Regions"), vconfig.bShowEFBCopyRegions)); szr_info->Add(new SettingCheckBox(page_advanced, wxT("EFB Copy Regions"), vconfig.bShowEFBCopyRegions));
} }
// - XFB // - XFB
{ {
wxStaticBoxSizer* const group_xfb = new wxStaticBoxSizer(wxHORIZONTAL, page_advanced, wxT("XFB")); wxStaticBoxSizer* const group_xfb = new wxStaticBoxSizer(wxHORIZONTAL, page_advanced, wxT("XFB"));
szr_advanced->Add(group_xfb, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); szr_advanced->Add(group_xfb, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
group_xfb->Add(new SettingCheckBox(page_advanced, wxT("Enable"), vconfig.bUseXFB), 0, wxLEFT | wxRIGHT | wxBOTTOM, 5); group_xfb->Add(new SettingCheckBox(page_advanced, wxT("Enable"), vconfig.bUseXFB), 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);
group_xfb->AddStretchSpacer(1); group_xfb->AddStretchSpacer(1);
group_xfb->Add(new SettingRadioButton(page_advanced, wxT("Virtual"), vconfig.bUseRealXFB, true, wxRB_GROUP), 0, wxRIGHT, 5); group_xfb->Add(new SettingRadioButton(page_advanced, wxT("Virtual"), vconfig.bUseRealXFB, true, wxRB_GROUP), 0, wxRIGHT, 5);
group_xfb->Add(new SettingRadioButton(page_advanced, wxT("Real"), vconfig.bUseRealXFB), 0, wxRIGHT, 5); group_xfb->Add(new SettingRadioButton(page_advanced, wxT("Real"), vconfig.bUseRealXFB), 0, wxRIGHT, 5);
} }
// - utility // - utility
{ {
wxStaticBoxSizer* const group_utility = new wxStaticBoxSizer(wxVERTICAL, page_advanced, wxT("Utility")); wxStaticBoxSizer* const group_utility = new wxStaticBoxSizer(wxVERTICAL, page_advanced, wxT("Utility"));
szr_advanced->Add(group_utility, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); szr_advanced->Add(group_utility, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
wxGridSizer* const szr_utility = new wxGridSizer(2, 5, 5); wxGridSizer* const szr_utility = new wxGridSizer(2, 5, 5);
group_utility->Add(szr_utility, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); group_utility->Add(szr_utility, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Dump Textures"), vconfig.bDumpTextures)); szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Dump Textures"), vconfig.bDumpTextures));
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Load Hi-Res Textures"), vconfig.bHiresTextures)); szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Load Hi-Res Textures"), vconfig.bHiresTextures));
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Dump EFB Target"), vconfig.bDumpEFBTarget)); szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Dump EFB Target"), vconfig.bDumpEFBTarget));
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Dump Frames"), vconfig.bDumpFrames)); szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Dump Frames"), vconfig.bDumpFrames));
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Free Look"), vconfig.bFreeLook)); szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Free Look"), vconfig.bFreeLook));
} }
// stuff to move/remove // stuff to move/remove
{ {
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Load Native Mipmaps"), vconfig.bUseNativeMips), 0, wxBOTTOM | wxLEFT, 5); szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Load Native Mipmaps"), vconfig.bUseNativeMips), 0, wxBOTTOM | wxLEFT, 5);
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("EFB Scaled Copy"), vconfig.bCopyEFBScaled), 0, wxBOTTOM | wxLEFT, 5); szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("EFB Scaled Copy"), vconfig.bCopyEFBScaled), 0, wxBOTTOM | wxLEFT, 5);
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Auto Scale"), vconfig.bAutoScale), 0, wxBOTTOM | wxLEFT, 5); szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Auto Scale"), vconfig.bAutoScale), 0, wxBOTTOM | wxLEFT, 5);
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Crop"), vconfig.bCrop), 0, wxBOTTOM | wxLEFT, 5); szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Crop"), vconfig.bCrop), 0, wxBOTTOM | wxLEFT, 5);
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Enable OpenCL"), vconfig.bEnableOpenCL), 0, wxBOTTOM | wxLEFT, 5); szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Enable OpenCL"), vconfig.bEnableOpenCL), 0, wxBOTTOM | wxLEFT, 5);
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Enable Display List Caching"), vconfig.bDlistCachingEnable), 0, wxBOTTOM | wxLEFT, 5); szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Enable Display List Caching"), vconfig.bDlistCachingEnable), 0, wxBOTTOM | wxLEFT, 5);
} }
page_advanced->SetSizerAndFit(szr_advanced); page_advanced->SetSizerAndFit(szr_advanced);
} }
wxButton* const btn_close = new wxButton(this, -1, wxT("Close"), wxDefaultPosition); wxButton* const btn_close = new wxButton(this, -1, wxT("Close"), wxDefaultPosition);
_connect_macro_(btn_close, VideoConfigDiag::CloseDiag, wxEVT_COMMAND_BUTTON_CLICKED, this); _connect_macro_(btn_close, VideoConfigDiag::CloseDiag, wxEVT_COMMAND_BUTTON_CLICKED, this);
wxBoxSizer* const szr_main = new wxBoxSizer(wxVERTICAL); wxBoxSizer* const szr_main = new wxBoxSizer(wxVERTICAL);
szr_main->Add(notebook, 1, wxEXPAND | wxALL, 5); szr_main->Add(notebook, 1, wxEXPAND | wxALL, 5);
szr_main->Add(btn_close, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 5); szr_main->Add(btn_close, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 5);
SetSizerAndFit(szr_main); SetSizerAndFit(szr_main);
Center(); Center();
} }
@@ -1,44 +1,44 @@
#ifndef _CONFIG_DIAG_H_ #ifndef _CONFIG_DIAG_H_
#define _CONFIG_DIAG_H_ #define _CONFIG_DIAG_H_
#include <wx/wx.h> #include <wx/wx.h>
#include <wx/textctrl.h> #include <wx/textctrl.h>
#include <wx/button.h> #include <wx/button.h>
#include <wx/stattext.h> #include <wx/stattext.h>
#include <wx/combobox.h> #include <wx/combobox.h>
#include <wx/checkbox.h> #include <wx/checkbox.h>
#include <wx/notebook.h> #include <wx/notebook.h>
#include <wx/panel.h> #include <wx/panel.h>
#include <wx/spinctrl.h> #include <wx/spinctrl.h>
template <typename W> template <typename W>
class BoolSetting : public W class BoolSetting : public W
{ {
public: public:
BoolSetting(wxWindow* parent, const wxString& label, bool &setting, bool reverse = false, long style = 0); BoolSetting(wxWindow* parent, const wxString& label, bool &setting, bool reverse = false, long style = 0);
void UpdateValue(wxCommandEvent& ev); void UpdateValue(wxCommandEvent& ev);
private: private:
bool &m_setting; bool &m_setting;
const bool m_reverse; const bool m_reverse;
}; };
class SettingChoice : public wxChoice class SettingChoice : public wxChoice
{ {
public: public:
SettingChoice(wxWindow* parent, int &setting, int num = 0, const wxString choices[] = NULL); SettingChoice(wxWindow* parent, int &setting, int num = 0, const wxString choices[] = NULL);
void UpdateValue(wxCommandEvent& ev); void UpdateValue(wxCommandEvent& ev);
private: private:
int &m_setting; int &m_setting;
}; };
class VideoConfigDiag : public wxDialog class VideoConfigDiag : public wxDialog
{ {
public: public:
VideoConfigDiag(wxWindow* parent); VideoConfigDiag(wxWindow* parent);
protected: protected:
void CloseDiag(wxCommandEvent&); void CloseDiag(wxCommandEvent&);
}; };
#endif #endif
@@ -13,6 +13,7 @@ files = [
'WiimoteEmu/Attachment/Nunchuk.cpp', 'WiimoteEmu/Attachment/Nunchuk.cpp',
'WiimoteEmu/Attachment/Drums.cpp', 'WiimoteEmu/Attachment/Drums.cpp',
'WiimoteEmu/Attachment/Guitar.cpp', 'WiimoteEmu/Attachment/Guitar.cpp',
'WiimoteEmu/Attachment/Turntable.cpp',
'WiimoteEmu/EmuSubroutines.cpp', 'WiimoteEmu/EmuSubroutines.cpp',
'WiimoteEmu/Encryption.cpp', 'WiimoteEmu/Encryption.cpp',
'WiimoteEmu/Speaker.cpp', 'WiimoteEmu/Speaker.cpp',
@@ -1,122 +1,122 @@
#include "Turntable.h" #include "Turntable.h"
namespace WiimoteEmu namespace WiimoteEmu
{ {
static const u8 turntable_id[] = {0x03, 0x00, 0xa4, 0x20, 0x01, 0x03}; static const u8 turntable_id[] = {0x03, 0x00, 0xa4, 0x20, 0x01, 0x03};
static const u16 turntable_button_bitmasks[] = static const u16 turntable_button_bitmasks[] =
{ {
Turntable::BUTTON_L_GREEN, Turntable::BUTTON_L_GREEN,
Turntable::BUTTON_L_RED, Turntable::BUTTON_L_RED,
Turntable::BUTTON_L_BLUE, Turntable::BUTTON_L_BLUE,
Turntable::BUTTON_R_GREEN, Turntable::BUTTON_R_GREEN,
Turntable::BUTTON_R_RED, Turntable::BUTTON_R_RED,
Turntable::BUTTON_R_BLUE, Turntable::BUTTON_R_BLUE,
Turntable::BUTTON_MINUS, Turntable::BUTTON_MINUS,
Turntable::BUTTON_PLUS, Turntable::BUTTON_PLUS,
Turntable::BUTTON_EUPHORIA, Turntable::BUTTON_EUPHORIA,
}; };
static const char* const turntable_button_names[] = static const char* const turntable_button_names[] =
{ {
"Green Left", "Red Left", "Blue Left", "Green Left", "Red Left", "Blue Left",
"Green Right", "Red Right", "Blue Right", "Green Right", "Red Right", "Blue Right",
"-", "+", "Euphoria", "-", "+", "Euphoria",
}; };
Turntable::Turntable() : Attachment("Turntable") Turntable::Turntable() : Attachment("Turntable")
{ {
// buttons // buttons
// TODO: separate buttons into Left and Right // TODO: separate buttons into Left and Right
groups.push_back(m_buttons = new Buttons("Buttons")); groups.push_back(m_buttons = new Buttons("Buttons"));
for (unsigned int i = 0; i < sizeof(turntable_button_names)/sizeof(*turntable_button_names); ++i) for (unsigned int i = 0; i < sizeof(turntable_button_names)/sizeof(*turntable_button_names); ++i)
m_buttons->controls.push_back(new ControlGroup::Input( turntable_button_names[i])); m_buttons->controls.push_back(new ControlGroup::Input( turntable_button_names[i]));
// stick // stick
groups.push_back(m_stick = new AnalogStick("Stick")); groups.push_back(m_stick = new AnalogStick("Stick"));
// TODO: // TODO:
groups.push_back(m_effect_dial = new Triggers("Effect")); groups.push_back(m_effect_dial = new Triggers("Effect"));
m_effect_dial->controls.push_back(new ControlGroup::Input("Dial")); m_effect_dial->controls.push_back(new ControlGroup::Input("Dial"));
//m_left_turntable //m_left_turntable
//m_right_turntable //m_right_turntable
//m_crossfade_slider //m_crossfade_slider
// set up register // set up register
// id // id
memcpy(&reg[0xfa], turntable_id, sizeof(turntable_id)); memcpy(&reg[0xfa], turntable_id, sizeof(turntable_id));
} }
void Turntable::GetState(u8* const data, const bool focus) void Turntable::GetState(u8* const data, const bool focus)
{ {
wm_turntable_extension* const ttdata = (wm_turntable_extension*)data; wm_turntable_extension* const ttdata = (wm_turntable_extension*)data;
ttdata->bt = 0; ttdata->bt = 0;
// stick // stick
{ {
u8 x, y; u8 x, y;
m_stick->GetState(&x, &y, 0x20, focus ? 0x1F /*0x15*/ : 0); m_stick->GetState(&x, &y, 0x20, focus ? 0x1F /*0x15*/ : 0);
ttdata->sx = x; ttdata->sx = x;
ttdata->sy = y; ttdata->sy = y;
} }
// left table // left table
// TODO: // TODO:
{ {
s8 tt = 0; s8 tt = 0;
//m_left_turntable->GetState(&tt .....); //m_left_turntable->GetState(&tt .....);
ttdata->ltable1 = tt; ttdata->ltable1 = tt;
ttdata->ltable2 = tt << 5; ttdata->ltable2 = tt << 5;
} }
// right table // right table
// TODO: // TODO:
{ {
s8 tt = 0; s8 tt = 0;
//m_right_turntable->GetState(&tt .....); //m_right_turntable->GetState(&tt .....);
ttdata->rtable1 = tt; ttdata->rtable1 = tt;
ttdata->rtable2 = tt << 1; ttdata->rtable2 = tt << 1;
ttdata->rtable3 = tt << 3; ttdata->rtable3 = tt << 3;
ttdata->rtable4 = tt << 5; ttdata->rtable4 = tt << 5;
} }
// effect dial // effect dial
{ {
u8 dial = 0; u8 dial = 0;
m_effect_dial->GetState(&dial, focus ? 0xF : 0); m_effect_dial->GetState(&dial, focus ? 0xF : 0);
ttdata->dial1 = dial; ttdata->dial1 = dial;
ttdata->dial2 = dial << 3; ttdata->dial2 = dial << 3;
} }
// crossfade slider // crossfade slider
// TODO: // TODO:
{ {
u8 cfs = 0; u8 cfs = 0;
//m_crossfade_slider->GetState(&cfs .....); //m_crossfade_slider->GetState(&cfs .....);
ttdata->slider = cfs; ttdata->slider = cfs;
} }
if (focus) if (focus)
{ {
// buttons // buttons
m_buttons->GetState(&ttdata->bt, turntable_button_bitmasks); m_buttons->GetState(&ttdata->bt, turntable_button_bitmasks);
} }
// flip button bits :/ // flip button bits :/
ttdata->bt ^= ( ttdata->bt ^= (
BUTTON_L_GREEN | BUTTON_L_RED | BUTTON_L_BLUE | BUTTON_L_GREEN | BUTTON_L_RED | BUTTON_L_BLUE |
BUTTON_R_GREEN | BUTTON_R_RED | BUTTON_R_BLUE | BUTTON_R_GREEN | BUTTON_R_RED | BUTTON_R_BLUE |
BUTTON_MINUS | BUTTON_PLUS | BUTTON_EUPHORIA BUTTON_MINUS | BUTTON_PLUS | BUTTON_EUPHORIA
); );
} }
} }
@@ -1,42 +1,42 @@
#include "Attachment.h" #include "Attachment.h"
namespace WiimoteEmu namespace WiimoteEmu
{ {
class Turntable : public Attachment class Turntable : public Attachment
{ {
public: public:
Turntable(); Turntable();
void GetState(u8* const data, const bool focus); void GetState(u8* const data, const bool focus);
enum enum
{ {
BUTTON_EUPHORIA = 0x1000, BUTTON_EUPHORIA = 0x1000,
BUTTON_L_GREEN = 0x0800, BUTTON_L_GREEN = 0x0800,
BUTTON_L_RED = 0x20, BUTTON_L_RED = 0x20,
BUTTON_L_BLUE = 0x8000, BUTTON_L_BLUE = 0x8000,
BUTTON_R_GREEN = 0x2000, BUTTON_R_GREEN = 0x2000,
BUTTON_R_RED = 0x02, BUTTON_R_RED = 0x02,
BUTTON_R_BLUE = 0x0400, BUTTON_R_BLUE = 0x0400,
BUTTON_MINUS = 0x10, BUTTON_MINUS = 0x10,
BUTTON_PLUS = 0x04, BUTTON_PLUS = 0x04,
}; };
private: private:
Buttons* m_buttons; Buttons* m_buttons;
MixedTriggers* m_triggers; MixedTriggers* m_triggers;
AnalogStick* m_stick; AnalogStick* m_stick;
Triggers *m_effect_dial; Triggers *m_effect_dial;
// TODO: // TODO:
//m_left_turntable //m_left_turntable
//m_right_turntable //m_right_turntable
//m_crossfade_slider //m_crossfade_slider
}; };
} }
+95 -95
View File
@@ -1,95 +1,95 @@
<?xml version="1.0" encoding="Windows-1252"?> <?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject <VisualStudioProject
ProjectType="Visual C++" ProjectType="Visual C++"
Version="9.00" Version="9.00"
Name="ASM" Name="ASM"
ProjectGUID="{B0723635-279A-44E0-80A6-FC21DBB7A4B4}" ProjectGUID="{B0723635-279A-44E0-80A6-FC21DBB7A4B4}"
RootNamespace="TestSuite" RootNamespace="TestSuite"
Keyword="MakeFileProj" Keyword="MakeFileProj"
TargetFrameworkVersion="196613" TargetFrameworkVersion="196613"
> >
<Platforms> <Platforms>
<Platform <Platform
Name="Win32" Name="Win32"
/> />
</Platforms> </Platforms>
<ToolFiles> <ToolFiles>
</ToolFiles> </ToolFiles>
<Configurations> <Configurations>
<Configuration <Configuration
Name="Release|Win32" Name="Release|Win32"
OutputDirectory="build" OutputDirectory="build"
IntermediateDirectory="build" IntermediateDirectory="build"
ConfigurationType="0" ConfigurationType="0"
BuildLogFile="build\BuildLog.htm" BuildLogFile="build\BuildLog.htm"
> >
<Tool <Tool
Name="VCNMakeTool" Name="VCNMakeTool"
BuildCommandLine="make -r 2&gt;&amp;1 | sed -e &apos;s/\(.[a-zA-Z]\+\):\([0-9]\+\):/\1(\2):/’" BuildCommandLine="make -r 2&gt;&amp;1 | sed -e &apos;s/\(.[a-zA-Z]\+\):\([0-9]\+\):/\1(\2):/’"
ReBuildCommandLine="make clean &amp;&amp; make -r 2&gt;&amp;1 | sed -e &apos;s/\(.[a-zA-Z]\+\):\([0-9]\+\):/\1(\2):/’" ReBuildCommandLine="make clean &amp;&amp; make -r 2&gt;&amp;1 | sed -e &apos;s/\(.[a-zA-Z]\+\):\([0-9]\+\):/\1(\2):/’"
CleanCommandLine="make clean" CleanCommandLine="make clean"
Output="dolphintest_asm.dol" Output="dolphintest_asm.dol"
PreprocessorDefinitions="WIN32;NDEBUG" PreprocessorDefinitions="WIN32;NDEBUG"
IncludeSearchPath="$(ProjectDir)\include;C:\devkitPro\libogc\include" IncludeSearchPath="$(ProjectDir)\include;C:\devkitPro\libogc\include"
ForcedIncludes="" ForcedIncludes=""
AssemblySearchPath="" AssemblySearchPath=""
ForcedUsingAssemblies="" ForcedUsingAssemblies=""
CompileAsManaged="" CompileAsManaged=""
/> />
</Configuration> </Configuration>
</Configurations> </Configurations>
<References> <References>
</References> </References>
<Files> <Files>
<File <File
RelativePath=".\source\asm_float.cpp" RelativePath=".\source\asm_float.cpp"
> >
</File> </File>
<File <File
RelativePath=".\source\asm_integer.cpp" RelativePath=".\source\asm_integer.cpp"
> >
</File> </File>
<File <File
RelativePath=".\source\asm_tables.cpp" RelativePath=".\source\asm_tables.cpp"
> >
</File> </File>
<File <File
RelativePath=".\source\asm_tables.h" RelativePath=".\source\asm_tables.h"
> >
</File> </File>
<File <File
RelativePath=".\source\Defines.h" RelativePath=".\source\Defines.h"
> >
</File> </File>
<File <File
RelativePath=".\source\dolphintest_asm.cpp" RelativePath=".\source\dolphintest_asm.cpp"
> >
</File> </File>
<File <File
RelativePath=".\source\Helpers.cpp" RelativePath=".\source\Helpers.cpp"
> >
</File> </File>
<File <File
RelativePath=".\source\Helpers.h" RelativePath=".\source\Helpers.h"
> >
</File> </File>
<File <File
RelativePath=".\source\Init.cpp" RelativePath=".\source\Init.cpp"
> >
</File> </File>
<File <File
RelativePath=".\source\Init.h" RelativePath=".\source\Init.h"
> >
</File> </File>
<File <File
RelativePath=".\source\Instructions.h" RelativePath=".\source\Instructions.h"
> >
</File> </File>
<File <File
RelativePath=".\Makefile" RelativePath=".\Makefile"
> >
</File> </File>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>
</VisualStudioProject> </VisualStudioProject>