summaryrefslogtreecommitdiff
path: root/Source/Plugins
diff options
context:
space:
mode:
authorskidau <skidau@gmail.com>2013-03-27 13:19:23 +1100
committerskidau <skidau@gmail.com>2013-03-27 13:19:23 +1100
commit7784fa4c67cc8d2545f45694d83805e7e89cd583 (patch)
tree7724133aabe971ec417d1dea0977a525bb8debfb /Source/Plugins
parentd33c19b0cd2bae982c8d35e86a9d3551f9e5c72f (diff)
parent5cea0d9defeaa23e7af94adf7615a44fb2c9c173 (diff)
Merge branch 'master' into wii-network
# By Ryan Houdek (185) and others # Via degasus (12) and others * master: (625 commits) Revert "Don't open/close file for every file operation." as it was crashing PokePark in Windows builds. Array overrun fixed in VertexShaderCache for the DX11 plugin. Fixed DSPTool build. Windows build fix Go back to assuming every HID device is a wiimote on Windows. Fixed issue 6117. Unfixed issue 6031. VideoSoftware: Improve fog range adjustment by using less magic and more comments. revert RasterFont for VideoSoftware ogl: fix virtual xfb Windows build fix from web interface... Adjusted the audio loop criteria, using >= on the Wii and == on GC. This fixes the audio static that occurred in Wii games after hours of play. Forced the exception check only for ARAM DMA transfers. Removed the Eternal Darkness boot hack and replaced it with an exception check. VideoSoftware: Implement fog range adjustment, fixing issue 6147. implement 4xSSAA for OGL move ogl-only settings into backend Fix description of disable fog, and move it to enhancements tab. Reverted rd76ca5783743 as it was made obsolete by r1d550f4496e4. Removed the tracking of the FIFO Writes as it was made obsolete by r1d550f4496e4. Forced the external exception check to occur sooner by changing the downcount. Mark the Direct3D9 backend deprecated. Prefer D3D11 and OpenGL over D3D9 by default. ... Conflicts: CMakeLists.txt Source/Core/Common/Common.vcxproj.filters Source/Core/Common/Src/CommonPaths.h Source/Core/Core/Core.vcxproj.filters Source/Core/Core/Src/Core.cpp Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp Source/VSProps/Dolphin.Win32.props Source/VSProps/Dolphin.x64.props
Diffstat (limited to 'Source/Plugins')
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj2
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters6
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp2
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp9
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp4
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp150
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h46
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/Render.cpp26
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp122
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h24
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp2
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/VideoBackend.h1
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/main.cpp13
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp228
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h11
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp6
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp30
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp4
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp2
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/Render.cpp41
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp4
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp257
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/VertexManager.h25
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/VideoBackend.h2
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/main.cpp14
-rw-r--r--Source/Plugins/Plugin_VideoOGL/CMakeLists.txt10
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj34
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters17
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp199
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.h6
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp44
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h24
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp242
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp133
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h46
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp358
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h91
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp167
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.h8
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp553
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h137
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp235
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/RasterFont.h25
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/Render.cpp756
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/Render.h19
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.cpp129
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.h80
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp242
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.h72
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp308
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h8
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp305
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h2
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp208
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h25
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp268
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h76
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/VideoBackend.h1
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/main.cpp79
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt1
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj2
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj.filters2
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp15
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp7
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h3
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp16
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h1
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h13
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp21
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h3
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.cpp223
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.h42
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp35
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h9
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp15
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp6
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h77
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp11
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp13
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h3
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp44
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp47
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp30
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h2
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp62
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Tev.h3
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp6
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h7
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h3
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp6
-rw-r--r--Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h11
91 files changed, 4384 insertions, 2293 deletions
diff --git a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj
index 52d1c37aed..aab9345ef7 100644
--- a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj
+++ b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj
@@ -199,6 +199,7 @@
<ClCompile Include="Src\LineGeometryShader.cpp" />
<ClCompile Include="Src\main.cpp" />
<ClCompile Include="Src\NativeVertexFormat.cpp" />
+ <ClCompile Include="Src\PerfQuery.cpp" />
<ClCompile Include="Src\PixelShaderCache.cpp" />
<ClCompile Include="Src\PointGeometryShader.cpp" />
<ClCompile Include="Src\PSTextureEncoder.cpp" />
@@ -228,6 +229,7 @@
<ClInclude Include="Src\Globals.h" />
<ClInclude Include="Src\LineGeometryShader.h" />
<ClInclude Include="Src\main.h" />
+ <ClInclude Include="Src\PerfQuery.h" />
<ClInclude Include="Src\PixelShaderCache.h" />
<ClInclude Include="Src\PointGeometryShader.h" />
<ClInclude Include="Src\PSTextureEncoder.h" />
diff --git a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters
index 6492e887ca..4b8efac92b 100644
--- a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters
+++ b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters
@@ -57,6 +57,9 @@
<ClCompile Include="Src\PointGeometryShader.cpp">
<Filter>Render</Filter>
</ClCompile>
+ <ClCompile Include="Src\PerfQuery.cpp">
+ <Filter>Render</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Src\Globals.h" />
@@ -117,6 +120,9 @@
<ClInclude Include="Src\PointGeometryShader.h">
<Filter>Render</Filter>
</ClInclude>
+ <ClInclude Include="Src\PerfQuery.h">
+ <Filter>Render</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="D3D">
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp
index 1dcc6dd193..873f3a47fd 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp
@@ -520,7 +520,7 @@ void EndFrame()
void Present()
{
// TODO: Is 1 the correct value for vsyncing?
- swapchain->Present((UINT)g_ActiveConfig.bVSync, 0);
+ swapchain->Present((UINT)g_ActiveConfig.IsVSync(), 0);
}
} // namespace D3D
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp
index 41e5423990..c688228945 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp
@@ -64,7 +64,8 @@ bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob)
static int num_failures = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
file << code;
file.close();
@@ -121,7 +122,8 @@ bool CompileGeometryShader(const char* code, unsigned int len, D3DBlob** blob,
static int num_failures = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sbad_gs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
file << code;
file.close();
@@ -180,7 +182,8 @@ bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob,
static int num_failures = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
file << code;
file.close();
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp
index cb94884eb7..199f063d40 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp
@@ -208,6 +208,8 @@ void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
void XFBSource::CopyEFB(float Gamma)
{
+ g_renderer->ResetAPIState(); // reset any game specific settings
+
// Copy EFB data to XFB and restore render target again
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)texWidth, (float)texHeight);
@@ -222,6 +224,8 @@ void XFBSource::CopyEFB(float Gamma)
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(),
FramebufferManager::GetEFBDepthTexture()->GetDSV());
+
+ g_renderer->RestoreAPIState();
}
} // namespace DX11 \ No newline at end of file
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp
new file mode 100644
index 0000000000..b859d50ec6
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp
@@ -0,0 +1,150 @@
+#include "RenderBase.h"
+
+#include "D3DBase.h"
+#include "PerfQuery.h"
+
+namespace DX11 {
+
+PerfQuery::PerfQuery()
+ : m_query_read_pos()
+ , m_query_count()
+{
+ for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i)
+ {
+ D3D11_QUERY_DESC qdesc = CD3D11_QUERY_DESC(D3D11_QUERY_OCCLUSION, 0);
+ D3D::device->CreateQuery(&qdesc, &m_query_buffer[i].query);
+ }
+ ResetQuery();
+}
+
+PerfQuery::~PerfQuery()
+{
+ for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i)
+ {
+ // TODO: EndQuery?
+ m_query_buffer[i].query->Release();
+ }
+}
+
+void PerfQuery::EnableQuery(PerfQueryGroup type)
+{
+ // Is this sane?
+ if (m_query_count > ARRAYSIZE(m_query_buffer) / 2)
+ WeakFlush();
+
+ if (ARRAYSIZE(m_query_buffer) == m_query_count)
+ {
+ // TODO
+ FlushOne();
+ ERROR_LOG(VIDEO, "flushed query buffer early!");
+ }
+
+ // start query
+ if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
+ {
+ auto& entry = m_query_buffer[(m_query_read_pos + m_query_count) % ARRAYSIZE(m_query_buffer)];
+
+ D3D::context->Begin(entry.query);
+ entry.query_type = type;
+
+ ++m_query_count;
+ }
+}
+
+void PerfQuery::DisableQuery(PerfQueryGroup type)
+{
+ // stop query
+ if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
+ {
+ auto& entry = m_query_buffer[(m_query_read_pos + m_query_count + ARRAYSIZE(m_query_buffer)-1) % ARRAYSIZE(m_query_buffer)];
+ D3D::context->End(entry.query);
+ }
+}
+
+void PerfQuery::ResetQuery()
+{
+ m_query_count = 0;
+ std::fill_n(m_results, ARRAYSIZE(m_results), 0);
+}
+
+u32 PerfQuery::GetQueryResult(PerfQueryType type)
+{
+ u32 result = 0;
+
+ if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC)
+ {
+ result = m_results[PQG_ZCOMP_ZCOMPLOC];
+ }
+ else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT)
+ {
+ result = m_results[PQG_ZCOMP];
+ }
+ else if (type == PQ_BLEND_INPUT)
+ {
+ result = m_results[PQG_ZCOMP] + m_results[PQG_ZCOMP_ZCOMPLOC];
+ }
+ else if (type == PQ_EFB_COPY_CLOCKS)
+ {
+ result = m_results[PQG_EFB_COPY_CLOCKS];
+ }
+
+ return result / 4;
+}
+
+void PerfQuery::FlushOne()
+{
+ auto& entry = m_query_buffer[m_query_read_pos];
+
+ UINT64 result = 0;
+ HRESULT hr = S_FALSE;
+ while (hr != S_OK)
+ {
+ // TODO: Might cause us to be stuck in an infinite loop!
+ hr = D3D::context->GetData(entry.query, &result, sizeof(result), 0);
+ }
+
+ // NOTE: Reported pixel metrics should be referenced to native resolution
+ m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight();
+
+ m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer);
+ --m_query_count;
+}
+
+// TODO: could selectively flush things, but I don't think that will do much
+void PerfQuery::FlushResults()
+{
+ while (!IsFlushed())
+ FlushOne();
+}
+
+void PerfQuery::WeakFlush()
+{
+ while (!IsFlushed())
+ {
+ auto& entry = m_query_buffer[m_query_read_pos];
+
+ UINT64 result = 0;
+ HRESULT hr = D3D::context->GetData(entry.query, &result, sizeof(result), D3D11_ASYNC_GETDATA_DONOTFLUSH);
+
+ if (hr == S_OK)
+ {
+ // NOTE: Reported pixel metrics should be referenced to native resolution
+ m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight();
+
+ m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer);
+ --m_query_count;
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+bool PerfQuery::IsFlushed() const
+{
+ return 0 == m_query_count;
+}
+
+
+} // namespace
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h
new file mode 100644
index 0000000000..b3709d1013
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h
@@ -0,0 +1,46 @@
+#ifndef _PERFQUERY_H_
+#define _PERFQUERY_H_
+
+#include "PerfQueryBase.h"
+
+namespace DX11 {
+
+class PerfQuery : public PerfQueryBase
+{
+public:
+ PerfQuery();
+ ~PerfQuery();
+
+ void EnableQuery(PerfQueryGroup type);
+ void DisableQuery(PerfQueryGroup type);
+ void ResetQuery();
+ u32 GetQueryResult(PerfQueryType type);
+ void FlushResults();
+ bool IsFlushed() const;
+
+private:
+ struct ActiveQuery
+ {
+ ID3D11Query* query;
+ PerfQueryGroup query_type;
+ };
+
+ void WeakFlush();
+
+ // Only use when non-empty
+ void FlushOne();
+
+ // when testing in SMS: 64 was too small, 128 was ok
+ static const int PERF_QUERY_BUFFER_SIZE = 512;
+
+ ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE];
+ int m_query_read_pos;
+
+ // TODO: sloppy
+ volatile int m_query_count;
+ volatile u32 m_results[PQG_NUM_MEMBERS];
+};
+
+} // namespace
+
+#endif // _PERFQUERY_H_
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp
index a6cb52c40f..2dcfcd041c 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp
@@ -65,6 +65,7 @@ ID3D11RasterizerState* resetraststate = NULL;
static ID3D11Texture2D* s_screenshot_texture = NULL;
+
// GX pipeline state
struct
{
@@ -761,11 +762,11 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle
return SUCCEEDED(hr);
}
-void formatBufferDump(const char *in, char *out, int w, int h, int p)
+void formatBufferDump(const u8* in, u8* out, int w, int h, int p)
{
for (int y = 0; y < h; ++y)
{
- const u8 *line = (u8*)(in + (h - y - 1) * p);
+ auto line = (in + (h - y - 1) * p);
for (int x = 0; x < w; ++x)
{
out[0] = line[2];
@@ -782,8 +783,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
{
if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
{
- if (g_ActiveConfig.bDumpFrames && frame_data)
- AVIDump::AddFrame(frame_data);
+ if (g_ActiveConfig.bDumpFrames && !frame_data.empty())
+ AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight);
Core::Callback_VideoCopiedToXFB(false);
return;
@@ -794,8 +795,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
{
- if (g_ActiveConfig.bDumpFrames && frame_data)
- AVIDump::AddFrame(frame_data);
+ if (g_ActiveConfig.bDumpFrames && !frame_data.empty())
+ AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight);
Core::Callback_VideoCopiedToXFB(false);
return;
@@ -934,16 +935,15 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map);
- if (!frame_data || w != s_recordWidth || h != s_recordHeight)
+ if (frame_data.empty() || w != s_recordWidth || h != s_recordHeight)
{
- delete[] frame_data;
- frame_data = new char[3 * s_recordWidth * s_recordHeight];
+ frame_data.resize(3 * s_recordWidth * s_recordHeight);
w = s_recordWidth;
h = s_recordHeight;
}
- char* source_ptr = (char*)map.pData + GetTargetRectangle().left*4 + GetTargetRectangle().top*map.RowPitch;
- formatBufferDump(source_ptr, frame_data, s_recordWidth, s_recordHeight, map.RowPitch);
- AVIDump::AddFrame(frame_data);
+ auto source_ptr = (const u8*)map.pData + GetTargetRectangle().left*4 + GetTargetRectangle().top*map.RowPitch;
+ formatBufferDump(source_ptr, &frame_data[0], s_recordWidth, s_recordHeight, map.RowPitch);
+ AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight);
D3D::context->Unmap(s_screenshot_texture, 0);
}
bLastFrameDumped = true;
@@ -952,7 +952,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
{
if (bLastFrameDumped && bAVIDumping)
{
- SAFE_DELETE_ARRAY(frame_data);
+ std::vector<u8>().swap(frame_data);
w = h = 0;
AVIDump::Stop();
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp
index ab8ed68654..da8c98e19e 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp
@@ -39,41 +39,41 @@ namespace DX11
{
// TODO: Find sensible values for these two
-const UINT IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * 16 * sizeof(u16);
-const UINT VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE * 16;
-const UINT MAXVBUFFER_COUNT = 2;
+const UINT IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * sizeof(u16) * 8;
+const UINT VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE;
+const UINT MAX_VBUFFER_COUNT = 2;
void VertexManager::CreateDeviceObjects()
{
D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(IBUFFER_SIZE,
D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
- m_vertexDrawOffset = 0;
- m_triangleDrawIndex = 0;
- m_lineDrawIndex = 0;
- m_pointDrawIndex = 0;
- m_indexBuffers = new PID3D11Buffer[MAXVBUFFER_COUNT];
- m_vertexBuffers = new PID3D11Buffer[MAXVBUFFER_COUNT];
- for (m_activeIndexBuffer = 0; m_activeIndexBuffer < MAXVBUFFER_COUNT; m_activeIndexBuffer++)
+ m_vertex_draw_offset = 0;
+ m_triangle_draw_index = 0;
+ m_line_draw_index = 0;
+ m_point_draw_index = 0;
+ m_index_buffers = new PID3D11Buffer[MAX_VBUFFER_COUNT];
+ m_vertex_buffers = new PID3D11Buffer[MAX_VBUFFER_COUNT];
+ for (m_current_index_buffer = 0; m_current_index_buffer < MAX_VBUFFER_COUNT; m_current_index_buffer++)
{
- m_indexBuffers[m_activeIndexBuffer] = NULL;
- CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_indexBuffers[m_activeIndexBuffer])),
+ m_index_buffers[m_current_index_buffer] = NULL;
+ CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_index_buffers[m_current_index_buffer])),
"Failed to create index buffer.");
- D3D::SetDebugObjectName((ID3D11DeviceChild*)m_indexBuffers[m_activeIndexBuffer], "index buffer of VertexManager");
+ D3D::SetDebugObjectName((ID3D11DeviceChild*)m_index_buffers[m_current_index_buffer], "index buffer of VertexManager");
}
bufdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufdesc.ByteWidth = VBUFFER_SIZE;
- for (m_activeVertexBuffer = 0; m_activeVertexBuffer < MAXVBUFFER_COUNT; m_activeVertexBuffer++)
+ for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
{
- m_vertexBuffers[m_activeVertexBuffer] = NULL;
- CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_vertexBuffers[m_activeVertexBuffer])),
+ m_vertex_buffers[m_current_vertex_buffer] = NULL;
+ CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_vertex_buffers[m_current_vertex_buffer])),
"Failed to create vertex buffer.");
- D3D::SetDebugObjectName((ID3D11DeviceChild*)m_vertexBuffers[m_activeVertexBuffer], "Vertex buffer of VertexManager");
+ D3D::SetDebugObjectName((ID3D11DeviceChild*)m_vertex_buffers[m_current_vertex_buffer], "Vertex buffer of VertexManager");
}
- m_activeVertexBuffer = 0;
- m_activeIndexBuffer = 0;
- m_indexBufferCursor = IBUFFER_SIZE;
- m_vertexBufferCursor = VBUFFER_SIZE;
+ m_current_vertex_buffer = 0;
+ m_current_index_buffer = 0;
+ m_index_buffer_cursor = IBUFFER_SIZE;
+ m_vertex_buffer_cursor = VBUFFER_SIZE;
m_lineShader.Init();
m_pointShader.Init();
}
@@ -82,10 +82,10 @@ void VertexManager::DestroyDeviceObjects()
{
m_pointShader.Shutdown();
m_lineShader.Shutdown();
- for (m_activeVertexBuffer = 0; m_activeVertexBuffer < MAXVBUFFER_COUNT; m_activeVertexBuffer++)
+ for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
{
- SAFE_RELEASE(m_vertexBuffers[m_activeVertexBuffer]);
- SAFE_RELEASE(m_indexBuffers[m_activeVertexBuffer]);
+ SAFE_RELEASE(m_vertex_buffers[m_current_vertex_buffer]);
+ SAFE_RELEASE(m_index_buffers[m_current_vertex_buffer]);
}
}
@@ -100,47 +100,47 @@ VertexManager::~VertexManager()
DestroyDeviceObjects();
}
-void VertexManager::LoadBuffers()
+void VertexManager::PrepareDrawBuffers()
{
D3D11_MAPPED_SUBRESOURCE map;
- UINT vSize = UINT(s_pCurBufferPointer - LocalVBuffer);
+ UINT vSize = UINT(s_pCurBufferPointer - s_pBaseBufferPointer);
D3D11_MAP MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
- if (m_vertexBufferCursor + vSize >= VBUFFER_SIZE)
+ if (m_vertex_buffer_cursor + vSize >= VBUFFER_SIZE)
{
// Wrap around
- m_activeVertexBuffer = (m_activeVertexBuffer + 1) % MAXVBUFFER_COUNT;
- m_vertexBufferCursor = 0;
+ m_current_vertex_buffer = (m_current_vertex_buffer + 1) % MAX_VBUFFER_COUNT;
+ m_vertex_buffer_cursor = 0;
MapType = D3D11_MAP_WRITE_DISCARD;
}
- D3D::context->Map(m_vertexBuffers[m_activeVertexBuffer], 0, MapType, 0, &map);
+ D3D::context->Map(m_vertex_buffers[m_current_vertex_buffer], 0, MapType, 0, &map);
- memcpy((u8*)map.pData + m_vertexBufferCursor, LocalVBuffer, vSize);
- D3D::context->Unmap(m_vertexBuffers[m_activeVertexBuffer], 0);
- m_vertexDrawOffset = m_vertexBufferCursor;
- m_vertexBufferCursor += vSize;
+ memcpy((u8*)map.pData + m_vertex_buffer_cursor, s_pBaseBufferPointer, vSize);
+ D3D::context->Unmap(m_vertex_buffers[m_current_vertex_buffer], 0);
+ m_vertex_draw_offset = m_vertex_buffer_cursor;
+ m_vertex_buffer_cursor += vSize;
UINT iCount = IndexGenerator::GetTriangleindexLen() +
IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen();
MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
- if (m_indexBufferCursor + iCount >= (IBUFFER_SIZE / sizeof(u16)))
+ if (m_index_buffer_cursor + iCount >= (IBUFFER_SIZE / sizeof(u16)))
{
// Wrap around
- m_activeIndexBuffer = (m_activeIndexBuffer + 1) % MAXVBUFFER_COUNT;
- m_indexBufferCursor = 0;
+ m_current_index_buffer = (m_current_index_buffer + 1) % MAX_VBUFFER_COUNT;
+ m_index_buffer_cursor = 0;
MapType = D3D11_MAP_WRITE_DISCARD;
}
- D3D::context->Map(m_indexBuffers[m_activeIndexBuffer], 0, MapType, 0, &map);
-
- m_triangleDrawIndex = m_indexBufferCursor;
- m_lineDrawIndex = m_triangleDrawIndex + IndexGenerator::GetTriangleindexLen();
- m_pointDrawIndex = m_lineDrawIndex + IndexGenerator::GetLineindexLen();
- memcpy((u16*)map.pData + m_triangleDrawIndex, TIBuffer, sizeof(u16) * IndexGenerator::GetTriangleindexLen());
- memcpy((u16*)map.pData + m_lineDrawIndex, LIBuffer, sizeof(u16) * IndexGenerator::GetLineindexLen());
- memcpy((u16*)map.pData + m_pointDrawIndex, PIBuffer, sizeof(u16) * IndexGenerator::GetPointindexLen());
- D3D::context->Unmap(m_indexBuffers[m_activeIndexBuffer], 0);
- m_indexBufferCursor += iCount;
+ D3D::context->Map(m_index_buffers[m_current_index_buffer], 0, MapType, 0, &map);
+
+ m_triangle_draw_index = m_index_buffer_cursor;
+ m_line_draw_index = m_triangle_draw_index + IndexGenerator::GetTriangleindexLen();
+ m_point_draw_index = m_line_draw_index + IndexGenerator::GetLineindexLen();
+ memcpy((u16*)map.pData + m_triangle_draw_index, GetTriangleIndexBuffer(), sizeof(u16) * IndexGenerator::GetTriangleindexLen());
+ memcpy((u16*)map.pData + m_line_draw_index, GetLineIndexBuffer(), sizeof(u16) * IndexGenerator::GetLineindexLen());
+ memcpy((u16*)map.pData + m_point_draw_index, GetPointIndexBuffer(), sizeof(u16) * IndexGenerator::GetPointindexLen());
+ D3D::context->Unmap(m_index_buffers[m_current_index_buffer], 0);
+ m_index_buffer_cursor += iCount;
}
static const float LINE_PT_TEX_OFFSETS[8] = {
@@ -149,13 +149,13 @@ static const float LINE_PT_TEX_OFFSETS[8] = {
void VertexManager::Draw(UINT stride)
{
- D3D::context->IASetVertexBuffers(0, 1, &m_vertexBuffers[m_activeVertexBuffer], &stride, &m_vertexDrawOffset);
- D3D::context->IASetIndexBuffer(m_indexBuffers[m_activeIndexBuffer], DXGI_FORMAT_R16_UINT, 0);
+ D3D::context->IASetVertexBuffers(0, 1, &m_vertex_buffers[m_current_vertex_buffer], &stride, &m_vertex_draw_offset);
+ D3D::context->IASetIndexBuffer(m_index_buffers[m_current_index_buffer], DXGI_FORMAT_R16_UINT, 0);
if (IndexGenerator::GetNumTriangles() > 0)
{
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
- D3D::context->DrawIndexed(IndexGenerator::GetTriangleindexLen(), m_triangleDrawIndex, 0);
+ D3D::context->DrawIndexed(IndexGenerator::GetTriangleindexLen(), m_triangle_draw_index, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
// Disable culling for lines and points
@@ -177,7 +177,7 @@ void VertexManager::Draw(UINT stride)
texOffset, vpWidth, vpHeight, texOffsetEnable))
{
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
- D3D::context->DrawIndexed(IndexGenerator::GetLineindexLen(), m_lineDrawIndex, 0);
+ D3D::context->DrawIndexed(IndexGenerator::GetLineindexLen(), m_line_draw_index, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
D3D::context->GSSetShader(NULL, NULL, 0);
@@ -199,7 +199,7 @@ void VertexManager::Draw(UINT stride)
texOffset, vpWidth, vpHeight, texOffsetEnable))
{
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
- D3D::context->DrawIndexed(IndexGenerator::GetPointindexLen(), m_pointDrawIndex, 0);
+ D3D::context->DrawIndexed(IndexGenerator::GetPointindexLen(), m_point_draw_index, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
D3D::context->GSSetShader(NULL, NULL, 0);
@@ -211,11 +211,6 @@ void VertexManager::Draw(UINT stride)
void VertexManager::vFlush()
{
- if (LocalVBuffer == s_pCurBufferPointer) return;
- if (Flushed) return;
- Flushed=true;
- VideoFifo_CheckEFBAccess();
-
u32 usedtextures = 0;
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i)
if (bpmem.tevorders[i / 2].getEnable(i & 1))
@@ -263,26 +258,25 @@ void VertexManager::vFlush()
g_nativeVertexFmt->m_components))
{
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
- goto shader_fail;
+ return;
}
if (!VertexShaderCache::SetShader(g_nativeVertexFmt->m_components))
{
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
- goto shader_fail;
+ return;
}
- LoadBuffers();
+ PrepareDrawBuffers();
unsigned int stride = g_nativeVertexFmt->GetVertexStride();
g_nativeVertexFmt->SetupVertexPointers();
g_renderer->ApplyState(useDstAlpha);
-
+
+ g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
Draw(stride);
+ g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
g_renderer->RestoreState();
-
-shader_fail:
- ResetBuffer();
}
} // namespace
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h
index 9e6b7f2dca..b5d0d21757 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h
+++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h
@@ -37,22 +37,22 @@ public:
private:
- void LoadBuffers();
- void Draw(UINT stride);
+ void PrepareDrawBuffers();
+ void Draw(u32 stride);
// temp
void vFlush();
- UINT m_indexBufferCursor;
- UINT m_vertexBufferCursor;
- UINT m_vertexDrawOffset;
- UINT m_triangleDrawIndex;
- UINT m_lineDrawIndex;
- UINT m_pointDrawIndex;
- UINT m_activeVertexBuffer;
- UINT m_activeIndexBuffer;
+ u32 m_vertex_buffer_cursor;
+ u32 m_vertex_draw_offset;
+ u32 m_index_buffer_cursor;
+ u32 m_current_vertex_buffer;
+ u32 m_current_index_buffer;
+ u32 m_triangle_draw_index;
+ u32 m_line_draw_index;
+ u32 m_point_draw_index;
typedef ID3D11Buffer* PID3D11Buffer;
- PID3D11Buffer* m_indexBuffers;
- PID3D11Buffer* m_vertexBuffers;
+ PID3D11Buffer* m_index_buffers;
+ PID3D11Buffer* m_vertex_buffers;
LineGeometryShader m_lineShader;
PointGeometryShader m_pointShader;
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp
index d727ce1ebf..6fdc815554 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp
@@ -162,7 +162,7 @@ void VertexShaderCache::Init()
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 < 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;
+ vs_constant_offset_table[C_DEPTHPARAMS] = 952;
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str());
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VideoBackend.h b/Source/Plugins/Plugin_VideoDX11/Src/VideoBackend.h
index 4c6de67ab1..a76935da72 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/VideoBackend.h
+++ b/Source/Plugins/Plugin_VideoDX11/Src/VideoBackend.h
@@ -15,6 +15,7 @@ class VideoBackend : public VideoBackendHardware
std::string GetName();
void Video_Prepare();
+ void Video_Cleanup();
void ShowConfig(void* parent);
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp
index b7dd9101d3..17bbdcf33c 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp
@@ -42,6 +42,7 @@
#include "D3DUtil.h"
#include "D3DBase.h"
+#include "PerfQuery.h"
#include "PixelShaderCache.h"
#include "TextureCache.h"
#include "VertexManager.h"
@@ -102,15 +103,13 @@ void InitBackendInfo()
if (FAILED(hr))
PanicAlert("Failed to create IDXGIFactory object");
- char tmpstr[512] = {};
- DXGI_ADAPTER_DESC desc;
// adapters
g_Config.backend_info.Adapters.clear();
g_Config.backend_info.AAModes.clear();
while (factory->EnumAdapters((UINT)g_Config.backend_info.Adapters.size(), &ad) != DXGI_ERROR_NOT_FOUND)
{
+ DXGI_ADAPTER_DESC desc;
ad->GetDesc(&desc);
- WideCharToMultiByte(/*CP_UTF8*/CP_ACP, 0, desc.Description, -1, tmpstr, 512, 0, false);
// TODO: These don't get updated on adapter change, yet
if (g_Config.backend_info.Adapters.size() == g_Config.iAdapter)
@@ -127,7 +126,7 @@ void InitBackendInfo()
}
}
- g_Config.backend_info.Adapters.push_back(tmpstr);
+ g_Config.backend_info.Adapters.push_back(UTF16ToUTF8(desc.Description));
ad->Release();
}
@@ -185,6 +184,7 @@ void VideoBackend::Video_Prepare()
g_renderer = new Renderer;
g_texture_cache = new TextureCache;
g_vertex_manager = new VertexManager;
+ g_perf_query = new PerfQuery;
VertexShaderCache::Init();
PixelShaderCache::Init();
D3D::InitUtils();
@@ -208,6 +208,7 @@ void VideoBackend::Shutdown()
{
s_BackendInitialized = false;
+ // TODO: should be in Video_Cleanup
if (g_renderer)
{
s_efbAccessRequested = FALSE;
@@ -227,6 +228,7 @@ void VideoBackend::Shutdown()
D3D::ShutdownUtils();
PixelShaderCache::Shutdown();
VertexShaderCache::Shutdown();
+ delete g_perf_query;
delete g_vertex_manager;
delete g_texture_cache;
delete g_renderer;
@@ -235,4 +237,7 @@ void VideoBackend::Shutdown()
}
}
+void VideoBackend::Video_Cleanup() {
+}
+
}
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp
index ff3f68a6cd..b3d241fe14 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp
@@ -66,6 +66,7 @@ static int numAdapters;
static int cur_adapter;
// Value caches for state filtering
+const int MaxStreamSources = 16;
const int MaxTextureStages = 9;
const int MaxRenderStates = 210 + 46;
const int MaxTextureTypes = 33;
@@ -83,10 +84,23 @@ static DWORD m_SamplerStates[MaxSamplerSize][MaxSamplerTypes];
static bool m_SamplerStatesSet[MaxSamplerSize][MaxSamplerTypes];
static bool m_SamplerStatesChanged[MaxSamplerSize][MaxSamplerTypes];
-LPDIRECT3DBASETEXTURE9 m_Textures[16];
-LPDIRECT3DVERTEXDECLARATION9 m_VtxDecl;
-LPDIRECT3DPIXELSHADER9 m_PixelShader;
-LPDIRECT3DVERTEXSHADER9 m_VertexShader;
+static LPDIRECT3DBASETEXTURE9 m_Textures[16];
+static LPDIRECT3DVERTEXDECLARATION9 m_VtxDecl;
+static bool m_VtxDeclChanged;
+static LPDIRECT3DPIXELSHADER9 m_PixelShader;
+static bool m_PixelShaderChanged;
+static LPDIRECT3DVERTEXSHADER9 m_VertexShader;
+static bool m_VertexShaderChanged;
+struct StreamSourceDescriptor
+{
+ LPDIRECT3DVERTEXBUFFER9 pStreamData;
+ UINT OffsetInBytes;
+ UINT Stride;
+};
+static StreamSourceDescriptor m_stream_sources[MaxStreamSources];
+static bool m_stream_sources_Changed[MaxStreamSources];
+static LPDIRECT3DINDEXBUFFER9 m_index_buffer;
+static bool m_index_buffer_Changed;
// Z buffer formats to be used for EFB depth surface
D3DFORMAT DepthFormats[] = {
@@ -170,9 +184,9 @@ void EnableAlphaToCoverage()
{
// Each vendor has their own specific little hack.
if (GetCurAdapter().ident.VendorId == VENDOR_ATI)
- D3D::SetRenderState(D3DRS_POINTSIZE, (D3DFORMAT)MAKEFOURCC('A', '2', 'M', '1'));
+ SetRenderState(D3DRS_POINTSIZE, (D3DFORMAT)MAKEFOURCC('A', '2', 'M', '1'));
else
- D3D::SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C'));
+ SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C'));
}
void InitPP(int adapter, int f, int aa_mode, D3DPRESENT_PARAMETERS *pp)
@@ -209,20 +223,20 @@ void InitPP(int adapter, int f, int aa_mode, D3DPRESENT_PARAMETERS *pp)
yres = pp->BackBufferHeight = client.bottom - client.top;
}
pp->SwapEffect = D3DSWAPEFFECT_DISCARD;
- pp->PresentationInterval = g_Config.bVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
+ pp->PresentationInterval = g_Config.IsVSync() ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
pp->Windowed = !g_Config.b3DVision;
}
void Enumerate()
{
- numAdapters = D3D::D3D->GetAdapterCount();
+ numAdapters = D3D->GetAdapterCount();
for (int i = 0; i < std::min(MAX_ADAPTERS, numAdapters); i++)
{
Adapter &a = adapters[i];
a.aa_levels.clear();
a.resolutions.clear();
- D3D::D3D->GetAdapterIdentifier(i, 0, &a.ident);
+ D3D->GetAdapterIdentifier(i, 0, &a.ident);
bool isNvidia = a.ident.VendorId == VENDOR_NVIDIA;
// Add SuperSamples modes
@@ -233,17 +247,17 @@ void Enumerate()
//disable them will they are not implemnted
/*
DWORD qlevels = 0;
- if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
+ if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
if (qlevels > 0)
a.aa_levels.push_back(AALevel("2x MSAA", D3DMULTISAMPLE_2_SAMPLES, 0));
- if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
+ if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
if (qlevels > 0)
a.aa_levels.push_back(AALevel("4x MSAA", D3DMULTISAMPLE_4_SAMPLES, 0));
- if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
+ if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
if (qlevels > 0)
a.aa_levels.push_back(AALevel("8x MSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
@@ -251,7 +265,7 @@ void Enumerate()
if (isNvidia)
{
// CSAA support
- if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
+ if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_4_SAMPLES, &qlevels))
{
if (qlevels > 2)
@@ -262,7 +276,7 @@ void Enumerate()
a.aa_levels.push_back(AALevel("8xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
}
}
- if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
+ if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
{
if (qlevels > 2)
@@ -296,11 +310,11 @@ void Enumerate()
{
strcpy(a.aa_levels[0].name, "(Not supported on this device)");
}
- int numModes = D3D::D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8);
+ int numModes = D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8);
for (int m = 0; m < numModes; m++)
{
D3DDISPLAYMODE mode;
- D3D::D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode);
+ D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode);
int found = -1;
for (int x = 0; x < (int)a.resolutions.size(); x++)
@@ -440,8 +454,8 @@ HRESULT Create(int adapter, HWND wnd, int _resolution, int aa_mode, bool auto_de
dev->GetRenderTarget(0, &back_buffer);
if (dev->GetDepthStencilSurface(&back_buffer_z) == D3DERR_NOTFOUND)
back_buffer_z = NULL;
- D3D::SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE );
- D3D::SetRenderState(D3DRS_FILLMODE, g_Config.bWireFrame ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
+ SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE );
+ SetRenderState(D3DRS_FILLMODE, g_Config.bWireFrame ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
memset(m_Textures, 0, sizeof(m_Textures));
memset(m_TextureStageStatesSet, 0, sizeof(m_TextureStageStatesSet));
memset(m_RenderStatesSet, 0, sizeof(m_RenderStatesSet));
@@ -452,6 +466,15 @@ HRESULT Create(int adapter, HWND wnd, int _resolution, int aa_mode, bool auto_de
m_VtxDecl = NULL;
m_PixelShader = NULL;
m_VertexShader = NULL;
+ m_index_buffer = NULL;
+ memset(m_stream_sources, 0, sizeof(m_stream_sources));
+ m_index_buffer = NULL;
+
+ m_VtxDeclChanged = false;
+ m_PixelShaderChanged = false;
+ m_VertexShaderChanged = false;
+ memset(m_stream_sources_Changed, 0 , sizeof(m_stream_sources_Changed));
+ m_index_buffer_Changed = false;
// Device state would normally be set here
return S_OK;
}
@@ -516,7 +539,7 @@ bool CheckDepthStencilSupport(D3DFORMAT target_format, D3DFORMAT depth_format)
D3DFORMAT GetSupportedDepthTextureFormat()
{
for (int i = 0; i < sizeof(DepthFormats)/sizeof(D3DFORMAT); ++i)
- if (D3D::CheckTextureSupport(D3DUSAGE_DEPTHSTENCIL, DepthFormats[i]))
+ if (CheckTextureSupport(D3DUSAGE_DEPTHSTENCIL, DepthFormats[i]))
return DepthFormats[i];
return D3DFMT_UNKNOWN;
@@ -525,7 +548,7 @@ D3DFORMAT GetSupportedDepthTextureFormat()
D3DFORMAT GetSupportedDepthSurfaceFormat(D3DFORMAT target_format)
{
for (int i = 0; i < sizeof(DepthFormats)/sizeof(D3DFORMAT); ++i)
- if (D3D::CheckDepthStencilSupport(target_format, DepthFormats[i]))
+ if (CheckDepthStencilSupport(target_format, DepthFormats[i]))
return DepthFormats[i];
return D3DFMT_UNKNOWN;
@@ -533,13 +556,13 @@ D3DFORMAT GetSupportedDepthSurfaceFormat(D3DFORMAT target_format)
const char *VertexShaderVersionString()
{
- int version = ((D3D::caps.VertexShaderVersion >> 8) & 0xFF);
+ int version = ((caps.VertexShaderVersion >> 8) & 0xFF);
return vsVersions[std::min(4, version)];
}
const char *PixelShaderVersionString()
{
- int version = ((D3D::caps.PixelShaderVersion >> 8) & 0xFF);
+ int version = ((caps.PixelShaderVersion >> 8) & 0xFF);
return psVersions[std::min(4, version)];
}
@@ -653,14 +676,14 @@ void ApplyCachedState()
for (int type = 0; type < MaxSamplerTypes; type++)
{
if(m_SamplerStatesSet[sampler][type])
- D3D::dev->SetSamplerState(sampler, (D3DSAMPLERSTATETYPE)type, m_SamplerStates[sampler][type]);
+ dev->SetSamplerState(sampler, (D3DSAMPLERSTATETYPE)type, m_SamplerStates[sampler][type]);
}
}
for (int rs = 0; rs < MaxRenderStates; rs++)
{
if (m_RenderStatesSet[rs])
- D3D::dev->SetRenderState((D3DRENDERSTATETYPE)rs, m_RenderStates[rs]);
+ dev->SetRenderState((D3DRENDERSTATETYPE)rs, m_RenderStates[rs]);
}
// We don't bother restoring these so let's just wipe the state copy
@@ -671,6 +694,13 @@ void ApplyCachedState()
m_VtxDecl = NULL;
m_PixelShader = NULL;
m_VertexShader = NULL;
+ memset(m_stream_sources, 0, sizeof(m_stream_sources));
+ m_index_buffer = NULL;
+ m_VtxDeclChanged = false;
+ m_PixelShaderChanged = false;
+ m_VertexShaderChanged = false;
+ memset(m_stream_sources_Changed, 0 , sizeof(m_stream_sources_Changed));
+ m_index_buffer_Changed = false;
}
void SetTexture(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture)
@@ -678,7 +708,7 @@ void SetTexture(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture)
if (m_Textures[Stage] != pTexture)
{
m_Textures[Stage] = pTexture;
- D3D::dev->SetTexture(Stage, pTexture);
+ dev->SetTexture(Stage, pTexture);
}
}
@@ -686,7 +716,7 @@ void RefreshRenderState(D3DRENDERSTATETYPE State)
{
if(m_RenderStatesSet[State] && m_RenderStatesChanged[State])
{
- D3D::dev->SetRenderState(State, m_RenderStates[State]);
+ dev->SetRenderState(State, m_RenderStates[State]);
m_RenderStatesChanged[State] = false;
}
}
@@ -698,7 +728,7 @@ void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value)
m_RenderStates[State] = Value;
m_RenderStatesSet[State] = true;
m_RenderStatesChanged[State] = false;
- D3D::dev->SetRenderState(State, Value);
+ dev->SetRenderState(State, Value);
}
}
@@ -707,7 +737,7 @@ void ChangeRenderState(D3DRENDERSTATETYPE State, DWORD Value)
if (m_RenderStates[State] != Value || !m_RenderStatesSet[State])
{
m_RenderStatesChanged[State] = m_RenderStatesSet[State];
- D3D::dev->SetRenderState(State, Value);
+ dev->SetRenderState(State, Value);
}
else
{
@@ -722,7 +752,7 @@ void SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Valu
m_TextureStageStates[Stage][Type] = Value;
m_TextureStageStatesSet[Stage][Type]=true;
m_TextureStageStatesChanged[Stage][Type]=false;
- D3D::dev->SetTextureStageState(Stage, Type, Value);
+ dev->SetTextureStageState(Stage, Type, Value);
}
}
@@ -730,7 +760,7 @@ void RefreshTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type)
{
if(m_TextureStageStatesSet[Stage][Type] && m_TextureStageStatesChanged[Stage][Type])
{
- D3D::dev->SetTextureStageState(Stage, Type, m_TextureStageStates[Stage][Type]);
+ dev->SetTextureStageState(Stage, Type, m_TextureStageStates[Stage][Type]);
m_TextureStageStatesChanged[Stage][Type] = false;
}
}
@@ -740,7 +770,7 @@ void ChangeTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD V
if (m_TextureStageStates[Stage][Type] != Value || !m_TextureStageStatesSet[Stage][Type])
{
m_TextureStageStatesChanged[Stage][Type] = m_TextureStageStatesSet[Stage][Type];
- D3D::dev->SetTextureStageState(Stage, Type, Value);
+ dev->SetTextureStageState(Stage, Type, Value);
}
else
{
@@ -755,7 +785,7 @@ void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
m_SamplerStates[Sampler][Type] = Value;
m_SamplerStatesSet[Sampler][Type] = true;
m_SamplerStatesChanged[Sampler][Type] = false;
- D3D::dev->SetSamplerState(Sampler, Type, Value);
+ dev->SetSamplerState(Sampler, Type, Value);
}
}
@@ -763,7 +793,7 @@ void RefreshSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type)
{
if(m_SamplerStatesSet[Sampler][Type] && m_SamplerStatesChanged[Sampler][Type])
{
- D3D::dev->SetSamplerState(Sampler, Type, m_SamplerStates[Sampler][Type]);
+ dev->SetSamplerState(Sampler, Type, m_SamplerStates[Sampler][Type]);
m_SamplerStatesChanged[Sampler][Type] = false;
}
}
@@ -773,7 +803,7 @@ void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
if (m_SamplerStates[Sampler][Type] != Value || !m_SamplerStatesSet[Sampler][Type])
{
m_SamplerStatesChanged[Sampler][Type] = m_SamplerStatesSet[Sampler][Type];
- D3D::dev->SetSamplerState(Sampler, Type, Value);
+ dev->SetSamplerState(Sampler, Type, Value);
}
else
{
@@ -783,67 +813,155 @@ void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
void RefreshVertexDeclaration()
{
- if (m_VtxDecl)
+ if (m_VtxDeclChanged)
{
- D3D::dev->SetVertexDeclaration(m_VtxDecl);
+ dev->SetVertexDeclaration(m_VtxDecl);
+ m_VtxDeclChanged = false;
}
}
void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl)
{
- if (!decl) {
- m_VtxDecl = NULL;
- return;
- }
if (decl != m_VtxDecl)
{
- D3D::dev->SetVertexDeclaration(decl);
+ dev->SetVertexDeclaration(decl);
m_VtxDecl = decl;
+ m_VtxDeclChanged = false;
+ }
+}
+
+void ChangeVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl)
+{
+ if (decl != m_VtxDecl) {
+ dev->SetVertexDeclaration(decl);
+ m_VtxDeclChanged = true;
+ }
+}
+
+void ChangeVertexShader(LPDIRECT3DVERTEXSHADER9 shader)
+{
+ if (shader != m_VertexShader)
+ {
+ dev->SetVertexShader(shader);
+ m_VertexShaderChanged = true;
}
}
void RefreshVertexShader()
{
- if (m_VertexShader)
+ if (m_VertexShaderChanged)
{
- D3D::dev->SetVertexShader(m_VertexShader);
+ dev->SetVertexShader(m_VertexShader);
+ m_VertexShaderChanged = false;
}
}
void SetVertexShader(LPDIRECT3DVERTEXSHADER9 shader)
{
- if (!shader) {
- m_VertexShader = NULL;
- return;
- }
if (shader != m_VertexShader)
{
- D3D::dev->SetVertexShader(shader);
+ dev->SetVertexShader(shader);
m_VertexShader = shader;
+ m_VertexShaderChanged = false;
}
}
void RefreshPixelShader()
{
- if (m_PixelShader)
+ if (m_PixelShaderChanged)
{
- D3D::dev->SetPixelShader(m_PixelShader);
+ dev->SetPixelShader(m_PixelShader);
+ m_PixelShaderChanged = false;
}
}
void SetPixelShader(LPDIRECT3DPIXELSHADER9 shader)
{
- if (!shader) {
- m_PixelShader = NULL;
- return;
- }
if (shader != m_PixelShader)
{
- D3D::dev->SetPixelShader(shader);
+ dev->SetPixelShader(shader);
m_PixelShader = shader;
+ m_PixelShaderChanged = false;
+ }
+}
+
+void ChangePixelShader(LPDIRECT3DPIXELSHADER9 shader)
+{
+ if (shader != m_PixelShader)
+ {
+ dev->SetPixelShader(shader);
+ m_PixelShaderChanged = true;
+ }
+}
+
+void SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride)
+{
+ if (m_stream_sources[StreamNumber].OffsetInBytes != OffsetInBytes
+ || m_stream_sources[StreamNumber].pStreamData != pStreamData
+ || m_stream_sources[StreamNumber].Stride != Stride)
+ {
+ m_stream_sources[StreamNumber].OffsetInBytes = OffsetInBytes;
+ m_stream_sources[StreamNumber].pStreamData = pStreamData;
+ m_stream_sources[StreamNumber].Stride = Stride;
+ dev->SetStreamSource(StreamNumber, pStreamData, OffsetInBytes, Stride);
+ m_stream_sources_Changed[StreamNumber] = false;
+ }
+}
+
+void ChangeStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride)
+{
+ if (m_stream_sources[StreamNumber].OffsetInBytes != OffsetInBytes
+ || m_stream_sources[StreamNumber].pStreamData != pStreamData
+ || m_stream_sources[StreamNumber].Stride != Stride)
+ {
+ dev->SetStreamSource(StreamNumber, pStreamData, OffsetInBytes, Stride);
+ m_stream_sources_Changed[StreamNumber] = true;
+ }
+
+}
+
+void RefreshStreamSource(UINT StreamNumber)
+{
+ if (m_PixelShaderChanged)
+ {
+ dev->SetStreamSource(
+ StreamNumber,
+ m_stream_sources[StreamNumber].pStreamData,
+ m_stream_sources[StreamNumber].OffsetInBytes,
+ m_stream_sources[StreamNumber].Stride);
+ m_stream_sources_Changed[StreamNumber] = false;
}
}
+void SetIndices(LPDIRECT3DINDEXBUFFER9 pIndexData)
+{
+ if(pIndexData != m_index_buffer)
+ {
+ m_index_buffer = pIndexData;
+ dev->SetIndices(pIndexData);
+ m_index_buffer_Changed = false;
+ }
+}
+
+void ChangeIndices(LPDIRECT3DINDEXBUFFER9 pIndexData)
+{
+ if(pIndexData != m_index_buffer)
+ {
+ dev->SetIndices(pIndexData);
+ m_index_buffer_Changed = true;
+ }
+}
+
+void RefreshIndices()
+{
+ if (m_index_buffer_Changed)
+ {
+ dev->SetIndices(m_index_buffer);
+ m_index_buffer_Changed = false;
+ }
+}
+
+
} // namespace
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h
index d1e7eeaa91..7be482a55f 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h
+++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h
@@ -100,12 +100,23 @@ void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
void RefreshVertexDeclaration();
void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl);
+void ChangeVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl);
void RefreshVertexShader();
void SetVertexShader(LPDIRECT3DVERTEXSHADER9 shader);
+void ChangeVertexShader(LPDIRECT3DVERTEXSHADER9 shader);
void RefreshPixelShader();
void SetPixelShader(LPDIRECT3DPIXELSHADER9 shader);
+void ChangePixelShader(LPDIRECT3DPIXELSHADER9 shader);
+
+void SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride);
+void ChangeStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride);
+void RefreshStreamSource(UINT StreamNumber);
+
+void SetIndices(LPDIRECT3DINDEXBUFFER9 pIndexData);
+void ChangeIndices(LPDIRECT3DINDEXBUFFER9 pIndexData);
+void RefreshIndices();
void ApplyCachedState();
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp
index 9c17c3df8c..c7c4cf266a 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp
@@ -50,7 +50,8 @@ bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecode
static int num_failures = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
file << code;
file.close();
@@ -105,7 +106,8 @@ bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodel
static int num_failures = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
file << code;
file.close();
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp
index 9510ad444c..d24720e6f9 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp
@@ -198,6 +198,8 @@ const int TS[6][2] =
void RestoreShaders()
{
D3D::SetTexture(0, 0);
+ D3D::RefreshStreamSource(0);
+ D3D::RefreshIndices();
D3D::RefreshVertexDeclaration();
D3D::RefreshPixelShader();
D3D::RefreshVertexShader();
@@ -217,9 +219,9 @@ void CD3DFont::SetRenderStates()
{
D3D::SetTexture(0, m_pTexture);
- dev->SetPixelShader(0);
- dev->SetVertexShader(0);
-
+ D3D::ChangePixelShader(0);
+ D3D::ChangeVertexShader(0);
+ D3D::ChangeVertexDeclaration(0);
dev->SetFVF(D3DFVF_FONT2DVERTEX);
for (int i = 0; i < 6; i++)
@@ -236,7 +238,7 @@ int CD3DFont::DrawTextScaled(float x, float y, float fXScale, float fYScale, flo
return 0;
SetRenderStates();
- dev->SetStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX));
+ D3D::ChangeStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX));
float vpWidth = 1;
float vpHeight = 1;
@@ -389,9 +391,10 @@ void drawShadedTexQuad(IDirect3DTexture9 *texture,
{ 1.0f - dw,-1.0f + dh, 0.0f,1.0f, u2, v2, sw, sh, g},
{ 1.0f - dw, 1.0f + dh, 0.0f,1.0f, u2, v1, sw, sh, g}
};
- dev->SetVertexShader(Vshader);
- dev->SetPixelShader(PShader);
+ D3D::ChangeVertexShader(Vshader);
+ D3D::ChangePixelShader(PShader);
D3D::SetTexture(0, texture);
+ D3D::ChangeVertexDeclaration(0);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE1(2));
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
@@ -424,9 +427,10 @@ void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
{ rDest->right - dw , rDest->top + dh, 1.0f,1.0f, u2, v2, sw, sh, g},
{ rDest->right - dw , rDest->bottom + dh, 1.0f,1.0f, u2, v1, sw, sh, g}
};
- dev->SetVertexShader(Vshader);
- dev->SetPixelShader(PShader);
+ D3D::ChangeVertexShader(Vshader);
+ D3D::ChangePixelShader(PShader);
D3D::SetTexture(0, texture);
+ D3D::ChangeVertexDeclaration(0);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE1(2));
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
@@ -442,8 +446,9 @@ void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2)
{ x1, y1, 0.f, 1.f, Color },
{ x2, y1, 0.f, 1.f, Color },
};
- dev->SetVertexShader(VertexShaderCache::GetClearVertexShader());
- dev->SetPixelShader(PixelShaderCache::GetClearProgram());
+ D3D::ChangeVertexShader(VertexShaderCache::GetClearVertexShader());
+ D3D::ChangePixelShader(PixelShaderCache::GetClearProgram());
+ D3D::ChangeVertexDeclaration(0);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_DIFFUSE);
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(CQVertex));
RestoreShaders();
@@ -457,8 +462,9 @@ void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVer
{ 1.0f, -1.0f, z, 1.0f, Color},
{-1.0f, -1.0f, z, 1.0f, Color}
};
- dev->SetVertexShader(Vshader);
- dev->SetPixelShader(PShader);
+ D3D::ChangeVertexShader(Vshader);
+ D3D::ChangePixelShader(PShader);
+ D3D::ChangeVertexDeclaration(0);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_DIFFUSE);
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp
index 1903bce989..5dfcc51c66 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp
@@ -187,6 +187,8 @@ void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, c
void XFBSource::CopyEFB(float Gamma)
{
+ g_renderer->ResetAPIState(); // reset any game specific settings
+
// Copy EFB data to XFB and restore render target again
LPDIRECT3DSURFACE9 Rendersurf = NULL;
texture->GetSurfaceLevel(0, &Rendersurf);
@@ -229,6 +231,8 @@ void XFBSource::CopyEFB(float Gamma)
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
Rendersurf->Release();
+
+ g_renderer->RestoreAPIState();
}
} // namespace DX9
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp b/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp
index bfaf21ec7e..d68228273c 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp
@@ -19,7 +19,7 @@
#include "D3DBase.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "MemoryUtil.h"
#include "VertexShaderGen.h"
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp
index 0657309801..7a175fd443 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp
@@ -67,6 +67,7 @@ static int s_fps = 0;
static u32 s_blendMode;
static u32 s_LastAA;
static bool IS_AMD;
+static float m_fMaxPointSize;
static char *st;
@@ -187,6 +188,9 @@ Renderer::Renderer()
D3D::BeginFrame();
D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, true);
D3D::dev->CreateOffscreenPlainSurface(s_backbuffer_width,s_backbuffer_height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL );
+ D3D::SetRenderState(D3DRS_POINTSCALEENABLE,false);
+ m_fMaxPointSize = D3D::GetCaps().MaxPointSize;
+
}
Renderer::~Renderer()
@@ -216,11 +220,11 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
}
-void formatBufferDump(const char *in, char *out, int w, int h, int p)
+void formatBufferDump(const u8* in, u8* out, int w, int h, int p)
{
for (int y = 0; y < h; y++)
{
- const char *line = in + (h - y - 1) * p;
+ auto line = in + (h - y - 1) * p;
for (int x = 0; x < w; x++)
{
memcpy(out, line, 3);
@@ -725,8 +729,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
{
if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
{
- if (g_ActiveConfig.bDumpFrames && frame_data)
- AVIDump::AddFrame(frame_data);
+ if (g_ActiveConfig.bDumpFrames && !frame_data.empty())
+ AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight);
Core::Callback_VideoCopiedToXFB(false);
return;
@@ -737,8 +741,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
{
- if (g_ActiveConfig.bDumpFrames && frame_data)
- AVIDump::AddFrame(frame_data);
+ if (g_ActiveConfig.bDumpFrames && !frame_data.empty())
+ AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight);
Core::Callback_VideoCopiedToXFB(false);
return;
@@ -935,15 +939,14 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
D3DLOCKED_RECT rect;
if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, GetTargetRectangle().AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY)))
{
- if (!frame_data || w != s_recordWidth || h != s_recordHeight)
+ if (frame_data.empty() || w != s_recordWidth || h != s_recordHeight)
{
- delete[] frame_data;
- frame_data = new char[3 * s_recordWidth * s_recordHeight];
+ frame_data.resize(3 * s_recordWidth * s_recordHeight);
w = s_recordWidth;
h = s_recordHeight;
}
- formatBufferDump((const char*)rect.pBits, frame_data, s_recordWidth, s_recordHeight, rect.Pitch);
- AVIDump::AddFrame(frame_data);
+ formatBufferDump((const u8*)rect.pBits, &frame_data[0], s_recordWidth, s_recordHeight, rect.Pitch);
+ AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight);
ScreenShootMEMSurface->UnlockRect();
}
}
@@ -953,12 +956,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
{
if (bLastFrameDumped && bAVIDumping)
{
- if (frame_data)
- {
- delete[] frame_data;
- frame_data = 0;
- w = h = 0;
- }
+ std::vector<u8>().swap(frame_data);
+ w = h = 0;
AVIDump::Stop();
bAVIDumping = false;
OSD::AddMessage("Stop dumping frames to AVI", 2000);
@@ -1285,7 +1284,15 @@ void Renderer::SetLineWidth()
// We can't change line width in D3D unless we use ID3DXLine
float fratio = xfregs.viewport.wd != 0 ? Renderer::EFBToScaledXf(1.f) : 1.0f;
float psize = bpmem.lineptwidth.linesize * fratio / 6.0f;
+ //little hack to compensate scalling problems in dx9 must be taken out when scalling is fixed.
+ psize *= 2.0f;
+ if (psize > m_fMaxPointSize)
+ {
+ psize = m_fMaxPointSize;
+ }
D3D::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize));
+ D3D::SetRenderState(D3DRS_POINTSIZE_MIN, *((DWORD*)&psize));
+ D3D::SetRenderState(D3DRS_POINTSIZE_MAX, *((DWORD*)&psize));
}
void Renderer::SetSamplerState(int stage, int texindex)
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp
index f105d0f774..0e7d82cf7a 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp
@@ -82,6 +82,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
const float *colmat)
{
+ g_renderer->ResetAPIState(); // reset any game specific settings
+
const LPDIRECT3DTEXTURE9 read_texture = (srcFormat == PIXELFMT_Z24) ?
FramebufferManager::GetEFBDepthTexture() :
FramebufferManager::GetEFBColorTexture();
@@ -179,6 +181,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
D3D::SetTexture(0, NULL);
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
+
+ g_renderer->RestoreAPIState();
}
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, unsigned int height,
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp
index 661cf36e76..543a1b9ddc 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp
@@ -42,9 +42,9 @@ extern NativeVertexFormat *g_nativeVertexFmt;
namespace DX9
{
//This are the initially requeted size for the buffers expresed in elements
-const u32 IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * 16;
-const u32 VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE * 16;
-const u32 MAXVBUFFER_COUNT = 2;
+const u32 IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * sizeof(u16) * 8;
+const u32 VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE;
+const u32 MAX_VBUFFER_COUNT = 2;
inline void DumpBadShaders()
{
@@ -67,88 +67,88 @@ inline void DumpBadShaders()
void VertexManager::CreateDeviceObjects()
{
- NumVBuffers = 0;
- VBuffers = NULL;
- IBuffers = NULL;
+ m_buffers_count = 0;
+ m_vertex_buffers = NULL;
+ m_index_buffers = NULL;
D3DCAPS9 DeviceCaps = D3D::GetCaps();
u32 devicevMaxBufferSize = DeviceCaps.MaxPrimitiveCount * 3 * DeviceCaps.MaxStreamStride;
//Calculate Device Dependant size
- CurrentVBufferSize = (VBUFFER_SIZE > devicevMaxBufferSize) ? devicevMaxBufferSize : VBUFFER_SIZE;
- CurrentIBufferSize = (IBUFFER_SIZE > DeviceCaps.MaxVertexIndex) ? DeviceCaps.MaxVertexIndex : IBUFFER_SIZE;
+ m_vertex_buffer_size = (VBUFFER_SIZE > devicevMaxBufferSize) ? devicevMaxBufferSize : VBUFFER_SIZE;
+ m_index_buffer_size = (IBUFFER_SIZE > DeviceCaps.MaxVertexIndex) ? DeviceCaps.MaxVertexIndex : IBUFFER_SIZE;
//if device caps are not enough for Vbuffer fall back to vertex arrays
- if (CurrentIBufferSize < MAXIBUFFERSIZE || CurrentVBufferSize < MAXVBUFFERSIZE) return;
+ if (m_index_buffer_size < MAXIBUFFERSIZE || m_vertex_buffer_size < MAXVBUFFERSIZE) return;
- VBuffers = new LPDIRECT3DVERTEXBUFFER9[MAXVBUFFER_COUNT];
- IBuffers = new LPDIRECT3DINDEXBUFFER9[MAXVBUFFER_COUNT];
+ m_vertex_buffers = new LPDIRECT3DVERTEXBUFFER9[MAX_VBUFFER_COUNT];
+ m_index_buffers = new LPDIRECT3DINDEXBUFFER9[MAX_VBUFFER_COUNT];
bool Fail = false;
- for (CurrentVBuffer = 0; CurrentVBuffer < MAXVBUFFER_COUNT; CurrentVBuffer++)
+ for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
{
- VBuffers[CurrentVBuffer] = NULL;
- IBuffers[CurrentVBuffer] = NULL;
+ m_vertex_buffers[m_current_vertex_buffer] = NULL;
+ m_index_buffers[m_current_vertex_buffer] = NULL;
}
- for (CurrentVBuffer = 0; CurrentVBuffer < MAXVBUFFER_COUNT; CurrentVBuffer++)
+ for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
{
- if(FAILED( D3D::dev->CreateVertexBuffer( CurrentVBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &VBuffers[CurrentVBuffer], NULL ) ) )
+ if(FAILED( D3D::dev->CreateVertexBuffer( m_vertex_buffer_size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_vertex_buffers[m_current_vertex_buffer], NULL ) ) )
{
Fail = true;
break;
}
- if( FAILED( D3D::dev->CreateIndexBuffer( CurrentIBufferSize * sizeof(u16), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &IBuffers[CurrentVBuffer], NULL ) ) )
+ if( FAILED( D3D::dev->CreateIndexBuffer( m_index_buffer_size * sizeof(u16), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_index_buffers[m_current_vertex_buffer], NULL ) ) )
{
Fail = true;
return;
}
}
- NumVBuffers = CurrentVBuffer;
- CurrentVBuffer = 0;
- CurrentIBuffer = 0;
- CurrentIBufferIndex = CurrentIBufferSize;
- CurrentVBufferIndex = CurrentVBufferSize;
-
+ m_buffers_count = m_current_vertex_buffer;
+ m_current_vertex_buffer = 0;
+ m_current_index_buffer = 0;
+ m_index_buffer_cursor = m_index_buffer_size;
+ m_vertex_buffer_cursor = m_vertex_buffer_size;
+ m_current_stride = 0;
if (Fail)
{
- NumVBuffers--;
- if (NumVBuffers < 2)
+ m_buffers_count--;
+ if (m_buffers_count < 2)
{
//Error creating Vertex buffers. clean and fall to Vertex arrays
- NumVBuffers = MAXVBUFFER_COUNT;
+ m_buffers_count = MAX_VBUFFER_COUNT;
DestroyDeviceObjects();
}
}
}
void VertexManager::DestroyDeviceObjects()
{
- D3D::dev->SetStreamSource( 0, NULL, 0, 0);
- D3D::dev->SetIndices(NULL);
- for (int i = 0; i < MAXVBUFFER_COUNT; i++)
+ D3D::SetStreamSource( 0, NULL, 0, 0);
+ D3D::SetIndices(NULL);
+ for (int i = 0; i < MAX_VBUFFER_COUNT; i++)
{
- if(VBuffers)
+ if(m_vertex_buffers)
{
- if (VBuffers[i])
+ if (m_vertex_buffers[i])
{
- VBuffers[i]->Release();
- VBuffers[i] = NULL;
+ m_vertex_buffers[i]->Release();
+ m_vertex_buffers[i] = NULL;
}
}
- if (IBuffers[i])
+ if (m_index_buffers[i])
{
- IBuffers[i]->Release();
- IBuffers[i] = NULL;
+ m_index_buffers[i]->Release();
+ m_index_buffers[i] = NULL;
}
}
- if(VBuffers)
- delete [] VBuffers;
- if(IBuffers)
- delete [] IBuffers;
- VBuffers = NULL;
- IBuffers = NULL;
+ if(m_vertex_buffers)
+ delete [] m_vertex_buffers;
+ if(m_index_buffers)
+ delete [] m_index_buffers;
+ m_vertex_buffers = NULL;
+ m_index_buffers = NULL;
}
-void VertexManager::PrepareVBuffers(int stride)
+void VertexManager::PrepareDrawBuffers(u32 stride)
{
- if (!NumVBuffers)
+ if (!m_buffers_count)
{
return;
}
@@ -158,145 +158,160 @@ void VertexManager::PrepareVBuffers(int stride)
int TdataSize = IndexGenerator::GetTriangleindexLen();
int LDataSize = IndexGenerator::GetLineindexLen();
int PDataSize = IndexGenerator::GetPointindexLen();
- int IndexDataSize = TdataSize + LDataSize + PDataSize;
+ int IndexDataSize = TdataSize + LDataSize;
DWORD LockMode = D3DLOCK_NOOVERWRITE;
-
- if (CurrentVBufferIndex > CurrentVBufferSize - datasize)
+ m_vertex_buffer_cursor--;
+ m_vertex_buffer_cursor = m_vertex_buffer_cursor - (m_vertex_buffer_cursor % stride) + stride;
+ if (m_vertex_buffer_cursor > m_vertex_buffer_size - datasize)
{
LockMode = D3DLOCK_DISCARD;
- CurrentVBufferIndex = 0;
- CurrentVBuffer = (CurrentVBuffer + 1) % NumVBuffers;
- }
-
- if(FAILED(VBuffers[CurrentVBuffer]->Lock(CurrentVBufferIndex, datasize,(VOID**)(&pVertices), LockMode)))
+ m_vertex_buffer_cursor = 0;
+ m_current_vertex_buffer = (m_current_vertex_buffer + 1) % m_buffers_count;
+ }
+ if(FAILED(m_vertex_buffers[m_current_vertex_buffer]->Lock(m_vertex_buffer_cursor, datasize,(VOID**)(&pVertices), LockMode)))
{
DestroyDeviceObjects();
return;
}
- memcpy(pVertices, LocalVBuffer, datasize);
- VBuffers[CurrentVBuffer]->Unlock();
+ memcpy(pVertices, s_pBaseBufferPointer, datasize);
+ m_vertex_buffers[m_current_vertex_buffer]->Unlock();
LockMode = D3DLOCK_NOOVERWRITE;
-
- if (CurrentIBufferIndex > CurrentIBufferSize - IndexDataSize)
+ if (m_index_buffer_cursor > m_index_buffer_size - IndexDataSize)
{
LockMode = D3DLOCK_DISCARD;
- CurrentIBufferIndex = 0;
- CurrentIBuffer = (CurrentIBuffer + 1) % NumVBuffers;
- }
+ m_index_buffer_cursor = 0;
+ m_current_index_buffer = (m_current_index_buffer + 1) % m_buffers_count;
+ }
- if(FAILED(IBuffers[CurrentIBuffer]->Lock(CurrentIBufferIndex * sizeof(u16), IndexDataSize * sizeof(u16), (VOID**)(&pIndices), LockMode )))
+ if(FAILED(m_index_buffers[m_current_index_buffer]->Lock(m_index_buffer_cursor * sizeof(u16), IndexDataSize * sizeof(u16), (VOID**)(&pIndices), LockMode )))
{
DestroyDeviceObjects();
return;
}
if(TdataSize)
{
- memcpy(pIndices, TIBuffer, TdataSize * sizeof(u16));
+ memcpy(pIndices, GetTriangleIndexBuffer(), TdataSize * sizeof(u16));
pIndices += TdataSize;
}
if(LDataSize)
{
- memcpy(pIndices, LIBuffer, LDataSize * sizeof(u16));
+ memcpy(pIndices, GetLineIndexBuffer(), LDataSize * sizeof(u16));
pIndices += LDataSize;
}
- if(PDataSize)
- {
- memcpy(pIndices, PIBuffer, PDataSize * sizeof(u16));
+ m_index_buffers[m_current_index_buffer]->Unlock();
+ if(m_current_stride != stride || m_vertex_buffer_cursor == 0)
+ {
+ m_current_stride = stride;
+ D3D::SetStreamSource( 0, m_vertex_buffers[m_current_vertex_buffer], 0, stride);
}
- IBuffers[CurrentIBuffer]->Unlock();
- D3D::dev->SetStreamSource( 0, VBuffers[CurrentVBuffer], CurrentVBufferIndex, stride);
- if(CurrentIBufferIndex == 0)
+ if (m_index_buffer_cursor == 0)
{
- D3D::dev->SetIndices(IBuffers[CurrentIBuffer]);
+ D3D::SetIndices(m_index_buffers[m_current_index_buffer]);
}
+
}
-void VertexManager::DrawVB(int stride)
+void VertexManager::DrawVertexBuffer(int stride)
{
- if (IndexGenerator::GetNumTriangles() > 0)
+ int triangles = IndexGenerator::GetNumTriangles();
+ int lines = IndexGenerator::GetNumLines();
+ int points = IndexGenerator::GetNumPoints();
+ int numverts = IndexGenerator::GetNumVerts();
+ int StartIndex = m_index_buffer_cursor;
+ int basevertex = m_vertex_buffer_cursor / stride;
+ if (triangles > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitive(
- D3DPT_TRIANGLELIST,
- 0,
+ D3DPT_TRIANGLELIST,
+ basevertex,
0,
- IndexGenerator::GetNumVerts(),
- CurrentIBufferIndex,
- IndexGenerator::GetNumTriangles())))
+ numverts,
+ StartIndex,
+ triangles)))
{
DumpBadShaders();
}
+ StartIndex += IndexGenerator::GetTriangleindexLen();
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
- if (IndexGenerator::GetNumLines() > 0)
+ if (lines > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitive(
D3DPT_LINELIST,
- 0,
+ basevertex,
0,
- IndexGenerator::GetNumVerts(),
- CurrentIBufferIndex + IndexGenerator::GetTriangleindexLen(),
+ numverts,
+ StartIndex,
IndexGenerator::GetNumLines())))
{
DumpBadShaders();
}
+ StartIndex += IndexGenerator::GetLineindexLen();
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
- if (IndexGenerator::GetNumPoints() > 0)
+ if (points > 0)
{
- if (FAILED(D3D::dev->DrawIndexedPrimitive(
- D3DPT_POINTLIST,
- 0,
- 0,
- IndexGenerator::GetNumVerts(),
- CurrentIBufferIndex + IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen(),
- IndexGenerator::GetNumPoints())))
+ //DrawIndexedPrimitive does not support point list so we have to draw the points one by one
+ for (int i = 0; i < points; i++)
{
- DumpBadShaders();
+ if (FAILED(D3D::dev->DrawPrimitive(
+ D3DPT_POINTLIST,
+ basevertex + GetPointIndexBuffer()[i],
+ 1)))
+ {
+ DumpBadShaders();
+ }
+ INCSTAT(stats.thisFrame.numDrawCalls);
}
- INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+
+
}
}
-void VertexManager::DrawVA(int stride)
-{
- if (IndexGenerator::GetNumTriangles() > 0)
+void VertexManager::DrawVertexArray(int stride)
+{
+ int triangles = IndexGenerator::GetNumTriangles();
+ int lines = IndexGenerator::GetNumLines();
+ int points = IndexGenerator::GetNumPoints();
+ int numverts = IndexGenerator::GetNumVerts();
+ if (triangles > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_TRIANGLELIST,
- 0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumTriangles(),
- TIBuffer,
+ 0, numverts, triangles,
+ GetTriangleIndexBuffer(),
D3DFMT_INDEX16,
- LocalVBuffer,
+ s_pBaseBufferPointer,
stride)))
{
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
- if (IndexGenerator::GetNumLines() > 0)
+ if (lines > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_LINELIST,
- 0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumLines(),
- LIBuffer,
+ 0, numverts, lines,
+ GetLineIndexBuffer(),
D3DFMT_INDEX16,
- LocalVBuffer,
+ s_pBaseBufferPointer,
stride)))
{
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
- if (IndexGenerator::GetNumPoints() > 0)
+ if (points > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_POINTLIST,
- 0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumPoints(),
- PIBuffer,
+ 0, numverts, points,
+ GetPointIndexBuffer(),
D3DFMT_INDEX16,
- LocalVBuffer,
+ s_pBaseBufferPointer,
stride)))
{
DumpBadShaders();
@@ -307,11 +322,6 @@ void VertexManager::DrawVA(int stride)
void VertexManager::vFlush()
{
- if (LocalVBuffer == s_pCurBufferPointer) return;
- if (Flushed) return;
- Flushed = true;
- VideoFifo_CheckEFBAccess();
-
u32 usedtextures = 0;
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i)
if (bpmem.tevorders[i / 2].getEnable(i & 1))
@@ -350,7 +360,7 @@ void VertexManager::vFlush()
// set global constants
VertexShaderManager::SetConstants();
PixelShaderManager::SetConstants();
- int stride = g_nativeVertexFmt->GetVertexStride();
+ u32 stride = g_nativeVertexFmt->GetVertexStride();
if (!PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components))
{
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
@@ -362,9 +372,16 @@ void VertexManager::vFlush()
goto shader_fail;
}
- PrepareVBuffers(stride);
+ PrepareDrawBuffers(stride);
g_nativeVertexFmt->SetupVertexPointers();
- if(NumVBuffers){ DrawVB(stride);} else { DrawVA(stride);}
+ if(m_buffers_count)
+ {
+ DrawVertexBuffer(stride);
+ }
+ else
+ {
+ DrawVertexArray(stride);
+ }
bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate &&
bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
@@ -377,18 +394,24 @@ void VertexManager::vFlush()
}
// update alpha only
g_renderer->ApplyState(true);
- if(NumVBuffers){ DrawVB(stride);} else { DrawVA(stride);}
+ if(m_buffers_count)
+ {
+ DrawVertexBuffer(stride);
+ }
+ else
+ {
+ DrawVertexArray(stride);
+ }
g_renderer->RestoreState();
}
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
shader_fail:
- if(NumVBuffers)
+ if(m_buffers_count)
{
- CurrentIBufferIndex += IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen();
- CurrentVBufferIndex += IndexGenerator::GetNumVerts() * stride;
+ m_index_buffer_cursor += IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen();
+ m_vertex_buffer_cursor += IndexGenerator::GetNumVerts() * stride;
}
- ResetBuffer();
}
}
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.h b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.h
index aa4e9ed57b..2a165aa9af 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.h
+++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.h
@@ -34,18 +34,19 @@ public:
void CreateDeviceObjects();
void DestroyDeviceObjects();
private:
- u32 CurrentVBufferIndex;
- u32 CurrentVBufferSize;
- u32 CurrentIBufferIndex;
- u32 CurrentIBufferSize;
- u32 NumVBuffers;
- u32 CurrentVBuffer;
- u32 CurrentIBuffer;
- LPDIRECT3DVERTEXBUFFER9 *VBuffers;
- LPDIRECT3DINDEXBUFFER9 *IBuffers;
- void PrepareVBuffers(int stride);
- void DrawVB(int stride);
- void DrawVA(int stride);
+ u32 m_vertex_buffer_cursor;
+ u32 m_vertex_buffer_size;
+ u32 m_index_buffer_cursor;
+ u32 m_index_buffer_size;
+ u32 m_buffers_count;
+ u32 m_current_vertex_buffer;
+ u32 m_current_stride;
+ u32 m_current_index_buffer;
+ LPDIRECT3DVERTEXBUFFER9 *m_vertex_buffers;
+ LPDIRECT3DINDEXBUFFER9 *m_index_buffers;
+ void PrepareDrawBuffers(u32 stride);
+ void DrawVertexBuffer(int stride);
+ void DrawVertexArray(int stride);
// temp
void vFlush();
};
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VideoBackend.h b/Source/Plugins/Plugin_VideoDX9/Src/VideoBackend.h
index 77cbd14dae..5b7c54d326 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/VideoBackend.h
+++ b/Source/Plugins/Plugin_VideoDX9/Src/VideoBackend.h
@@ -13,8 +13,10 @@ class VideoBackend : public VideoBackendHardware
void Shutdown();
std::string GetName();
+ std::string GetDisplayName();
void Video_Prepare();
+ void Video_Cleanup();
void ShowConfig(void* parent);
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp
index 3c00e1d619..4b4fc6608e 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp
@@ -57,6 +57,7 @@
#include "ConfigManager.h"
#include "VideoBackend.h"
+#include "PerfQueryBase.h"
namespace DX9
{
@@ -86,6 +87,11 @@ std::string VideoBackend::GetName()
return "Direct3D9";
}
+std::string VideoBackend::GetDisplayName()
+{
+ return "Direct3D9 (deprecated)";
+}
+
void InitBackendInfo()
{
DX9::D3D::Init();
@@ -97,8 +103,6 @@ void InitBackendInfo()
g_Config.backend_info.bSupports3DVision = true;
g_Config.backend_info.bSupportsDualSourceBlend = false;
g_Config.backend_info.bSupportsFormatReinterpretation = true;
-
-
g_Config.backend_info.bSupportsPixelLighting = C_PLIGHTS + 40 <= maxConstants && C_PMATERIALS + 4 <= maxConstants;
// adapters
@@ -172,6 +176,7 @@ void VideoBackend::Video_Prepare()
g_vertex_manager = new VertexManager;
g_renderer = new Renderer;
g_texture_cache = new TextureCache;
+ g_perf_query = new PerfQueryBase;
// VideoCommon
BPInit();
Fifo_Init();
@@ -191,6 +196,7 @@ void VideoBackend::Shutdown()
{
s_BackendInitialized = false;
+ // TODO: should be in Video_Cleanup
if (g_renderer)
{
s_efbAccessRequested = FALSE;
@@ -209,6 +215,7 @@ void VideoBackend::Shutdown()
// internal interfaces
PixelShaderCache::Shutdown();
VertexShaderCache::Shutdown();
+ delete g_perf_query;
delete g_texture_cache;
delete g_renderer;
delete g_vertex_manager;
@@ -218,4 +225,7 @@ void VideoBackend::Shutdown()
D3D::Shutdown();
}
+void VideoBackend::Video_Cleanup() {
+}
+
}
diff --git a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt
index 43b127f5ef..3d4e225932 100644
--- a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt
+++ b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt
@@ -2,10 +2,14 @@ set(SRCS Src/FramebufferManager.cpp
Src/GLUtil.cpp
Src/main.cpp
Src/NativeVertexFormat.cpp
+ Src/PerfQuery.cpp
Src/PixelShaderCache.cpp
Src/PostProcessing.cpp
+ Src/ProgramShaderCache.cpp
Src/RasterFont.cpp
Src/Render.cpp
+ Src/SamplerCache.cpp
+ Src/StreamBuffer.cpp
Src/TextureCache.cpp
Src/TextureConverter.cpp
Src/VertexShaderCache.cpp
@@ -33,12 +37,6 @@ if(wxWidgets_FOUND)
set(LIBS ${LIBS} ${wxWidgets_LIBRARIES})
endif(wxWidgets_FOUND)
-if(WIN32 OR ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
- set(LIBS ${LIBS} Cg CgGL)
-elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- list(APPEND LIBS "${CMAKE_SOURCE_DIR}/Externals/Cg/Cg.framework")
-endif()
-
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(LIBS ${LIBS} clrun)
endif()
diff --git a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj
index d74bc2edb5..403aac2c30 100644
--- a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj
+++ b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj
@@ -121,8 +121,8 @@
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib />
@@ -133,8 +133,8 @@
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib />
@@ -147,8 +147,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib />
@@ -161,8 +161,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib />
@@ -175,8 +175,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib />
@@ -189,8 +189,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib />
@@ -200,10 +200,14 @@
<ClCompile Include="Src\GLUtil.cpp" />
<ClCompile Include="Src\main.cpp" />
<ClCompile Include="Src\NativeVertexFormat.cpp" />
+ <ClCompile Include="Src\PerfQuery.cpp" />
<ClCompile Include="Src\PixelShaderCache.cpp" />
<ClCompile Include="Src\PostProcessing.cpp" />
+ <ClCompile Include="Src\ProgramShaderCache.cpp" />
<ClCompile Include="Src\RasterFont.cpp" />
<ClCompile Include="Src\Render.cpp" />
+ <ClCompile Include="Src\SamplerCache.cpp" />
+ <ClCompile Include="Src\StreamBuffer.cpp" />
<ClCompile Include="Src\stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
@@ -222,15 +226,17 @@
<ClInclude Include="Src\Globals.h" />
<ClInclude Include="Src\GLUtil.h" />
<ClInclude Include="Src\main.h" />
- <ClInclude Include="Src\PixelShaderCache.h" />
+ <ClInclude Include="Src\PerfQuery.h" />
<ClInclude Include="Src\PostProcessing.h" />
+ <ClInclude Include="Src\ProgramShaderCache.h" />
<ClInclude Include="Src\RasterFont.h" />
<ClInclude Include="Src\Render.h" />
+ <ClInclude Include="Src\SamplerCache.h" />
+ <ClInclude Include="Src\StreamBuffer.h" />
<ClInclude Include="Src\stdafx.h" />
<ClInclude Include="Src\TextureCache.h" />
<ClInclude Include="Src\TextureConverter.h" />
<ClInclude Include="Src\VertexManager.h" />
- <ClInclude Include="Src\VertexShaderCache.h" />
<ClInclude Include="Src\VideoBackend.h" />
</ItemGroup>
<ItemGroup>
diff --git a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters
index cd170691da..a8b79d85ad 100644
--- a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters
+++ b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters
@@ -27,15 +27,24 @@
<ClCompile Include="Src\PostProcessing.cpp">
<Filter>Render</Filter>
</ClCompile>
+ <ClCompile Include="Src\ProgramShaderCache.cpp">
+ <Filter>Render</Filter>
+ </ClCompile>
<ClCompile Include="Src\Render.cpp">
<Filter>Render</Filter>
</ClCompile>
+ <ClCompile Include="Src\StreamBuffer.cpp">
+ <Filter>Render</Filter>
+ </ClCompile>
<ClCompile Include="Src\TextureCache.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="Src\VertexShaderCache.cpp">
<Filter>Render</Filter>
</ClCompile>
+ <ClCompile Include="Src\PerfQuery.cpp">
+ <Filter>Render</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Src\Globals.h" />
@@ -57,10 +66,10 @@
<ClInclude Include="Src\FramebufferManager.h">
<Filter>Render</Filter>
</ClInclude>
- <ClInclude Include="Src\PixelShaderCache.h">
+ <ClInclude Include="Src\PostProcessing.h">
<Filter>Render</Filter>
</ClInclude>
- <ClInclude Include="Src\PostProcessing.h">
+ <ClInclude Include="Src\ProgramShaderCache.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="Src\Render.h">
@@ -69,7 +78,7 @@
<ClInclude Include="Src\TextureCache.h">
<Filter>Render</Filter>
</ClInclude>
- <ClInclude Include="Src\VertexShaderCache.h">
+ <ClInclude Include="Src\PerfQuery.h">
<Filter>Render</Filter>
</ClInclude>
</ItemGroup>
@@ -90,4 +99,4 @@
<UniqueIdentifier>{aaa16061-dca9-4155-be44-f77538e839fc}</UniqueIdentifier>
</Filter>
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp
index 0e37c3adb6..27a88bf68a 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp
@@ -17,6 +17,7 @@
#include "Globals.h"
#include "FramebufferManager.h"
+#include "VertexShaderGen.h"
#include "TextureConverter.h"
#include "Render.h"
@@ -25,8 +26,6 @@
namespace OGL
{
-extern bool s_bHaveFramebufferBlit; // comes from Render.cpp. ugly.
-
int FramebufferManager::m_targetWidth;
int FramebufferManager::m_targetHeight;
int FramebufferManager::m_msaaSamples;
@@ -41,7 +40,7 @@ GLuint FramebufferManager::m_resolvedFramebuffer;
GLuint FramebufferManager::m_resolvedColorTexture;
GLuint FramebufferManager::m_resolvedDepthTexture;
-GLuint FramebufferManager::m_xfbFramebuffer; // Only used in MSAA mode
+GLuint FramebufferManager::m_xfbFramebuffer;
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
{
@@ -52,7 +51,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
m_resolvedColorTexture = 0;
m_resolvedDepthTexture = 0;
m_xfbFramebuffer = 0;
-
+
m_targetWidth = targetWidth;
m_targetHeight = targetHeight;
@@ -72,7 +71,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
// Create EFB target.
- glGenFramebuffersEXT(1, &m_efbFramebuffer);
+ glGenFramebuffers(1, &m_efbFramebuffer);
if (m_msaaSamples <= 1)
{
@@ -83,20 +82,20 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
m_efbColor = glObj[0];
m_efbDepth = glObj[1];
- 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);
+ glBindTexture(GL_TEXTURE_RECTANGLE, m_efbColor);
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- 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);
+ glBindTexture(GL_TEXTURE_RECTANGLE, m_efbDepth);
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 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, 0);
// Bind target textures to the EFB framebuffer.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
- 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);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, m_efbColor, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_RECTANGLE, m_efbDepth, 0);
GL_REPORT_FBO_ERROR();
}
@@ -109,67 +108,67 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
// Create EFB target renderbuffers.
GLuint glObj[2];
- glGenRenderbuffersEXT(2, glObj);
+ glGenRenderbuffers(2, glObj);
m_efbColor = glObj[0];
m_efbDepth = glObj[1];
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor);
+ glBindRenderbuffer(GL_RENDERBUFFER, m_efbColor);
if (m_msaaCoverageSamples)
- glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
+ glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
else
- glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth);
+ glBindRenderbuffer(GL_RENDERBUFFER, m_efbDepth);
if (m_msaaCoverageSamples)
- glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
+ glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
else
- glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
// Bind target renderbuffers to EFB framebuffer.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
- 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);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_efbColor);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_efbDepth);
GL_REPORT_FBO_ERROR();
// Create resolved targets for transferring multisampled EFB to texture.
- glGenFramebuffersEXT(1, &m_resolvedFramebuffer);
+ glGenFramebuffers(1, &m_resolvedFramebuffer);
glGenTextures(2, glObj);
m_resolvedColorTexture = glObj[0];
m_resolvedDepthTexture = glObj[1];
- 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);
+ glBindTexture(GL_TEXTURE_RECTANGLE, m_resolvedColorTexture);
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- 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);
+ glBindTexture(GL_TEXTURE_RECTANGLE, m_resolvedDepthTexture);
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 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, 0);
// Bind resolved textures to resolved framebuffer.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer);
- 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);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, m_resolvedColorTexture, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_RECTANGLE, m_resolvedDepthTexture, 0);
GL_REPORT_FBO_ERROR();
// Return to EFB framebuffer.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
}
// Create XFB framebuffer; targets will be created elsewhere.
- glGenFramebuffersEXT(1, &m_xfbFramebuffer);
-
+ glGenFramebuffers(1, &m_xfbFramebuffer);
+
// EFB framebuffer is currently bound, make sure to clear its alpha value to 1.f
glViewport(0, 0, m_targetWidth, m_targetHeight);
glScissor(0, 0, m_targetWidth, m_targetHeight);
@@ -180,7 +179,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
FramebufferManager::~FramebufferManager()
{
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
GLuint glObj[3];
@@ -189,7 +188,7 @@ FramebufferManager::~FramebufferManager()
glObj[0] = m_efbFramebuffer;
glObj[1] = m_resolvedFramebuffer;
glObj[2] = m_xfbFramebuffer;
- glDeleteFramebuffersEXT(3, glObj);
+ glDeleteFramebuffers(3, glObj);
m_efbFramebuffer = 0;
m_xfbFramebuffer = 0;
@@ -204,7 +203,7 @@ FramebufferManager::~FramebufferManager()
if (m_msaaSamples <= 1)
glDeleteTextures(2, glObj);
else
- glDeleteRenderbuffersEXT(2, glObj);
+ glDeleteRenderbuffers(2, glObj);
m_efbColor = 0;
m_efbDepth = 0;
}
@@ -224,16 +223,16 @@ GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight);
// Resolve.
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
- glBlitFramebufferEXT(
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer);
+ glBlitFramebuffer(
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
GL_COLOR_BUFFER_BIT, GL_NEAREST
);
// Return to EFB.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
return m_resolvedColorTexture;
}
@@ -254,16 +253,16 @@ GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc)
targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight);
// Resolve.
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
- glBlitFramebufferEXT(
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer);
+ glBlitFramebuffer(
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
GL_DEPTH_BUFFER_BIT, GL_NEAREST
);
// Return to EFB.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
return m_resolvedDepthTexture;
}
@@ -284,7 +283,7 @@ void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, c
void FramebufferManager::SetFramebuffer(GLuint fb)
{
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb != 0 ? fb : GetEFBFramebuffer());
+ glBindFramebuffer(GL_FRAMEBUFFER, fb != 0 ? fb : GetEFBFramebuffer());
}
// Apply AA if enabled
@@ -298,106 +297,60 @@ GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_r
return GetEFBDepthTexture(source_rect);
}
+XFBSource::~XFBSource()
+{
+ glDeleteRenderbuffers(1, &renderbuf);
+}
+
+
void XFBSource::Draw(const MathUtil::Rectangle<float> &sourcerc,
const MathUtil::Rectangle<float> &drawrc, int width, int height) const
{
// Texture map xfbSource->texture onto the main buffer
-
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
-
- glBegin(GL_QUADS);
- glTexCoord2f(sourcerc.left, sourcerc.bottom);
- glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0);
- glVertex2f(drawrc.left, drawrc.bottom);
-
- glTexCoord2f(sourcerc.left, sourcerc.top);
- glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1);
- glVertex2f(drawrc.left, drawrc.top);
-
- glTexCoord2f(sourcerc.right, sourcerc.top);
- glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1);
- glVertex2f(drawrc.right, drawrc.top);
-
- glTexCoord2f(sourcerc.right, sourcerc.bottom);
- glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0);
- glVertex2f(drawrc.right, drawrc.bottom);
- glEnd();
+ glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuf);
+ glBlitFramebuffer(sourcerc.left, sourcerc.bottom, sourcerc.right, sourcerc.top,
+ drawrc.left, drawrc.bottom, drawrc.right, drawrc.top,
+ GL_COLOR_BUFFER_BIT, GL_LINEAR);
GL_REPORT_ERRORD();
}
void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
{
- TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, texture);
+ TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, renderbuf);
}
void XFBSource::CopyEFB(float Gamma)
{
// Copy EFB data to XFB and restore render target again
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetEFBFramebuffer());
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer());
-#if 0
- if (m_msaaSamples <= 1)
-#else
- if (!s_bHaveFramebufferBlit)
-#endif
- {
- // Just copy the EFB directly.
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer());
-
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
- glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, texWidth, texHeight, 0);
+ // Bind texture.
+ glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuf);
+ GL_REPORT_FBO_ERROR();
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
- }
- else
- {
- // OpenGL cannot copy directly from a multisampled framebuffer, so use
- // EXT_framebuffer_blit.
-
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer());
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, FramebufferManager::GetXFBFramebuffer());
-
- // Bind texture.
- glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, texture, 0);
- GL_REPORT_FBO_ERROR();
-
- glBlitFramebufferEXT(
- 0, 0, texWidth, texHeight,
- 0, 0, texWidth, texHeight,
- GL_COLOR_BUFFER_BIT, GL_NEAREST
- );
+ glBlitFramebuffer(
+ 0, 0, texWidth, texHeight,
+ 0, 0, texWidth, texHeight,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST
+ );
- // Unbind texture.
- glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
+ // Return to EFB.
+ FramebufferManager::SetFramebuffer(0);
- // Return to EFB.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer());
- }
}
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
{
- GLuint texture;
-
- glGenTextures(1, &texture);
+ GLuint renderbuf;
-#if 0// XXX: Some video drivers don't handle glCopyTexImage2D correctly, so use EXT_framebuffer_blit whenever possible.
- if (m_msaaSamples > 1)
-#else
- if (s_bHaveFramebufferBlit)
-#endif
- {
- // In MSAA mode, allocate the texture image here. In non-MSAA mode,
- // the image will be allocated by glCopyTexImage2D (later).
-
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, target_width, target_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
-
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
- }
+ glGenRenderbuffers(1, &renderbuf);
+
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuf);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, target_width, target_height);
- return new XFBSource(texture);
+ return new XFBSource(renderbuf);
}
void FramebufferManager::GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc)
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.h b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.h
index ffe3399705..2a7b20defd 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.h
@@ -57,15 +57,15 @@ namespace OGL {
struct XFBSource : public XFBSourceBase
{
- XFBSource(GLuint tex) : texture(tex) {}
- ~XFBSource() { glDeleteTextures(1, &texture); }
+ XFBSource(GLuint rbuf) : renderbuf(rbuf) {}
+ ~XFBSource();
void CopyEFB(float Gamma);
void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
void Draw(const MathUtil::Rectangle<float> &sourcerc,
const MathUtil::Rectangle<float> &drawrc, int width, int height) const;
- const GLuint texture;
+ const GLuint renderbuf;
};
class FramebufferManager : public FramebufferManagerBase
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp
index 29a1b6a662..4f71fb4a7d 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp
@@ -51,10 +51,10 @@ void VideoBackend::UpdateFPSDisplay(const char *text)
}
void InitInterface()
{
- #if defined(USE_EGL) && USE_EGL
+ #ifdef ANDROID
+ GLInterface = new cInterfaceBase;
+ #elif defined(USE_EGL) && USE_EGL
GLInterface = new cInterfaceEGL;
- #elif defined(USE_WX) && USE_WX
- GLInterface = new cInterfaceWX;
#elif defined(__APPLE__)
GLInterface = new cInterfaceAGL;
#elif defined(_WIN32)
@@ -70,14 +70,14 @@ GLuint OpenGL_CompileProgram ( const char* vertexShader, const char* fragmentSha
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
GLuint programID = glCreateProgram();
- GLint Result = GL_FALSE;
- char stringBuffer[1024];
- GLsizei stringBufferUsage = 0;
// compile vertex shader
glShaderSource(vertexShaderID, 1, &vertexShader, NULL);
glCompileShader(vertexShaderID);
#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL)
+ GLint Result = GL_FALSE;
+ char stringBuffer[1024];
+ GLsizei stringBufferUsage = 0;
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderInfoLog(vertexShaderID, 1024, &stringBufferUsage, stringBuffer);
if(Result && stringBufferUsage) {
@@ -157,32 +157,26 @@ void OpenGL_ReportARBProgramError()
bool OpenGL_ReportFBOError(const char *function, const char *file, int line)
{
#ifndef USE_GLES
- unsigned int fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- if (fbo_status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ unsigned int fbo_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (fbo_status != GL_FRAMEBUFFER_COMPLETE)
{
- const char *error = "-";
+ const char *error = "unknown error";
switch (fbo_status)
{
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
- error = "INCOMPLETE_ATTACHMENT_EXT";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
- error = "INCOMPLETE_MISSING_ATTACHMENT_EXT";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
- error = "INCOMPLETE_DIMENSIONS_EXT";
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ error = "INCOMPLETE_ATTACHMENT";
break;
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
- error = "INCOMPLETE_FORMATS_EXT";
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ error = "INCOMPLETE_MISSING_ATTACHMENT";
break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
- error = "INCOMPLETE_DRAW_BUFFER_EXT";
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+ error = "INCOMPLETE_DRAW_BUFFER";
break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
- error = "INCOMPLETE_READ_BUFFER_EXT";
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+ error = "INCOMPLETE_READ_BUFFER";
break;
- case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
- error = "UNSUPPORTED_EXT";
+ case GL_FRAMEBUFFER_UNSUPPORTED:
+ error = "UNSUPPORTED";
break;
}
ERROR_LOG(VIDEO, "%s:%d: (%s) OpenGL FBO error - %s\n",
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h
index 09d38bb731..7ebe9b3b23 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h
@@ -63,26 +63,22 @@ bool OpenGL_ReportFBOError(const char *function, const char *file, int line);
#define GL_REPORT_FBO_ERROR() OpenGL_ReportFBOError(__FUNCTION__, __FILE__, __LINE__)
#define GL_REPORT_PROGRAM_ERROR() OpenGL_ReportARBProgramError()
#else
-#define GL_REPORT_ERROR() GL_NO_ERROR
+__forceinline GLenum GL_REPORT_ERROR() { return GL_NO_ERROR; }
#define GL_REPORT_ERRORD() (void)GL_NO_ERROR
#define GL_REPORT_FBO_ERROR() (void)true
#define GL_REPORT_PROGRAM_ERROR() (void)0
#endif
-#if defined __APPLE__ || defined __linux__ || defined _WIN32
-#include <Cg/cg.h>
-#include <Cg/cgGL.h>
-#define HAVE_CG 1
-extern CGcontext g_cgcontext;
-extern CGprofile g_cgvProf, g_cgfProf;
+// this should be removed in future, but as long as glsl is unstable, we should really read this messages
+#if defined(_DEBUG) || defined(DEBUGFAST)
+#define DEBUG_GLSL 1
+#else
+#define DEBUG_GLSL 0
#endif
-// XXX: Dual-source blending in OpenGL does not work correctly yet. To make it
-// work, we may need to use glBindFragDataLocation. To use that, we need to
-// use GLSL shaders across the whole pipeline. Yikes!
-//#define USE_DUAL_SOURCE_BLEND
-
-// TODO: should be removed if we use glsl a lot
-#define DEBUG_GLSL
+// Isn't defined if we aren't using GLEW 1.6
+#ifndef GL_ONE_MINUS_SRC1_ALPHA
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#endif
#endif // _GLINIT_H_
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp
index ae20649433..acfdb7ee2e 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp
@@ -17,56 +17,18 @@
#include "GLUtil.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "MemoryUtil.h"
+#include "ProgramShaderCache.h"
#include "VertexShaderGen.h"
#include "CPMemory.h"
#include "NativeVertexFormat.h"
#include "VertexManager.h"
-#define COMPILED_CODE_SIZE 4096
-
-// TODO: this guy is never initialized
-u32 s_prevcomponents; // previous state set
-/*
-#ifdef _WIN32
-#ifdef _M_IX86
-#define USE_JIT
-#endif
-#endif
-*/
-// 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
-// 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.
-
-// 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
// machine.
-#ifdef USE_JIT
-DECLARE_IMPORT(glNormalPointer);
-DECLARE_IMPORT(glVertexPointer);
-DECLARE_IMPORT(glColorPointer);
-DECLARE_IMPORT(glTexCoordPointer);
-#endif
-
-class GLVertexFormat : public NativeVertexFormat
-{
- u8 *m_compiledCode;
- PortableVertexDeclaration vtx_decl;
-
-public:
- GLVertexFormat();
- ~GLVertexFormat();
-
- virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
- virtual void SetupVertexPointers();
- virtual void EnableComponents(u32 components);
-};
-
namespace OGL
{
@@ -75,23 +37,14 @@ NativeVertexFormat* VertexManager::CreateNativeVertexFormat()
return new GLVertexFormat();
}
-}
-
GLVertexFormat::GLVertexFormat()
{
-#ifdef USE_JIT
- m_compiledCode = (u8 *)AllocateExecutableMemory(COMPILED_CODE_SIZE, false);
- if (m_compiledCode)
- memset(m_compiledCode, 0, COMPILED_CODE_SIZE);
-#endif
+
}
GLVertexFormat::~GLVertexFormat()
{
-#ifdef USE_JIT
- FreeMemoryPages(m_compiledCode, COMPILED_CODE_SIZE);
- m_compiledCode = 0;
-#endif
+ glDeleteVertexArrays(1, &VAO);
}
inline GLuint VarToGL(VarType t)
@@ -104,183 +57,56 @@ inline GLuint VarToGL(VarType t)
void GLVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
{
- s_prevcomponents = 0;
-
- vertex_stride = _vtx_decl.stride;
- using namespace Gen;
+ this->vtx_decl = _vtx_decl;
+ vertex_stride = vtx_decl.stride;
// We will not allow vertex components causing uneven strides.
- if (_vtx_decl.stride & 3)
- PanicAlert("Uneven vertex stride: %i", _vtx_decl.stride);
-
-#ifdef USE_JIT
- Gen::XEmitter emit(m_compiledCode);
- // Alright, we have our vertex declaration. Compile some crazy code to set it quickly using GL.
- emit.ABI_EmitPrologue(6);
+ if (vertex_stride & 3)
+ PanicAlert("Uneven vertex stride: %i", vertex_stride);
- emit.CallCdeclFunction4_I(glVertexPointer, 3, GL_FLOAT, _vtx_decl.stride, 0);
-
- if (_vtx_decl.num_normals >= 1)
- {
- emit.CallCdeclFunction3_I(glNormalPointer, VarToGL(_vtx_decl.normal_gl_type), _vtx_decl.stride, _vtx_decl.normal_offset[0]);
- 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_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++)
- {
- if (_vtx_decl.color_offset[i] != -1)
- {
- if (i == 0)
- emit.CallCdeclFunction4_I(glColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]);
- else
- emit.CallCdeclFunction4((void *)glSecondaryColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]);
- }
- }
-
- for (int i = 0; i < 8; i++)
- {
- if (_vtx_decl.texcoord_offset[i] != -1)
- {
- int id = GL_TEXTURE0 + i;
-#ifdef _M_X64
-#ifdef _MSC_VER
- emit.MOV(32, R(RCX), Imm32(id));
-#else
- emit.MOV(32, R(RDI), Imm32(id));
-#endif
-#else
- emit.ABI_AlignStack(1 * 4);
- emit.PUSH(32, Imm32(id));
-#endif
- emit.CALL((void *)glClientActiveTexture);
-#ifndef _M_X64
-#ifdef _WIN32
- // don't inc stack on windows, stdcall
-#else
- emit.ABI_RestoreStack(1 * 4);
-#endif
-#endif
- emit.CallCdeclFunction4_I(
- glTexCoordPointer, _vtx_decl.texcoord_size[i], VarToGL(_vtx_decl.texcoord_gl_type[i]),
- _vtx_decl.stride, _vtx_decl.texcoord_offset[i]);
- }
- }
-
- 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.ABI_EmitEpilogue(6);
-
- if (emit.GetCodePtr() - (u8*)m_compiledCode > COMPILED_CODE_SIZE)
- Crash();
-
-#endif
- this->vtx_decl = _vtx_decl;
-}
+ VertexManager *vm = (OGL::VertexManager*)g_vertex_manager;
+
+ glGenVertexArrays(1, &VAO);
+ glBindVertexArray(VAO);
+
+ // the element buffer is bound directly to the vao, so we must it set for every vao
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vm->m_index_buffers);
+ glBindBuffer(GL_ARRAY_BUFFER, vm->m_vertex_buffers);
-void GLVertexFormat::SetupVertexPointers() {
- // 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.
-#ifdef USE_JIT
- ((void (*)())(void*)m_compiledCode)();
-#else
- glVertexPointer(3, GL_FLOAT, vtx_decl.stride, VertexManager::s_pBaseBufferPointer);
- 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]));
- 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_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]));
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 3, GL_FLOAT, GL_FALSE, vtx_decl.stride, (u8*)NULL);
+
+ for (int i = 0; i < 3; i++) {
+ if (vtx_decl.num_normals > i) {
+ glEnableVertexAttribArray(SHADER_NORM0_ATTRIB+i);
+ glVertexAttribPointer(SHADER_NORM0_ATTRIB+i, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (u8*)NULL + vtx_decl.normal_offset[i]);
}
}
for (int i = 0; i < 2; i++) {
if (vtx_decl.color_offset[i] != -1) {
- if (i == 0)
- glColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i]));
- else {
- glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i]));
- }
+ glEnableVertexAttribArray(SHADER_COLOR0_ATTRIB+i);
+ glVertexAttribPointer(SHADER_COLOR0_ATTRIB+i, 4, GL_UNSIGNED_BYTE, GL_TRUE, vtx_decl.stride, (u8*)NULL + vtx_decl.color_offset[i]);
}
}
for (int i = 0; i < 8; i++) {
if (vtx_decl.texcoord_offset[i] != -1) {
- int id = GL_TEXTURE0 + i;
- glClientActiveTexture(id);
- 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]));
+ glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB+i);
+ glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB+i, vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]),
+ GL_FALSE, vtx_decl.stride, (u8*)NULL + vtx_decl.texcoord_offset[i]);
}
}
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));
+ glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB);
+ glVertexAttribIPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, vtx_decl.stride, (u8*)NULL + vtx_decl.posmtx_offset);
}
-#endif
-}
-
-void GLVertexFormat::EnableComponents(u32 components)
-{
- if (s_prevcomponents != components)
- {
- VertexManager::Flush();
- // matrices
- if ((components & VB_HAS_POSMTXIDX) != (s_prevcomponents & VB_HAS_POSMTXIDX))
- {
- if (components & VB_HAS_POSMTXIDX)
- glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB);
- else
- glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB);
- }
-
- // normals
- if ((components & VB_HAS_NRM0) != (s_prevcomponents & VB_HAS_NRM0))
- {
- if (components & VB_HAS_NRM0)
- glEnableClientState(GL_NORMAL_ARRAY);
- else
- glDisableClientState(GL_NORMAL_ARRAY);
- }
- if ((components & VB_HAS_NRM1) != (s_prevcomponents & VB_HAS_NRM1))
- {
- if (components & VB_HAS_NRM1) {
- glEnableVertexAttribArray(SHADER_NORM1_ATTRIB);
- glEnableVertexAttribArray(SHADER_NORM2_ATTRIB);
- }
- else {
- glDisableVertexAttribArray(SHADER_NORM1_ATTRIB);
- glDisableVertexAttribArray(SHADER_NORM2_ATTRIB);
- }
- }
-
- // color
- 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))
- glEnableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY);
- else
- glDisableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY);
- }
- }
+ vm->m_last_vao = VAO;
+}
- // tex
- for (int i = 0; i < 8; ++i)
- {
- if ((components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i)))
- {
- glClientActiveTexture(GL_TEXTURE0 + i);
- if (components & (VB_HAS_UV0 << i))
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- else
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- }
- }
+void GLVertexFormat::SetupVertexPointers() {
+}
- s_prevcomponents = components;
- }
}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp
new file mode 100644
index 0000000000..db47217655
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp
@@ -0,0 +1,133 @@
+#include "RenderBase.h"
+#include "GLUtil.h"
+#include "PerfQuery.h"
+
+namespace OGL
+{
+
+PerfQuery::PerfQuery()
+ : m_query_read_pos()
+ , m_query_count()
+{
+ for (u32 i = 0; i != ARRAYSIZE(m_query_buffer); ++i)
+ glGenQueries(1, &m_query_buffer[i].query_id);
+
+ ResetQuery();
+}
+
+PerfQuery::~PerfQuery()
+{
+ for (u32 i = 0; i != ARRAYSIZE(m_query_buffer); ++i)
+ glDeleteQueries(1, &m_query_buffer[i].query_id);
+}
+
+void PerfQuery::EnableQuery(PerfQueryGroup type)
+{
+ // Is this sane?
+ if (m_query_count > ARRAYSIZE(m_query_buffer) / 2)
+ WeakFlush();
+
+ if (ARRAYSIZE(m_query_buffer) == m_query_count)
+ {
+ FlushOne();
+ //ERROR_LOG(VIDEO, "flushed query buffer early!");
+ }
+
+ // start query
+ if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
+ {
+ auto& entry = m_query_buffer[(m_query_read_pos + m_query_count) % ARRAYSIZE(m_query_buffer)];
+
+ glBeginQuery(GL_SAMPLES_PASSED, entry.query_id);
+ entry.query_type = type;
+
+ ++m_query_count;
+ }
+}
+
+void PerfQuery::DisableQuery(PerfQueryGroup type)
+{
+ // stop query
+ if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
+ {
+ glEndQuery(GL_SAMPLES_PASSED);
+ }
+}
+
+bool PerfQuery::IsFlushed() const
+{
+ return 0 == m_query_count;
+}
+
+void PerfQuery::FlushOne()
+{
+ auto& entry = m_query_buffer[m_query_read_pos];
+
+ GLuint result = 0;
+ glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT, &result);
+
+ // NOTE: Reported pixel metrics should be referenced to native resolution
+ m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight();
+
+ m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer);
+ --m_query_count;
+}
+
+// TODO: could selectively flush things, but I don't think that will do much
+void PerfQuery::FlushResults()
+{
+ while (!IsFlushed())
+ FlushOne();
+}
+
+void PerfQuery::WeakFlush()
+{
+ while (!IsFlushed())
+ {
+ auto& entry = m_query_buffer[m_query_read_pos];
+
+ GLuint result = GL_FALSE;
+ glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT_AVAILABLE, &result);
+
+ if (GL_TRUE == result)
+ {
+ FlushOne();
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+void PerfQuery::ResetQuery()
+{
+ m_query_count = 0;
+ std::fill_n(m_results, ARRAYSIZE(m_results), 0);
+}
+
+u32 PerfQuery::GetQueryResult(PerfQueryType type)
+{
+ u32 result = 0;
+
+ if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC)
+ {
+ result = m_results[PQG_ZCOMP_ZCOMPLOC];
+ }
+ else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT)
+ {
+ result = m_results[PQG_ZCOMP];
+ }
+ else if (type == PQ_BLEND_INPUT)
+ {
+ result = m_results[PQG_ZCOMP] + m_results[PQG_ZCOMP_ZCOMPLOC];
+ }
+ else if (type == PQ_EFB_COPY_CLOCKS)
+ {
+ result = m_results[PQG_EFB_COPY_CLOCKS];
+ }
+
+ return result / 4;
+}
+
+} // namespace
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h
new file mode 100644
index 0000000000..b96fe7a4a0
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h
@@ -0,0 +1,46 @@
+#ifndef _PERFQUERY_H_
+#define _PERFQUERY_H_
+
+#include "PerfQueryBase.h"
+
+namespace OGL {
+
+class PerfQuery : public PerfQueryBase
+{
+public:
+ PerfQuery();
+ ~PerfQuery();
+
+ void EnableQuery(PerfQueryGroup type);
+ void DisableQuery(PerfQueryGroup type);
+ void ResetQuery();
+ u32 GetQueryResult(PerfQueryType type);
+ void FlushResults();
+ bool IsFlushed() const;
+
+private:
+ struct ActiveQuery
+ {
+ GLuint query_id;
+ PerfQueryGroup query_type;
+ };
+
+ // when testing in SMS: 64 was too small, 128 was ok
+ static const u32 PERF_QUERY_BUFFER_SIZE = 512;
+
+ void WeakFlush();
+ // Only use when non-empty
+ void FlushOne();
+
+ // This contains gl query objects with unretrieved results.
+ ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE];
+ u32 m_query_read_pos;
+
+ // TODO: sloppy
+ volatile u32 m_query_count;
+ volatile u32 m_results[PQG_NUM_MEMBERS];
+};
+
+} // namespace
+
+#endif // _PERFQUERY_H_
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp
index 61e41008b3..1d3865851a 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp
@@ -27,346 +27,88 @@
#include "Common.h"
#include "Render.h"
#include "VertexShaderGen.h"
-#include "PixelShaderCache.h"
+#include "ProgramShaderCache.h"
#include "PixelShaderManager.h"
+#include "OnScreenDisplay.h"
+#include "StringUtil.h"
#include "FileUtil.h"
#include "Debugger.h"
namespace OGL
{
-static int s_nMaxPixelInstructions;
-static GLuint s_ColorMatrixProgram = 0;
-static GLuint s_DepthMatrixProgram = 0;
-PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
-PIXELSHADERUID PixelShaderCache::s_curuid;
-bool PixelShaderCache::s_displayCompileAlert;
-GLuint PixelShaderCache::CurrentShader;
-bool PixelShaderCache::ShaderEnabled;
-
-PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry = NULL;
-PIXELSHADERUID PixelShaderCache::last_uid;
-
-GLuint PixelShaderCache::GetDepthMatrixProgram()
-{
- return s_DepthMatrixProgram;
-}
-
-GLuint PixelShaderCache::GetColorMatrixProgram()
+void SetPSConstant4fvByName(const char * name, unsigned int offset, const float *f, const unsigned int count = 1)
{
- return s_ColorMatrixProgram;
-}
-
-void PixelShaderCache::Init()
-{
- glEnable(GL_FRAGMENT_PROGRAM_ARB);
- ShaderEnabled = true;
- CurrentShader = 0;
- last_entry = NULL;
- GL_REPORT_ERRORD();
-
- s_displayCompileAlert = true;
-
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions);
-
- if(s_nMaxPixelInstructions == 0) // Some combination of drivers and hardware returns zero for some reason.
- s_nMaxPixelInstructions = 4096;
- if (strstr((const char*)glGetString(GL_VENDOR), "Humper") != NULL) s_nMaxPixelInstructions = 4096;
-#if CG_VERSION_NUM == 2100
- if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
+ ProgramShaderCache::PCacheEntry tmp = ProgramShaderCache::GetShaderProgram();
+ for (int a = 0; a < NUM_UNIFORMS; ++a)
{
- s_nMaxPixelInstructions = 4096;
- }
-#endif
-
- 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_ATTRIBS_ARB, (GLint *)&maxattribs);
- INFO_LOG(VIDEO, "pixel max_alu=%d, max_inst=%d, max_attrib=%d", s_nMaxPixelInstructions, maxinst, maxattribs);
-
- char pmatrixprog[2048];
- sprintf(pmatrixprog, "!!ARBfp1.0"
- "TEMP R0;\n"
- "TEMP R1;\n"
- "PARAM K0 = { 0.5, 0.5, 0.5, 0.5};\n"
- "TEX R0, fragment.texcoord[0], texture[0], RECT;\n"
- "MUL R0, R0, program.env[%d];\n"
- "ADD R0, R0, K0;\n"
- "FLR R0, R0;\n"
- "MUL R0, R0, program.env[%d];\n"
- "DP4 R1.x, R0, program.env[%d];\n"
- "DP4 R1.y, R0, program.env[%d];\n"
- "DP4 R1.z, R0, program.env[%d];\n"
- "DP4 R1.w, R0, program.env[%d];\n"
- "ADD result.color, R1, program.env[%d];\n"
- "END\n",C_COLORMATRIX+5,C_COLORMATRIX+6, C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+2, C_COLORMATRIX+3, C_COLORMATRIX+4);
- glGenProgramsARB(1, &s_ColorMatrixProgram);
- SetCurrentShader(s_ColorMatrixProgram);
- glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog);
-
- GLenum err = GL_REPORT_ERROR();
- if (err != GL_NO_ERROR) {
- ERROR_LOG(VIDEO, "Failed to create color matrix fragment program");
- glDeleteProgramsARB(1, &s_ColorMatrixProgram);
- s_ColorMatrixProgram = 0;
- }
-
- sprintf(pmatrixprog, "!!ARBfp1.0\n"
- "TEMP R0;\n"
- "TEMP R1;\n"
- "TEMP R2;\n"
- //16777215/16777216*256, 1/255, 256, 0
- "PARAM K0 = { 255.99998474121, 0.003921568627451, 256.0, 0.0};\n"
- "PARAM K1 = { 15.0, 0.066666666666, 0.0, 0.0};\n"
- //sample the depth value
- "TEX R2, fragment.texcoord[0], texture[0], RECT;\n"
-
- //scale from [0*16777216..1*16777216] to
- //[0*16777215..1*16777215], multiply by 256
- "MUL R0, R2.x, K0.x;\n" // *16777215/16777216*256
-
- //It is easy to get bad results due to low precision
- //here, for example converting like this:
- //MUL R0,R0,{ 65536, 256, 1, 16777216 }
- //FRC R0,R0
- //gives {?, 128/255, 254/255, ?} for depth value 254/255
- //on some gpus
-
- "FLR R0.x,R0;\n" //bits 31..24
-
- "SUB R0.yzw,R0,R0.x;\n" //subtract bits 31..24 from rest
- "MUL R0.yzw,R0,K0.z;\n" // *256
- "FLR R0.y,R0;\n" //bits 23..16
-
- "SUB R0.zw,R0,R0.y;\n" //subtract bits 23..16 from rest
- "MUL R0.zw,R0,K0.z;\n" // *256
- "FLR R0.z,R0;\n" //bits 15..8
-
- "MOV R0.w,R0.x;\n" //duplicate bit 31..24
-
- "MUL R0,R0,K0.y;\n" // /255
-
- "MUL R0.w,R0,K1.x;\n" // *15
- "FLR R0.w,R0;\n" //bits 31..28
- "MUL R0.w,R0,K1.y;\n" // /15
-
- "DP4 R1.x, R0, program.env[%d];\n"
- "DP4 R1.y, R0, program.env[%d];\n"
- "DP4 R1.z, R0, program.env[%d];\n"
- "DP4 R1.w, R0, 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);
- glGenProgramsARB(1, &s_DepthMatrixProgram);
- SetCurrentShader(s_DepthMatrixProgram);
- glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog);
-
- err = GL_REPORT_ERROR();
- if (err != GL_NO_ERROR) {
- ERROR_LOG(VIDEO, "Failed to create depth matrix fragment program");
- glDeleteProgramsARB(1, &s_DepthMatrixProgram);
- s_DepthMatrixProgram = 0;
- }
-
-}
-
-void PixelShaderCache::Shutdown()
-{
- glDeleteProgramsARB(1, &s_ColorMatrixProgram);
- s_ColorMatrixProgram = 0;
- glDeleteProgramsARB(1, &s_DepthMatrixProgram);
- s_DepthMatrixProgram = 0;
- PSCache::iterator iter = PixelShaders.begin();
- for (; iter != PixelShaders.end(); iter++)
- iter->second.Destroy();
- PixelShaders.clear();
-}
-
-FRAGMENTSHADER* PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
-{
- PIXELSHADERUID uid;
- GetPixelShaderId(&uid, dstAlphaMode, components);
-
- // Check if the shader is already set
- if (last_entry)
- {
- if (uid == last_uid)
+ if (!strcmp(name, UniformNames[a]))
{
- GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
- ValidatePixelShaderIDs(API_OPENGL, last_entry->safe_uid, last_entry->shader.strprog, dstAlphaMode, components);
- return &last_entry->shader;
+ if (tmp.shader.UniformLocations[a] == -1)
+ return;
+ else
+ {
+ glUniform4fv(tmp.shader.UniformLocations[a] + offset, count, f);
+ return;
+ }
}
}
-
- last_uid = uid;
-
- PSCache::iterator iter = PixelShaders.find(uid);
- if (iter != PixelShaders.end())
- {
- PSCacheEntry &entry = iter->second;
- last_entry = &entry;
-
- GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
- ValidatePixelShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, dstAlphaMode, components);
- return &last_entry->shader;
- }
-
- // Make an entry in the table
- PSCacheEntry& newentry = PixelShaders[uid];
- last_entry = &newentry;
- const char *code = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, components);
-
- if (g_ActiveConfig.bEnableShaderDebugging && code)
- {
- GetSafePixelShaderId(&newentry.safe_uid, dstAlphaMode, components);
- newentry.shader.strprog = code;
- }
-
-#if defined(_DEBUG) || defined(DEBUGFAST)
- if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
- static int counter = 0;
- char szTemp[MAX_PATH];
- sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
-
- SaveData(szTemp, code);
- }
-#endif
-
- if (!code || !CompilePixelShader(newentry.shader, code)) {
- GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
- return NULL;
- }
-
- INCSTAT(stats.numPixelShadersCreated);
- SETSTAT(stats.numPixelShadersAlive, PixelShaders.size());
- GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
- return &last_entry->shader;
}
-bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
+// Renderer functions
+void Renderer::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{
- GLenum err = GL_REPORT_ERROR();
- if (err != GL_NO_ERROR)
- {
- ERROR_LOG(VIDEO, "glError %08x before PS!", err);
- }
-
-#if defined HAVE_CG && HAVE_CG
- char stropt[128];
- sprintf(stropt, "MaxLocalParams=224,NumInstructionSlots=%d", s_nMaxPixelInstructions);
- const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
- CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts);
+ float const f[4] = {f1, f2, f3, f4};
- // handle errors
- if (!cgIsProgram(tempprog))
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- cgDestroyProgram(tempprog);
-
- static int num_failures = 0;
- char szTemp[MAX_PATH];
- sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
- file << pstrprogram;
- file.close();
-
- PanicAlert("Failed to compile pixel shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%d):\n%s",
- szTemp,
- g_cgfProf,
- cgGetLastListing(g_cgcontext));
-
- return false;
+ ProgramShaderCache::SetMultiPSConstant4fv(const_number, f, 1);
+ return;
}
-
- // handle warnings
- if (cgGetError() != CG_NO_ERROR)
+ for (unsigned int a = 0; a < 10; ++a)
{
- WARN_LOG(VIDEO, "Warnings on compile ps %s:", cgGetLastListing(g_cgcontext));
- WARN_LOG(VIDEO, "%s", pstrprogram);
+ if (const_number >= PSVar_Loc[a].reg && const_number < (PSVar_Loc[a].reg + PSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - PSVar_Loc[a].reg;
+ SetPSConstant4fvByName(PSVar_Loc[a].name, offset, f);
+ return;
+ }
}
+}
- // 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...
- char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
- char *plocal = strstr(pcompiledprog, "program.local");
- while (plocal != NULL)
+void Renderer::SetPSConstant4fv(unsigned int const_number, const float *f)
+{
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- const char *penv = " program.env";
- memcpy(plocal, penv, 13);
- plocal = strstr(plocal+13, "program.local");
+ ProgramShaderCache::SetMultiPSConstant4fv(const_number, f, 1);
+ return;
}
-
- glGenProgramsARB(1, &ps.glprogid);
- SetCurrentShader(ps.glprogid);
- glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
-
- err = GL_REPORT_ERROR();
- if (err != GL_NO_ERROR)
+ for (unsigned int a = 0; a < 10; ++a)
{
- GLint error_pos, native_limit;
- glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native_limit);
- // Error occur
- if (error_pos != -1) {
- const char *program_error = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);
- char line[256];
- strncpy(line, (const char *)pcompiledprog + error_pos, 255);
- line[255] = 0;
- ERROR_LOG(VIDEO, "Error at %i: %s", error_pos, program_error);
- ERROR_LOG(VIDEO, "Line dump: \n%s", line);
- } else if (native_limit != -1) {
- ERROR_LOG(VIDEO, "Hit limit? %i", native_limit);
- // TODO
+ if (const_number >= PSVar_Loc[a].reg && const_number < (PSVar_Loc[a].reg + PSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - PSVar_Loc[a].reg;
+ SetPSConstant4fvByName(PSVar_Loc[a].name, offset, f);
+ return;
}
- ERROR_LOG(VIDEO, "%s", pstrprogram);
- ERROR_LOG(VIDEO, "%s", pcompiledprog);
}
-
- cgDestroyProgram(tempprog);
-#endif
-
- return true;
}
-//Disable Fragment programs and reset the selected Program
-void PixelShaderCache::DisableShader()
-{
- if(ShaderEnabled)
- {
- glDisable(GL_FRAGMENT_PROGRAM_ARB);
- ShaderEnabled = false;
- }
-}
-
-//bind a program if is diferent from the binded oone
-void PixelShaderCache::SetCurrentShader(GLuint Shader)
+void Renderer::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
{
- if(!ShaderEnabled)
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- glEnable(GL_FRAGMENT_PROGRAM_ARB);
- ShaderEnabled = true;
+ ProgramShaderCache::SetMultiPSConstant4fv(const_number, f, count);
+ return;
}
- if(CurrentShader != Shader)
+ for (unsigned int a = 0; a < 10; ++a)
{
- if(Shader != 0)
- CurrentShader = Shader;
- glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, CurrentShader);
+ if (const_number >= PSVar_Loc[a].reg && const_number < (PSVar_Loc[a].reg + PSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - PSVar_Loc[a].reg;
+ SetPSConstant4fvByName(PSVar_Loc[a].name, offset, f, count);
+ return;
+ }
}
}
-
-void Renderer::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
-{
- float f[4] = { f1, f2, f3, f4 };
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
-}
-
-void Renderer::SetPSConstant4fv(unsigned int const_number, const float *f)
-{
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
-}
-
-void Renderer::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
-{
- for (unsigned int i = 0; i < count; i++,f+=4)
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number + i, f);
-}
-
} // namespace OGL
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h
deleted file mode 100644
index f528eeb35b..0000000000
--- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (C) 2003 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#ifndef _PIXELSHADERCACHE_H_
-#define _PIXELSHADERCACHE_H_
-
-#include <map>
-#include <string>
-
-#include "BPMemory.h"
-#include "PixelShaderGen.h"
-
-namespace OGL
-{
-
-struct FRAGMENTSHADER
-{
- FRAGMENTSHADER() : glprogid(0) { }
- void Destroy()
- {
- if (glprogid)
- {
- glDeleteProgramsARB(1, &glprogid);
- glprogid = 0;
- }
- }
- GLuint glprogid; // opengl program id
- std::string strprog;
-};
-
-class PixelShaderCache
-{
- struct PSCacheEntry
- {
- FRAGMENTSHADER shader;
- PSCacheEntry() {}
- ~PSCacheEntry() {}
- void Destroy()
- {
- shader.Destroy();
- }
- PIXELSHADERUIDSAFE safe_uid;
- };
-
- typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
-
- static PSCache PixelShaders;
-
- static PIXELSHADERUID s_curuid; // the current pixel shader uid (progressively changed as memory is written)
-
- static bool s_displayCompileAlert;
-
- static GLuint CurrentShader;
- static PSCacheEntry* last_entry;
- static PIXELSHADERUID last_uid;
-
- static bool ShaderEnabled;
-
-public:
- static void Init();
- static void Shutdown();
-
- static FRAGMENTSHADER* SetShader(DSTALPHA_MODE dstAlphaMode, u32 components);
- static bool CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram);
-
- static GLuint GetColorMatrixProgram();
-
- static GLuint GetDepthMatrixProgram();
-
- static void SetCurrentShader(GLuint Shader);
-
- static void DisableShader();
-};
-
-} // namespace OGL
-
-#endif // _PIXELSHADERCACHE_H_
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp
index 7442e5d294..9a3e0b9bed 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp
@@ -20,7 +20,8 @@
#include "VideoConfig.h"
#include "GLUtil.h"
#include "PostProcessing.h"
-#include "PixelShaderCache.h"
+#include "ProgramShaderCache.h"
+#include "FramebufferManager.h"
namespace OGL
{
@@ -29,16 +30,72 @@ namespace PostProcessing
{
static std::string s_currentShader;
-static FRAGMENTSHADER s_shader;
+static SHADER s_shader;
+static bool s_enable;
+
+static u32 s_width;
+static u32 s_height;
+static GLuint s_fbo;
+static GLuint s_texture;
+static GLuint s_vao;
+static GLuint s_vbo;
+
+static GLuint s_uniform_resolution;
+
+static char s_vertex_shader[] =
+ "in vec2 rawpos;\n"
+ "in vec2 tex0;\n"
+ "out vec2 uv0;\n"
+ "void main(void) {\n"
+ " gl_Position = vec4(rawpos,0,1);\n"
+ " uv0 = tex0;\n"
+ "}\n";
void Init()
{
s_currentShader = "";
+ s_enable = 0;
+ s_width = 0;
+ s_height = 0;
+
+ glGenFramebuffers(1, &s_fbo);
+ glGenTextures(1, &s_texture);
+ glBindTexture(GL_TEXTURE_2D, s_texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); // disable mipmaps
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glBindFramebuffer(GL_FRAMEBUFFER, s_fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, s_texture, 0);
+ FramebufferManager::SetFramebuffer(0);
+
+ glGenBuffers(1, &s_vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, s_vbo);
+ GLfloat vertices[] = {
+ -1.f, -1.f, 0.f, 0.f,
+ -1.f, 1.f, 0.f, 1.f,
+ 1.f, -1.f, 1.f, 0.f,
+ 1.f, 1.f, 1.f, 1.f
+ };
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+ glGenVertexArrays(1, &s_vao);
+ glBindVertexArray( s_vao );
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, NULL);
+ glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
+ glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
}
void Shutdown()
{
s_shader.Destroy();
+
+ glDeleteFramebuffers(1, &s_vbo);
+ glDeleteTextures(1, &s_texture);
+
+ glDeleteBuffers(1, &s_vbo);
+ glDeleteVertexArrays(1, &s_vao);
}
void ReloadShader()
@@ -46,45 +103,83 @@ void ReloadShader()
s_currentShader = "";
}
-bool ApplyShader()
+void BindTargetFramebuffer ()
{
- if (s_currentShader != File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".txt")
- {
- // Set immediately to prevent endless recompiles on failure.
- if (!g_ActiveConfig.sPostProcessingShader.empty())
- s_currentShader = File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".txt";
- else
- s_currentShader.clear();
-
- s_shader.Destroy();
-
- if (!s_currentShader.empty())
- {
- std::string code;
- if (File::ReadFileToString(true, s_currentShader.c_str(), code))
- {
- if (!PixelShaderCache::CompilePixelShader(s_shader, code.c_str()))
- {
- ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
- }
- }
- else
- {
- ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str());
- }
- }
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, s_enable ? s_fbo : 0);
+}
+
+void BlitToScreen()
+{
+ if(!s_enable) return;
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ glViewport(0, 0, s_width, s_height);
+
+ glBindVertexArray(s_vao);
+ s_shader.Bind();
+
+ glUniform4f(s_uniform_resolution, (float)s_width, (float)s_height, 1.0f/(float)s_width, 1.0f/(float)s_height);
+
+ glActiveTexture(GL_TEXTURE0+9);
+ glBindTexture(GL_TEXTURE_2D, s_texture);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+/* glBindFramebuffer(GL_READ_FRAMEBUFFER, s_fbo);
+
+ glBlitFramebuffer(rc.left, rc.bottom, rc.right, rc.top,
+ rc.left, rc.bottom, rc.right, rc.top,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);*/
+}
+
+void Update ( u32 width, u32 height )
+{
+ ApplyShader();
+
+ if(s_enable && (width != s_width || height != s_height)) {
+ s_width = width;
+ s_height = height;
+
+ // alloc texture for framebuffer
+ glActiveTexture(GL_TEXTURE0+9);
+ glBindTexture(GL_TEXTURE_2D, s_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
}
+}
- if (s_shader.glprogid != 0)
- {
- PixelShaderCache::SetCurrentShader(s_shader.glprogid);
- return true;
+void ApplyShader()
+{
+ // shader didn't changed
+ if (s_currentShader == g_ActiveConfig.sPostProcessingShader) return;
+ s_currentShader = g_ActiveConfig.sPostProcessingShader;
+ s_enable = false;
+ s_shader.Destroy();
+
+ // shader disabled
+ if (g_ActiveConfig.sPostProcessingShader == "") return;
+
+ // so need to compile shader
+
+ // loading shader code
+ std::string code;
+ std::string path = File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".txt";
+ if(!File::ReadFileToString(true, path.c_str(), code)) {
+ ERROR_LOG(VIDEO, "post-processing shader not found: %s", path.c_str());
+ return;
}
- else
- {
- PixelShaderCache::DisableShader();
- return false;
+
+ // and compile it
+ if (!ProgramShaderCache::CompileShader(s_shader, s_vertex_shader, code.c_str())) {
+ ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
+ return;
}
+
+ // read uniform locations
+ s_uniform_resolution = glGetUniformLocation(s_shader.glprogid, "resolution");
+
+ // successful
+ s_enable = true;
}
} // namespace
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.h b/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.h
index 5d667e2b0a..10a30d9e27 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.h
@@ -30,9 +30,13 @@ namespace PostProcessing
void Init();
void Shutdown();
+void BindTargetFramebuffer();
+void BlitToScreen();
+void Update(u32 width, u32 height);
+
void ReloadShader();
-// Returns false if no shader was applied.
-bool ApplyShader();
+
+void ApplyShader();
} // namespace
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp
new file mode 100644
index 0000000000..4c516853d7
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp
@@ -0,0 +1,553 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "ProgramShaderCache.h"
+#include "MathUtil.h"
+#include "StreamBuffer.h"
+#include "Debugger.h"
+#include "Statistics.h"
+#include "ImageWrite.h"
+#include "Render.h"
+
+namespace OGL
+{
+
+static const u32 UBO_LENGTH = 32*1024*1024;
+
+GLintptr ProgramShaderCache::s_vs_data_size;
+GLintptr ProgramShaderCache::s_ps_data_size;
+GLintptr ProgramShaderCache::s_vs_data_offset;
+u8 *ProgramShaderCache::s_ubo_buffer;
+u32 ProgramShaderCache::s_ubo_buffer_size;
+bool ProgramShaderCache::s_ubo_dirty;
+
+static StreamBuffer *s_buffer;
+
+LinearDiskCache<SHADERUID, u8> g_program_disk_cache;
+static GLuint CurrentProgram = 0;
+ProgramShaderCache::PCache ProgramShaderCache::pshaders;
+ProgramShaderCache::PCacheEntry* ProgramShaderCache::last_entry;
+SHADERUID ProgramShaderCache::last_uid;
+
+static char s_glsl_header[1024] = "";
+
+const char *UniformNames[NUM_UNIFORMS] =
+{
+ // PIXEL SHADER UNIFORMS
+ I_COLORS,
+ I_KCOLORS,
+ I_ALPHA,
+ I_TEXDIMS,
+ I_ZBIAS ,
+ I_INDTEXSCALE ,
+ I_INDTEXMTX,
+ I_FOG,
+ I_PLIGHTS,
+ I_PMATERIALS,
+ // VERTEX SHADER UNIFORMS
+ I_POSNORMALMATRIX,
+ I_PROJECTION ,
+ I_MATERIALS,
+ I_LIGHTS,
+ I_TEXMATRICES,
+ I_TRANSFORMMATRICES ,
+ I_NORMALMATRICES ,
+ I_POSTTRANSFORMMATRICES,
+ I_DEPTHPARAMS,
+};
+
+void SHADER::SetProgramVariables()
+{
+ // glsl shader must be bind to set samplers
+ Bind();
+
+ // Bind UBO
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ {
+ GLint PSBlock_id = glGetUniformBlockIndex(glprogid, "PSBlock");
+ GLint VSBlock_id = glGetUniformBlockIndex(glprogid, "VSBlock");
+
+ if(PSBlock_id != -1)
+ glUniformBlockBinding(glprogid, PSBlock_id, 1);
+ if(VSBlock_id != -1)
+ glUniformBlockBinding(glprogid, VSBlock_id, 2);
+ }
+
+ // We cache our uniform locations for now
+ // Once we move up to a newer version of GLSL, ~1.30
+ // We can remove this
+
+ // (Sonicadvance): For some reason this fails on my hardware
+ //glGetUniformIndices(glprogid, NUM_UNIFORMS, UniformNames, UniformLocations);
+ // Got to do it this crappy way.
+ UniformLocations[0] = glGetUniformLocation(glprogid, UniformNames[0]);
+ if (!g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ for (int a = 1; a < NUM_UNIFORMS; ++a)
+ UniformLocations[a] = glGetUniformLocation(glprogid, UniformNames[a]);
+
+ // Bind Texture Sampler
+ for (int a = 0; a <= 9; ++a)
+ {
+ char name[8];
+ snprintf(name, 8, "samp%d", a);
+
+ // Still need to get sampler locations since we aren't binding them statically in the shaders
+ int loc = glGetUniformLocation(glprogid, name);
+ if (loc != -1)
+ glUniform1i(loc, a);
+ }
+
+}
+
+void SHADER::SetProgramBindings()
+{
+ if (g_ActiveConfig.backend_info.bSupportsDualSourceBlend)
+ {
+ // So we do support extended blending
+ // So we need to set a few more things here.
+ // Bind our out locations
+ glBindFragDataLocationIndexed(glprogid, 0, 0, "ocol0");
+ glBindFragDataLocationIndexed(glprogid, 0, 1, "ocol1");
+ }
+ else
+ glBindFragDataLocation(glprogid, 0, "ocol0");
+
+ // Need to set some attribute locations
+ glBindAttribLocation(glprogid, SHADER_POSITION_ATTRIB, "rawpos");
+
+ glBindAttribLocation(glprogid, SHADER_POSMTX_ATTRIB, "fposmtx");
+
+ glBindAttribLocation(glprogid, SHADER_COLOR0_ATTRIB, "color0");
+ glBindAttribLocation(glprogid, SHADER_COLOR1_ATTRIB, "color1");
+
+ glBindAttribLocation(glprogid, SHADER_NORM0_ATTRIB, "rawnorm0");
+ glBindAttribLocation(glprogid, SHADER_NORM1_ATTRIB, "rawnorm1");
+ glBindAttribLocation(glprogid, SHADER_NORM2_ATTRIB, "rawnorm2");
+
+ for(int i=0; i<8; i++) {
+ char attrib_name[8];
+ snprintf(attrib_name, 8, "tex%d", i);
+ glBindAttribLocation(glprogid, SHADER_TEXTURE0_ATTRIB+i, attrib_name);
+ }
+}
+
+void SHADER::Bind()
+{
+ if(CurrentProgram != glprogid)
+ {
+ glUseProgram(glprogid);
+ CurrentProgram = glprogid;
+ }
+}
+
+
+void ProgramShaderCache::SetMultiPSConstant4fv(unsigned int offset, const float *f, unsigned int count)
+{
+ s_ubo_dirty = true;
+ memcpy(s_ubo_buffer+(offset*4*sizeof(float)), f, count*4*sizeof(float));
+}
+
+void ProgramShaderCache::SetMultiVSConstant4fv(unsigned int offset, const float *f, unsigned int count)
+{
+ s_ubo_dirty = true;
+ memcpy(s_ubo_buffer+(offset*4*sizeof(float))+s_vs_data_offset, f, count*4*sizeof(float));
+}
+
+void ProgramShaderCache::UploadConstants()
+{
+ if(s_ubo_dirty) {
+ s_buffer->Alloc(s_ubo_buffer_size);
+ size_t offset = s_buffer->Upload(s_ubo_buffer, s_ubo_buffer_size);
+ glBindBufferRange(GL_UNIFORM_BUFFER, 1, s_buffer->getBuffer(), offset, s_ps_data_size);
+ glBindBufferRange(GL_UNIFORM_BUFFER, 2, s_buffer->getBuffer(), offset + s_vs_data_offset, s_vs_data_size);
+ s_ubo_dirty = false;
+ }
+}
+
+GLuint ProgramShaderCache::GetCurrentProgram(void)
+{
+ return CurrentProgram;
+}
+
+SHADER* ProgramShaderCache::SetShader ( DSTALPHA_MODE dstAlphaMode, u32 components )
+{
+ SHADERUID uid;
+ GetShaderId(&uid, dstAlphaMode, components);
+
+ // Check if the shader is already set
+ if (last_entry)
+ {
+ if (uid == last_uid)
+ {
+ GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
+ ValidateShaderIDs(last_entry, dstAlphaMode, components);
+ last_entry->shader.Bind();
+ return &last_entry->shader;
+ }
+ }
+
+ last_uid = uid;
+
+ // Check if shader is already in cache
+ PCache::iterator iter = pshaders.find(uid);
+ if (iter != pshaders.end())
+ {
+ PCacheEntry *entry = &iter->second;
+ last_entry = entry;
+
+ GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
+ ValidateShaderIDs(entry, dstAlphaMode, components);
+ last_entry->shader.Bind();
+ return &last_entry->shader;
+ }
+
+ // Make an entry in the table
+ PCacheEntry& newentry = pshaders[uid];
+ last_entry = &newentry;
+ newentry.in_cache = 0;
+
+ const char *vcode = GenerateVertexShaderCode(components, API_OPENGL);
+ const char *pcode = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, components);
+
+ if (g_ActiveConfig.bEnableShaderDebugging)
+ {
+ GetSafeShaderId(&newentry.safe_uid, dstAlphaMode, components);
+ newentry.shader.strvprog = vcode;
+ newentry.shader.strpprog = pcode;
+ }
+
+#if defined(_DEBUG) || defined(DEBUGFAST)
+ if (g_ActiveConfig.iLog & CONF_SAVESHADERS) {
+ static int counter = 0;
+ char szTemp[MAX_PATH];
+ sprintf(szTemp, "%svs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
+ SaveData(szTemp, vcode);
+ sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
+ SaveData(szTemp, pcode);
+ }
+#endif
+
+ if (!CompileShader(newentry.shader, vcode, pcode)) {
+ GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
+ return NULL;
+ }
+
+ INCSTAT(stats.numPixelShadersCreated);
+ SETSTAT(stats.numPixelShadersAlive, pshaders.size());
+ GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
+
+ last_entry->shader.Bind();
+ return &last_entry->shader;
+}
+
+bool ProgramShaderCache::CompileShader ( SHADER& shader, const char* vcode, const char* pcode )
+{
+ GLuint vsid = CompileSingleShader(GL_VERTEX_SHADER, vcode);
+ GLuint psid = CompileSingleShader(GL_FRAGMENT_SHADER, pcode);
+
+ if(!vsid || !psid)
+ {
+ glDeleteShader(vsid);
+ glDeleteShader(psid);
+ return false;
+ }
+
+ GLuint pid = shader.glprogid = glCreateProgram();;
+
+ glAttachShader(pid, vsid);
+ glAttachShader(pid, psid);
+
+ if (g_ogl_config.bSupportsGLSLCache)
+ glProgramParameteri(pid, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
+
+ shader.SetProgramBindings();
+
+ glLinkProgram(pid);
+
+ // original shaders aren't needed any more
+ glDeleteShader(vsid);
+ glDeleteShader(psid);
+
+ GLint linkStatus;
+ glGetProgramiv(pid, GL_LINK_STATUS, &linkStatus);
+ GLsizei length = 0;
+ glGetProgramiv(pid, GL_INFO_LOG_LENGTH, &length);
+ if (linkStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
+ {
+ GLsizei charsWritten;
+ GLchar* infoLog = new GLchar[length];
+ glGetProgramInfoLog(pid, length, &charsWritten, infoLog);
+ ERROR_LOG(VIDEO, "Program info log:\n%s", infoLog);
+ char szTemp[MAX_PATH];
+ sprintf(szTemp, "%sp_%d.txt", File::GetUserPath(D_DUMP_IDX).c_str(), pid);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
+ file << infoLog << s_glsl_header << vcode << s_glsl_header << pcode;
+ file.close();
+ delete [] infoLog;
+ }
+ if (linkStatus != GL_TRUE)
+ {
+ // Compile failed
+ ERROR_LOG(VIDEO, "Program linking failed; see info log");
+
+ // Don't try to use this shader
+ glDeleteProgram(pid);
+ return false;
+ }
+
+ shader.SetProgramVariables();
+
+ return true;
+}
+
+GLuint ProgramShaderCache::CompileSingleShader (GLuint type, const char* code )
+{
+ GLuint result = glCreateShader(type);
+
+ const char *src[] = {s_glsl_header, code};
+
+ glShaderSource(result, 2, src, NULL);
+ glCompileShader(result);
+ GLint compileStatus;
+ glGetShaderiv(result, GL_COMPILE_STATUS, &compileStatus);
+ GLsizei length = 0;
+ glGetShaderiv(result, GL_INFO_LOG_LENGTH, &length);
+ if (compileStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
+ {
+ GLsizei charsWritten;
+ GLchar* infoLog = new GLchar[length];
+ glGetShaderInfoLog(result, length, &charsWritten, infoLog);
+ ERROR_LOG(VIDEO, "PS Shader info log:\n%s", infoLog);
+ char szTemp[MAX_PATH];
+ sprintf(szTemp, "%sps_%d.txt", File::GetUserPath(D_DUMP_IDX).c_str(), result);
+ std::ofstream file;
+ OpenFStream(file, szTemp, std::ios_base::out);
+ file << infoLog << s_glsl_header << code;
+ file.close();
+ delete[] infoLog;
+ }
+ if (compileStatus != GL_TRUE)
+ {
+ // Compile failed
+ ERROR_LOG(VIDEO, "Shader compilation failed; see info log");
+
+ // Don't try to use this shader
+ glDeleteShader(result);
+ return 0;
+ }
+ (void)GL_REPORT_ERROR();
+ return result;
+}
+
+
+
+void ProgramShaderCache::GetShaderId ( SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, u32 components )
+{
+ GetPixelShaderId(&uid->puid, dstAlphaMode, components);
+ GetVertexShaderId(&uid->vuid, components);
+}
+
+void ProgramShaderCache::GetSafeShaderId ( SHADERUIDSAFE* uid, DSTALPHA_MODE dstAlphaMode, u32 components )
+{
+ GetSafePixelShaderId(&uid->puid, dstAlphaMode, components);
+ GetSafeVertexShaderId(&uid->vuid, components);
+}
+
+void ProgramShaderCache::ValidateShaderIDs ( PCacheEntry *entry, DSTALPHA_MODE dstAlphaMode, u32 components )
+{
+ ValidateVertexShaderIDs(API_OPENGL, entry->safe_uid.vuid, entry->shader.strvprog, components);
+ ValidatePixelShaderIDs(API_OPENGL, entry->safe_uid.puid, entry->shader.strpprog, dstAlphaMode, components);
+}
+
+
+
+ProgramShaderCache::PCacheEntry ProgramShaderCache::GetShaderProgram(void)
+{
+ return *last_entry;
+}
+
+void ProgramShaderCache::Init(void)
+{
+ // We have to get the UBO alignment here because
+ // if we generate a buffer that isn't aligned
+ // then the UBO will fail.
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ {
+ GLint Align;
+ glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &Align);
+
+ s_ps_data_size = C_PENVCONST_END * sizeof(float) * 4;
+ s_vs_data_size = C_VENVCONST_END * sizeof(float) * 4;
+ s_vs_data_offset = ROUND_UP(s_ps_data_size, Align);
+ s_ubo_buffer_size = ROUND_UP(s_ps_data_size, Align) + ROUND_UP(s_vs_data_size, Align);
+
+ // We multiply by *4*4 because we need to get down to basic machine units.
+ // So multiply by four to get how many floats we have from vec4s
+ // Then once more to get bytes
+ s_buffer = new StreamBuffer(GL_UNIFORM_BUFFER, UBO_LENGTH);
+
+ s_ubo_buffer = new u8[s_ubo_buffer_size];
+ memset(s_ubo_buffer, 0, s_ubo_buffer_size);
+ s_ubo_dirty = true;
+ }
+
+ // Read our shader cache, only if supported
+ if (g_ogl_config.bSupportsGLSLCache)
+ {
+ GLint Supported;
+ glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &Supported);
+ if(!Supported)
+ {
+ ERROR_LOG(VIDEO, "GL_ARB_get_program_binary is supported, but no binary format is known. So disable shader cache.");
+ g_ogl_config.bSupportsGLSLCache = false;
+ }
+ else
+ {
+ if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
+ File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str());
+
+ char cache_filename[MAX_PATH];
+ sprintf(cache_filename, "%sogl-%s-shaders.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
+ SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
+
+ ProgramShaderCacheInserter inserter;
+ g_program_disk_cache.OpenAndRead(cache_filename, inserter);
+ }
+ SETSTAT(stats.numPixelShadersAlive, pshaders.size());
+ }
+
+ CreateHeader();
+
+ CurrentProgram = 0;
+ last_entry = NULL;
+}
+
+void ProgramShaderCache::Shutdown(void)
+{
+ // store all shaders in cache on disk
+ if (g_ogl_config.bSupportsGLSLCache)
+ {
+ PCache::iterator iter = pshaders.begin();
+ for (; iter != pshaders.end(); ++iter)
+ {
+ if(iter->second.in_cache) continue;
+
+ GLint binary_size;
+ glGetProgramiv(iter->second.shader.glprogid, GL_PROGRAM_BINARY_LENGTH, &binary_size);
+ if(!binary_size) continue;
+
+ u8 *data = new u8[binary_size+sizeof(GLenum)];
+ u8 *binary = data + sizeof(GLenum);
+ GLenum *prog_format = (GLenum*)data;
+ glGetProgramBinary(iter->second.shader.glprogid, binary_size, NULL, prog_format, binary);
+
+ g_program_disk_cache.Append(iter->first, data, binary_size+sizeof(GLenum));
+ delete [] data;
+ }
+
+ g_program_disk_cache.Sync();
+ g_program_disk_cache.Close();
+ }
+
+ glUseProgram(0);
+
+ PCache::iterator iter = pshaders.begin();
+ for (; iter != pshaders.end(); ++iter)
+ iter->second.Destroy();
+ pshaders.clear();
+
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ {
+ delete s_buffer;
+ s_buffer = 0;
+ delete [] s_ubo_buffer;
+ s_ubo_buffer = 0;
+ }
+}
+
+void ProgramShaderCache::CreateHeader ( void )
+{
+#ifdef _WIN32
+ // Intel Windows driver has a issue:
+ // their glsl doesn't know about the ubo extension, so we can't load it.
+ // but as version 140, ubo is in core and don't have to be loaded in glsl.
+ // as sandy do ogl3.1, glsl 140 is supported, so force it in this way.
+ // TODO: remove this again when the issue is fixed:
+ // see http://communities.intel.com/thread/36084
+ bool glsl140_hack = strcmp(g_ogl_config.gl_vendor, "Intel") == 0;
+#elif __APPLE__
+ // as apple doesn't support glsl130 at all, we also have to use glsl140
+ bool glsl140_hack = true;
+#else
+ bool glsl140_hack = false;
+#endif
+
+ snprintf(s_glsl_header, sizeof(s_glsl_header),
+ "#version %s\n"
+ "%s\n" // tex_rect
+ "%s\n" // ubo
+
+ "\n"// A few required defines and ones that will make our lives a lot easier
+ "#define ATTRIN in\n"
+ "#define ATTROUT out\n"
+ "#define VARYIN centroid in\n"
+ "#define VARYOUT centroid out\n"
+
+ // Silly differences
+ "#define float2 vec2\n"
+ "#define float3 vec3\n"
+ "#define float4 vec4\n"
+
+ // hlsl to glsl function translation
+ "#define frac(x) fract(x)\n"
+ "#define saturate(x) clamp(x, 0.0f, 1.0f)\n"
+ "#define lerp(x, y, z) mix(x, y, z)\n"
+
+
+ , glsl140_hack ? "140" : "130"
+ , glsl140_hack ? "#define texture2DRect texture" : "#extension GL_ARB_texture_rectangle : enable"
+ , g_ActiveConfig.backend_info.bSupportsGLSLUBO && !glsl140_hack ? "#extension GL_ARB_uniform_buffer_object : enable" : "// ubo disabled"
+ );
+}
+
+
+void ProgramShaderCache::ProgramShaderCacheInserter::Read ( const SHADERUID& key, const u8* value, u32 value_size )
+{
+ const u8 *binary = value+sizeof(GLenum);
+ GLenum *prog_format = (GLenum*)value;
+ GLint binary_size = value_size-sizeof(GLenum);
+
+ PCacheEntry entry;
+ entry.in_cache = 1;
+ entry.shader.glprogid = glCreateProgram();
+ glProgramBinary(entry.shader.glprogid, *prog_format, binary, binary_size);
+
+ GLint success;
+ glGetProgramiv(entry.shader.glprogid, GL_LINK_STATUS, &success);
+
+ if (success)
+ {
+ pshaders[key] = entry;
+ entry.shader.SetProgramVariables();
+ }
+ else
+ glDeleteProgram(entry.shader.glprogid);
+}
+
+
+} // namespace OGL
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h
new file mode 100644
index 0000000000..c4b03c2973
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h
@@ -0,0 +1,137 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef PROGRAM_SHADER_CACHE_H_
+#define PROGRAM_SHADER_CACHE_H_
+
+#include "GLUtil.h"
+
+#include "PixelShaderGen.h"
+#include "VertexShaderGen.h"
+
+#include "LinearDiskCache.h"
+#include "ConfigManager.h"
+
+namespace OGL
+{
+
+template<bool safe>
+class _SHADERUID
+{
+public:
+ _VERTEXSHADERUID<safe> vuid;
+ _PIXELSHADERUID<safe> puid;
+
+ _SHADERUID() {}
+
+ _SHADERUID(const _SHADERUID& r) : vuid(r.vuid), puid(r.puid) {}
+
+ bool operator <(const _SHADERUID& r) const
+ {
+ if(puid < r.puid) return true;
+ if(r.puid < puid) return false;
+ if(vuid < r.vuid) return true;
+ return false;
+ }
+
+ bool operator ==(const _SHADERUID& r) const
+ {
+ return puid == r.puid && vuid == r.vuid;
+ }
+};
+typedef _SHADERUID<false> SHADERUID;
+typedef _SHADERUID<true> SHADERUIDSAFE;
+
+
+const int NUM_UNIFORMS = 19;
+extern const char *UniformNames[NUM_UNIFORMS];
+
+struct SHADER
+{
+ SHADER() : glprogid(0) { }
+ void Destroy()
+ {
+ glDeleteProgram(glprogid);
+ glprogid = 0;
+ }
+ GLuint glprogid; // opengl program id
+
+ std::string strvprog, strpprog;
+ GLint UniformLocations[NUM_UNIFORMS];
+
+ void SetProgramVariables();
+ void SetProgramBindings();
+ void Bind();
+};
+
+class ProgramShaderCache
+{
+public:
+
+ struct PCacheEntry
+ {
+ SHADER shader;
+ SHADERUIDSAFE safe_uid;
+ bool in_cache;
+
+ void Destroy()
+ {
+ shader.Destroy();
+ }
+ };
+
+ static PCacheEntry GetShaderProgram(void);
+ static GLuint GetCurrentProgram(void);
+ static SHADER* SetShader(DSTALPHA_MODE dstAlphaMode, u32 components);
+ static void GetShaderId(SHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 components);
+ static void GetSafeShaderId(SHADERUIDSAFE *uid, DSTALPHA_MODE dstAlphaMode, u32 components);
+ static void ValidateShaderIDs(PCacheEntry *entry, DSTALPHA_MODE dstAlphaMode, u32 components);
+
+ static bool CompileShader(SHADER &shader, const char* vcode, const char* pcode);
+ static GLuint CompileSingleShader(GLuint type, const char *code);
+
+ static void SetMultiPSConstant4fv(unsigned int offset, const float *f, unsigned int count);
+ static void SetMultiVSConstant4fv(unsigned int offset, const float *f, unsigned int count);
+ static void UploadConstants();
+
+ static void Init(void);
+ static void Shutdown(void);
+ static void CreateHeader(void);
+
+private:
+ class ProgramShaderCacheInserter : public LinearDiskCacheReader<SHADERUID, u8>
+ {
+ public:
+ void Read(const SHADERUID &key, const u8 *value, u32 value_size);
+ };
+
+ typedef std::map<SHADERUID, PCacheEntry> PCache;
+
+ static PCache pshaders;
+ static PCacheEntry* last_entry;
+ static SHADERUID last_uid;
+
+ static GLintptr s_vs_data_size;
+ static GLintptr s_ps_data_size;
+ static GLintptr s_vs_data_offset;
+ static u8 *s_ubo_buffer;
+ static u32 s_ubo_buffer_size;
+ static bool s_ubo_dirty;
+};
+
+} // namespace OGL
+#endif
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp b/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp
index da53fae6d5..0ba2a5b1ae 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp
@@ -17,12 +17,18 @@
#include "GLUtil.h"
-#include <string.h>
-
#include "RasterFont.h"
+#include "ProgramShaderCache.h"
// globals
-const GLubyte rasters[][13] = {
+namespace OGL {
+
+static const u32 char_width = 8;
+static const u32 char_height = 13;
+static const u32 char_offset = 32;
+static const u32 char_count = 95;
+
+const u8 rasters[char_count][char_height] = {
{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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
@@ -120,104 +126,159 @@ const GLubyte rasters[][13] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
};
+static const char *s_vertexShaderSrc =
+ "uniform vec2 charSize;\n"
+ "in vec2 rawpos;\n"
+ "in vec2 tex0;\n"
+ "out vec2 uv0;\n"
+ "void main(void) {\n"
+ " gl_Position = vec4(rawpos,0,1);\n"
+ " uv0 = tex0 * charSize;\n"
+ "}\n";
+
+static const char *s_fragmentShaderSrc =
+ "uniform sampler2D samp8;\n"
+ "uniform vec4 color;\n"
+ "in vec2 uv0;\n"
+ "out vec4 ocol0;\n"
+ "void main(void) {\n"
+ " ocol0 = texture(samp8,uv0) * color;\n"
+ "}\n";
+
+static SHADER s_shader;
+
RasterFont::RasterFont()
{
- // set GL modes
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- // create the raster font
- fontOffset = glGenLists(128);
- for (int i = 32; i < 127; i++) {
- glNewList(i + fontOffset, GL_COMPILE);
- glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
- glEndList();
+ // generate the texture
+ glGenTextures(1, &texture);
+ glActiveTexture(GL_TEXTURE0+8);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ u32* texture_data = new u32[char_width*char_count*char_height];
+ for(u32 y=0; y<char_height; y++) {
+ for(u32 c=0; c<char_count; c++) {
+ for(u32 x=0; x<char_width; x++) {
+ bool pixel = rasters[c][y] & (1<<(char_width-x-1));
+ texture_data[char_width*char_count*y+char_width*c+x] = pixel ? -1 : 0;
+ }
+ }
}
-
- temp_buffer = new char[TEMP_BUFFER_SIZE];
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, char_width*char_count, char_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
+ delete [] texture_data;
+
+ // generate shader
+ ProgramShaderCache::CompileShader(s_shader, s_vertexShaderSrc, s_fragmentShaderSrc);
+
+ // bound uniforms
+ glUniform2f(glGetUniformLocation(s_shader.glprogid,"charSize"), 1.0f / GLfloat(char_count), 1.0f);
+ uniform_color_id = glGetUniformLocation(s_shader.glprogid,"color");
+ glUniform4f(uniform_color_id, 1.0f, 1.0f, 1.0f, 1.0f);
+ cached_color = -1;
+
+ // generate VBO & VAO
+ glGenBuffers(1, &VBO);
+ glGenVertexArrays(1, &VAO);
+ glBindBuffer(GL_ARRAY_BUFFER, VBO);
+ glBindVertexArray(VAO);
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, NULL);
+ glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
+ glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
}
RasterFont::~RasterFont()
{
- glDeleteLists(fontOffset, 128);
- delete [] temp_buffer;
+ glDeleteTextures(1, &texture);
+ glDeleteBuffers(1, &VBO);
+ glDeleteVertexArrays(1, &VAO);
+ s_shader.Destroy();
}
-void RasterFont::printString(const char *s, double x, double y, double z)
+void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight, u32 color)
{
- int length = (int)strlen(s);
- if (!length)
- return;
- if (length >= TEMP_BUFFER_SIZE)
- length = TEMP_BUFFER_SIZE - 1;
-
- // Sanitize string to avoid GL errors.
- char *s2 = temp_buffer;
- memcpy(s2, s, length);
- s2[length] = 0;
- for (int i = 0; i < length; i++) {
- if (s2[i] < 32 || s2[i] > 126)
- s2[i] = '!';
- }
-
- // go to the right spot
- glRasterPos3d(x, y, z);
- GL_REPORT_ERRORD();
-
- glPushAttrib (GL_LIST_BIT);
- glListBase(fontOffset);
- glCallLists((GLsizei)strlen(s2), GL_UNSIGNED_BYTE, (GLubyte *) s2);
- GL_REPORT_ERRORD();
- glPopAttrib();
- GL_REPORT_ERRORD();
-}
-
-void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z)
-{
- int length = (int)strlen(s);
- int x = (int)(screen_width/2.0 - (length/2.0)*char_width);
- printString(s, x, y, z);
-}
-
-void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight)
-{
- double x = start_x;
- double y = start_y;
- char temp[1024];
- char *t = temp;
- while (*text)
- {
- if (*text == '\n')
- {
- *t = 0;
- printString(temp, x, y, z);
- y -= char_height * 2.0f / bbHeight;
+ size_t length = strlen(text);
+ GLfloat *vertices = new GLfloat[length*6*4];
+
+ int usage = 0;
+ GLfloat delta_x = GLfloat(2*char_width)/GLfloat(bbWidth);
+ GLfloat delta_y = GLfloat(2*char_height)/GLfloat(bbHeight);
+ GLfloat border_x = 2.0/GLfloat(bbWidth);
+ GLfloat border_y = 4.0/GLfloat(bbHeight);
+
+ GLfloat x = GLfloat(start_x);
+ GLfloat y = GLfloat(start_y);
+
+ for(size_t i=0; i<length; i++) {
+ u8 c = text[i];
+
+ if(c == '\n') {
x = start_x;
- t = temp;
- }
- else if (*text == '\r')
- {
- t = temp;
+ y -= delta_y + border_y;
+ continue;
}
- else if (*text == '\t')
- {
- //todo: add tabs every something like 4*char_width
- *t = 0;
- int cpos = (int)strlen(temp);
- int newpos = (cpos + 4) & (~3);
- printString(temp, x, y, z);
- x = start_x + (char_width*newpos) * 2.0f / bbWidth;
- t = temp;
- *t++ = ' ';
+
+ // do not print spaces, they can be skipped easyly
+ if(c == ' ') {
+ x += delta_x + border_x;
+ continue;
}
- else
- *t++ = *text;
-
- text++;
+
+ if(c < char_offset || c >= char_count+char_offset) continue;
+
+ vertices[usage++] = x;
+ vertices[usage++] = y;
+ vertices[usage++] = GLfloat(c-char_offset);
+ vertices[usage++] = 0.0f;
+
+ vertices[usage++] = x+delta_x;
+ vertices[usage++] = y;
+ vertices[usage++] = GLfloat(c-char_offset+1);
+ vertices[usage++] = 0.0f;
+
+ vertices[usage++] = x+delta_x;
+ vertices[usage++] = y+delta_y;
+ vertices[usage++] = GLfloat(c-char_offset+1);
+ vertices[usage++] = 1.0f;
+
+ vertices[usage++] = x;
+ vertices[usage++] = y;
+ vertices[usage++] = GLfloat(c-char_offset);
+ vertices[usage++] = 0.0f;
+
+ vertices[usage++] = x+delta_x;
+ vertices[usage++] = y+delta_y;
+ vertices[usage++] = GLfloat(c-char_offset+1);
+ vertices[usage++] = 1.0f;
+
+ vertices[usage++] = x;
+ vertices[usage++] = y+delta_y;
+ vertices[usage++] = GLfloat(c-char_offset);
+ vertices[usage++] = 1.0f;
+
+ x += delta_x + border_x;
+ }
+
+ if(!usage) {
+ delete [] vertices;
+ return;
}
+
+ glBindVertexArray(VAO);
+ glBindBuffer(GL_ARRAY_BUFFER, VBO);
+ glBufferData(GL_ARRAY_BUFFER, usage*sizeof(GLfloat), vertices, GL_STREAM_DRAW);
+
+ delete [] vertices;
- // ????
- if (t != text)
- {
- *t = 0;
- printString(temp, x, y, z);
+ s_shader.Bind();
+
+ if(color != cached_color) {
+ glUniform4f(uniform_color_id, GLfloat((color>>16)&0xff)/255.f,GLfloat((color>>8)&0xff)/255.f,GLfloat((color>>0)&0xff)/255.f,GLfloat((color>>24)&0xff)/255.f);
+ cached_color = color;
}
+
+ glActiveTexture(GL_TEXTURE0+8);
+ glDrawArrays(GL_TRIANGLES, 0, usage/4);
+}
+
}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.h b/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.h
index 3ebc684dd0..3715a91213 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.h
@@ -18,25 +18,24 @@
#ifndef _RASTERFONT_H_
#define _RASTERFONT_H_
+namespace OGL {
+
class RasterFont {
public:
RasterFont();
~RasterFont(void);
static int debug;
-
- // some useful constants
- enum {char_width = 10};
- enum {char_height = 15};
-
- // and the happy helper functions
- 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 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, u32 color);
private:
- int fontOffset;
- char *temp_buffer;
- enum {TEMP_BUFFER_SIZE = 64 * 1024};
+
+ u32 VBO;
+ u32 VAO;
+ u32 texture;
+ u32 uniform_color_id;
+ u32 cached_color;
};
+}
+
#endif // _RASTERFONT_H_
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
index 3ff8b834ce..97015db667 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
@@ -24,6 +24,9 @@
#include <cstdio>
#include "GLUtil.h"
+#if defined(HAVE_WX) && HAVE_WX
+#include "WxUtils.h"
+#endif
#include "FileUtil.h"
@@ -43,9 +46,8 @@
#include "RasterFont.h"
#include "VertexShaderGen.h"
#include "DLCache.h"
-#include "PixelShaderCache.h"
#include "PixelShaderManager.h"
-#include "VertexShaderCache.h"
+#include "ProgramShaderCache.h"
#include "VertexShaderManager.h"
#include "VertexLoaderManager.h"
#include "VertexLoader.h"
@@ -63,6 +65,9 @@
#include "BPFunctions.h"
#include "FPSCounter.h"
#include "ConfigManager.h"
+#include "VertexManager.h"
+#include "SamplerCache.h"
+#include "StreamBuffer.h"
#include "main.h" // Local
#ifdef _WIN32
@@ -94,31 +99,41 @@ typedef struct
} ScrStrct;
#endif
-#if defined HAVE_CG && HAVE_CG
-CGcontext g_cgcontext;
-CGprofile g_cgvProf;
-CGprofile g_cgfProf;
-#endif
int OSDInternalW, OSDInternalH;
namespace OGL
{
+enum MultisampleMode {
+ MULTISAMPLE_OFF,
+ MULTISAMPLE_2X,
+ MULTISAMPLE_4X,
+ MULTISAMPLE_8X,
+ MULTISAMPLE_CSAA_8X,
+ MULTISAMPLE_CSAA_8XQ,
+ MULTISAMPLE_CSAA_16X,
+ MULTISAMPLE_CSAA_16XQ,
+ MULTISAMPLE_SSAA_4X,
+};
+
+
+VideoConfig g_ogl_config;
+
// Declarations and definitions
// ----------------------------
-int s_fps=0;
-
+static int s_fps = 0;
+static GLuint s_ShowEFBCopyRegions_VBO = 0;
+static GLuint s_ShowEFBCopyRegions_VAO = 0;
+static SHADER s_ShowEFBCopyRegions;
-RasterFont* s_pfont = NULL;
+static RasterFont* s_pfont = NULL;
// 1 for no MSAA. Use s_MSAASamples > 1 to check for MSAA.
static int s_MSAASamples = 1;
static int s_MSAACoverageSamples = 0;
static int s_LastMultisampleMode = 0;
-bool s_bHaveFramebufferBlit = false; // export to FramebufferManager.cpp
-static bool s_bHaveCoverageMSAA = false;
static u32 s_blendMode;
#if defined(HAVE_WX) && HAVE_WX
@@ -126,69 +141,82 @@ static std::thread scrshotThread;
#endif
// EFB cache related
-const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks.
-const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up
-const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE;
+static const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks.
+static const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up
+static const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE;
static bool s_efbCacheValid[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT];
static std::vector<u32> s_efbCache[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT]; // 2 for PEEK_Z and PEEK_COLOR
-
-#if defined HAVE_CG && HAVE_CG
-void HandleCgError(CGcontext ctx, CGerror err, void* appdata)
-{
- DEBUG_LOG(VIDEO, "Cg error: %s", cgGetErrorString(err));
- const char* listing = cgGetLastListing(g_cgcontext);
- if (listing != NULL)
- DEBUG_LOG(VIDEO, " last listing: %s", listing);
-}
-#endif
-
int GetNumMSAASamples(int MSAAMode)
{
- // required for MSAA
- if (!s_bHaveFramebufferBlit)
- return 1;
-
+ int samples;
switch (MSAAMode)
{
case MULTISAMPLE_OFF:
- return 1;
+ samples = 1;
+ break;
case MULTISAMPLE_2X:
- return 2;
+ samples = 2;
+ break;
case MULTISAMPLE_4X:
case MULTISAMPLE_CSAA_8X:
case MULTISAMPLE_CSAA_16X:
- return 4;
+ case MULTISAMPLE_SSAA_4X:
+ samples = 4;
+ break;
case MULTISAMPLE_8X:
case MULTISAMPLE_CSAA_8XQ:
case MULTISAMPLE_CSAA_16XQ:
- return 8;
+ samples = 8;
+ break;
default:
- return 1;
+ samples = 1;
}
+
+ if(samples <= g_ogl_config.max_samples) return samples;
+
+ ERROR_LOG(VIDEO, "MSAA Bug: %d samples selected, but only %d supported by gpu.", samples, g_ogl_config.max_samples);
+ return g_ogl_config.max_samples;
}
int GetNumMSAACoverageSamples(int MSAAMode)
{
- if (!s_bHaveCoverageMSAA)
- return 0;
-
+ int samples;
switch (g_ActiveConfig.iMultisampleMode)
{
case MULTISAMPLE_CSAA_8X:
case MULTISAMPLE_CSAA_8XQ:
- return 8;
+ samples = 8;
+ break;
case MULTISAMPLE_CSAA_16X:
case MULTISAMPLE_CSAA_16XQ:
- return 16;
+ samples = 16;
+ break;
default:
- return 0;
+ samples = 0;
+ }
+ if(g_ogl_config.bSupportCoverageMSAA || samples == 0) return samples;
+
+ ERROR_LOG(VIDEO, "MSAA Bug: CSAA selected, but not supported by gpu.");
+ return 0;
+}
+
+void ApplySSAASettings() {
+ if(g_ActiveConfig.iMultisampleMode == MULTISAMPLE_SSAA_4X) {
+ if(g_ogl_config.bSupportSampleShading) {
+ glEnable(GL_SAMPLE_SHADING_ARB);
+ glMinSampleShadingARB(s_MSAASamples);
+ } else {
+ ERROR_LOG(VIDEO, "MSAA Bug: SSAA selected, but not supported by gpu.");
+ }
+ } else if(g_ogl_config.bSupportSampleShading) {
+ glDisable(GL_SAMPLE_SHADING_ARB);
}
}
@@ -199,39 +227,14 @@ Renderer::Renderer()
OSDInternalH = 0;
s_fps=0;
+ s_ShowEFBCopyRegions_VBO = 0;
s_blendMode = 0;
-
InitFPSCounter();
-#if defined HAVE_CG && HAVE_CG
- g_cgcontext = cgCreateContext();
- cgGetError();
- cgSetErrorHandler(HandleCgError, NULL);
-#endif
-
- // Look for required extensions.
- const char *ptoken = (const char*)glGetString(GL_EXTENSIONS);
- if (!ptoken)
- {
- PanicAlert("Your OpenGL Driver seems to be not working.\n"
- "Please make sure your drivers are up-to-date and\n"
- "that your video hardware is OpenGL 2.x compatible.");
- return; // TODO: fail
- }
-
- INFO_LOG(VIDEO, "Supported OpenGL Extensions:");
- INFO_LOG(VIDEO, "%s", ptoken); // write to the log file
- INFO_LOG(VIDEO, "\n");
-
- OSD::AddMessage(StringFromFormat("Video Info: %s, %s, %s",
- glGetString(GL_VENDOR),
- glGetString(GL_RENDERER),
- glGetString(GL_VERSION)).c_str(), 5000);
-
bool bSuccess = true;
GLint numvertexattribs = 0;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &numvertexattribs);
- if (numvertexattribs < 11)
+ if (numvertexattribs < 16)
{
ERROR_LOG(VIDEO, "GPU: OGL ERROR: Number of attributes %d not enough.\n"
"GPU: Does your video card support OpenGL 2.x?",
@@ -240,42 +243,113 @@ Renderer::Renderer()
}
// Init extension support.
+#ifdef __APPLE__
+ glewExperimental = 1;
+#endif
if (glewInit() != GLEW_OK)
{
ERROR_LOG(VIDEO, "glewInit() failed! Does your video card support OpenGL 2.x?");
return; // TODO: fail
}
- if (!GLEW_EXT_framebuffer_object)
+ if (!GLEW_EXT_secondary_color)
{
- ERROR_LOG(VIDEO, "GPU: ERROR: Need GL_EXT_framebufer_object for multiple render targets.\n"
+ ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_EXT_secondary_color.\n"
"GPU: Does your video card support OpenGL 2.x?");
bSuccess = false;
}
- if (!GLEW_EXT_secondary_color)
+ if (!GLEW_ARB_framebuffer_object)
{
- ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_EXT_secondary_color.\n"
- "GPU: Does your video card support OpenGL 2.x?");
+ ERROR_LOG(VIDEO, "GPU: ERROR: Need GL_ARB_framebufer_object for multiple render targets.\n"
+ "GPU: Does your video card support OpenGL 3.0?");
bSuccess = false;
}
- s_bHaveFramebufferBlit = strstr(ptoken, "GL_EXT_framebuffer_blit") != NULL;
- s_bHaveCoverageMSAA = strstr(ptoken, "GL_NV_framebuffer_multisample_coverage") != NULL;
+ if (!GLEW_ARB_vertex_array_object)
+ {
+ ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_ARB_vertex_array_object.\n"
+ "GPU: Does your video card support OpenGL 3.0?");
+ bSuccess = false;
+ }
+
+ if (!GLEW_ARB_map_buffer_range)
+ {
+ ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_ARB_map_buffer_range.\n"
+ "GPU: Does your video card support OpenGL 3.0?");
+ bSuccess = false;
+ }
- s_LastMultisampleMode = g_ActiveConfig.iMultisampleMode;
- s_MSAASamples = GetNumMSAASamples(s_LastMultisampleMode);
- s_MSAACoverageSamples = GetNumMSAACoverageSamples(s_LastMultisampleMode);
+ if (!GLEW_ARB_sampler_objects && bSuccess)
+ {
+ ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_ARB_sampler_objects."
+ "GPU: Does your video card support OpenGL 3.2?"
+ "Please report this issue, then there will be a workaround");
+ bSuccess = false;
+ }
if (!bSuccess)
return; // TODO: fail
+
+ g_Config.backend_info.bSupportsDualSourceBlend = GLEW_ARB_blend_func_extended;
+ g_Config.backend_info.bSupportsGLSLUBO = GLEW_ARB_uniform_buffer_object;
+
+ g_ogl_config.bSupportsGLSLCache = GLEW_ARB_get_program_binary;
+ g_ogl_config.bSupportsGLPinnedMemory = GLEW_AMD_pinned_memory;
+ g_ogl_config.bSupportsGLSync = GLEW_ARB_sync;
+ g_ogl_config.bSupportsGLBaseVertex = GLEW_ARB_draw_elements_base_vertex;
+ g_ogl_config.bSupportCoverageMSAA = GLEW_NV_framebuffer_multisample_coverage;
+ g_ogl_config.bSupportSampleShading = GLEW_ARB_sample_shading;
+
+ g_ogl_config.gl_vendor = (const char*)glGetString(GL_VENDOR);
+ g_ogl_config.gl_renderer = (const char*)glGetString(GL_RENDERER);
+ g_ogl_config.gl_version = (const char*)glGetString(GL_VERSION);
+
+ glGetIntegerv(GL_MAX_SAMPLES, &g_ogl_config.max_samples);
+
+ if(g_Config.backend_info.bSupportsGLSLUBO && (
+ // hd3000 get corruption, hd4000 also and a big slowdown
+ !strcmp(g_ogl_config.gl_vendor, "Intel Open Source Technology Center") && (
+ !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.0.0") ||
+ !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.0.1") ||
+ !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.0.2") ||
+ !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.0.3") ||
+ !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.1.0") ||
+ !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.1.1") )
+ )) {
+ g_Config.backend_info.bSupportsGLSLUBO = false;
+ ERROR_LOG(VIDEO, "buggy driver detected. Disable UBO");
+ }
+
+ UpdateActiveConfig();
+ OSD::AddMessage(StringFromFormat("Video Info: %s, %s, %s",
+ g_ogl_config.gl_vendor,
+ g_ogl_config.gl_renderer,
+ g_ogl_config.gl_version).c_str(), 5000);
+
+ OSD::AddMessage(StringFromFormat("Missing Extensions: %s%s%s%s%s%s%s%s",
+ g_ActiveConfig.backend_info.bSupportsDualSourceBlend ? "" : "DualSourceBlend ",
+ g_ActiveConfig.backend_info.bSupportsGLSLUBO ? "" : "UniformBuffer ",
+ g_ogl_config.bSupportsGLPinnedMemory ? "" : "PinnedMemory ",
+ g_ogl_config.bSupportsGLSLCache ? "" : "ShaderCache ",
+ g_ogl_config.bSupportsGLBaseVertex ? "" : "BaseVertex ",
+ g_ogl_config.bSupportsGLSync ? "" : "Sync ",
+ g_ogl_config.bSupportCoverageMSAA ? "" : "CSAA ",
+ g_ogl_config.bSupportSampleShading ? "" : "SSAA "
+ ).c_str(), 5000);
+
+ s_LastMultisampleMode = g_ActiveConfig.iMultisampleMode;
+ s_MSAASamples = GetNumMSAASamples(s_LastMultisampleMode);
+ s_MSAACoverageSamples = GetNumMSAACoverageSamples(s_LastMultisampleMode);
+ ApplySSAASettings();
+
// Decide frambuffer size
s_backbuffer_width = (int)GLInterface->GetBackBufferWidth();
s_backbuffer_height = (int)GLInterface->GetBackBufferHeight();
// Handle VSync on/off
- int swapInterval = g_ActiveConfig.bVSync ? 1 : 0;
+ int swapInterval = g_ActiveConfig.IsVSync() ? 1 : 0;
GLInterface->SwapInterval(swapInterval);
// check the max texture width and height
@@ -288,9 +362,6 @@ Renderer::Renderer()
if (GL_REPORT_ERROR() != GL_NO_ERROR)
bSuccess = false;
- if (glDrawBuffers == NULL && !GLEW_ARB_draw_buffers)
- glDrawBuffers = glDrawBuffersARB;
-
if (!GLEW_ARB_texture_non_power_of_two)
WARN_LOG(VIDEO, "ARB_texture_non_power_of_two not supported.");
@@ -314,90 +385,17 @@ Renderer::Renderer()
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
s_MSAASamples, s_MSAACoverageSamples);
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
-
if (GL_REPORT_ERROR() != GL_NO_ERROR)
bSuccess = false;
-
- s_pfont = new RasterFont();
-
-#if defined HAVE_CG && HAVE_CG
- // load the effect, find the best profiles (if any)
- if (cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE)
- {
- ERROR_LOG(VIDEO, "arbvp1 not supported");
- return; // TODO: fail
- }
-
- if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE)
- {
- ERROR_LOG(VIDEO, "arbfp1 not supported");
- return; // TODO: fail
- }
-
- g_cgvProf = cgGLGetLatestProfile(CG_GL_VERTEX);
- g_cgfProf = cgGLGetLatestProfile(CG_GL_FRAGMENT);
- if (strstr((const char*)glGetString(GL_VENDOR), "Humper") == NULL)
- {
-#if CG_VERSION_NUM == 2100
- // A bug was introduced in Cg2.1's handling of very large profile option values
- // so this will not work on ATI. ATI returns MAXINT = 2147483647 (0x7fffffff)
- // which is correct in OpenGL but Cg fails to handle it properly. As a result
- // -1 is used by Cg resulting (signedness incorrect) and compilation fails.
- if (strstr((const char*)glGetString(GL_VENDOR), "ATI") == NULL)
-#endif
- {
- cgGLSetOptimalOptions(g_cgvProf);
- cgGLSetOptimalOptions(g_cgfProf);
- }
- }
-#endif // HAVE_CG
-
- int nenvvertparams, nenvfragparams, naddrregisters[2];
- glGetProgramivARB(GL_VERTEX_PROGRAM_ARB,
- GL_MAX_PROGRAM_ENV_PARAMETERS_ARB,
- (GLint *)&nenvvertparams);
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
- GL_MAX_PROGRAM_ENV_PARAMETERS_ARB,
- (GLint *)&nenvfragparams);
- glGetProgramivARB(GL_VERTEX_PROGRAM_ARB,
- GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB,
- (GLint *)&naddrregisters[0]);
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
- GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB,
- (GLint *)&naddrregisters[1]);
- DEBUG_LOG(VIDEO, "Max program env parameters: vert=%d, frag=%d",
- nenvvertparams, nenvfragparams);
- DEBUG_LOG(VIDEO, "Max program address register parameters: vert=%d, frag=%d",
- naddrregisters[0], naddrregisters[1]);
-
- if (nenvvertparams < 238)
- ERROR_LOG(VIDEO, "Not enough vertex shader environment constants!!");
-
-#if defined HAVE_CG && HAVE_CG
- INFO_LOG(VIDEO, "Max buffer sizes: %d %d",
- cgGetProgramBufferMaxSize(g_cgvProf),
- cgGetProgramBufferMaxSize(g_cgfProf));
-#ifndef _DEBUG
- cgGLSetDebugMode(GL_FALSE);
-#endif
-#endif
-
+
glStencilFunc(GL_ALWAYS, 0, 0);
glBlendFunc(GL_ONE, GL_ONE);
glViewport(0, 0, GetTargetWidth(), GetTargetHeight()); // Reset The Current Viewport
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
- glDisable(GL_LIGHTING);
glDepthFunc(GL_LEQUAL);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
@@ -406,39 +404,14 @@ Renderer::Renderer()
glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, GetTargetWidth(), GetTargetHeight());
- glBlendColorEXT(0, 0, 0, 0.5f);
+ glBlendColor(0, 0, 0, 0.5f);
glClearDepth(1.0f);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- // legacy multitexturing: select texture channel only.
- glActiveTexture(GL_TEXTURE0);
- glClientActiveTexture(GL_TEXTURE0);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-
UpdateActiveConfig();
-
- //return GL_REPORT_ERROR() == GL_NO_ERROR && bSuccess;
- return;
}
Renderer::~Renderer()
{
- g_Config.bRunning = false;
- UpdateActiveConfig();
- delete s_pfont;
- s_pfont = 0;
-
-#if defined HAVE_CG && HAVE_CG
- if (g_cgcontext)
- {
- cgDestroyContext(g_cgcontext);
- g_cgcontext = 0;
- }
-#endif
#if defined(HAVE_WX) && HAVE_WX
if (scrshotThread.joinable())
@@ -448,6 +421,49 @@ Renderer::~Renderer()
delete g_framebuffer_manager;
}
+void Renderer::Shutdown()
+{
+ g_Config.bRunning = false;
+ UpdateActiveConfig();
+
+ glDeleteBuffers(1, &s_ShowEFBCopyRegions_VBO);
+ glDeleteVertexArrays(1, &s_ShowEFBCopyRegions_VAO);
+ s_ShowEFBCopyRegions_VBO = 0;
+
+ delete s_pfont;
+ s_pfont = 0;
+ s_ShowEFBCopyRegions.Destroy();
+}
+
+void Renderer::Init()
+{
+ s_pfont = new RasterFont();
+
+ ProgramShaderCache::CompileShader(s_ShowEFBCopyRegions,
+ "in vec2 rawpos;\n"
+ "in vec3 color0;\n"
+ "out vec4 c;\n"
+ "void main(void) {\n"
+ " gl_Position = vec4(rawpos,0,1);\n"
+ " c = vec4(color0, 1.0);\n"
+ "}\n",
+ "in vec4 c;\n"
+ "out vec4 ocol0;\n"
+ "void main(void) {\n"
+ " ocol0 = c;\n"
+ "}\n");
+
+ // creating buffers
+ glGenBuffers(1, &s_ShowEFBCopyRegions_VBO);
+ glGenVertexArrays(1, &s_ShowEFBCopyRegions_VAO);
+ glBindBuffer(GL_ARRAY_BUFFER, s_ShowEFBCopyRegions_VBO);
+ glBindVertexArray( s_ShowEFBCopyRegions_VAO );
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*5, NULL);
+ glEnableVertexAttribArray(SHADER_COLOR0_ATTRIB);
+ glVertexAttribPointer(SHADER_COLOR0_ATTRIB, 3, GL_FLOAT, 0, sizeof(GLfloat)*5, (GLfloat*)NULL+2);
+}
+
// Create On-Screen-Messages
void Renderer::DrawDebugInfo()
{
@@ -469,16 +485,18 @@ void Renderer::DrawDebugInfo()
if (g_ActiveConfig.bShowEFBCopyRegions)
{
- // Store Line Size
- GLfloat lSize;
- glGetFloatv(GL_LINE_WIDTH, &lSize);
-
// Set Line Size
glLineWidth(3.0f);
- glBegin(GL_LINES);
+ // 2*Coords + 3*Color
+ glBindBuffer(GL_ARRAY_BUFFER, s_ShowEFBCopyRegions_VBO);
+ glBufferData(GL_ARRAY_BUFFER, stats.efb_regions.size() * sizeof(GLfloat) * (2+3)*2*6, NULL, GL_STREAM_DRAW);
+ GLfloat *Vertices = (GLfloat*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
// Draw EFB copy regions rectangles
+ int a = 0;
+ GLfloat color[3] = {0.0f, 1.0f, 1.0f};
+
for (std::vector<EFBRectangle>::const_iterator it = stats.efb_regions.begin();
it != stats.efb_regions.end(); ++it)
{
@@ -489,25 +507,97 @@ void Renderer::DrawDebugInfo()
GLfloat x2 = (GLfloat) -1.0f + ((GLfloat)it->right / halfWidth);
GLfloat y2 = (GLfloat) 1.0f - ((GLfloat)it->bottom / halfHeight);
- // Draw shadow of rect
- glColor3f(0.0f, 0.0f, 0.0f);
- glVertex2f(x, y - 0.01); glVertex2f(x2, y - 0.01);
- glVertex2f(x, y2 - 0.01); glVertex2f(x2, y2 - 0.01);
- glVertex2f(x + 0.005, y); glVertex2f(x + 0.005, y2);
- glVertex2f(x2 + 0.005, y); glVertex2f(x2 + 0.005, y2);
-
- // Draw rect
- glColor3f(0.0f, 1.0f, 1.0f);
- glVertex2f(x, y); glVertex2f(x2, y);
- glVertex2f(x, y2); glVertex2f(x2, y2);
- glVertex2f(x, y); glVertex2f(x, y2);
- glVertex2f(x2, y); glVertex2f(x2, y2);
+ Vertices[a++] = x;
+ Vertices[a++] = y;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ Vertices[a++] = x2;
+ Vertices[a++] = y;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+
+ Vertices[a++] = x2;
+ Vertices[a++] = y;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ Vertices[a++] = x2;
+ Vertices[a++] = y2;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+
+ Vertices[a++] = x2;
+ Vertices[a++] = y2;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ Vertices[a++] = x;
+ Vertices[a++] = y2;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+
+ Vertices[a++] = x;
+ Vertices[a++] = y2;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ Vertices[a++] = x;
+ Vertices[a++] = y;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+
+ Vertices[a++] = x;
+ Vertices[a++] = y;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ Vertices[a++] = x2;
+ Vertices[a++] = y2;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+
+ Vertices[a++] = x2;
+ Vertices[a++] = y;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ Vertices[a++] = x;
+ Vertices[a++] = y2;
+ Vertices[a++] = color[0];
+ Vertices[a++] = color[1];
+ Vertices[a++] = color[2];
+
+ // TO DO: build something nicer here
+ GLfloat temp = color[0];
+ color[0] = color[1];
+ color[1] = color[2];
+ color[2] = temp;
}
-
- glEnd();
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+
+ s_ShowEFBCopyRegions.Bind();
+ glBindVertexArray( s_ShowEFBCopyRegions_VAO );
+ glDrawArrays(GL_LINES, 0, stats.efb_regions.size() * 2*6);
// Restore Line Size
- glLineWidth(lSize);
+ SetLineWidth();
// Clear stored regions
stats.efb_regions.clear();
@@ -532,20 +622,12 @@ void Renderer::RenderText(const char *text, int left, int top, u32 color)
const int nBackbufferWidth = (int)GLInterface->GetBackBufferWidth();
const int nBackbufferHeight = (int)GLInterface->GetBackBufferHeight();
- glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
- ((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
s_pfont->printMultilineText(text,
left * 2.0f / (float)nBackbufferWidth - 1,
1 - top * 2.0f / (float)nBackbufferHeight,
- 0, nBackbufferWidth, nBackbufferHeight);
+ 0, nBackbufferWidth, nBackbufferHeight, color);
GL_REPORT_ERRORD();
-
- glDisable(GL_BLEND);
}
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
@@ -671,7 +753,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
{
// Resolve our rectangle.
FramebufferManager::GetEFBDepthTexture(efbPixelRc);
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetResolvedFramebuffer());
}
u32* depthMap = new u32[targetPixelRcWidth * targetPixelRcHeight];
@@ -720,7 +802,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
{
// Resolve our rectangle.
FramebufferManager::GetEFBColorTexture(efbPixelRc);
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetResolvedFramebuffer());
}
u32* colorMap = new u32[targetPixelRcWidth * targetPixelRcHeight];
@@ -858,7 +940,11 @@ void Renderer::SetBlendMode(bool forceUpdate)
{
// Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel
// Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1.
- bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
+ bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
+
+ bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && target_has_alpha;
+ bool useDualSource = useDstAlpha && g_ActiveConfig.backend_info.bSupportsDualSourceBlend;
+
const GLenum glSrcFactors[8] =
{
GL_ZERO,
@@ -884,11 +970,13 @@ void Renderer::SetBlendMode(bool forceUpdate)
// blend mode bit mask
// 0 - blend enable
+ // 1 - dst alpha enabled
// 2 - reverse subtract enable (else add)
// 3-5 - srcRGB function
// 6-8 - dstRGB function
- u32 newval = bpmem.blendmode.subtract << 2;
+ u32 newval = useDualSource << 1;
+ newval |= bpmem.blendmode.subtract << 2;
if (bpmem.blendmode.subtract)
newval |= 0x0049; // enable blending src 1 dst 1
@@ -901,33 +989,23 @@ void Renderer::SetBlendMode(bool forceUpdate)
u32 changes = forceUpdate ? 0xFFFFFFFF : newval ^ s_blendMode;
-#ifdef USE_DUAL_SOURCE_BLEND
- bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate
- && bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
- bool useDualSource = useDstAlpha && GLEW_ARB_blend_func_extended;
-#endif
-
if (changes & 1)
// blend enable change
(newval & 1) ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
if (changes & 4)
{
-#ifdef USE_DUAL_SOURCE_BLEND
// subtract enable change
GLenum equation = newval & 4 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD;
GLenum equationAlpha = useDualSource ? GL_FUNC_ADD : equation;
+
glBlendEquationSeparate(equation, equationAlpha);
-#else
- glBlendEquation(newval & 4 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD);
-#endif
}
- if (changes & 0x1F8)
+ if (changes & 0x1FA)
{
GLenum srcFactor = glSrcFactors[(newval >> 3) & 7];
GLenum dstFactor = glDestFactors[(newval >> 6) & 7];
-#ifdef USE_DUAL_SOURCE_BLEND
GLenum srcFactorAlpha = srcFactor;
GLenum dstFactorAlpha = dstFactor;
if (useDualSource)
@@ -945,31 +1023,31 @@ void Renderer::SetBlendMode(bool forceUpdate)
else if (dstFactor == GL_ONE_MINUS_SRC_ALPHA)
dstFactor = GL_ONE_MINUS_SRC1_ALPHA;
}
-
+
// blend RGB change
glBlendFuncSeparate(srcFactor, dstFactor, srcFactorAlpha, dstFactorAlpha);
-#else
- glBlendFunc(srcFactor, dstFactor);
-#endif
}
s_blendMode = newval;
}
+void DumpFrame(const std::vector<u8>& data, int w, int h)
+{
+#if defined(HAVE_LIBAV) || defined(_WIN32)
+ if (g_ActiveConfig.bDumpFrames && !data.empty())
+ {
+ AVIDump::AddFrame(&data[0], w, h);
+ }
+#endif
+}
+
// This function has the final picture. We adjust the aspect ratio here.
void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma)
{
static int w = 0, h = 0;
if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
{
- if (g_ActiveConfig.bDumpFrames && frame_data)
- {
-#ifdef _WIN32
- AVIDump::AddFrame(frame_data);
-#elif defined HAVE_LIBAV
- AVIDump::AddFrame((u8*)frame_data, w, h);
-#endif
- }
+ DumpFrame(frame_data, w, h);
Core::Callback_VideoCopiedToXFB(false);
return;
}
@@ -979,20 +1057,14 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if (g_ActiveConfig.VirtualXFBEnabled() && (!xfbSourceList || xfbCount == 0))
{
- if (g_ActiveConfig.bDumpFrames && frame_data)
- {
-#ifdef _WIN32
- AVIDump::AddFrame(frame_data);
-#elif defined HAVE_LIBAV
- AVIDump::AddFrame((u8*)frame_data, w, h);
-#endif
- }
+ DumpFrame(frame_data, w, h);
Core::Callback_VideoCopiedToXFB(false);
return;
}
ResetAPIState();
+ PostProcessing::Update(s_backbuffer_width, s_backbuffer_height);
UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height);
TargetRectangle flipped_trc = GetTargetRectangle();
@@ -1000,38 +1072,20 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
int tmp = flipped_trc.top;
flipped_trc.top = flipped_trc.bottom;
flipped_trc.bottom = tmp;
-
- // Textured triangles are necessary because of post-processing shaders
-
- // Disable all other stages
- for (int i = 1; i < 8; ++i)
- OGL::TextureCache::DisableStage(i);
-
- // Update GLViewPort
- glViewport(flipped_trc.left, flipped_trc.bottom, flipped_trc.GetWidth(), flipped_trc.GetHeight());
-
+
GL_REPORT_ERRORD();
// Copy the framebuffer to screen.
- // Texture map s_xfbTexture onto the main buffer
- glActiveTexture(GL_TEXTURE0);
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- // Use linear filtering.
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-
- // We must call ApplyShader here even if no post proc is selected - it takes
- // care of disabling it in that case. It returns false in case of no post processing.
- bool applyShader = PostProcessing::ApplyShader();
-
const XFBSourceBase* xfbSource = NULL;
if(g_ActiveConfig.bUseXFB)
{
+ // Render to the real/postprocessing buffer now.
+ PostProcessing::BindTargetFramebuffer();
+
// draw each xfb source
- // Render to the real buffer now.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the window backbuffer
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer());
for (u32 i = 0; i < xfbCount; ++i)
{
@@ -1041,10 +1095,10 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
if (g_ActiveConfig.bUseRealXFB)
{
- drawRc.top = 1;
- drawRc.bottom = -1;
- drawRc.left = -1;
- drawRc.right = 1;
+ drawRc.top = flipped_trc.top;
+ drawRc.bottom = flipped_trc.bottom;
+ drawRc.left = flipped_trc.left;
+ drawRc.right = flipped_trc.right;
}
else
{
@@ -1052,12 +1106,12 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
int xfbHeight = xfbSource->srcHeight;
int xfbWidth = xfbSource->srcWidth;
int hOffset = ((s32)xfbSource->srcAddr - (s32)xfbAddr) / ((s32)fbWidth * 2);
-
- drawRc.top = 1.0f - (2.0f * (hOffset) / (float)fbHeight);
- drawRc.bottom = 1.0f - (2.0f * (hOffset + xfbHeight) / (float)fbHeight);
- drawRc.left = -(xfbWidth / (float)fbWidth);
- drawRc.right = (xfbWidth / (float)fbWidth);
-
+
+ drawRc.top = flipped_trc.top - hOffset * flipped_trc.GetHeight() / fbHeight;
+ drawRc.bottom = flipped_trc.top - (hOffset + xfbHeight) * flipped_trc.GetHeight() / fbHeight;
+ drawRc.left = flipped_trc.left + (flipped_trc.GetWidth() - xfbWidth * flipped_trc.GetWidth() / fbWidth)/2;
+ drawRc.right = flipped_trc.left + (flipped_trc.GetWidth() + xfbWidth * flipped_trc.GetWidth() / fbWidth)/2;
+
// The following code disables auto stretch. Kept for reference.
// scale draw area for a 1 to 1 pixel mapping with the draw target
//float vScale = (float)fbHeight / (float)flipped_trc.GetHeight();
@@ -1077,62 +1131,30 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
sourceRc.bottom = xfbSource->sourceRc.bottom;
xfbSource->Draw(sourceRc, drawRc, 0, 0);
-
- // We must call ApplyShader here even if no post proc is selected.
- // It takes care of disabling it in that case. It returns false in
- // case of no post processing.
- if (applyShader)
- PixelShaderCache::DisableShader();
}
}
else
{
TargetRectangle targetRc = ConvertEFBRectangle(rc);
- GLuint read_texture = FramebufferManager::ResolveAndGetRenderTarget(rc);
- // Render to the real buffer now.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the window backbuffer
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture);
- if (applyShader)
- {
- glBegin(GL_QUADS);
- glTexCoord2f(targetRc.left, targetRc.bottom);
- glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0);
- glVertex2f(-1, -1);
-
- glTexCoord2f(targetRc.left, targetRc.top);
- glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1);
- glVertex2f(-1, 1);
-
- glTexCoord2f(targetRc.right, targetRc.top);
- glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1);
- glVertex2f( 1, 1);
-
- glTexCoord2f(targetRc.right, targetRc.bottom);
- glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0);
- glVertex2f( 1, -1);
- glEnd();
- PixelShaderCache::DisableShader();
- }
- else
- {
- glBegin(GL_QUADS);
- glTexCoord2f(targetRc.left, targetRc.bottom);
- glVertex2f(-1, -1);
-
- glTexCoord2f(targetRc.left, targetRc.top);
- glVertex2f(-1, 1);
-
- glTexCoord2f(targetRc.right, targetRc.top);
- glVertex2f( 1, 1);
-
- glTexCoord2f(targetRc.right, targetRc.bottom);
- glVertex2f( 1, -1);
- glEnd();
- }
+
+ // for msaa mode, we must resolve the efb content to non-msaa
+ FramebufferManager::ResolveAndGetRenderTarget(rc);
+
+ // Render to the real/postprocessing buffer now. (resolve have changed this in msaa mode)
+ PostProcessing::BindTargetFramebuffer();
+
+ // always the non-msaa fbo
+ GLuint fb = s_MSAASamples>1?FramebufferManager::GetResolvedFramebuffer():FramebufferManager::GetEFBFramebuffer();
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
+ glBlitFramebuffer(targetRc.left, targetRc.bottom, targetRc.right, targetRc.top,
+ flipped_trc.left, flipped_trc.bottom, flipped_trc.right, flipped_trc.top,
+ GL_COLOR_BUFFER_BIT, GL_LINEAR);
}
+
+ PostProcessing::BlitToScreen();
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
- OGL::TextureCache::DisableStage(0);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
// Save screenshot
if (s_bScreenshot)
@@ -1149,16 +1171,15 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
if (g_ActiveConfig.bDumpFrames)
{
std::lock_guard<std::mutex> lk(s_criticalScreenshot);
- if (!frame_data || w != flipped_trc.GetWidth() ||
+ if (frame_data.empty() || w != flipped_trc.GetWidth() ||
h != flipped_trc.GetHeight())
{
- if (frame_data) delete[] frame_data;
w = flipped_trc.GetWidth();
h = flipped_trc.GetHeight();
- frame_data = new char[3 * w * h];
+ frame_data.resize(3 * w * h);
}
glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glReadPixels(flipped_trc.left, flipped_trc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data);
+ glReadPixels(flipped_trc.left, flipped_trc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, &frame_data[0]);
if (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0)
{
if (!bLastFrameDumped)
@@ -1179,12 +1200,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
}
if (bAVIDumping)
{
- #ifdef _WIN32
- AVIDump::AddFrame(frame_data);
- #else
- FlipImageData((u8*)frame_data, w, h);
- AVIDump::AddFrame((u8*)frame_data, w, h);
+ #ifndef _WIN32
+ FlipImageData(&frame_data[0], w, h);
#endif
+
+ AVIDump::AddFrame(&frame_data[0], w, h);
}
bLastFrameDumped = true;
@@ -1196,12 +1216,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
{
if (bLastFrameDumped && bAVIDumping)
{
- if (frame_data)
- {
- delete[] frame_data;
- frame_data = NULL;
- w = h = 0;
- }
+ std::vector<u8>().swap(frame_data);
+ w = h = 0;
AVIDump::Stop();
bAVIDumping = false;
OSD::AddMessage("Stop dumping frames", 2000);
@@ -1215,9 +1231,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
std::string movie_file_name;
w = GetTargetRectangle().GetWidth();
h = GetTargetRectangle().GetHeight();
- frame_data = new char[3 * w * h];
+ frame_data.resize(3 * w * h);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glReadPixels(GetTargetRectangle().left, GetTargetRectangle().bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data);
+ glReadPixels(GetTargetRectangle().left, GetTargetRectangle().bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, &frame_data[0]);
if (GL_REPORT_ERROR() == GL_NO_ERROR)
{
if (!bLastFrameDumped)
@@ -1228,21 +1244,17 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
OSD::AddMessage("Error opening framedump.raw for writing.", 2000);
else
{
- char msg [255];
- sprintf(msg, "Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h);
- OSD::AddMessage(msg, 2000);
+ OSD::AddMessage(StringFromFormat("Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h).c_str(), 2000);
}
}
if (pFrameDump)
{
- FlipImageData((u8*)frame_data, w, h);
- pFrameDump.WriteBytes(frame_data, w * 3 * h);
+ FlipImageData(&frame_data[0], w, h);
+ pFrameDump.WriteBytes(&frame_data[0], w * 3 * h);
pFrameDump.Flush();
}
bLastFrameDumped = true;
}
-
- delete[] frame_data;
}
else
{
@@ -1289,11 +1301,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
s_LastMultisampleMode = g_ActiveConfig.iMultisampleMode;
s_MSAASamples = GetNumMSAASamples(s_LastMultisampleMode);
s_MSAACoverageSamples = GetNumMSAACoverageSamples(s_LastMultisampleMode);
-
+ ApplySSAASettings();
+
delete g_framebuffer_manager;
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
s_MSAASamples, s_MSAACoverageSamples);
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
}
}
@@ -1301,18 +1313,16 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
s_fps = UpdateFPSCounter();
// ---------------------------------------------------------------------
GL_REPORT_ERRORD();
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- DrawDebugText();
DrawDebugInfo();
+ DrawDebugText();
GL_REPORT_ERRORD();
- // Get the status of the Blend mode
- GLboolean blend_enabled = glIsEnabled(GL_BLEND);
- glDisable(GL_BLEND);
OSD::DrawMessages();
- if (blend_enabled)
- glEnable(GL_BLEND);
GL_REPORT_ERRORD();
// Copy the rendered frame to the real window
@@ -1329,6 +1339,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
GL_REPORT_ERRORD();
+ GLInterface->SwapInterval(g_ActiveConfig.IsVSync() ? 1 : 0);
+
// Clean out old stuff from caches. It's not worth it to clean out the shader caches.
DLCache::ProgressiveCleanup();
TextureCache::Cleanup();
@@ -1371,8 +1383,6 @@ void Renderer::ResetAPIState()
{
// Gets us to a reasonably sane state where it's possible to do things like
// image copies with textured quads, etc.
- VertexShaderCache::DisableShader();
- PixelShaderCache::DisableShader();
glDisable(GL_SCISSOR_TEST);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
@@ -1393,9 +1403,12 @@ void Renderer::RestoreAPIState()
VertexShaderManager::SetViewportChanged();
glPolygonMode(GL_FRONT_AND_BACK, g_ActiveConfig.bWireFrame ? GL_LINE : GL_FILL);
-
- VertexShaderCache::SetCurrentShader(0);
- PixelShaderCache::SetCurrentShader(0);
+
+ VertexManager *vm = (OGL::VertexManager*)g_vertex_manager;
+ glBindBuffer(GL_ARRAY_BUFFER, vm->m_vertex_buffers);
+ vm->m_last_vao = 0;
+
+ TextureCache::SetStage();
}
void Renderer::SetGenerationMode()
@@ -1433,6 +1446,7 @@ void Renderer::SetDepthMode()
else
{
// if the test is disabled write is disabled too
+ // TODO: When PE performance metrics are being emulated via occlusion queries, we should (probably?) enable depth test with depth function ALWAYS here
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
}
@@ -1492,7 +1506,11 @@ void Renderer::SetLineWidth()
void Renderer::SetSamplerState(int stage, int texindex)
{
- // TODO
+ auto const& tex = bpmem.tex[texindex];
+ auto const& tm0 = tex.texMode0[stage];
+ auto const& tm1 = tex.texMode1[stage];
+
+ g_sampler_cache->SetSamplerState((texindex * 4) + stage, tm0, tm1);
}
void Renderer::SetInterlacingMode()
@@ -1552,7 +1570,7 @@ void TakeScreenshot(ScrStrct* threadStruct)
// Save the screenshot and finally kill the wxImage object
// This is really expensive when saving to PNG, but not at all when using BMP
- threadStruct->img->SaveFile(wxString::FromAscii(threadStruct->filename.c_str()),
+ threadStruct->img->SaveFile(StrToWxStr(threadStruct->filename),
wxBITMAP_TYPE_PNG);
threadStruct->img->Destroy();
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.h b/Source/Plugins/Plugin_VideoOGL/Src/Render.h
index 9cf1573b56..d5510753c2 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/Render.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.h
@@ -9,11 +9,30 @@ namespace OGL
void ClearEFBCache();
+// ogl-only config, so not in VideoConfig.h
+extern struct VideoConfig {
+ bool bSupportsGLSLCache;
+ bool bSupportsGLPinnedMemory;
+ bool bSupportsGLSync;
+ bool bSupportsGLBaseVertex;
+ bool bSupportCoverageMSAA;
+ bool bSupportSampleShading;
+
+ const char *gl_vendor;
+ const char *gl_renderer;
+ const char* gl_version;
+
+ s32 max_samples;
+} g_ogl_config;
+
class Renderer : public ::Renderer
{
public:
Renderer();
~Renderer();
+
+ static void Init();
+ static void Shutdown();
void SetColorMask();
void SetBlendMode(bool forceUpdate);
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.cpp
new file mode 100644
index 0000000000..b007f89796
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.cpp
@@ -0,0 +1,129 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "SamplerCache.h"
+
+namespace OGL
+{
+
+SamplerCache *g_sampler_cache;
+
+SamplerCache::SamplerCache()
+ : m_last_max_anisotropy()
+{}
+
+SamplerCache::~SamplerCache()
+{
+ Clear();
+}
+
+void SamplerCache::SetSamplerState(int stage, const TexMode0& tm0, const TexMode1& tm1)
+{
+ // TODO: can this go somewhere else?
+ if (m_last_max_anisotropy != g_ActiveConfig.iMaxAnisotropy)
+ {
+ m_last_max_anisotropy = g_ActiveConfig.iMaxAnisotropy;
+ Clear();
+ }
+
+ Params params(tm0, tm1);
+
+ // take equivalent forced linear when bForceFiltering
+ if (g_ActiveConfig.bForceFiltering)
+ {
+ params.tm0.min_filter |= 0x4;
+ params.tm0.mag_filter |= 0x1;
+ }
+
+ // TODO: Should keep a circular buffer for each stage of recently used samplers.
+
+ auto& active_sampler = m_active_samplers[stage];
+ if (active_sampler.first != params || !active_sampler.second.sampler_id)
+ {
+ // Active sampler does not match parameters (or is invalid), bind the proper one.
+ active_sampler.first = params;
+ active_sampler.second = GetEntry(params);
+ glBindSampler(stage, active_sampler.second.sampler_id);
+ }
+}
+
+auto SamplerCache::GetEntry(const Params& params) -> Value&
+{
+ auto& val = m_cache[params];
+ if (!val.sampler_id)
+ {
+ // Sampler not found in cache, create it.
+ glGenSamplers(1, &val.sampler_id);
+ SetParameters(val.sampler_id, params);
+
+ // TODO: Maybe kill old samplers if the cache gets huge. It doesn't seem to get huge though.
+ //ERROR_LOG(VIDEO, "Sampler cache size is now %ld.", m_cache.size());
+ }
+
+ return val;
+}
+
+void SamplerCache::SetParameters(GLuint sampler_id, const Params& params)
+{
+ static const GLint min_filters[8] =
+ {
+ GL_NEAREST,
+ GL_NEAREST_MIPMAP_NEAREST,
+ GL_NEAREST_MIPMAP_LINEAR,
+ GL_NEAREST,
+ GL_LINEAR,
+ GL_LINEAR_MIPMAP_NEAREST,
+ GL_LINEAR_MIPMAP_LINEAR,
+ GL_LINEAR,
+ };
+
+ static const GLint wrap_settings[4] =
+ {
+ GL_CLAMP_TO_EDGE,
+ GL_REPEAT,
+ GL_MIRRORED_REPEAT,
+ GL_REPEAT,
+ };
+
+ auto& tm0 = params.tm0;
+ auto& tm1 = params.tm1;
+
+ glSamplerParameteri(sampler_id, GL_TEXTURE_MIN_FILTER, min_filters[tm0.min_filter % ARRAYSIZE(min_filters)]);
+ glSamplerParameteri(sampler_id, GL_TEXTURE_MAG_FILTER, tm0.mag_filter ? GL_LINEAR : GL_NEAREST);
+
+ glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_S, wrap_settings[tm0.wrap_s]);
+ glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_T, wrap_settings[tm0.wrap_t]);
+
+ glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, tm0.lod_bias / 32.f);
+
+ glSamplerParameterf(sampler_id, GL_TEXTURE_MIN_LOD, tm1.min_lod / 16.f);
+ glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_LOD, tm1.max_lod / 16.f);
+
+ if (g_ActiveConfig.iMaxAnisotropy > 0)
+ glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_ActiveConfig.iMaxAnisotropy));
+}
+
+void SamplerCache::Clear()
+{
+ for (auto it = m_cache.begin(); it != m_cache.end(); ++it)
+ {
+ glDeleteSamplers(1, &it->second.sampler_id);
+ }
+ m_cache.clear();
+}
+
+}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.h b/Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.h
new file mode 100644
index 0000000000..81180d2a7a
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/SamplerCache.h
@@ -0,0 +1,80 @@
+
+#ifndef INCLUDE_SAMPLER_CACHE_H_
+#define INCLUDE_SAMPLER_CACHE_H_
+
+#include <map>
+
+#include "Render.h"
+#include "GLUtil.h"
+
+namespace OGL
+{
+
+class SamplerCache : NonCopyable
+{
+public:
+ SamplerCache();
+ ~SamplerCache();
+
+ void SetSamplerState(int stage, const TexMode0& tm0, const TexMode1& tm1);
+ void Clear();
+
+private:
+ struct Params
+ {
+ union
+ {
+ struct
+ {
+ TexMode0 tm0;
+ TexMode1 tm1;
+ };
+
+ u64 hex;
+ };
+
+ Params()
+ : hex()
+ {}
+
+ Params(const TexMode0& _tm0, const TexMode1& _tm1)
+ : tm0(_tm0)
+ , tm1(_tm1)
+ {
+ static_assert(sizeof(Params) == 8, "Assuming I can treat this as a 64bit int.");
+ }
+
+ bool operator<(const Params& other) const
+ {
+ return hex < other.hex;
+ }
+
+ bool operator!=(const Params& other) const
+ {
+ return hex != other.hex;
+ }
+ };
+
+ struct Value
+ {
+ Value()
+ : sampler_id()
+ {}
+
+ GLuint sampler_id;
+ };
+
+ void SetParameters(GLuint sampler_id, const Params& params);
+ Value& GetEntry(const Params& params);
+
+ std::map<Params, Value> m_cache;
+ std::pair<Params, Value> m_active_samplers[8];
+
+ int m_last_max_anisotropy;
+};
+
+extern SamplerCache *g_sampler_cache;
+
+}
+
+#endif
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp
new file mode 100644
index 0000000000..24b6b7d9b4
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp
@@ -0,0 +1,242 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Globals.h"
+#include "GLUtil.h"
+#include "StreamBuffer.h"
+#include "MemoryUtil.h"
+#include "Render.h"
+
+namespace OGL
+{
+
+static const u32 SYNC_POINTS = 16;
+static const u32 ALIGN_PINNED_MEMORY = 4096;
+
+StreamBuffer::StreamBuffer(u32 type, size_t size, StreamType uploadType)
+: m_uploadtype(uploadType), m_buffertype(type), m_size(size)
+{
+ glGenBuffers(1, &m_buffer);
+
+ bool nvidia = !strcmp(g_ogl_config.gl_vendor, "NVIDIA Corporation");
+
+ if(m_uploadtype & STREAM_DETECT)
+ {
+ if(!g_ogl_config.bSupportsGLBaseVertex && (m_uploadtype & BUFFERSUBDATA))
+ m_uploadtype = BUFFERSUBDATA;
+ else if(g_ogl_config.bSupportsGLSync && g_Config.bHackedBufferUpload && (m_uploadtype & MAP_AND_RISK))
+ m_uploadtype = MAP_AND_RISK;
+ else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory && (m_uploadtype & PINNED_MEMORY))
+ m_uploadtype = PINNED_MEMORY;
+ else if(nvidia && (m_uploadtype & BUFFERSUBDATA))
+ m_uploadtype = BUFFERSUBDATA;
+ else if(g_ogl_config.bSupportsGLSync && (m_uploadtype & MAP_AND_SYNC))
+ m_uploadtype = MAP_AND_SYNC;
+ else
+ m_uploadtype = MAP_AND_ORPHAN;
+ }
+
+ Init();
+}
+
+StreamBuffer::~StreamBuffer()
+{
+ Shutdown();
+ glDeleteBuffers(1, &m_buffer);
+}
+
+#define SLOT(x) (x)*SYNC_POINTS/m_size
+
+void StreamBuffer::Alloc ( size_t size, u32 stride )
+{
+ size_t m_iterator_aligned = m_iterator;
+ if(m_iterator_aligned && stride) {
+ m_iterator_aligned--;
+ m_iterator_aligned = m_iterator_aligned - (m_iterator_aligned % stride) + stride;
+ }
+ size_t iter_end = m_iterator_aligned + size;
+
+ switch(m_uploadtype) {
+ case MAP_AND_ORPHAN:
+ if(iter_end >= m_size) {
+ glBufferData(m_buffertype, m_size, NULL, GL_STREAM_DRAW);
+ m_iterator_aligned = 0;
+ }
+ break;
+ case MAP_AND_SYNC:
+ case PINNED_MEMORY:
+
+ // insert waiting slots for used memory
+ for(u32 i=SLOT(m_used_iterator); i<SLOT(m_iterator); i++)
+ {
+ fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ }
+ m_used_iterator = m_iterator;
+
+ // wait for new slots to end of buffer
+ for(u32 i=SLOT(m_free_iterator)+1; i<=SLOT(iter_end) && i < SYNC_POINTS; i++)
+ {
+ glClientWaitSync(fences[i], GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
+ glDeleteSync(fences[i]);
+ }
+ m_free_iterator = iter_end;
+
+ // if buffer is full
+ if(iter_end >= m_size) {
+
+ // insert waiting slots in unused space at the end of the buffer
+ for(u32 i=SLOT(m_used_iterator); i < SYNC_POINTS; i++)
+ fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+ // move to the start
+ m_used_iterator = m_iterator_aligned = m_iterator = 0; // offset 0 is always aligned
+ iter_end = size;
+
+ // wait for space at the start
+ for(u32 i=0; i<=SLOT(iter_end); i++)
+ {
+ glClientWaitSync(fences[i], GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
+ glDeleteSync(fences[i]);
+ }
+ m_free_iterator = iter_end;
+ }
+
+ break;
+ case MAP_AND_RISK:
+ if(iter_end >= m_size) {
+ m_iterator_aligned = 0;
+ }
+ break;
+ case BUFFERSUBDATA:
+ m_iterator_aligned = 0;
+ break;
+ case STREAM_DETECT:
+ case DETECT_MASK: // Just to shutup warnings
+ break;
+ }
+ m_iterator = m_iterator_aligned;
+}
+
+size_t StreamBuffer::Upload ( u8* data, size_t size )
+{
+ switch(m_uploadtype) {
+ case MAP_AND_SYNC:
+ case MAP_AND_ORPHAN:
+ pointer = (u8*)glMapBufferRange(m_buffertype, m_iterator, size, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
+ if(pointer) {
+ memcpy(pointer, data, size);
+ glUnmapBuffer(m_buffertype);
+ } else {
+ ERROR_LOG(VIDEO, "buffer mapping failed");
+ }
+ break;
+ case PINNED_MEMORY:
+ case MAP_AND_RISK:
+ if(pointer)
+ memcpy(pointer+m_iterator, data, size);
+ break;
+ case BUFFERSUBDATA:
+ glBufferSubData(m_buffertype, m_iterator, size, data);
+ break;
+ case STREAM_DETECT:
+ case DETECT_MASK: // Just to shutup warnings
+ break;
+ }
+ size_t ret = m_iterator;
+ m_iterator += size;
+ return ret;
+}
+
+void StreamBuffer::Init()
+{
+ m_iterator = 0;
+ m_used_iterator = 0;
+ m_free_iterator = 0;
+
+ switch(m_uploadtype) {
+ case MAP_AND_SYNC:
+ fences = new GLsync[SYNC_POINTS];
+ for(u32 i=0; i<SYNC_POINTS; i++)
+ fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+ case MAP_AND_ORPHAN:
+ case BUFFERSUBDATA:
+ glBindBuffer(m_buffertype, m_buffer);
+ glBufferData(m_buffertype, m_size, NULL, GL_STREAM_DRAW);
+ break;
+ case PINNED_MEMORY:
+ glGetError(); // errors before this allocation should be ignored
+ fences = new GLsync[SYNC_POINTS];
+ for(u32 i=0; i<SYNC_POINTS; i++)
+ fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+ pointer = (u8*)AllocateAlignedMemory(ROUND_UP(m_size,ALIGN_PINNED_MEMORY), ALIGN_PINNED_MEMORY );
+ glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_buffer);
+ glBufferData(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, ROUND_UP(m_size,ALIGN_PINNED_MEMORY), pointer, GL_STREAM_COPY);
+ glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0);
+ glBindBuffer(m_buffertype, m_buffer);
+
+ // on error, switch to another backend. some old catalyst seems to have broken pinned memory support
+ if(glGetError() != GL_NO_ERROR) {
+ ERROR_LOG(VIDEO, "pinned memory detected, but not working. Please report this: %s, %s, %s", g_ogl_config.gl_vendor, g_ogl_config.gl_renderer, g_ogl_config.gl_version);
+ Shutdown();
+ m_uploadtype = MAP_AND_SYNC;
+ Init();
+ }
+ break;
+ case MAP_AND_RISK:
+ glBindBuffer(m_buffertype, m_buffer);
+ glBufferData(m_buffertype, m_size, NULL, GL_STREAM_DRAW);
+ pointer = (u8*)glMapBuffer(m_buffertype, GL_WRITE_ONLY);
+ glUnmapBuffer(m_buffertype);
+ if(!pointer)
+ ERROR_LOG(VIDEO, "buffer allocation failed");
+
+ case STREAM_DETECT:
+ case DETECT_MASK: // Just to shutup warnings
+ break;
+ }
+}
+
+void StreamBuffer::Shutdown()
+{
+ switch(m_uploadtype) {
+ case MAP_AND_SYNC:
+ for(u32 i=0; i<SYNC_POINTS; i++)
+ glDeleteSync(fences[i]);
+ delete [] fences;
+ break;
+
+ case MAP_AND_RISK:
+ case MAP_AND_ORPHAN:
+ case BUFFERSUBDATA:
+ break;
+ case PINNED_MEMORY:
+ for(u32 i=0; i<SYNC_POINTS; i++)
+ glDeleteSync(fences[i]);
+ delete [] fences;
+ glBindBuffer(m_buffertype, 0);
+ glFinish(); // ogl pipeline must be flushed, else this buffer can be in use
+ FreeAlignedMemory(pointer);
+ break;
+ case STREAM_DETECT:
+ case DETECT_MASK: // Just to shutup warnings
+ break;
+ }
+}
+
+}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.h b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.h
new file mode 100644
index 0000000000..fa3fd539ea
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.h
@@ -0,0 +1,72 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+
+#ifndef STREAMBUFFER_H
+#define STREAMBUFFER_H
+
+#include "VideoCommon.h"
+#include "FramebufferManager.h"
+#include "GLUtil.h"
+
+// glew < 1.8 doesn't support pinned memory
+#ifndef GLEW_AMD_pinned_memory
+#define GLEW_AMD_pinned_memory glewIsSupported("GL_AMD_pinned_memory")
+#define GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD 0x9160
+#endif
+
+namespace OGL
+{
+enum StreamType {
+ DETECT_MASK = 0x1F,
+ STREAM_DETECT = (1 << 0),
+ MAP_AND_ORPHAN = (1 << 1),
+ MAP_AND_SYNC = (1 << 2),
+ MAP_AND_RISK = (1 << 3),
+ PINNED_MEMORY = (1 << 4),
+ BUFFERSUBDATA = (1 << 5)
+};
+
+class StreamBuffer {
+
+public:
+ StreamBuffer(u32 type, size_t size, StreamType uploadType = DETECT_MASK);
+ ~StreamBuffer();
+
+ void Alloc(size_t size, u32 stride = 0);
+ size_t Upload(u8 *data, size_t size);
+
+ u32 getBuffer() { return m_buffer; }
+
+private:
+ void Init();
+ void Shutdown();
+
+ StreamType m_uploadtype;
+ u32 m_buffer;
+ u32 m_buffertype;
+ size_t m_size;
+ u8 *pointer;
+ size_t m_iterator;
+ size_t m_used_iterator;
+ size_t m_free_iterator;
+ GLsync *fences;
+};
+
+}
+
+#endif // STREAMBUFFER_H
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp
index ee918ee6c0..b0bc682f29 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp
@@ -42,7 +42,7 @@
#include "HW/Memmap.h"
#include "ImageWrite.h"
#include "MemoryUtil.h"
-#include "PixelShaderCache.h"
+#include "ProgramShaderCache.h"
#include "PixelShaderManager.h"
#include "Render.h"
#include "Statistics.h"
@@ -56,6 +56,24 @@
namespace OGL
{
+static SHADER s_ColorMatrixProgram;
+static SHADER s_DepthMatrixProgram;
+static GLuint s_ColorMatrixUniform;
+static GLuint s_DepthMatrixUniform;
+static u32 s_ColorCbufid;
+static u32 s_DepthCbufid;
+
+static u32 s_Textures[8];
+static u32 s_ActiveTexture;
+static u32 s_NextStage;
+
+struct VBOCache {
+ GLuint vbo;
+ GLuint vao;
+ TargetRectangle targetSource;
+};
+static std::map<u64,VBOCache> s_VBO;
+
static u32 s_TempFramebuffer = 0;
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level)
@@ -63,8 +81,11 @@ bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width
int width = std::max(virtual_width >> level, 1);
int height = std::max(virtual_height >> level, 1);
std::vector<u32> data(width * height);
+ glActiveTexture(GL_TEXTURE0+9);
glBindTexture(textarget, tex);
glGetTexImage(textarget, level, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]);
+ glBindTexture(textarget, 0);
+ TextureCache::SetStage();
const GLenum err = GL_REPORT_ERROR();
if (GL_NO_ERROR != err)
@@ -80,6 +101,9 @@ TextureCache::TCacheEntry::~TCacheEntry()
{
if (texture)
{
+ for(int i=0; i<8; i++)
+ if(s_Textures[i] == texture)
+ s_Textures[i] = 0;
glDeleteTextures(1, &texture);
texture = 0;
}
@@ -93,14 +117,17 @@ TextureCache::TCacheEntry::TCacheEntry()
void TextureCache::TCacheEntry::Bind(unsigned int stage)
{
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, texture);
- GL_REPORT_ERRORD();
-
- // TODO: is this already done somewhere else?
- TexMode0 &tm0 = bpmem.tex[stage >> 2].texMode0[stage & 3];
- TexMode1 &tm1 = bpmem.tex[stage >> 2].texMode1[stage & 3];
- SetTextureParameters(tm0, tm1);
+ if (s_Textures[stage] != texture)
+ {
+ if (s_ActiveTexture != stage)
+ {
+ glActiveTexture(GL_TEXTURE0 + stage);
+ s_ActiveTexture = stage;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, texture);
+ s_Textures[stage] = texture;
+ }
}
bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
@@ -129,13 +156,13 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
PanicAlert("Invalid PC texture format %i", pcfmt);
case PC_TEX_FMT_BGRA32:
gl_format = GL_BGRA;
- gl_iformat = 4;
+ gl_iformat = GL_RGBA;
gl_type = GL_UNSIGNED_BYTE;
break;
case PC_TEX_FMT_RGBA32:
gl_format = GL_RGBA;
- gl_iformat = 4;
+ gl_iformat = GL_RGBA;
gl_type = GL_UNSIGNED_BYTE;
break;
@@ -177,7 +204,7 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
entry.gl_type = gl_type;
entry.pcfmt = pcfmt;
- entry.bHaveMipMaps = tex_levels != 1;
+ entry.m_tex_levels = tex_levels;
entry.Load(width, height, expanded_width, 0);
@@ -187,19 +214,33 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int level)
{
- //glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, texture);
- //GL_REPORT_ERRORD();
+ if (s_ActiveTexture != s_NextStage)
+ {
+ glActiveTexture(GL_TEXTURE0 + s_NextStage);
+ s_ActiveTexture = s_NextStage;
+ }
+
+ if (s_Textures[s_NextStage] != texture)
+ {
+ glBindTexture(GL_TEXTURE_2D, texture);
+ s_Textures[s_NextStage] = texture;
+ }
+
+ // TODO: sloppy, just do this on creation?
+ if (level == 0)
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, m_tex_levels - 1);
+ }
if (pcfmt != PC_TEX_FMT_DXT1)
{
if (expanded_width != 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, temp);
if (expanded_width != width)
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
else
{
@@ -214,31 +255,26 @@ TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(
unsigned int scaled_tex_w, unsigned int scaled_tex_h)
{
TCacheEntry *const entry = new TCacheEntry;
+ glActiveTexture(GL_TEXTURE0+9);
glBindTexture(GL_TEXTURE_2D, entry->texture);
GL_REPORT_ERRORD();
const GLenum
gl_format = GL_RGBA,
- gl_iformat = 4,
+ gl_iformat = GL_RGBA,
gl_type = GL_UNSIGNED_BYTE;
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+ entry->m_tex_levels = 1;
glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, scaled_tex_w, scaled_tex_h, 0, gl_format, gl_type, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ SetStage();
+
GL_REPORT_ERRORD();
- 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_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- if (GL_REPORT_ERROR() != GL_NO_ERROR)
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- GL_REPORT_ERRORD();
- }
-
return entry;
}
@@ -247,8 +283,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
const float *colmat)
{
- glBindTexture(GL_TEXTURE_2D, texture);
-
+ g_renderer->ResetAPIState(); // reset any game specific settings
+
// Make sure to resolve anything we need to read from.
const GLuint read_texture = (srcFormat == PIXELFMT_Z24) ?
FramebufferManager::ResolveAndGetDepthTarget(srcRect) :
@@ -259,38 +295,85 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture)
{
if (s_TempFramebuffer == 0)
- glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer);
+ glGenFramebuffers(1, (GLuint*)&s_TempFramebuffer);
FramebufferManager::SetFramebuffer(s_TempFramebuffer);
// Bind texture to temporary framebuffer
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
GL_REPORT_FBO_ERROR();
GL_REPORT_ERRORD();
-
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
- glActiveTexture(GL_TEXTURE0);
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture);
+
+ glActiveTexture(GL_TEXTURE0+9);
+ glBindTexture(GL_TEXTURE_RECTANGLE, read_texture);
glViewport(0, 0, virtual_width, virtual_height);
- PixelShaderCache::SetCurrentShader((srcFormat == PIXELFMT_Z24) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram());
- PixelShaderManager::SetColorMatrix(colmat); // set transformation
+ if(srcFormat == PIXELFMT_Z24) {
+ s_DepthMatrixProgram.Bind();
+ if(s_DepthCbufid != cbufid)
+ glUniform4fv(s_DepthMatrixUniform, 5, colmat);
+ s_DepthCbufid = cbufid;
+ } else {
+ s_ColorMatrixProgram.Bind();
+ if(s_ColorCbufid != cbufid)
+ glUniform4fv(s_ColorMatrixUniform, 7, colmat);
+ s_ColorCbufid = cbufid;
+ }
GL_REPORT_ERRORD();
TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect);
-
- glBegin(GL_QUADS);
- glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.bottom); 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.bottom); glVertex2f( 1, 1);
- glEnd();
+ GL_REPORT_ERRORD();
+
+ // should be unique enough, if not, vbo will "only" be uploaded to much
+ u64 targetSourceHash = u64(targetSource.left)<<48 | u64(targetSource.top)<<32 | u64(targetSource.right)<<16 | u64(targetSource.bottom);
+ std::map<u64, VBOCache>::iterator vbo_it = s_VBO.find(targetSourceHash);
+
+ if(vbo_it == s_VBO.end()) {
+ VBOCache item;
+ item.targetSource.bottom = -1;
+ item.targetSource.top = -1;
+ item.targetSource.left = -1;
+ item.targetSource.right = -1;
+ glGenBuffers(1, &item.vbo);
+ glGenVertexArrays(1, &item.vao);
+
+ glBindBuffer(GL_ARRAY_BUFFER, item.vbo);
+ glBindVertexArray(item.vao);
+
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL);
+ glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
+ glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
+
+ vbo_it = s_VBO.insert(std::pair<u64,VBOCache>(targetSourceHash, item)).first;
+ }
+ if(!(vbo_it->second.targetSource == targetSource)) {
+ GLfloat vertices[] = {
+ -1.f, 1.f,
+ (GLfloat)targetSource.left, (GLfloat)targetSource.bottom,
+ -1.f, -1.f,
+ (GLfloat)targetSource.left, (GLfloat)targetSource.top,
+ 1.f, -1.f,
+ (GLfloat)targetSource.right, (GLfloat)targetSource.top,
+ 1.f, 1.f,
+ (GLfloat)targetSource.right, (GLfloat)targetSource.bottom
+ };
+
+ glBindBuffer(GL_ARRAY_BUFFER, vbo_it->second.vbo);
+ glBufferData(GL_ARRAY_BUFFER, 4*4*sizeof(GLfloat), vertices, GL_STREAM_DRAW);
+
+ vbo_it->second.targetSource = targetSource;
+ }
+
+ glBindVertexArray(vbo_it->second.vao);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
GL_REPORT_ERRORD();
// Unbind texture from temporary framebuffer
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
}
if (false == g_ActiveConfig.bCopyEFBToTexture)
@@ -318,7 +401,6 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
FramebufferManager::SetFramebuffer(0);
VertexShaderManager::SetViewportChanged();
- DisableStage(0);
GL_REPORT_ERRORD();
@@ -328,63 +410,97 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
count++).c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, 0);
}
+
+ g_renderer->RestoreAPIState();
}
-void TextureCache::TCacheEntry::SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1)
+TextureCache::TextureCache()
{
- const GLint c_MinLinearFilter[8] =
- {
- GL_NEAREST,
- GL_NEAREST_MIPMAP_NEAREST,
- GL_NEAREST_MIPMAP_LINEAR,
- GL_NEAREST,
- GL_LINEAR,
- GL_LINEAR_MIPMAP_NEAREST,
- GL_LINEAR_MIPMAP_LINEAR,
- GL_LINEAR,
- };
- const GLint c_WrapSettings[4] =
- {
- GL_CLAMP_TO_EDGE,
- GL_REPEAT,
- GL_MIRRORED_REPEAT,
- GL_REPEAT,
- };
-
- int filt = newmode.min_filter;
- if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
- filt += 4; // take equivalent forced linear
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod / 16.f);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod / 16.f);
- glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (s32)newmode.lod_bias / 32.0f);
-
- 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]);
-
- // TODO: Reset anisotrop when changed to 1
- if (g_Config.iMaxAnisotropy >= 1)
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
- (float)(1 << g_ActiveConfig.iMaxAnisotropy));
+ const char *pColorMatrixProg =
+ "uniform sampler2DRect samp9;\n"
+ "uniform vec4 colmat[7];\n"
+ "in vec2 uv0;\n"
+ "out vec4 ocol0;\n"
+ "\n"
+ "void main(){\n"
+ " vec4 texcol = texture2DRect(samp9, uv0);\n"
+ " texcol = round(texcol * colmat[5]) * colmat[6];\n"
+ " ocol0 = texcol * mat4(colmat[0], colmat[1], colmat[2], colmat[3]) + colmat[4];\n"
+ "}\n";
+
+ const char *pDepthMatrixProg =
+ "uniform sampler2DRect samp9;\n"
+ "uniform vec4 colmat[5];\n"
+ "in vec2 uv0;\n"
+ "out vec4 ocol0;\n"
+ "\n"
+ "void main(){\n"
+ " vec4 texcol = texture2DRect(samp9, uv0);\n"
+ " vec4 EncodedDepth = fract((texcol.r * (16777215.0f/16777216.0f)) * vec4(1.0f,256.0f,256.0f*256.0f,1.0f));\n"
+ " texcol = round(EncodedDepth * (16777216.0f/16777215.0f) * vec4(255.0f,255.0f,255.0f,15.0f)) / vec4(255.0f,255.0f,255.0f,15.0f);\n"
+ " ocol0 = texcol * mat4(colmat[0], colmat[1], colmat[2], colmat[3]) + colmat[4];"
+ "}\n";
+
+
+ const char *VProgram =
+ "in vec2 rawpos;\n"
+ "in vec2 tex0;\n"
+ "out vec2 uv0;\n"
+ "void main()\n"
+ "{\n"
+ " uv0 = tex0;\n"
+ " gl_Position = vec4(rawpos,0,1);\n"
+ "}\n";
+
+ ProgramShaderCache::CompileShader(s_ColorMatrixProgram, VProgram, pColorMatrixProg);
+ ProgramShaderCache::CompileShader(s_DepthMatrixProgram, VProgram, pDepthMatrixProg);
+
+ s_ColorMatrixUniform = glGetUniformLocation(s_ColorMatrixProgram.glprogid, "colmat");
+ s_DepthMatrixUniform = glGetUniformLocation(s_DepthMatrixProgram.glprogid, "colmat");
+ s_ColorCbufid = -1;
+ s_DepthCbufid = -1;
+
+ s_ActiveTexture = -1;
+ s_NextStage = -1;
+ for(int i=0; i<8; i++)
+ s_Textures[i] = -1;
}
+
TextureCache::~TextureCache()
{
- if (s_TempFramebuffer)
+ s_ColorMatrixProgram.Destroy();
+ s_DepthMatrixProgram.Destroy();
+
+ for(std::map<u64, VBOCache>::iterator it = s_VBO.begin(); it != s_VBO.end(); it++) {
+ glDeleteBuffers(1, &it->second.vbo);
+ glDeleteVertexArrays(1, &it->second.vao);
+ }
+ s_VBO.clear();
+
+ if (s_TempFramebuffer)
{
- glDeleteFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer);
- s_TempFramebuffer = 0;
- }
+ glDeleteFramebuffers(1, (GLuint*)&s_TempFramebuffer);
+ s_TempFramebuffer = 0;
+ }
}
void TextureCache::DisableStage(unsigned int stage)
{
- glActiveTexture(GL_TEXTURE0 + stage);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_TEXTURE_RECTANGLE_ARB);
}
+void TextureCache::SetStage ()
+{
+ // -1 is the initial value as we don't know which testure should be bound
+ if(s_ActiveTexture != (u32)-1)
+ glActiveTexture(GL_TEXTURE0 + s_ActiveTexture);
+}
+
+void TextureCache::SetNextStage ( unsigned int stage )
+{
+ s_NextStage = stage;
+}
+
+
+
}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h
index a26aa4049e..a41c86e0b3 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h
@@ -32,7 +32,10 @@ namespace OGL
class TextureCache : public ::TextureCache
{
public:
+ TextureCache();
static void DisableStage(unsigned int stage);
+ static void SetStage();
+ static void SetNextStage(unsigned int stage);
private:
struct TCacheEntry : TCacheEntryBase
@@ -45,7 +48,7 @@ private:
int gl_iformat;
int gl_type;
- bool bHaveMipMaps;
+ int m_tex_levels;
//TexMode0 mode; // current filter and clamp modes that texture is set to
//TexMode1 mode1; // current filter and clamp modes that texture is set to
@@ -63,9 +66,6 @@ private:
void Bind(unsigned int stage);
bool Save(const char filename[], unsigned int level);
-
- private:
- void SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1);
};
~TextureCache();
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp
index c73d3abdbf..c076563310 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp
@@ -23,7 +23,7 @@
#include "TextureConverter.h"
#include "TextureConversionShader.h"
#include "TextureCache.h"
-#include "PixelShaderCache.h"
+#include "ProgramShaderCache.h"
#include "VertexShaderManager.h"
#include "FramebufferManager.h"
#include "Globals.h"
@@ -50,64 +50,73 @@ static GLuint s_dstRenderBuffer = 0; // for encoding to RAM
const int renderBufferWidth = 1024;
const int renderBufferHeight = 1024;
-static FRAGMENTSHADER s_rgbToYuyvProgram;
-static FRAGMENTSHADER s_yuyvToRgbProgram;
+static SHADER s_rgbToYuyvProgram;
+static SHADER s_yuyvToRgbProgram;
// Not all slots are taken - but who cares.
const u32 NUM_ENCODING_PROGRAMS = 64;
-static FRAGMENTSHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS];
-
-void CreateRgbToYuyvProgram()
-{
- // Output is BGRA because that is slightly faster than RGBA.
- const char *FProgram =
- "uniform samplerRECT samp0 : register(s0);\n"
- "void main(\n"
- " out float4 ocol0 : COLOR0,\n"
- " in float2 uv0 : TEXCOORD0)\n"
+static SHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS];
+
+static GLuint s_encode_VBO = 0;
+static GLuint s_encode_VAO = 0;
+static GLuint s_decode_VBO = 0;
+static GLuint s_decode_VAO = 0;
+static TargetRectangle s_cached_sourceRc;
+static int s_cached_srcWidth = 0;
+static int s_cached_srcHeight = 0;
+
+static const char *VProgram =
+ "in vec2 rawpos;\n"
+ "in vec2 tex0;\n"
+ "out vec2 uv0;\n"
+ "void main()\n"
"{\n"
- " float2 uv1 = float2(uv0.x + 1.0f, uv0.y);\n"
- " float3 c0 = texRECT(samp0, uv0).rgb;\n"
- " float3 c1 = texRECT(samp0, uv1).rgb;\n"
- " float3 y_const = float3(0.257f,0.504f,0.098f);\n"
- " float3 u_const = float3(-0.148f,-0.291f,0.439f);\n"
- " float3 v_const = float3(0.439f,-0.368f,-0.071f);\n"
- " float4 const3 = float4(0.0625f,0.5f,0.0625f,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"
+ " uv0 = tex0;\n"
+ " gl_Position = vec4(rawpos,0,1);\n"
"}\n";
- if (!PixelShaderCache::CompilePixelShader(s_rgbToYuyvProgram, FProgram))
- ERROR_LOG(VIDEO, "Failed to create RGB to YUYV fragment program.");
-}
-
-void CreateYuyvToRgbProgram()
+void CreatePrograms()
{
- const char *FProgram =
- "uniform samplerRECT samp0 : register(s0);\n"
- "void main(\n"
- " out float4 ocol0 : COLOR0,\n"
- " in float2 uv0 : TEXCOORD0)\n"
- "{\n"
- " float4 c0 = texRECT(samp0, uv0).rgba;\n"
-
- " float f = step(0.5, frac(uv0.x));\n"
- " float y = lerp(c0.b, c0.r, f);\n"
- " float yComp = 1.164f * (y - 0.0625f);\n"
- " float uComp = c0.g - 0.5f;\n"
- " float vComp = c0.a - 0.5f;\n"
-
- " ocol0 = float4(yComp + (1.596f * vComp),\n"
- " yComp - (0.813f * vComp) - (0.391f * uComp),\n"
- " yComp + (2.018f * uComp),\n"
- " 1.0f);\n"
- "}\n";
-
- if (!PixelShaderCache::CompilePixelShader(s_yuyvToRgbProgram, FProgram))
- ERROR_LOG(VIDEO, "Failed to create YUYV to RGB fragment program.");
+ // Output is BGRA because that is slightly faster than RGBA.
+ const char *FProgramRgbToYuyv =
+ "uniform sampler2DRect samp9;\n"
+ "in vec2 uv0;\n"
+ "out vec4 ocol0;\n"
+ "void main()\n"
+ "{\n"
+ " vec3 c0 = texture2DRect(samp9, uv0).rgb;\n"
+ " vec3 c1 = texture2DRect(samp9, uv0 + vec2(1.0, 0.0)).rgb;\n"
+ " vec3 c01 = (c0 + c1) * 0.5;\n"
+ " vec3 y_const = vec3(0.257,0.504,0.098);\n"
+ " vec3 u_const = vec3(-0.148,-0.291,0.439);\n"
+ " vec3 v_const = vec3(0.439,-0.368,-0.071);\n"
+ " vec4 const3 = vec4(0.0625,0.5,0.0625f,0.5);\n"
+ " ocol0 = vec4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + const3;\n"
+ "}\n";
+
+ const char *FProgramYuyvToRgb =
+ "uniform sampler2DRect samp9;\n"
+ "in vec2 uv0;\n"
+ "out vec4 ocol0;\n"
+ "void main()\n"
+ "{\n"
+ " vec4 c0 = texture2DRect(samp9, uv0).rgba;\n"
+ " float f = step(0.5, fract(uv0.x));\n"
+ " float y = mix(c0.b, c0.r, f);\n"
+ " float yComp = 1.164f * (y - 0.0625f);\n"
+ " float uComp = c0.g - 0.5f;\n"
+ " float vComp = c0.a - 0.5f;\n"
+ " ocol0 = vec4(yComp + (1.596f * vComp),\n"
+ " yComp - (0.813f * vComp) - (0.391f * uComp),\n"
+ " yComp + (2.018f * uComp),\n"
+ " 1.0f);\n"
+ "}\n";
+
+ ProgramShaderCache::CompileShader(s_rgbToYuyvProgram, VProgram, FProgramRgbToYuyv);
+ ProgramShaderCache::CompileShader(s_yuyvToRgbProgram, VProgram, FProgramYuyvToRgb);
}
-FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format)
+SHADER &GetOrCreateEncodingShader(u32 format)
{
if (format > NUM_ENCODING_PROGRAMS)
{
@@ -117,7 +126,7 @@ FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format)
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 (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader)
@@ -130,20 +139,43 @@ FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format)
}
#endif
- if (!PixelShaderCache::CompilePixelShader(s_encodingPrograms[format], shader)) {
- ERROR_LOG(VIDEO, "Failed to create encoding fragment program");
- }
+ ProgramShaderCache::CompileShader(s_encodingPrograms[format], VProgram, shader);
}
return s_encodingPrograms[format];
}
void Init()
{
- glGenFramebuffersEXT(1, &s_texConvFrameBuffer);
-
- glGenRenderbuffersEXT(1, &s_dstRenderBuffer);
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, renderBufferWidth, renderBufferHeight);
+ glGenFramebuffers(1, &s_texConvFrameBuffer);
+
+ glGenBuffers(1, &s_encode_VBO );
+ glGenVertexArrays(1, &s_encode_VAO );
+ glBindBuffer(GL_ARRAY_BUFFER, s_encode_VBO );
+ glBindVertexArray( s_encode_VAO );
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL);
+ glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
+ glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
+ s_cached_sourceRc.top = -1;
+ s_cached_sourceRc.bottom = -1;
+ s_cached_sourceRc.left = -1;
+ s_cached_sourceRc.right = -1;
+
+ glGenBuffers(1, &s_decode_VBO );
+ glGenVertexArrays(1, &s_decode_VAO );
+ glBindBuffer(GL_ARRAY_BUFFER, s_decode_VBO );
+ glBindVertexArray( s_decode_VAO );
+ s_cached_srcWidth = -1;
+ s_cached_srcHeight = -1;
+ glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
+ glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL);
+ glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
+ glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
+
+ glGenRenderbuffers(1, &s_dstRenderBuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, s_dstRenderBuffer);
+
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, renderBufferWidth, renderBufferHeight);
s_srcTextureWidth = 0;
s_srcTextureHeight = 0;
@@ -152,16 +184,20 @@ void Init()
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_MIN_FILTER, GL_NEAREST);
-
- CreateRgbToYuyvProgram();
- CreateYuyvToRgbProgram();
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+
+ CreatePrograms();
}
void Shutdown()
{
glDeleteTextures(1, &s_srcTexture);
- glDeleteRenderbuffersEXT(1, &s_dstRenderBuffer);
- glDeleteFramebuffersEXT(1, &s_texConvFrameBuffer);
+ glDeleteRenderbuffers(1, &s_dstRenderBuffer);
+ glDeleteFramebuffers(1, &s_texConvFrameBuffer);
+ glDeleteBuffers(1, &s_encode_VBO );
+ glDeleteVertexArrays(1, &s_encode_VAO );
+ glDeleteBuffers(1, &s_decode_VBO );
+ glDeleteVertexArrays(1, &s_decode_VAO );
s_rgbToYuyvProgram.Destroy();
s_yuyvToRgbProgram.Destroy();
@@ -174,8 +210,8 @@ void Shutdown()
s_texConvFrameBuffer = 0;
}
-void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const TargetRectangle& sourceRc,
- u8* destAddr, int dstWidth, int dstHeight, int readStride,
+void EncodeToRamUsingShader(GLuint srcTexture, const TargetRectangle& sourceRc,
+ u8* destAddr, int dstWidth, int dstHeight, int readStride,
bool toTexture, bool linearFilter)
{
@@ -184,42 +220,52 @@ void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const Tar
// attach render buffer as color destination
FramebufferManager::SetFramebuffer(s_texConvFrameBuffer);
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, s_dstRenderBuffer);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, s_dstRenderBuffer);
GL_REPORT_ERRORD();
- for (int i = 1; i < 8; ++i)
- TextureCache::DisableStage(i);
-
// set source texture
- glActiveTexture(GL_TEXTURE0);
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture);
+ glActiveTexture(GL_TEXTURE0+9);
+ glBindTexture(GL_TEXTURE_RECTANGLE, srcTexture);
if (linearFilter)
{
- 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, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
else
{
- 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, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
GL_REPORT_ERRORD();
glViewport(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight);
- PixelShaderCache::SetCurrentShader(shader.glprogid);
-
- // Draw...
- glBegin(GL_QUADS);
- glTexCoord2f((float)sourceRc.left, (float)sourceRc.top); 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.top); glVertex2f(1,-1);
- glEnd();
+ GL_REPORT_ERRORD();
+ if(!(s_cached_sourceRc == sourceRc)) {
+ GLfloat vertices[] = {
+ -1.f, -1.f,
+ (float)sourceRc.left, (float)sourceRc.top,
+ -1.f, 1.f,
+ (float)sourceRc.left, (float)sourceRc.bottom,
+ 1.f, 1.f,
+ (float)sourceRc.right, (float)sourceRc.bottom,
+ 1.f, -1.f,
+ (float)sourceRc.right, (float)sourceRc.top
+ };
+ glBindBuffer(GL_ARRAY_BUFFER, s_encode_VBO );
+ glBufferData(GL_ARRAY_BUFFER, 4*4*sizeof(GLfloat), vertices, GL_STREAM_DRAW);
+
+ s_cached_sourceRc = sourceRc;
+ }
+
+ glBindVertexArray( s_encode_VAO );
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+
GL_REPORT_ERRORD();
// .. and then read back the results.
@@ -266,9 +312,7 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt))
format |= _GX_TF_CTF;
- FRAGMENTSHADER& texconv_shader = GetOrCreateEncodingShader(format);
- if (texconv_shader.glprogid == 0)
- return 0;
+ SHADER& texconv_shader = GetOrCreateEncodingShader(format);
u8 *dest_ptr = Memory::GetPointer(address);
@@ -285,14 +329,18 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
// extra pixels are copied but not displayed in the resulting texture
s32 expandedWidth = (width + blkW) & (~blkW);
s32 expandedHeight = (height + blkH) & (~blkH);
-
+
float sampleStride = bScaleByHalf ? 2.f : 1.f;
- TextureConversionShader::SetShaderParameters((float)expandedWidth,
- (float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this?
- (float)Renderer::EFBToScaledX(source.left),
- (float)Renderer::EFBToScaledY(EFB_HEIGHT - source.top - expandedHeight),
- Renderer::EFBToScaledXf(sampleStride),
- Renderer::EFBToScaledYf(sampleStride));
+
+ float params[] = {
+ Renderer::EFBToScaledXf(sampleStride), Renderer::EFBToScaledYf(sampleStride),
+ 0.0f, 0.0f,
+ (float)expandedWidth, (float)Renderer::EFBToScaledY(expandedHeight)-1,
+ (float)Renderer::EFBToScaledX(source.left), (float)Renderer::EFBToScaledY(EFB_HEIGHT - source.top - expandedHeight)
+ };
+
+ texconv_shader.Bind();
+ glUniform4fv(texconv_shader.UniformLocations[C_COLORS], 2, params);
TargetRectangle scaledSource;
scaledSource.top = 0;
@@ -305,7 +353,7 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
int readStride = (expandedWidth * cacheBytes) /
TexDecoder_GetBlockWidthInTexels(format);
- EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource,
+ EncodeToRamUsingShader(source_texture, scaledSource,
dest_ptr, expandedWidth / samples, expandedHeight, readStride,
true, bScaleByHalf > 0 && !bFromZBuffer);
return size_in_bytes; // TODO: D3D11 is calculating this value differently!
@@ -315,10 +363,12 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight)
{
g_renderer->ResetAPIState();
- EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
+
+ s_rgbToYuyvProgram.Bind();
+
+ EncodeToRamUsingShader(srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
FramebufferManager::SetFramebuffer(0);
VertexShaderManager::SetViewportChanged();
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
TextureCache::DisableStage(0);
g_renderer->RestoreAPIState();
GL_REPORT_ERRORD();
@@ -326,7 +376,7 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* des
// Should be scale free.
-void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture)
+void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destRenderbuf)
{
u8* srcAddr = Memory::GetPointer(xfbAddr);
if (!srcAddr)
@@ -342,51 +392,60 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur
// switch to texture converter frame buffer
// attach destTexture as color destination
FramebufferManager::SetFramebuffer(s_texConvFrameBuffer);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destTexture);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destTexture, 0);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, destRenderbuf);
GL_REPORT_FBO_ERROR();
- for (int i = 1; i < 8; ++i)
- TextureCache::DisableStage(i);
-
// activate source texture
// set srcAddr as data for source texture
- glActiveTexture(GL_TEXTURE0);
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture);
+ glActiveTexture(GL_TEXTURE0+9);
+ glBindTexture(GL_TEXTURE_RECTANGLE, s_srcTexture);
// 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,
+ glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0,0,0,s_srcTextureWidth, s_srcTextureHeight,
GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
}
else
{
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)srcFmtWidth, (GLsizei)srcHeight,
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA8, (GLsizei)srcFmtWidth, (GLsizei)srcHeight,
0, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
s_srcTextureWidth = (GLsizei)srcFmtWidth;
s_srcTextureHeight = (GLsizei)srcHeight;
}
glViewport(0, 0, srcWidth, srcHeight);
-
- PixelShaderCache::SetCurrentShader(s_yuyvToRgbProgram.glprogid);
+ s_yuyvToRgbProgram.Bind();
GL_REPORT_ERRORD();
-
- glBegin(GL_QUADS);
- glTexCoord2f((float)srcFmtWidth, (float)srcHeight); glVertex2f(1,-1);
- glTexCoord2f((float)srcFmtWidth, 0); glVertex2f(1,1);
- glTexCoord2f(0, 0); glVertex2f(-1,1);
- glTexCoord2f(0, (float)srcHeight); glVertex2f(-1,-1);
- glEnd();
+
+ if(s_cached_srcHeight != srcHeight || s_cached_srcWidth != srcWidth) {
+ GLfloat vertices[] = {
+ 1.f, -1.f,
+ (float)srcFmtWidth, (float)srcHeight,
+ 1.f, 1.f,
+ (float)srcFmtWidth, 0.f,
+ -1.f, 1.f,
+ 0.f, 0.f,
+ -1.f, -1.f,
+ 0.f, (float)srcHeight
+ };
+
+ glBindBuffer(GL_ARRAY_BUFFER, s_decode_VBO );
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*4, vertices, GL_STREAM_DRAW);
+
+ s_cached_srcHeight = srcHeight;
+ s_cached_srcWidth = srcWidth;
+ }
+
+ glBindVertexArray( s_decode_VAO );
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ GL_REPORT_ERRORD();
// reset state
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
- TextureCache::DisableStage(0);
VertexShaderManager::SetViewportChanged();
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h
index 4113778603..b226e20180 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h
@@ -35,7 +35,7 @@ void Shutdown();
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
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 destRenderbuf);
// returns size of the encoded data (in bytes)
int EncodeToRamFromTexture(u32 address, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp
index 6ea10fc077..228eeb757d 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp
@@ -29,10 +29,9 @@
#include "ImageWrite.h"
#include "BPMemory.h"
#include "TextureCache.h"
-#include "PixelShaderCache.h"
#include "PixelShaderManager.h"
-#include "VertexShaderCache.h"
#include "VertexShaderManager.h"
+#include "ProgramShaderCache.h"
#include "VertexShaderGen.h"
#include "VertexLoader.h"
#include "VertexManager.h"
@@ -40,6 +39,9 @@
#include "OpcodeDecoding.h"
#include "FileUtil.h"
#include "Debugger.h"
+#include "StreamBuffer.h"
+#include "PerfQueryBase.h"
+#include "Render.h"
#include "main.h"
@@ -48,62 +50,117 @@ extern NativeVertexFormat *g_nativeVertexFmt;
namespace OGL
{
+//This are the initially requeted size for the buffers expresed in bytes
+const u32 MAX_IBUFFER_SIZE = 2*1024*1024;
+const u32 MAX_VBUFFER_SIZE = 16*1024*1024;
-//static GLint max_Index_size = 0;
-
-//static GLuint s_vboBuffers[MAXVBOBUFFERCOUNT] = {0};
-//static int s_nCurVBOIndex = 0; // current free buffer
+static StreamBuffer *s_vertexBuffer;
+static StreamBuffer *s_indexBuffer;
+static u32 s_baseVertex;
+static u32 s_offset[3];
VertexManager::VertexManager()
{
- // TODO: doesn't seem to be used anywhere
-
- //glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*)&max_Index_size);
- //
- //if (max_Index_size > MAXIBUFFERSIZE)
- // max_Index_size = MAXIBUFFERSIZE;
- //
- //GL_REPORT_ERRORD();
+ CreateDeviceObjects();
+}
- glEnableClientState(GL_VERTEX_ARRAY);
- GL_REPORT_ERRORD();
+VertexManager::~VertexManager()
+{
+ DestroyDeviceObjects();
}
void VertexManager::CreateDeviceObjects()
{
+ s_vertexBuffer = new StreamBuffer(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE);
+ m_vertex_buffers = s_vertexBuffer->getBuffer();
+ s_indexBuffer = new StreamBuffer(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE, (StreamType)(DETECT_MASK & ~PINNED_MEMORY));
+ m_index_buffers = s_indexBuffer->getBuffer();
-
+ m_CurrentVertexFmt = NULL;
+ m_last_vao = 0;
}
+
void VertexManager::DestroyDeviceObjects()
{
+ GL_REPORT_ERRORD();
+ glBindBuffer(GL_ARRAY_BUFFER, 0 );
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0 );
+ GL_REPORT_ERROR();
+ delete s_vertexBuffer;
+ delete s_indexBuffer;
+ GL_REPORT_ERROR();
}
-void VertexManager::Draw()
+void VertexManager::PrepareDrawBuffers(u32 stride)
{
- if (IndexGenerator::GetNumTriangles() > 0)
+ u32 vertex_data_size = IndexGenerator::GetNumVerts() * stride;
+ u32 triangle_index_size = IndexGenerator::GetTriangleindexLen();
+ u32 line_index_size = IndexGenerator::GetLineindexLen();
+ u32 point_index_size = IndexGenerator::GetPointindexLen();
+ u32 index_size = (triangle_index_size+line_index_size+point_index_size) * sizeof(u16);
+
+ s_vertexBuffer->Alloc(vertex_data_size, stride);
+ u32 offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size);
+ s_baseVertex = offset / stride;
+
+ s_indexBuffer->Alloc(index_size);
+ if(triangle_index_size)
{
- glDrawElements(GL_TRIANGLES, IndexGenerator::GetTriangleindexLen(), GL_UNSIGNED_SHORT, TIBuffer);
- INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ s_offset[0] = s_indexBuffer->Upload((u8*)GetTriangleIndexBuffer(), triangle_index_size * sizeof(u16));
}
- if (IndexGenerator::GetNumLines() > 0)
+ if(line_index_size)
{
- glDrawElements(GL_LINES, IndexGenerator::GetLineindexLen(), GL_UNSIGNED_SHORT, LIBuffer);
- INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ s_offset[1] = s_indexBuffer->Upload((u8*)GetLineIndexBuffer(), line_index_size * sizeof(u16));
}
- if (IndexGenerator::GetNumPoints() > 0)
+ if(point_index_size)
{
- glDrawElements(GL_POINTS, IndexGenerator::GetPointindexLen(), GL_UNSIGNED_SHORT, PIBuffer);
- INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ s_offset[2] = s_indexBuffer->Upload((u8*)GetPointIndexBuffer(), point_index_size * sizeof(u16));
+ }
+}
+
+void VertexManager::Draw(u32 stride)
+{
+ u32 triangle_index_size = IndexGenerator::GetTriangleindexLen();
+ u32 line_index_size = IndexGenerator::GetLineindexLen();
+ u32 point_index_size = IndexGenerator::GetPointindexLen();
+ if(g_ogl_config.bSupportsGLBaseVertex) {
+ if (triangle_index_size > 0)
+ {
+ glDrawElementsBaseVertex(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], s_baseVertex);
+ INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ }
+ if (line_index_size > 0)
+ {
+ glDrawElementsBaseVertex(GL_LINES, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1], s_baseVertex);
+ INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ }
+ if (point_index_size > 0)
+ {
+ glDrawElementsBaseVertex(GL_POINTS, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2], s_baseVertex);
+ INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ }
+ } else {
+ if (triangle_index_size > 0)
+ {
+ glDrawElements(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0]);
+ INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ }
+ if (line_index_size > 0)
+ {
+ glDrawElements(GL_LINES, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1]);
+ INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ }
+ if (point_index_size > 0)
+ {
+ glDrawElements(GL_POINTS, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2]);
+ INCSTAT(stats.thisFrame.numIndexedDrawCalls);
+ }
}
}
void VertexManager::vFlush()
{
- if (LocalVBuffer == s_pCurBufferPointer) return;
- if (Flushed) return;
- Flushed=true;
- VideoFifo_CheckEFBAccess();
#if defined(_DEBUG) || defined(DEBUGFAST)
PRIM_LOG("frame%d:\n texgen=%d, numchan=%d, dualtex=%d, ztex=%d, cole=%d, alpe=%d, ze=%d", g_ActiveConfig.iSaveTargetId, xfregs.numTexGen.numTexGens,
xfregs.numChan.numColorChans, xfregs.dualTexTrans.enabled, bpmem.ztex2.op,
@@ -134,13 +191,15 @@ void VertexManager::vFlush()
(void)GL_REPORT_ERROR();
- //glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[s_nCurVBOIndex]);
- //glBufferData(GL_ARRAY_BUFFER, s_pCurBufferPointer - LocalVBuffer, LocalVBuffer, GL_STREAM_DRAW);
- GL_REPORT_ERRORD();
+ GLVertexFormat *nativeVertexFmt = (GLVertexFormat*)g_nativeVertexFmt;
+ u32 stride = nativeVertexFmt->GetVertexStride();
+
+ if(m_last_vao != nativeVertexFmt->VAO) {
+ glBindVertexArray(nativeVertexFmt->VAO);
+ m_last_vao = nativeVertexFmt->VAO;
+ }
- // setup the pointers
- if (g_nativeVertexFmt)
- g_nativeVertexFmt->SetupVertexPointers();
+ PrepareDrawBuffers(stride);
GL_REPORT_ERRORD();
u32 usedtextures = 0;
@@ -153,11 +212,12 @@ void VertexManager::vFlush()
if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages)
usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt);
- for (int i = 0; i < 8; i++)
+ for (u32 i = 0; i < 8; i++)
{
if (usedtextures & (1 << i))
{
- glActiveTexture(GL_TEXTURE0 + i);
+ TextureCache::SetNextStage(i);
+ g_renderer->SetSamplerState(i % 4, i / 4);
FourTexUnits &tex = bpmem.tex[i >> 2];
TextureCache::TCacheEntryBase* tentry = TextureCache::Load(i,
(tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5,
@@ -178,59 +238,64 @@ void VertexManager::vFlush()
}
}
- // set global constants
- VertexShaderManager::SetConstants();
- PixelShaderManager::SetConstants();
-
bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate
&& bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
-#ifdef USE_DUAL_SOURCE_BLEND
- bool dualSourcePossible = GLEW_ARB_blend_func_extended;
+ // Makes sure we can actually do Dual source blending
+ bool dualSourcePossible = g_ActiveConfig.backend_info.bSupportsDualSourceBlend;
// finally bind
- FRAGMENTSHADER* ps;
if (dualSourcePossible)
{
if (useDstAlpha)
{
// If host supports GL_ARB_blend_func_extended, we can do dst alpha in
// the same pass as regular rendering.
- g_renderer->SetBlendMode(true);
- ps = PixelShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, g_nativeVertexFmt->m_components);
+ ProgramShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, g_nativeVertexFmt->m_components);
}
else
{
- g_renderer->SetBlendMode(true);
- ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
+ ProgramShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
}
}
else
{
- ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
+ ProgramShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
}
-#else
- bool dualSourcePossible = false;
- FRAGMENTSHADER* ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
-#endif
- VERTEXSHADER* vs = VertexShaderCache::SetShader(g_nativeVertexFmt->m_components);
- if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid); // Lego Star Wars crashes here.
- if (vs) VertexShaderCache::SetCurrentShader(vs->glprogid);
- Draw();
+ // set global constants
+ VertexShaderManager::SetConstants();
+ PixelShaderManager::SetConstants();
+ ProgramShaderCache::UploadConstants();
+
+ // setup the pointers
+ if (g_nativeVertexFmt)
+ g_nativeVertexFmt->SetupVertexPointers();
+ GL_REPORT_ERRORD();
+
+ g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
+ Draw(stride);
+ g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
+ //ERROR_LOG(VIDEO, "PerfQuery result: %d", g_perf_query->GetQueryResult(bpmem.zcontrol.early_ztest ? PQ_ZCOMP_OUTPUT_ZCOMPLOC : PQ_ZCOMP_OUTPUT));
// run through vertex groups again to set alpha
if (useDstAlpha && !dualSourcePossible)
{
- ps = PixelShaderCache::SetShader(DSTALPHA_ALPHA_PASS,g_nativeVertexFmt->m_components);
- if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid);
-
+ ProgramShaderCache::SetShader(DSTALPHA_ALPHA_PASS,g_nativeVertexFmt->m_components);
+ if (!g_ActiveConfig.backend_info.bSupportsGLSLUBO)
+ {
+ // Need to set these again, if we don't support UBO
+ VertexShaderManager::SetConstants();
+ PixelShaderManager::SetConstants();
+ }
+
// only update alpha
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glDisable(GL_BLEND);
- Draw();
+ Draw(stride);
+
// restore color mask
g_renderer->SetColorMask();
@@ -238,22 +303,21 @@ void VertexManager::vFlush()
glEnable(GL_BLEND);
}
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
-
- //s_nCurVBOIndex = (s_nCurVBOIndex + 1) % ARRAYSIZE(s_vboBuffers);
- s_pCurBufferPointer = LocalVBuffer;
- IndexGenerator::Start(TIBuffer,LIBuffer,PIBuffer);
-
+
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS)
{
// save the shaders
+ ProgramShaderCache::PCacheEntry prog = ProgramShaderCache::GetShaderProgram();
char strfile[255];
sprintf(strfile, "%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
- std::ofstream fps(strfile);
- fps << ps->strprog.c_str();
+ std::ofstream fps;
+ OpenFStream(fps, strfile, std::ios_base::out);
+ fps << prog.shader.strpprog.c_str();
sprintf(strfile, "%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
- std::ofstream fvs(strfile);
- fvs << vs->strprog.c_str();
+ std::ofstream fvs;
+ OpenFStream(fvs, strfile, std::ios_base::out);
+ fvs << prog.shader.strvprog.c_str();
}
if (g_ActiveConfig.iLog & CONF_SAVETARGETS)
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h
index 5cec1bf97e..6a33799d98 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.h
@@ -24,6 +24,19 @@
namespace OGL
{
+ class GLVertexFormat : public NativeVertexFormat
+ {
+ PortableVertexDeclaration vtx_decl;
+
+ public:
+ GLVertexFormat();
+ ~GLVertexFormat();
+
+ virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
+ virtual void SetupVertexPointers();
+
+ GLuint VAO;
+ };
// Handles the OpenGL details of drawing lots of vertices quickly.
// Other functionality is moving out.
@@ -31,14 +44,20 @@ class VertexManager : public ::VertexManager
{
public:
VertexManager();
-
+ ~VertexManager();
NativeVertexFormat* CreateNativeVertexFormat();
void CreateDeviceObjects();
void DestroyDeviceObjects();
+
+ // NativeVertexFormat use this
+ GLuint m_vertex_buffers;
+ GLuint m_index_buffers;
+ GLuint m_last_vao;
private:
- void Draw();
- // temp
+ void Draw(u32 stride);
void vFlush();
+ void PrepareDrawBuffers(u32 stride);
+ NativeVertexFormat *m_CurrentVertexFmt;
};
}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp
index dbbb7ee29b..038021c490 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp
@@ -26,7 +26,7 @@
#include "Render.h"
#include "VertexShaderGen.h"
#include "VertexShaderManager.h"
-#include "VertexShaderCache.h"
+#include "ProgramShaderCache.h"
#include "VertexManager.h"
#include "VertexLoader.h"
#include "XFMemory.h"
@@ -37,236 +37,104 @@
namespace OGL
{
-VertexShaderCache::VSCache VertexShaderCache::vshaders;
-GLuint VertexShaderCache::CurrentShader;
-bool VertexShaderCache::ShaderEnabled;
-
-VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry = NULL;
-VERTEXSHADERUID VertexShaderCache::last_uid;
-
-static int s_nMaxVertexInstructions;
-
-
-void VertexShaderCache::Init()
+void SetVSConstant4fvByName(const char * name, unsigned int offset, const float *f, const unsigned int count = 1)
{
- glEnable(GL_VERTEX_PROGRAM_ARB);
- ShaderEnabled = true;
- CurrentShader = 0;
- last_entry = NULL;
-
- glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions);
- if (strstr((const char*)glGetString(GL_VENDOR), "Humper") != NULL) s_nMaxVertexInstructions = 4096;
-#if CG_VERSION_NUM == 2100
- if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
+ ProgramShaderCache::PCacheEntry tmp = ProgramShaderCache::GetShaderProgram();
+ for (int a = 0; a < NUM_UNIFORMS; ++a)
{
- s_nMaxVertexInstructions = 4096;
+ if (!strcmp(name, UniformNames[a]))
+ {
+ if (tmp.shader.UniformLocations[a] == -1)
+ return;
+ else
+ {
+ glUniform4fv(tmp.shader.UniformLocations[a] + offset, count, f);
+ return;
+ }
+ }
}
-#endif
}
-void VertexShaderCache::Shutdown()
+void Renderer::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{
- for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter)
- iter->second.Destroy();
- vshaders.clear();
-}
+ float const buf[4] = {f1, f2, f3, f4};
-
-VERTEXSHADER* VertexShaderCache::SetShader(u32 components)
-{
- VERTEXSHADERUID uid;
- GetVertexShaderId(&uid, components);
- if (last_entry)
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- if (uid == last_uid)
- {
- GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
- ValidateVertexShaderIDs(API_OPENGL, vshaders[uid].safe_uid, vshaders[uid].shader.strprog, components);
- return &last_entry->shader;
- }
+ ProgramShaderCache::SetMultiVSConstant4fv(const_number, buf, 1);
+ return;
}
-
- last_uid = uid;
-
- VSCache::iterator iter = vshaders.find(uid);
- if (iter != vshaders.end())
+ for (unsigned int a = 0; a < 9; ++a)
{
- VSCacheEntry &entry = iter->second;
- last_entry = &entry;
-
- GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
- ValidateVertexShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, components);
- return &last_entry->shader;
- }
-
- // Make an entry in the table
- VSCacheEntry& entry = vshaders[uid];
- last_entry = &entry;
- const char *code = GenerateVertexShaderCode(components, API_OPENGL);
- GetSafeVertexShaderId(&entry.safe_uid, components);
-
-#if defined(_DEBUG) || defined(DEBUGFAST)
- if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
- static int counter = 0;
- char szTemp[MAX_PATH];
- sprintf(szTemp, "%svs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
-
- SaveData(szTemp, code);
- }
-#endif
-
- if (!code || !VertexShaderCache::CompileVertexShader(entry.shader, code)) {
- GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
- return NULL;
+ if (const_number >= VSVar_Loc[a].reg && const_number < ( VSVar_Loc[a].reg + VSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - VSVar_Loc[a].reg;
+ SetVSConstant4fvByName(VSVar_Loc[a].name, offset, buf);
+ return;
+ }
}
-
- INCSTAT(stats.numVertexShadersCreated);
- SETSTAT(stats.numVertexShadersAlive, vshaders.size());
- GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
- return &last_entry->shader;
}
-bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
+void Renderer::SetVSConstant4fv(unsigned int const_number, const float *f)
{
- // Reset GL error before compiling shaders. Yeah, we need to investigate the causes of these.
- GLenum err = GL_REPORT_ERROR();
- if (err != GL_NO_ERROR)
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- ERROR_LOG(VIDEO, "glError %08x before VS!", err);
- }
-
-#if defined HAVE_CG && HAVE_CG
- char stropt[64];
- sprintf(stropt, "MaxLocalParams=256,MaxInstructions=%d", s_nMaxVertexInstructions);
- const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
- CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgvProf, "main", opts);
- if (!cgIsProgram(tempprog)) {
- static int num_failures = 0;
- char szTemp[MAX_PATH];
- sprintf(szTemp, "%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
- std::ofstream file(szTemp);
- file << pstrprogram;
- file.close();
-
- PanicAlert("Failed to compile vertex shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%d):\n%s",
- szTemp,
- g_cgfProf,
- cgGetLastListing(g_cgcontext));
-
- cgDestroyProgram(tempprog);
- ERROR_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
- ERROR_LOG(VIDEO, "%s", pstrprogram);
- return false;
+ ProgramShaderCache::SetMultiVSConstant4fv(const_number, f, 1);
+ return;
}
-
- if (cgGetError() != CG_NO_ERROR)
+ for (unsigned int a = 0; a < 9; ++a)
{
- WARN_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
- WARN_LOG(VIDEO, "%s", pstrprogram);
- }
-
- // 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...
- char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
- char *plocal = strstr(pcompiledprog, "program.local");
- while (plocal != NULL) {
- const char* penv = " program.env";
- memcpy(plocal, penv, 13);
- plocal = strstr(plocal + 13, "program.local");
- }
- glGenProgramsARB(1, &vs.glprogid);
- SetCurrentShader(vs.glprogid);
-
- glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
- err = GL_REPORT_ERROR();
- if (err != GL_NO_ERROR) {
- ERROR_LOG(VIDEO, "%s", pstrprogram);
- ERROR_LOG(VIDEO, "%s", pcompiledprog);
+ if (const_number >= VSVar_Loc[a].reg && const_number < ( VSVar_Loc[a].reg + VSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - VSVar_Loc[a].reg;
+ SetVSConstant4fvByName(VSVar_Loc[a].name, offset, f);
+ return;
+ }
}
-
- cgDestroyProgram(tempprog);
-#endif
-
- if (g_ActiveConfig.bEnableShaderDebugging)
- vs.strprog = pstrprogram;
-
- return true;
}
-void VertexShaderCache::DisableShader()
+void Renderer::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
{
- if (ShaderEnabled)
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- glDisable(GL_VERTEX_PROGRAM_ARB);
- ShaderEnabled = false;
+ ProgramShaderCache::SetMultiVSConstant4fv(const_number, f, count);
+ return;
+ }
+ for (unsigned int a = 0; a < 9; ++a)
+ {
+ if (const_number >= VSVar_Loc[a].reg && const_number < ( VSVar_Loc[a].reg + VSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - VSVar_Loc[a].reg;
+ SetVSConstant4fvByName(VSVar_Loc[a].name, offset, f, count);
+ return;
+ }
}
}
-
-void VertexShaderCache::SetCurrentShader(GLuint Shader)
+void Renderer::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
{
- if (!ShaderEnabled)
+ float buf[4 * C_VENVCONST_END];
+ for (unsigned int i = 0; i < count; i++)
{
- glEnable(GL_VERTEX_PROGRAM_ARB);
- ShaderEnabled= true;
+ buf[4*i ] = *f++;
+ buf[4*i+1] = *f++;
+ buf[4*i+2] = *f++;
+ buf[4*i+3] = 0.f;
}
- if (CurrentShader != Shader)
+ if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
{
- if(Shader != 0)
- CurrentShader = Shader;
- glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
+ ProgramShaderCache::SetMultiVSConstant4fv(const_number, buf, count);
+ return;
}
-}
-
-void Renderer::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
-{
- glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, const_number, f1, f2, f3, f4);
-}
-
-void Renderer::SetVSConstant4fv(unsigned int const_number, const float *f)
-{
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f);
-}
-
-void Renderer::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
-{
- if(GLEW_EXT_gpu_program_parameters)
- {
- glProgramEnvParameters4fvEXT(GL_VERTEX_PROGRAM_ARB, const_number, count, f);
- }
- else
- {
- for (unsigned int i = 0; i < count; i++,f+=4)
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, f);
- }
-}
-
-void Renderer::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
-{
- if(GLEW_EXT_gpu_program_parameters)
+ for (unsigned int a = 0; a < 9; ++a)
{
- float buf[4 * C_VENVCONST_END];
- for (unsigned int i = 0; i < count; i++)
- {
- buf[4*i ] = *f++;
- buf[4*i+1] = *f++;
- buf[4*i+2] = *f++;
- buf[4*i+3] = 0.f;
- }
- glProgramEnvParameters4fvEXT(GL_VERTEX_PROGRAM_ARB, const_number, count, buf);
- }
- else
- {
- for (unsigned int i = 0; i < count; i++)
- {
- float buf[4];
- buf[0] = *f++;
- buf[1] = *f++;
- buf[2] = *f++;
- buf[3] = 0.f;
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, buf);
- }
- }
+ if (const_number >= VSVar_Loc[a].reg && const_number < ( VSVar_Loc[a].reg + VSVar_Loc[a].size))
+ {
+ unsigned int offset = const_number - VSVar_Loc[a].reg;
+ SetVSConstant4fvByName(VSVar_Loc[a].name, offset, buf, count);
+ return;
+ }
+ }
}
} // namespace OGL
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h
deleted file mode 100644
index 6f4cbe25c2..0000000000
--- a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (C) 2003 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#ifndef _VERTEXSHADERCACHE_H_
-#define _VERTEXSHADERCACHE_H_
-
-#include <map>
-#include <string>
-
-#include "BPMemory.h"
-#include "VertexShaderGen.h"
-
-namespace OGL
-{
-
-struct VERTEXSHADER
-{
- VERTEXSHADER() : glprogid(0) {}
- GLuint glprogid; // opengl program id
-
- std::string strprog;
-};
-
-class VertexShaderCache
-{
- struct VSCacheEntry
- {
- VERTEXSHADER shader;
- VERTEXSHADERUIDSAFE safe_uid;
- VSCacheEntry() {}
- void Destroy() {
- // printf("Destroying vs %i\n", shader.glprogid);
- glDeleteProgramsARB(1, &shader.glprogid);
- shader.glprogid = 0;
- }
- };
-
- typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
-
- static VSCache vshaders;
-
- static VSCacheEntry* last_entry;
- static VERTEXSHADERUID last_uid;
-
- static GLuint CurrentShader;
- static bool ShaderEnabled;
-
-public:
- static void Init();
- static void Shutdown();
-
- static VERTEXSHADER* SetShader(u32 components);
- static bool CompileVertexShader(VERTEXSHADER& ps, const char* pstrprogram);
-
- static void SetCurrentShader(GLuint Shader);
- static void DisableShader();
-
-};
-
-} // namespace OGL
-
-#endif // _VERTEXSHADERCACHE_H_
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VideoBackend.h b/Source/Plugins/Plugin_VideoOGL/Src/VideoBackend.h
index 4c7414794d..2520c72763 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/VideoBackend.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/VideoBackend.h
@@ -15,6 +15,7 @@ class VideoBackend : public VideoBackendHardware
std::string GetName();
void Video_Prepare();
+ void Video_Cleanup();
void ShowConfig(void* parent);
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp
index 05f21beed1..ddce3bb01f 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp
@@ -55,6 +55,7 @@ Make AA apply instantly during gameplay if possible
#include "LogManager.h"
#include <cstdarg>
+#include <algorithm>
#ifdef _WIN32
#include "EmuWindow.h"
@@ -79,10 +80,9 @@ Make AA apply instantly during gameplay if possible
#include "VertexLoader.h"
#include "VertexLoaderManager.h"
#include "VertexManager.h"
-#include "PixelShaderCache.h"
#include "PixelShaderManager.h"
-#include "VertexShaderCache.h"
#include "VertexShaderManager.h"
+#include "ProgramShaderCache.h"
#include "CommandProcessor.h"
#include "PixelEngine.h"
#include "TextureConverter.h"
@@ -92,6 +92,8 @@ Make AA apply instantly during gameplay if possible
#include "FramebufferManager.h"
#include "Core.h"
#include "Host.h"
+#include "SamplerCache.h"
+#include "PerfQuery.h"
#include "VideoState.h"
#include "VideoBackend.h"
@@ -107,37 +109,39 @@ std::string VideoBackend::GetName()
void GetShaders(std::vector<std::string> &shaders)
{
- shaders.clear();
- if (File::IsDirectory(File::GetUserPath(D_SHADERS_IDX)))
- {
- File::FSTEntry entry;
- File::ScanDirectoryTree(File::GetUserPath(D_SHADERS_IDX), entry);
- for (u32 i = 0; i < entry.children.size(); i++)
- {
- std::string name = entry.children[i].virtualName.c_str();
- if (!strcasecmp(name.substr(name.size() - 4).c_str(), ".txt"))
- name = name.substr(0, name.size() - 4);
- shaders.push_back(name);
- }
- }
- else
- {
- File::CreateDir(File::GetUserPath(D_SHADERS_IDX).c_str());
- }
+ shaders.clear();
+ if (File::IsDirectory(File::GetUserPath(D_SHADERS_IDX)))
+ {
+ File::FSTEntry entry;
+ File::ScanDirectoryTree(File::GetUserPath(D_SHADERS_IDX), entry);
+ for (u32 i = 0; i < entry.children.size(); i++)
+ {
+ std::string name = entry.children[i].virtualName.c_str();
+ if (!strcasecmp(name.substr(name.size() - 4).c_str(), ".txt")) {
+ name = name.substr(0, name.size() - 4);
+ shaders.push_back(name);
+ }
+ }
+ std::sort(shaders.begin(), shaders.end());
+ }
+ else
+ {
+ File::CreateDir(File::GetUserPath(D_SHADERS_IDX).c_str());
+ }
}
void InitBackendInfo()
{
g_Config.backend_info.APIType = API_OPENGL;
- g_Config.backend_info.bUseRGBATextures = false;
+ g_Config.backend_info.bUseRGBATextures = true;
g_Config.backend_info.bUseMinimalMipCount = false;
g_Config.backend_info.bSupports3DVision = false;
- g_Config.backend_info.bSupportsDualSourceBlend = false; // supported, but broken
+ //g_Config.backend_info.bSupportsDualSourceBlend = true; // is gpu depenend and must be set in renderer
g_Config.backend_info.bSupportsFormatReinterpretation = false;
g_Config.backend_info.bSupportsPixelLighting = true;
// aamodes
- const char* caamodes[] = {"None", "2x", "4x", "8x", "8x CSAA", "8xQ CSAA", "16x CSAA", "16xQ CSAA"};
+ const char* caamodes[] = {"None", "2x", "4x", "8x", "8x CSAA", "8xQ CSAA", "16x CSAA", "16xQ CSAA", "4x SSAA"};
g_Config.backend_info.AAModes.assign(caamodes, caamodes + sizeof(caamodes)/sizeof(*caamodes));
// pp shaders
@@ -190,21 +194,24 @@ void VideoBackend::Video_Prepare()
CommandProcessor::Init();
PixelEngine::Init();
- g_texture_cache = new TextureCache;
-
BPInit();
g_vertex_manager = new VertexManager;
+ g_perf_query = new PerfQuery;
Fifo_Init(); // must be done before OpcodeDecoder_Init()
OpcodeDecoder_Init();
- VertexShaderCache::Init();
VertexShaderManager::Init();
- PixelShaderCache::Init();
PixelShaderManager::Init();
+ ProgramShaderCache::Init();
PostProcessing::Init();
+ g_texture_cache = new TextureCache();
+ g_sampler_cache = new SamplerCache();
+ Renderer::Init();
GL_REPORT_ERRORD();
VertexLoaderManager::Init();
TextureConverter::Init();
+#ifndef _M_GENERIC
DLCache::Init();
+#endif
// Notify the core that the video backend is ready
Host_Message(WM_USER_CREATE);
@@ -213,32 +220,40 @@ void VideoBackend::Video_Prepare()
void VideoBackend::Shutdown()
{
s_BackendInitialized = false;
+ GLInterface->Shutdown();
+}
+void VideoBackend::Video_Cleanup() {
+
if (g_renderer)
{
s_efbAccessRequested = false;
s_FifoShuttingDown = false;
s_swapRequested = false;
+#ifndef _M_GENERIC
DLCache::Shutdown();
+#endif
Fifo_Shutdown();
- PostProcessing::Shutdown();
// The following calls are NOT Thread Safe
// And need to be called from the video thread
+ Renderer::Shutdown();
TextureConverter::Shutdown();
VertexLoaderManager::Shutdown();
- VertexShaderCache::Shutdown();
+ delete g_sampler_cache;
+ g_sampler_cache = NULL;
+ delete g_texture_cache;
+ g_texture_cache = NULL;
+ PostProcessing::Shutdown();
+ ProgramShaderCache::Shutdown();
VertexShaderManager::Shutdown();
PixelShaderManager::Shutdown();
- PixelShaderCache::Shutdown();
delete g_vertex_manager;
- delete g_texture_cache;
+ g_vertex_manager = NULL;
OpcodeDecoder_Shutdown();
delete g_renderer;
g_renderer = NULL;
- g_texture_cache = NULL;
}
- GLInterface->Shutdown();
}
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt b/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt
index 15db15e654..0488f728b8 100644
--- a/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt
+++ b/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt
@@ -10,6 +10,7 @@ set(SRCS Src/BPMemLoader.cpp
Src/OpcodeDecoder.cpp
Src/SWPixelEngine.cpp
Src/Rasterizer.cpp
+ Src/RasterFont.cpp
Src/SWRenderer.cpp
Src/SetupUnit.cpp
Src/SWStatistics.cpp
diff --git a/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj b/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj
index 66cfab9b01..0f18d096f8 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj
+++ b/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj
@@ -184,6 +184,7 @@
<ClCompile Include="Src\OpcodeDecoder.cpp" />
<ClCompile Include="Src\SWPixelEngine.cpp" />
<ClCompile Include="Src\Rasterizer.cpp" />
+ <ClCompile Include="Src\RasterFont.cpp" />
<ClCompile Include="Src\SWRenderer.cpp" />
<ClCompile Include="Src\SetupUnit.cpp" />
<ClCompile Include="Src\SWStatistics.cpp" />
@@ -217,6 +218,7 @@
<ClInclude Include="Src\OpcodeDecoder.h" />
<ClInclude Include="Src\SWPixelEngine.h" />
<ClInclude Include="Src\Rasterizer.h" />
+ <ClInclude Include="Src\RasterFont.h" />
<ClInclude Include="Src\SWRenderer.h" />
<ClInclude Include="Src\SetupUnit.h" />
<ClInclude Include="Src\SWStatistics.h" />
diff --git a/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj.filters b/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj.filters
index 4bc1901325..14be6ff447 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj.filters
+++ b/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj.filters
@@ -13,6 +13,7 @@
<ClCompile Include="Src\OpcodeDecoder.cpp" />
<ClCompile Include="Src\SWPixelEngine.cpp" />
<ClCompile Include="Src\Rasterizer.cpp" />
+ <ClCompile Include="Src\RasterFont.cpp" />
<ClCompile Include="Src\SWRenderer.cpp" />
<ClCompile Include="Src\SetupUnit.cpp" />
<ClCompile Include="Src\SWStatistics.cpp" />
@@ -39,6 +40,7 @@
<ClInclude Include="Src\OpcodeDecoder.h" />
<ClInclude Include="Src\SWPixelEngine.h" />
<ClInclude Include="Src\Rasterizer.h" />
+ <ClInclude Include="Src\RasterFont.h" />
<ClInclude Include="Src\SWRenderer.h" />
<ClInclude Include="Src\SetupUnit.h" />
<ClInclude Include="Src\SWStatistics.h" />
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp
index f05f9f8b57..0d7c77c767 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp
@@ -90,6 +90,21 @@ void SWBPWritten(int address, int newvalue)
SWPixelEngine::pereg.boxBottom = newvalue >> 10;
SWPixelEngine::pereg.boxTop = newvalue & 0x3ff;
break;
+ case BPMEM_CLEAR_PIXEL_PERF:
+ // TODO: I didn't test if the value written to this register affects the amount of cleared registers
+ SWPixelEngine::pereg.perfZcompInputZcomplocLo = 0;
+ SWPixelEngine::pereg.perfZcompInputZcomplocHi = 0;
+ SWPixelEngine::pereg.perfZcompOutputZcomplocLo = 0;
+ SWPixelEngine::pereg.perfZcompOutputZcomplocHi = 0;
+ SWPixelEngine::pereg.perfZcompInputLo = 0;
+ SWPixelEngine::pereg.perfZcompInputHi = 0;
+ SWPixelEngine::pereg.perfZcompOutputLo = 0;
+ SWPixelEngine::pereg.perfZcompOutputHi = 0;
+ SWPixelEngine::pereg.perfBlendInputLo = 0;
+ SWPixelEngine::pereg.perfBlendInputHi = 0;
+ SWPixelEngine::pereg.perfEfbCopyClocksLo = 0;
+ SWPixelEngine::pereg.perfEfbCopyClocksHi = 0;
+ break;
case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here.
break;
case BPMEM_LOADTLUT1: // Load a Texture Look Up Table
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp
index e9a3525d84..c4755b50bf 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp
@@ -65,6 +65,13 @@ namespace Clipper
OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES];
OutputVertexData *Vertices[NUM_INDICES];
+ void DoState(PointerWrap &p)
+ {
+ p.DoArray(m_ViewOffset,2);
+ for (int i = 0; i< NUM_CLIPPED_VERTICES; ++i)
+ ClippedVertices[i].DoState(p);
+ }
+
void Init()
{
for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h
index 5e5dd4d02c..babc8b4e88 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h
@@ -21,6 +21,7 @@
#include "Common.h"
#include "NativeVertexFormat.h"
+#include "ChunkFile.h"
namespace Clipper
@@ -36,6 +37,8 @@ namespace Clipper
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface);
void PerspectiveDivide(OutputVertexData *vertex);
+
+ void DoState(PointerWrap &p);
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp
index 6722ec7935..77d87988c8 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp
@@ -28,6 +28,7 @@ u8 efb[EFB_WIDTH*EFB_HEIGHT*6];
namespace EfbInterface
{
+
u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4];
inline u32 GetColorOffset(u16 x, u16 y)
@@ -40,6 +41,12 @@ namespace EfbInterface
return (x + y * EFB_WIDTH) * 3 + DEPTH_BUFFER_START;
}
+ void DoState(PointerWrap &p)
+ {
+ p.DoArray(efb, EFB_WIDTH*EFB_HEIGHT*6);
+ p.DoArray(efbColorTexture, EFB_WIDTH*EFB_HEIGHT*4);
+ }
+
void SetPixelAlphaOnly(u32 offset, u8 a)
{
switch (bpmem.zcontrol.pixel_format)
@@ -454,10 +461,11 @@ namespace EfbInterface
SetPixelAlphaOnly(offset, color[ALP_C]);
}
- void SetDepth(u16 x, u16 y, u32 depth)
- {
- SetPixelDepth(GetDepthOffset(x, y), depth);
- }
+ void SetDepth(u16 x, u16 y, u32 depth)
+ {
+ if (bpmem.zmode.updateenable)
+ SetPixelDepth(GetDepthOffset(x, y), depth);
+ }
void GetColor(u16 x, u16 y, u8 *color)
{
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h
index 15d19e7783..fdad69567c 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h
@@ -47,6 +47,7 @@ namespace EfbInterface
void UpdateColorTexture();
extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // RGBA format
+ void DoState(PointerWrap &p);
}
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h b/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h
index d19844105f..e2d87e207e 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h
@@ -19,6 +19,7 @@
#define _NATIVEVERTEXFORMAT_H
#include "Vec3.h"
+#include "ChunkFile.h"
#ifdef WIN32
#define LOADERDECL __cdecl
@@ -92,6 +93,18 @@ struct OutputVertexData
#undef LINTERP
#undef LINTERP_INT
}
+ void DoState(PointerWrap &p)
+ {
+ mvPosition.DoState(p);
+ p.Do(projectedPosition);
+ screenPosition.DoState(p);
+ for (int i = 0; i < 3;++i)
+ normal[i].DoState(p);
+ p.DoArray(color, sizeof color);
+ for (int i = 0; i < 8;++i)
+ texCoords[i].DoState(p);
+ }
+
};
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp
index 0091e4eaca..4848cb4d43 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp
@@ -35,7 +35,6 @@ typedef void (*DecodingFunction)(u32);
namespace OpcodeDecoder
{
-
static DecodingFunction currentFunction = NULL;
static u32 minCommandSize;
static u16 streamSize;
@@ -46,6 +45,20 @@ static bool inObjectStream;
static u8 lastPrimCmd;
+void DoState(PointerWrap &p)
+{
+ p.Do(minCommandSize);
+ // Not sure what is wrong with this. Something(s) in here is causing dolphin to crash/hang when loading states saved from another run of dolphin. Doesn't seem too important anyway...
+ //vertexLoader.DoState(p);
+ p.Do(readOpcode);
+ p.Do(inObjectStream);
+ p.Do(lastPrimCmd);
+ p.Do(streamSize);
+ p.Do(streamAddress);
+ if (p.GetMode() == PointerWrap::MODE_READ)
+ ResetDecoding();
+}
+
void DecodePrimitiveStream(u32 iBufferSize)
{
u32 vertexSize = vertexLoader.GetVertexSize();
@@ -125,7 +138,9 @@ void DecodeStandard(u32 bufferSize)
if (Cmd == GX_NOP)
return;
-
+ // Causes a SIGBUS error on Android
+ // XXX: Investigate
+#ifndef ANDROID
// check if switching in or out of an object
// only used for debuggging
if (inObjectStream && (Cmd & 0x87) != lastPrimCmd)
@@ -139,7 +154,7 @@ void DecodeStandard(u32 bufferSize)
lastPrimCmd = Cmd & 0x87;
DebugUtil::OnObjectBegin();
}
-
+#endif
switch(Cmd)
{
case GX_NOP:
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h
index 635fcc24ee..53715b2832 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h
@@ -20,6 +20,7 @@
#define _OPCODEDECODER_H_
#include "CommonTypes.h"
+#include "ChunkFile.h"
namespace OpcodeDecoder
{
@@ -57,6 +58,8 @@ namespace OpcodeDecoder
bool CommandRunnable(u32 iBufferSize);
void Run(u32 iBufferSize);
+
+ void DoState(PointerWrap &p);
}
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.cpp
new file mode 100644
index 0000000000..fe20146e31
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.cpp
@@ -0,0 +1,223 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "../../Plugin_VideoOGL/Src/GLUtil.h"
+
+#include <string.h>
+
+#include "RasterFont.h"
+// globals
+
+const GLubyte rasters[][13] = {
+ {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, 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, 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, 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, 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, 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, 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, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {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, 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, 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, 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, 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, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
+ {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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18},
+ {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, 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, 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, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
+ {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},
+ {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},
+ {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, 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, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 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},
+ {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, 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, 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, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 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},
+ {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},
+ {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, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
+};
+
+RasterFont::RasterFont()
+{
+ // set GL modes
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ // create the raster font
+ fontOffset = glGenLists(128);
+ for (int i = 32; i < 127; i++) {
+ glNewList(i + fontOffset, GL_COMPILE);
+ glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
+ glEndList();
+ }
+
+ temp_buffer = new char[TEMP_BUFFER_SIZE];
+}
+
+RasterFont::~RasterFont()
+{
+ glDeleteLists(fontOffset, 128);
+ delete [] temp_buffer;
+}
+
+void RasterFont::printString(const char *s, double x, double y, double z)
+{
+ int length = (int)strlen(s);
+ if (!length)
+ return;
+ if (length >= TEMP_BUFFER_SIZE)
+ length = TEMP_BUFFER_SIZE - 1;
+
+ // Sanitize string to avoid GL errors.
+ char *s2 = temp_buffer;
+ memcpy(s2, s, length);
+ s2[length] = 0;
+ for (int i = 0; i < length; i++) {
+ if (s2[i] < 32 || s2[i] > 126)
+ s2[i] = '!';
+ }
+
+ // go to the right spot
+ glRasterPos3d(x, y, z);
+ GL_REPORT_ERRORD();
+
+ glPushAttrib (GL_LIST_BIT);
+ glListBase(fontOffset);
+ glCallLists((GLsizei)strlen(s2), GL_UNSIGNED_BYTE, (GLubyte *) s2);
+ GL_REPORT_ERRORD();
+ glPopAttrib();
+ GL_REPORT_ERRORD();
+}
+
+void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z)
+{
+ int length = (int)strlen(s);
+ int x = (int)(screen_width/2.0 - (length/2.0)*char_width);
+ printString(s, x, y, z);
+}
+
+void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight)
+{
+ double x = start_x;
+ double y = start_y;
+ char temp[1024];
+ char *t = temp;
+ while (*text)
+ {
+ if (*text == '\n')
+ {
+ *t = 0;
+ printString(temp, x, y, z);
+ y -= char_height * 2.0f / bbHeight;
+ x = start_x;
+ t = temp;
+ }
+ else if (*text == '\r')
+ {
+ t = temp;
+ }
+ else if (*text == '\t')
+ {
+ //todo: add tabs every something like 4*char_width
+ *t = 0;
+ int cpos = (int)strlen(temp);
+ int newpos = (cpos + 4) & (~3);
+ printString(temp, x, y, z);
+ x = start_x + (char_width*newpos) * 2.0f / bbWidth;
+ t = temp;
+ *t++ = ' ';
+ }
+ else
+ *t++ = *text;
+
+ text++;
+ }
+
+ // ????
+ if (t != text)
+ {
+ *t = 0;
+ printString(temp, x, y, z);
+ }
+}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.h b/Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.h
new file mode 100644
index 0000000000..3ebc684dd0
--- /dev/null
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/RasterFont.h
@@ -0,0 +1,42 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef _RASTERFONT_H_
+#define _RASTERFONT_H_
+
+class RasterFont {
+public:
+ RasterFont();
+ ~RasterFont(void);
+ static int debug;
+
+ // some useful constants
+ enum {char_width = 10};
+ enum {char_height = 15};
+
+ // and the happy helper functions
+ 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 printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight);
+private:
+ int fontOffset;
+ char *temp_buffer;
+ enum {TEMP_BUFFER_SIZE = 64 * 1024};
+};
+
+#endif // _RASTERFONT_H_
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp
index 225400e08b..badb123fa0 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp
@@ -23,6 +23,7 @@
#include "BPMemLoader.h"
#include "XFMemLoader.h"
#include "Tev.h"
+#include "SWPixelEngine.h"
#include "SWStatistics.h"
#include "SWVideoConfig.h"
@@ -62,6 +63,28 @@ s32 scissorBottom = 0;
Tev tev;
RasterBlock rasterBlock;
+void DoState(PointerWrap &p)
+{
+ ZSlope.DoState(p);
+ WSlope.DoState(p);
+ for (int i=0;i<2;++i)
+ for (int n=0; n<4; ++n)
+ ColorSlopes[i][n].DoState(p);
+ for (int i=0;i<8;++i)
+ for (int n=0; n<3; ++n)
+ TexSlopes[i][n].DoState(p);
+ p.Do(vertex0X);
+ p.Do(vertex0Y);
+ p.Do(vertexOffsetX);
+ p.Do(vertexOffsetY);
+ p.Do(scissorLeft);
+ p.Do(scissorTop);
+ p.Do(scissorRight);
+ p.Do(scissorBottom);
+ tev.DoState(p);
+ p.Do(rasterBlock);
+}
+
void Init()
{
tev.Init();
@@ -127,9 +150,15 @@ inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
if (bpmem.zcontrol.early_ztest && bpmem.zmode.testenable && g_SWVideoConfig.bZComploc)
{
- // early z
- if (!EfbInterface::ZCompare(x, y, z))
- return;
+ // TODO: Test if perf regs are incremented even if test is disabled
+ SWPixelEngine::pereg.IncZInputQuadCount(true);
+ if (bpmem.zmode.testenable)
+ {
+ // early z
+ if (!EfbInterface::ZCompare(x, y, z))
+ return;
+ }
+ SWPixelEngine::pereg.IncZOutputQuadCount(true);
}
RasterBlockPixel& pixel = rasterBlock.Pixel[xi][yi];
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h
index f8850571a9..784c4a8d62 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h
@@ -19,6 +19,7 @@
#define _RASTERIZER_H_
#include "NativeVertexFormat.h"
+#include "ChunkFile.h"
namespace Rasterizer
{
@@ -37,6 +38,12 @@ namespace Rasterizer
float f0;
float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); }
+ void DoState(PointerWrap &p)
+ {
+ p.Do(dfdx);
+ p.Do(dfdy);
+ p.Do(f0);
+ }
};
struct RasterBlockPixel
@@ -53,6 +60,8 @@ namespace Rasterizer
s32 TextureLod[16];
bool TextureLinear[16];
};
+
+ void DoState(PointerWrap &p);
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp
index b9afc1abb5..6cc4ee4dc8 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp
@@ -57,6 +57,15 @@ CPReg cpreg; // shared between gfx and emulator thread
void DoState(PointerWrap &p)
{
p.Do(cpreg);
+ p.DoArray(commandBuffer, commandBufferSize);
+ p.Do(readPos);
+ p.Do(writePos);
+ p.Do(et_UpdateInterrupts);
+ p.Do(interruptSet);
+ p.Do(interruptWaiting);
+
+ // Is this right?
+ p.DoArray(g_pVideoData,writePos);
}
// does it matter that there is no synchronization between threads during writes?
@@ -115,15 +124,15 @@ void RunGpu()
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
{
// We are going to do FP math on the main thread so have to save the current state
- SaveSSEState();
- LoadDefaultSSEState();
+ FPURoundMode::SaveSIMDState();
+ FPURoundMode::LoadDefaultSIMDState();
// run the opcode decoder
do {
RunBuffer();
} while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr);
- LoadSSEState();
+ FPURoundMode::LoadSIMDState();
}
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp
index 33a6164b01..118e59629e 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp
@@ -53,6 +53,8 @@ void DoState(PointerWrap &p)
p.Do(pereg);
p.Do(g_bSignalTokenInterrupt);
p.Do(g_bSignalFinishInterrupt);
+ p.Do(et_SetTokenOnMainThread);
+ p.Do(et_SetFinishOnMainThread);
}
void UpdateInterrupts();
@@ -77,7 +79,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
u16 address = _iAddress & 0xFFF;
- if (address <= 0x16)
+ if (address <= 0x2e)
_uReturnValue = ((u16*)&pereg)[address >> 1];
}
@@ -109,7 +111,7 @@ void Write16(const u16 _iValue, const u32 _iAddress)
}
break;
default:
- if (address <= 0x16)
+ if (address <= 0x2e)
((u16*)&pereg)[address >> 1] = _iValue;
break;
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h
index 6a87143e8c..351e53456d 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h
@@ -38,6 +38,21 @@ namespace SWPixelEngine
PE_BBOX_RIGHT = 0x012, // Flip Right
PE_BBOX_TOP = 0x014, // Flip Top
PE_BBOX_BOTTOM = 0x016, // Flip Bottom
+
+ // NOTE: Order not verified
+ // These indicate the number of quads that are being used as input/output for each particular stage
+ PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L = 0x18,
+ PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H = 0x1a,
+ PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L = 0x1c,
+ PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H = 0x1e,
+ PE_PERF_ZCOMP_INPUT_L = 0x20,
+ PE_PERF_ZCOMP_INPUT_H = 0x22,
+ PE_PERF_ZCOMP_OUTPUT_L = 0x24,
+ PE_PERF_ZCOMP_OUTPUT_H = 0x26,
+ PE_PERF_BLEND_INPUT_L = 0x28,
+ PE_PERF_BLEND_INPUT_H = 0x2a,
+ PE_PERF_EFB_COPY_CLOCKS_L = 0x2c,
+ PE_PERF_EFB_COPY_CLOCKS_H = 0x2e,
};
union UPEZConfReg
@@ -125,10 +140,72 @@ namespace SWPixelEngine
UPECtrlReg ctrl;
u16 unk0;
u16 token;
+
u16 boxLeft;
u16 boxRight;
u16 boxTop;
u16 boxBottom;
+
+ u16 perfZcompInputZcomplocLo;
+ u16 perfZcompInputZcomplocHi;
+ u16 perfZcompOutputZcomplocLo;
+ u16 perfZcompOutputZcomplocHi;
+ u16 perfZcompInputLo;
+ u16 perfZcompInputHi;
+ u16 perfZcompOutputLo;
+ u16 perfZcompOutputHi;
+ u16 perfBlendInputLo;
+ u16 perfBlendInputHi;
+ u16 perfEfbCopyClocksLo;
+ u16 perfEfbCopyClocksHi;
+
+ // NOTE: hardware doesn't process individual pixels but quads instead. Current software renderer architecture works on pixels though, so we have this "quad" hack here to only increment the registers on every fourth rendered pixel
+ void IncZInputQuadCount(bool early_ztest)
+ {
+ static int quad = 0;
+ if (++quad != 3)
+ return;
+ quad = 0;
+
+ if (early_ztest)
+ {
+ if (++perfZcompInputZcomplocLo == 0)
+ perfZcompInputZcomplocHi++;
+ }
+ else
+ {
+ if (++perfZcompInputLo == 0)
+ perfZcompInputHi++;
+ }
+ }
+ void IncZOutputQuadCount(bool early_ztest)
+ {
+ static int quad = 0;
+ if (++quad != 3)
+ return;
+ quad = 0;
+
+ if (early_ztest)
+ {
+ if (++perfZcompOutputZcomplocLo == 0)
+ perfZcompOutputZcomplocHi++;
+ }
+ else
+ {
+ if (++perfZcompOutputLo == 0)
+ perfZcompOutputHi++;
+ }
+ }
+ void IncBlendInputQuadCount()
+ {
+ static int quad = 0;
+ if (++quad != 3)
+ return;
+ quad = 0;
+
+ if (++perfBlendInputLo == 0)
+ perfBlendInputHi++;
+ }
};
extern PEReg pereg;
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp
index fb472cfdba..111e6ca57b 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp
@@ -19,7 +19,7 @@
#include <math.h>
#include "../../Plugin_VideoOGL/Src/GLUtil.h"
-#include "../../Plugin_VideoOGL/Src/RasterFont.h"
+#include "RasterFont.h"
#include "SWRenderer.h"
#include "SWStatistics.h"
@@ -30,6 +30,7 @@ static GLint uni_tex = -1;
static GLuint program;
// Rasterfont isn't compatible with GLES
+// degasus: I think it does, but I can't test it
#ifndef USE_GLES
RasterFont* s_pfont = NULL;
#endif
@@ -99,11 +100,11 @@ void SWRenderer::RenderText(const char* pstr, int left, int top, u32 color)
int nBackbufferWidth = (int)GLInterface->GetBackBufferWidth();
int nBackbufferHeight = (int)GLInterface->GetBackBufferHeight();
glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
- ((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
+ ((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
s_pfont->printMultilineText(pstr,
- left * 2.0f / (float)nBackbufferWidth - 1,
- 1 - top * 2.0f / (float)nBackbufferHeight,
- 0, nBackbufferWidth, nBackbufferHeight);
+ left * 2.0f / (float)nBackbufferWidth - 1,
+ 1 - top * 2.0f / (float)nBackbufferHeight,
+ 0, nBackbufferWidth, nBackbufferHeight);
#endif
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp
index cc5ee66772..1c1eeb2005 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp
@@ -328,4 +328,15 @@ void SWVertexLoader::LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData
vertexLoader->m_texCoordLoader[index]();
}
-
+void SWVertexLoader::DoState(PointerWrap &p)
+{
+ p.DoArray(m_AttributeLoaders, sizeof m_AttributeLoaders);
+ p.Do(m_VertexSize);
+ p.Do(*m_CurrentVat);
+ p.Do(m_positionLoader);
+ p.Do(m_normalLoader);
+ p.DoArray(m_colorLoader, sizeof m_colorLoader);
+ p.Do(m_NumAttributeLoaders);
+ m_SetupUnit->DoState(p);
+ p.Do(m_TexGenSpecialCase);
+} \ No newline at end of file
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h
index 91a0d8e911..e05346a7a5 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h
@@ -22,6 +22,7 @@
#include "NativeVertexFormat.h"
#include "CPMemLoader.h"
+#include "ChunkFile.h"
class SetupUnit;
@@ -69,7 +70,7 @@ public:
u32 GetVertexSize() { return m_VertexSize; }
void LoadVertex();
-
+ void DoState(PointerWrap &p);
};
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp
index 07947e0ee7..a6705a5236 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp
@@ -23,36 +23,36 @@ SWVideoConfig g_SWVideoConfig;
SWVideoConfig::SWVideoConfig()
{
- bFullscreen = false;
- bHideCursor = false;
- renderToMainframe = false;
+ bFullscreen = false;
+ bHideCursor = false;
+ renderToMainframe = false;
bHwRasterizer = false;
- bShowStats = false;
+ bShowStats = false;
- bDumpTextures = false;
- bDumpObjects = false;
- bDumpFrames = false;
+ bDumpTextures = false;
+ bDumpObjects = false;
+ bDumpFrames = false;
bZComploc = true;
bZFreeze = true;
- bDumpTevStages = false;
+ bDumpTevStages = false;
bDumpTevTextureFetches = false;
- drawStart = 0;
- drawEnd = 100000;
+ drawStart = 0;
+ drawEnd = 100000;
}
void SWVideoConfig::Load(const char* ini_file)
{
- std::string temp;
- IniFile iniFile;
- iniFile.Load(ini_file);
-
- iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware
- iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, false);
+ std::string temp;
+ IniFile iniFile;
+ iniFile.Load(ini_file);
+
+ iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware
+ iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, false);
iniFile.Get("Rendering", "HwRasterizer", &bHwRasterizer, false);
iniFile.Get("Rendering", "ZComploc", &bZComploc, true);
@@ -72,11 +72,11 @@ void SWVideoConfig::Load(const char* ini_file)
void SWVideoConfig::Save(const char* ini_file)
{
- IniFile iniFile;
- iniFile.Load(ini_file);
+ IniFile iniFile;
+ iniFile.Load(ini_file);
- iniFile.Set("Hardware", "Fullscreen", bFullscreen);
- iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe);
+ iniFile.Set("Hardware", "Fullscreen", bFullscreen);
+ iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe);
iniFile.Set("Rendering", "HwRasterizer", bHwRasterizer);
iniFile.Set("Rendering", "ZComploc", &bZComploc);
@@ -92,7 +92,7 @@ void SWVideoConfig::Save(const char* ini_file)
iniFile.Set("Misc", "DrawStart", drawStart);
iniFile.Set("Misc", "DrawEnd", drawEnd);
-
- iniFile.Save(ini_file);
+
+ iniFile.Save(ini_file);
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp
index 332e83d0e8..b524ded329 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp
@@ -39,6 +39,9 @@
#include "FileUtil.h"
#include "VideoBackend.h"
#include "Core.h"
+#include "OpcodeDecoder.h"
+#include "SWVertexLoader.h"
+#include "SWStatistics.h"
#define VSYNC_ENABLED 0
@@ -93,9 +96,33 @@ bool VideoSoftware::Initialize(void *&window_handle)
return true;
}
-void VideoSoftware::DoState(PointerWrap&)
+void VideoSoftware::DoState(PointerWrap& p)
{
- // NYI
+ bool software = true;
+ p.Do(software);
+ if (p.GetMode() == PointerWrap::MODE_READ && software == false)
+ // change mode to abort load of incompatible save state.
+ p.SetMode(PointerWrap::MODE_VERIFY);
+
+ // TODO: incomplete?
+ SWCommandProcessor::DoState(p);
+ SWPixelEngine::DoState(p);
+ EfbInterface::DoState(p);
+ OpcodeDecoder::DoState(p);
+ Clipper::DoState(p);
+ p.Do(swxfregs);
+ p.Do(bpmem);
+ p.Do(swstats);
+
+ // CP Memory
+ p.DoArray(arraybases, 16);
+ p.DoArray(arraystrides, 16);
+ p.Do(MatrixIndexA);
+ p.Do(MatrixIndexB);
+ p.Do(g_VtxDesc.Hex);
+ p.DoArray(g_VtxAttr, 8);
+ p.DoMarker("CP Memory");
+
}
void VideoSoftware::CheckInvalidState()
@@ -132,18 +159,26 @@ void VideoSoftware::EmuStateChange(EMUSTATE_CHANGE newState)
void VideoSoftware::Shutdown()
{
+ // TODO: should be in Video_Cleanup
HwRasterizer::Shutdown();
SWRenderer::Shutdown();
+
GLInterface->Shutdown();
}
+void VideoSoftware::Video_Cleanup()
+{
+}
+
// This is called after Video_Initialize() from the Core
void VideoSoftware::Video_Prepare()
{
GLInterface->MakeCurrent();
// Init extension support.
- // Required for WGL SwapInterval
#ifndef USE_GLES
+#ifdef __APPLE__
+ glewExperimental = 1;
+#endif
if (glewInit() != GLEW_OK) {
ERROR_LOG(VIDEO, "glewInit() failed!Does your video card support OpenGL 2.x?");
return;
@@ -198,6 +233,12 @@ u32 VideoSoftware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputDa
return value;
}
+u32 VideoSoftware::Video_GetQueryResult(PerfQueryType type)
+{
+ // TODO:
+ return 0;
+}
+
bool VideoSoftware::Video_Screenshot(const char *_szFilename)
{
return false;
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp
index 6e0fab57d8..d2185e31d5 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp
@@ -25,13 +25,13 @@
void SetupUnit::Init(u8 primitiveType)
{
- m_PrimType = primitiveType;
+ m_PrimType = primitiveType;
- m_VertexCounter = 0;
- m_VertPointer[0] = &m_Vertices[0];
- m_VertPointer[1] = &m_Vertices[1];
- m_VertPointer[2] = &m_Vertices[2];
- m_VertWritePointer = m_VertPointer[0];
+ m_VertexCounter = 0;
+ m_VertPointer[0] = &m_Vertices[0];
+ m_VertPointer[1] = &m_Vertices[1];
+ m_VertPointer[2] = &m_Vertices[2];
+ m_VertWritePointer = m_VertPointer[0];
}
void SetupUnit::SetupVertex()
@@ -169,3 +169,21 @@ void SetupUnit::SetupLineStrip()
void SetupUnit::SetupPoint()
{}
+
+void SetupUnit::DoState(PointerWrap &p)
+{
+ // TODO: some or all of this is making the save states stop working once dolphin is closed...sometimes (usually)
+ // I have no idea what specifically is wrong, or if this is even important. Disabling it doesn't seem to make any noticible difference...
+/* p.Do(m_PrimType);
+ p.Do(m_VertexCounter);
+ for (int i = 0; i < 3; ++i)
+ m_Vertices[i].DoState(p);
+
+ if (p.GetMode() == PointerWrap::MODE_READ)
+ {
+ m_VertPointer[0] = &m_Vertices[0];
+ m_VertPointer[1] = &m_Vertices[1];
+ m_VertPointer[2] = &m_Vertices[2];
+ m_VertWritePointer = m_VertPointer[0];
+ }*/
+}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h
index 45a575afcb..f337de21a2 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h
@@ -21,6 +21,7 @@
#include "Common.h"
#include "NativeVertexFormat.h"
+#include "ChunkFile.h"
class SetupUnit
{
@@ -45,6 +46,7 @@ public:
OutputVertexData* GetVertex() { return m_VertWritePointer; }
void SetupVertex();
+ void DoState(PointerWrap &p);
};
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp
index 927f8931e9..fa072508eb 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp
@@ -20,11 +20,13 @@
#include "Tev.h"
#include "EfbInterface.h"
#include "TextureSampler.h"
+#include "XFMemLoader.h"
+#include "SWPixelEngine.h"
#include "SWStatistics.h"
#include "SWVideoConfig.h"
#include "DebugUtil.h"
-#include <math.h>
+#include <cmath>
#ifdef _DEBUG
#define ALLOW_TEV_DUMPS 1
@@ -747,10 +749,22 @@ void Tev::Draw()
}
- // stuff to do!
- // here, where we'll have to add/handle x range adjustment (if related BP register it's enabled)
- // x_adjust = sqrt((x-center)^2 + k^2)/k
- // ze *= x_adjust
+ if(bpmem.fogRange.Base.Enabled)
+ {
+ // TODO: This is untested and should definitely be checked against real hw.
+ // - No idea if offset is really normalized against the viewport width or against the projection matrix or yet something else
+ // - scaling of the "k" coefficient isn't clear either.
+
+ // First, calculate the offset from the viewport center (normalized to 0..1)
+ float offset = (Position[0] - (bpmem.fogRange.Base.Center - 342)) / (float)swxfregs.viewport.wd;
+ // Based on that, choose the index such that points which are far away from the z-axis use the 10th "k" value and such that central points use the first value.
+ int index = 9 - std::abs(offset) * 9.f;
+ index = (index < 0) ? 0 : (index > 9) ? 9 : 0; // TODO: Shouldn't be necessary!
+ // Look up coefficient... Seems like multiplying by 4 makes Fortune Street work properly (fog is too strong without the factor)
+ float k = bpmem.fogRange.K[index/2].GetValue(index%2) * 4.f;
+ float x_adjust = sqrt(offset*offset + k*k)/k;
+ ze *= x_adjust; // NOTE: This is basically dividing by a cosine (hidden behind GXInitFogAdjTable): 1/cos = c/b = sqrt(a^2+b^2)/b
+ }
ze -= bpmem.fog.c_proj_fsel.GetC();
@@ -787,8 +801,13 @@ void Tev::Draw()
bool late_ztest = !bpmem.zcontrol.early_ztest || !g_SWVideoConfig.bZComploc;
if (late_ztest && bpmem.zmode.testenable)
{
- if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2]))
- return;
+ // TODO: Check against hw if these values get incremented even if depth testing is disabled
+ SWPixelEngine::pereg.IncZInputQuadCount(false);
+
+ if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2]))
+ return;
+
+ SWPixelEngine::pereg.IncZOutputQuadCount(false);
}
#if ALLOW_TEV_DUMPS
@@ -812,6 +831,7 @@ void Tev::Draw()
#endif
INCSTAT(swstats.thisFrame.tevPixelsOut);
+ SWPixelEngine::pereg.IncBlendInputQuadCount();
EfbInterface::BlendTev(Position[0], Position[1], output);
}
@@ -827,3 +847,31 @@ void Tev::SetRegColor(int reg, int comp, bool konst, s16 color)
Reg[reg][comp] = color;
}
}
+
+void Tev::DoState(PointerWrap &p)
+{
+ p.DoArray(Reg, sizeof(Reg));
+
+ p.DoArray(KonstantColors, sizeof(KonstantColors));
+ p.DoArray(TexColor,4);
+ p.DoArray(RasColor,4);
+ p.DoArray(StageKonst,4);
+ p.DoArray(Zero16,4);
+
+ p.DoArray(FixedConstants,9);
+ p.Do(AlphaBump);
+ p.DoArray(IndirectTex, sizeof(IndirectTex));
+ p.Do(TexCoord);
+
+ p.DoArray(m_BiasLUT,4);
+ p.DoArray(m_ScaleLShiftLUT,4);
+ p.DoArray(m_ScaleRShiftLUT,4);
+
+ p.DoArray(Position,3);
+ p.DoArray(Color, sizeof(Color));
+ p.DoArray(Uv, 8);
+ p.DoArray(IndirectLod,4);
+ p.DoArray(IndirectLinear,4);
+ p.DoArray(TextureLod,16);
+ p.DoArray(TextureLinear,16);
+}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h
index bdd265170c..1d1bc8d2ba 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h
@@ -19,6 +19,7 @@
#define _TEV_H_
#include "BPMemLoader.h"
+#include "ChunkFile.h"
class Tev
{
@@ -96,6 +97,8 @@ public:
void SetRegColor(int reg, int comp, bool konst, s16 color);
enum { ALP_C, BLU_C, GRN_C, RED_C };
+
+ void DoState(PointerWrap &p);
};
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp
index c95365eddd..e7bb4b91f2 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp
@@ -88,13 +88,13 @@ void TransformPosition(const InputVertexData *src, OutputVertexData *dst)
const float* mat = (const float*)&swxfregs.posMatrices[src->posMtx * 4];
MultiplyVec3Mat34(src->position, mat, dst->mvPosition);
- if (swxfregs.projection[6] == 0)
+ if (swxfregs.projection.type == GX_PERSPECTIVE)
{
- MultipleVec3Perspective(dst->mvPosition, swxfregs.projection, dst->projectedPosition);
+ MultipleVec3Perspective(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
}
else
{
- MultipleVec3Ortho(dst->mvPosition, swxfregs.projection, dst->projectedPosition);
+ MultipleVec3Ortho(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
}
}
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h b/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h
index 3a36a13307..80460edd60 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <math.h>
+#include "ChunkFile.h"
class Vec3
{
@@ -111,6 +112,12 @@ public:
{
memset((void *)this,0,sizeof(float)*3);
}
+ void DoState(PointerWrap &p)
+ {
+ p.Do(x);
+ p.Do(y);
+ p.Do(z);
+ }
};
#endif
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h b/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h
index 3e1490031f..37fe817f07 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h
@@ -21,12 +21,15 @@ class VideoSoftware : public VideoBackend
void ShowConfig(void* parent);
void Video_Prepare();
+ void Video_Cleanup();
void Video_EnterLoop();
void Video_ExitLoop();
void Video_BeginField(u32, FieldType, u32, u32);
void Video_EndField();
+
u32 Video_AccessEFB(EFBAccessType, u32, u32, u32);
+ u32 Video_GetQueryResult(PerfQueryType type);
void Video_AddMessage(const char* pstr, unsigned int milliseconds);
void Video_ClearMessages();
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp
index bd085a3edf..e7122d2f71 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp
@@ -34,7 +34,7 @@ IntegerSetting<T>::IntegerSetting(wxWindow* parent, const wxString& label, T& se
VideoConfigDialog::VideoConfigDialog(wxWindow* parent, const std::string& title, const std::string& _ininame) :
wxDialog(parent, -1,
- wxString(wxT("Dolphin ")).append(wxString::FromAscii(title.c_str())).append(wxT(" Graphics Configuration")),
+ wxString(wxT("Dolphin ")).append(StrToWxStr(title)).append(wxT(" Graphics Configuration")),
wxDefaultPosition, wxDefaultSize),
vconfig(g_SWVideoConfig),
ininame(_ininame)
@@ -64,10 +64,10 @@ VideoConfigDialog::VideoConfigDialog(wxWindow* parent, const std::string& title,
it = g_available_video_backends.begin(),
itend = g_available_video_backends.end();
for (; it != itend; ++it)
- choice_backend->AppendString(wxString::FromAscii((*it)->GetName().c_str()));
+ choice_backend->AppendString(StrToWxStr((*it)->GetName()));
// TODO: How to get the translated plugin name?
- choice_backend->SetStringSelection(wxString::FromAscii(g_video_backend->GetName().c_str()));
+ choice_backend->SetStringSelection(StrToWxStr(g_video_backend->GetName()));
choice_backend->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDialog::Event_Backend, this);
szr_rendering->Add(label_backend, 1, wxALIGN_CENTER_VERTICAL, 5);
diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h b/Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h
index f5bb8c3c43..86e8e6c9d8 100644
--- a/Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h
+++ b/Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h
@@ -85,6 +85,9 @@ struct Light
#define LIGHTATTN_NONE 2
#define LIGHTATTN_DIR 3
+#define GX_PERSPECTIVE 0
+#define GX_ORTHOGRAPHIC 1
+
union LitChannel
{
struct
@@ -160,6 +163,12 @@ struct Viewport
float farZ;
};
+struct Projection
+{
+ float rawProjection[6];
+ u32 type; // only GX_PERSPECTIVE or GX_ORTHOGRAPHIC are allowed
+};
+
union TexMtxInfo
{
struct
@@ -218,7 +227,7 @@ struct XFRegisters
TXFMatrixIndexA MatrixIndexA; // 0x1018
TXFMatrixIndexB MatrixIndexB; // 0x1019
Viewport viewport; // 0x101a - 0x101f
- float projection[7]; // 0x1020 - 0x1026
+ Projection projection; // 0x1020 - 0x1026
u32 unk8[24]; // 0x1027 - 0x103e
u32 numTexGens; // 0x103f
TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047