Add Turntable.cpp to SCons build.
Set native eol-style on recently added files. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6252 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
c6fa5804de
commit
4b5b9ad05c
|
@ -1,32 +1,32 @@
|
|||
// Copyright (C) 2010 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 _CPUCOREBASE_H
|
||||
#define _CPUCOREBASE_H
|
||||
|
||||
class CPUCoreBase
|
||||
{
|
||||
public:
|
||||
virtual void Init() = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
virtual void ClearCache() = 0;
|
||||
virtual void Run() = 0;
|
||||
virtual void SingleStep() = 0;
|
||||
virtual const char *GetName() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2010 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 _CPUCOREBASE_H
|
||||
#define _CPUCOREBASE_H
|
||||
|
||||
class CPUCoreBase
|
||||
{
|
||||
public:
|
||||
virtual void Init() = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
virtual void ClearCache() = 0;
|
||||
virtual void Run() = 0;
|
||||
virtual void SingleStep() = 0;
|
||||
virtual const char *GetName() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,158 +1,158 @@
|
|||
|
||||
#include "Common.h"
|
||||
|
||||
#include "Statistics.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "IndexGenerator.h"
|
||||
|
||||
#include "VertexManagerBase.h"
|
||||
|
||||
VertexManager *g_vertex_manager;
|
||||
|
||||
u8 *VertexManager::s_pCurBufferPointer;
|
||||
u8 *VertexManager::s_pBaseBufferPointer;
|
||||
|
||||
u8 *VertexManager::LocalVBuffer;
|
||||
u16 *VertexManager::TIBuffer;
|
||||
u16 *VertexManager::LIBuffer;
|
||||
u16 *VertexManager::PIBuffer;
|
||||
|
||||
bool VertexManager::Flushed;
|
||||
|
||||
VertexManager::VertexManager()
|
||||
{
|
||||
Flushed = false;
|
||||
|
||||
LocalVBuffer = new u8[MAXVBUFFERSIZE];
|
||||
s_pCurBufferPointer = s_pBaseBufferPointer = LocalVBuffer;
|
||||
|
||||
TIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
LIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
PIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
|
||||
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
|
||||
}
|
||||
|
||||
void VertexManager::ResetBuffer()
|
||||
{
|
||||
s_pCurBufferPointer = LocalVBuffer;
|
||||
}
|
||||
|
||||
VertexManager::~VertexManager()
|
||||
{
|
||||
delete[] LocalVBuffer;
|
||||
|
||||
delete[] TIBuffer;
|
||||
delete[] LIBuffer;
|
||||
delete[] PIBuffer;
|
||||
|
||||
// TODO: necessary??
|
||||
ResetBuffer();
|
||||
}
|
||||
|
||||
void VertexManager::AddIndices(int primitive, int numVertices)
|
||||
{
|
||||
//switch (primitive)
|
||||
//{
|
||||
//case GX_DRAW_QUADS: IndexGenerator::AddQuads(numVertices); break;
|
||||
//case GX_DRAW_TRIANGLES: IndexGenerator::AddList(numVertices); break;
|
||||
//case GX_DRAW_TRIANGLE_STRIP: IndexGenerator::AddStrip(numVertices); break;
|
||||
//case GX_DRAW_TRIANGLE_FAN: IndexGenerator::AddFan(numVertices); break;
|
||||
//case GX_DRAW_LINES: IndexGenerator::AddLineList(numVertices); break;
|
||||
//case GX_DRAW_LINE_STRIP: IndexGenerator::AddLineStrip(numVertices); break;
|
||||
//case GX_DRAW_POINTS: IndexGenerator::AddPoints(numVertices); break;
|
||||
//}
|
||||
|
||||
static void (*const primitive_table[])(int) =
|
||||
{
|
||||
IndexGenerator::AddQuads,
|
||||
NULL,
|
||||
IndexGenerator::AddList,
|
||||
IndexGenerator::AddStrip,
|
||||
IndexGenerator::AddFan,
|
||||
IndexGenerator::AddLineList,
|
||||
IndexGenerator::AddLineStrip,
|
||||
IndexGenerator::AddPoints,
|
||||
};
|
||||
|
||||
primitive_table[primitive](numVertices);
|
||||
}
|
||||
|
||||
int VertexManager::GetRemainingSize()
|
||||
{
|
||||
return MAXVBUFFERSIZE - (int)(s_pCurBufferPointer - LocalVBuffer);
|
||||
}
|
||||
|
||||
int VertexManager::GetRemainingVertices(int primitive)
|
||||
{
|
||||
switch (primitive)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
case GX_DRAW_TRIANGLES:
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3;
|
||||
break;
|
||||
|
||||
case GX_DRAW_LINES:
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2;
|
||||
break;
|
||||
|
||||
case GX_DRAW_POINTS:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen());
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexManager::AddVertices(int primitive, int numVertices)
|
||||
{
|
||||
if (numVertices <= 0)
|
||||
return;
|
||||
|
||||
switch (primitive)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
case GX_DRAW_TRIANGLES:
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen() < 3 * numVertices)
|
||||
Flush();
|
||||
break;
|
||||
|
||||
case GX_DRAW_LINES:
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen() < 2 * numVertices)
|
||||
Flush();
|
||||
break;
|
||||
|
||||
case GX_DRAW_POINTS:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen() < numVertices)
|
||||
Flush();
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Flushed)
|
||||
{
|
||||
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
|
||||
Flushed = false;
|
||||
}
|
||||
|
||||
ADDSTAT(stats.thisFrame.numPrims, numVertices);
|
||||
INCSTAT(stats.thisFrame.numPrimitiveJoins);
|
||||
AddIndices(primitive, numVertices);
|
||||
}
|
||||
|
||||
// TODO: merge this func, (need to merge TextureCache)
|
||||
void VertexManager::Flush()
|
||||
{
|
||||
g_vertex_manager->vFlush();
|
||||
}
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "Statistics.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "IndexGenerator.h"
|
||||
|
||||
#include "VertexManagerBase.h"
|
||||
|
||||
VertexManager *g_vertex_manager;
|
||||
|
||||
u8 *VertexManager::s_pCurBufferPointer;
|
||||
u8 *VertexManager::s_pBaseBufferPointer;
|
||||
|
||||
u8 *VertexManager::LocalVBuffer;
|
||||
u16 *VertexManager::TIBuffer;
|
||||
u16 *VertexManager::LIBuffer;
|
||||
u16 *VertexManager::PIBuffer;
|
||||
|
||||
bool VertexManager::Flushed;
|
||||
|
||||
VertexManager::VertexManager()
|
||||
{
|
||||
Flushed = false;
|
||||
|
||||
LocalVBuffer = new u8[MAXVBUFFERSIZE];
|
||||
s_pCurBufferPointer = s_pBaseBufferPointer = LocalVBuffer;
|
||||
|
||||
TIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
LIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
PIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
|
||||
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
|
||||
}
|
||||
|
||||
void VertexManager::ResetBuffer()
|
||||
{
|
||||
s_pCurBufferPointer = LocalVBuffer;
|
||||
}
|
||||
|
||||
VertexManager::~VertexManager()
|
||||
{
|
||||
delete[] LocalVBuffer;
|
||||
|
||||
delete[] TIBuffer;
|
||||
delete[] LIBuffer;
|
||||
delete[] PIBuffer;
|
||||
|
||||
// TODO: necessary??
|
||||
ResetBuffer();
|
||||
}
|
||||
|
||||
void VertexManager::AddIndices(int primitive, int numVertices)
|
||||
{
|
||||
//switch (primitive)
|
||||
//{
|
||||
//case GX_DRAW_QUADS: IndexGenerator::AddQuads(numVertices); break;
|
||||
//case GX_DRAW_TRIANGLES: IndexGenerator::AddList(numVertices); break;
|
||||
//case GX_DRAW_TRIANGLE_STRIP: IndexGenerator::AddStrip(numVertices); break;
|
||||
//case GX_DRAW_TRIANGLE_FAN: IndexGenerator::AddFan(numVertices); break;
|
||||
//case GX_DRAW_LINES: IndexGenerator::AddLineList(numVertices); break;
|
||||
//case GX_DRAW_LINE_STRIP: IndexGenerator::AddLineStrip(numVertices); break;
|
||||
//case GX_DRAW_POINTS: IndexGenerator::AddPoints(numVertices); break;
|
||||
//}
|
||||
|
||||
static void (*const primitive_table[])(int) =
|
||||
{
|
||||
IndexGenerator::AddQuads,
|
||||
NULL,
|
||||
IndexGenerator::AddList,
|
||||
IndexGenerator::AddStrip,
|
||||
IndexGenerator::AddFan,
|
||||
IndexGenerator::AddLineList,
|
||||
IndexGenerator::AddLineStrip,
|
||||
IndexGenerator::AddPoints,
|
||||
};
|
||||
|
||||
primitive_table[primitive](numVertices);
|
||||
}
|
||||
|
||||
int VertexManager::GetRemainingSize()
|
||||
{
|
||||
return MAXVBUFFERSIZE - (int)(s_pCurBufferPointer - LocalVBuffer);
|
||||
}
|
||||
|
||||
int VertexManager::GetRemainingVertices(int primitive)
|
||||
{
|
||||
switch (primitive)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
case GX_DRAW_TRIANGLES:
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3;
|
||||
break;
|
||||
|
||||
case GX_DRAW_LINES:
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2;
|
||||
break;
|
||||
|
||||
case GX_DRAW_POINTS:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen());
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexManager::AddVertices(int primitive, int numVertices)
|
||||
{
|
||||
if (numVertices <= 0)
|
||||
return;
|
||||
|
||||
switch (primitive)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
case GX_DRAW_TRIANGLES:
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen() < 3 * numVertices)
|
||||
Flush();
|
||||
break;
|
||||
|
||||
case GX_DRAW_LINES:
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen() < 2 * numVertices)
|
||||
Flush();
|
||||
break;
|
||||
|
||||
case GX_DRAW_POINTS:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen() < numVertices)
|
||||
Flush();
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Flushed)
|
||||
{
|
||||
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
|
||||
Flushed = false;
|
||||
}
|
||||
|
||||
ADDSTAT(stats.thisFrame.numPrims, numVertices);
|
||||
INCSTAT(stats.thisFrame.numPrimitiveJoins);
|
||||
AddIndices(primitive, numVertices);
|
||||
}
|
||||
|
||||
// TODO: merge this func, (need to merge TextureCache)
|
||||
void VertexManager::Flush()
|
||||
{
|
||||
g_vertex_manager->vFlush();
|
||||
}
|
||||
|
|
|
@ -1,57 +1,57 @@
|
|||
|
||||
#ifndef _VERTEXMANAGERBASE_H
|
||||
#define _VERTEXMANAGERBASE_H
|
||||
|
||||
class VertexManager
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
// values from OGL plugin
|
||||
//MAXVBUFFERSIZE = 0x1FFFF,
|
||||
//MAXIBUFFERSIZE = 0xFFFF,
|
||||
|
||||
// values from DX9 plugin
|
||||
//MAXVBUFFERSIZE = 0x50000,
|
||||
//MAXIBUFFERSIZE = 0xFFFF,
|
||||
|
||||
// values from DX11 plugin
|
||||
MAXVBUFFERSIZE = 0x50000,
|
||||
MAXIBUFFERSIZE = 0x10000,
|
||||
};
|
||||
|
||||
VertexManager();
|
||||
virtual ~VertexManager(); // needs to be virtual for DX11's dtor
|
||||
|
||||
static void AddVertices(int _primitive, int _numVertices);
|
||||
|
||||
// TODO: protected?
|
||||
static u8 *s_pCurBufferPointer;
|
||||
static u8 *s_pBaseBufferPointer;
|
||||
|
||||
static int GetRemainingSize();
|
||||
static int GetRemainingVertices(int primitive);
|
||||
|
||||
static void Flush();
|
||||
|
||||
protected:
|
||||
// TODO: make private after Flush() is merged
|
||||
static void ResetBuffer();
|
||||
|
||||
static u8 *LocalVBuffer;
|
||||
static u16 *TIBuffer;
|
||||
static u16 *LIBuffer;
|
||||
static u16 *PIBuffer;
|
||||
|
||||
static bool Flushed;
|
||||
|
||||
private:
|
||||
static void AddIndices(int primitive, int numVertices);
|
||||
// temporary
|
||||
virtual void vFlush() = 0;
|
||||
};
|
||||
|
||||
extern VertexManager *g_vertex_manager;
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _VERTEXMANAGERBASE_H
|
||||
#define _VERTEXMANAGERBASE_H
|
||||
|
||||
class VertexManager
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
// values from OGL plugin
|
||||
//MAXVBUFFERSIZE = 0x1FFFF,
|
||||
//MAXIBUFFERSIZE = 0xFFFF,
|
||||
|
||||
// values from DX9 plugin
|
||||
//MAXVBUFFERSIZE = 0x50000,
|
||||
//MAXIBUFFERSIZE = 0xFFFF,
|
||||
|
||||
// values from DX11 plugin
|
||||
MAXVBUFFERSIZE = 0x50000,
|
||||
MAXIBUFFERSIZE = 0x10000,
|
||||
};
|
||||
|
||||
VertexManager();
|
||||
virtual ~VertexManager(); // needs to be virtual for DX11's dtor
|
||||
|
||||
static void AddVertices(int _primitive, int _numVertices);
|
||||
|
||||
// TODO: protected?
|
||||
static u8 *s_pCurBufferPointer;
|
||||
static u8 *s_pBaseBufferPointer;
|
||||
|
||||
static int GetRemainingSize();
|
||||
static int GetRemainingVertices(int primitive);
|
||||
|
||||
static void Flush();
|
||||
|
||||
protected:
|
||||
// TODO: make private after Flush() is merged
|
||||
static void ResetBuffer();
|
||||
|
||||
static u8 *LocalVBuffer;
|
||||
static u16 *TIBuffer;
|
||||
static u16 *LIBuffer;
|
||||
static u16 *PIBuffer;
|
||||
|
||||
static bool Flushed;
|
||||
|
||||
private:
|
||||
static void AddIndices(int primitive, int numVertices);
|
||||
// temporary
|
||||
virtual void vFlush() = 0;
|
||||
};
|
||||
|
||||
extern VertexManager *g_vertex_manager;
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,144 +1,144 @@
|
|||
// 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/
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
#include "BPFunctions.h"
|
||||
#include "Renderer.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VertexManager.h"
|
||||
|
||||
#include "Main.h"
|
||||
|
||||
namespace BPFunctions
|
||||
{
|
||||
|
||||
void FlushPipeline()
|
||||
{
|
||||
g_vertex_manager->Flush();
|
||||
}
|
||||
|
||||
void SetGenerationMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetGenerationMode();
|
||||
}
|
||||
|
||||
void SetScissor(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetScissorRect();
|
||||
}
|
||||
|
||||
void SetLineWidth(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetLineWidth();
|
||||
}
|
||||
|
||||
void SetDepthMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetDepthMode();
|
||||
}
|
||||
|
||||
void SetBlendMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetBlendMode(false);
|
||||
}
|
||||
|
||||
void SetDitherMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetDitherMode();
|
||||
}
|
||||
|
||||
void SetLogicOpMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetLogicOpMode();
|
||||
}
|
||||
|
||||
void SetColorMask(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetColorMask();
|
||||
}
|
||||
|
||||
void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©fmt, const int &scaleByHalf)
|
||||
{
|
||||
if (!g_ActiveConfig.bEFBCopyDisable)
|
||||
{
|
||||
// if (g_ActiveConfig.bCopyEFBToTexture)
|
||||
// {
|
||||
g_texture_cache->CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, !!scaleByHalf, rc);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// PanicAlert("TODO: Implement EFB copying to RAM %s %d\n", __FILE__, __LINE__);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
void ClearScreen(const BPCmd &bp, const EFBRectangle &rc)
|
||||
{
|
||||
bool colorEnable = bpmem.blendmode.colorupdate;
|
||||
bool alphaEnable = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24 && bpmem.blendmode.alphaupdate);
|
||||
bool zEnable = bpmem.zmode.updateenable;
|
||||
|
||||
if (colorEnable || alphaEnable || zEnable)
|
||||
{
|
||||
u32 color = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
|
||||
u32 z = bpmem.clearZValue;
|
||||
|
||||
g_renderer->ClearScreen(rc, colorEnable, alphaEnable, zEnable, color, z);
|
||||
}
|
||||
}
|
||||
|
||||
void RestoreRenderState(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
bool GetConfig(const int &type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CONFIG_ISWII:
|
||||
return g_VideoInitialize.bWii;
|
||||
case CONFIG_DISABLEFOG:
|
||||
return g_ActiveConfig.bDisableFog;
|
||||
case CONFIG_SHOWEFBREGIONS:
|
||||
return false;
|
||||
default:
|
||||
PanicAlert("GetConfig Error: Unknown Config Type!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
u8 *GetPointer(const u32 &address)
|
||||
{
|
||||
return g_VideoInitialize.pGetMemoryPointer(address);
|
||||
}
|
||||
|
||||
void SetTextureMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetSamplerState(bp.address & 3, (bp.address & 0xE0) == 0xA0);
|
||||
}
|
||||
|
||||
void SetInterlacingMode(const BPCmd &bp)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
#include "BPFunctions.h"
|
||||
#include "Renderer.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VertexManager.h"
|
||||
|
||||
#include "Main.h"
|
||||
|
||||
namespace BPFunctions
|
||||
{
|
||||
|
||||
void FlushPipeline()
|
||||
{
|
||||
g_vertex_manager->Flush();
|
||||
}
|
||||
|
||||
void SetGenerationMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetGenerationMode();
|
||||
}
|
||||
|
||||
void SetScissor(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetScissorRect();
|
||||
}
|
||||
|
||||
void SetLineWidth(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetLineWidth();
|
||||
}
|
||||
|
||||
void SetDepthMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetDepthMode();
|
||||
}
|
||||
|
||||
void SetBlendMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetBlendMode(false);
|
||||
}
|
||||
|
||||
void SetDitherMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetDitherMode();
|
||||
}
|
||||
|
||||
void SetLogicOpMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetLogicOpMode();
|
||||
}
|
||||
|
||||
void SetColorMask(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetColorMask();
|
||||
}
|
||||
|
||||
void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©fmt, const int &scaleByHalf)
|
||||
{
|
||||
if (!g_ActiveConfig.bEFBCopyDisable)
|
||||
{
|
||||
// if (g_ActiveConfig.bCopyEFBToTexture)
|
||||
// {
|
||||
g_texture_cache->CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, !!scaleByHalf, rc);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// PanicAlert("TODO: Implement EFB copying to RAM %s %d\n", __FILE__, __LINE__);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
void ClearScreen(const BPCmd &bp, const EFBRectangle &rc)
|
||||
{
|
||||
bool colorEnable = bpmem.blendmode.colorupdate;
|
||||
bool alphaEnable = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24 && bpmem.blendmode.alphaupdate);
|
||||
bool zEnable = bpmem.zmode.updateenable;
|
||||
|
||||
if (colorEnable || alphaEnable || zEnable)
|
||||
{
|
||||
u32 color = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
|
||||
u32 z = bpmem.clearZValue;
|
||||
|
||||
g_renderer->ClearScreen(rc, colorEnable, alphaEnable, zEnable, color, z);
|
||||
}
|
||||
}
|
||||
|
||||
void RestoreRenderState(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
bool GetConfig(const int &type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CONFIG_ISWII:
|
||||
return g_VideoInitialize.bWii;
|
||||
case CONFIG_DISABLEFOG:
|
||||
return g_ActiveConfig.bDisableFog;
|
||||
case CONFIG_SHOWEFBREGIONS:
|
||||
return false;
|
||||
default:
|
||||
PanicAlert("GetConfig Error: Unknown Config Type!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
u8 *GetPointer(const u32 &address)
|
||||
{
|
||||
return g_VideoInitialize.pGetMemoryPointer(address);
|
||||
}
|
||||
|
||||
void SetTextureMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetSamplerState(bp.address & 3, (bp.address & 0xE0) == 0xA0);
|
||||
}
|
||||
|
||||
void SetInterlacingMode(const BPCmd &bp)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,338 +1,338 @@
|
|||
// 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/
|
||||
|
||||
// Common
|
||||
#include "StringUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
#include "XFStructs.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DTexture.h"
|
||||
#include "DX11_D3DShader.h"
|
||||
#include "DX11_Render.h"
|
||||
|
||||
#include <D3Dcompiler.h>
|
||||
|
||||
#pragma comment(lib, "dxguid.lib")
|
||||
#pragma comment(lib, "d3d11.lib")
|
||||
#pragma comment(lib, "dxgi.lib")
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
HINSTANCE hD3DXDll = NULL;
|
||||
D3DX11COMPILEFROMMEMORYTYPE PD3DX11CompileFromMemory = NULL;
|
||||
D3DX11FILTERTEXTURETYPE PD3DX11FilterTexture = NULL;
|
||||
D3DX11SAVETEXTURETOFILEATYPE PD3DX11SaveTextureToFileA = NULL;
|
||||
D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW = NULL;
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
ID3D11Device* device = NULL;
|
||||
ID3D11DeviceContext* context = NULL;
|
||||
IDXGISwapChain* swapchain = NULL;
|
||||
D3D_FEATURE_LEVEL featlevel;
|
||||
D3DTexture2D* backbuf = NULL;
|
||||
HWND hWnd;
|
||||
|
||||
bool bgra_textures_supported;
|
||||
|
||||
#define NUM_SUPPORTED_FEATURE_LEVELS 3
|
||||
const D3D_FEATURE_LEVEL supported_feature_levels[NUM_SUPPORTED_FEATURE_LEVELS] = {
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
D3D_FEATURE_LEVEL_10_1,
|
||||
D3D_FEATURE_LEVEL_10_0
|
||||
};
|
||||
|
||||
unsigned int xres, yres;
|
||||
|
||||
bool bFrameInProgress = false;
|
||||
|
||||
HRESULT Create(HWND wnd)
|
||||
{
|
||||
hWnd = wnd;
|
||||
HRESULT hr;
|
||||
|
||||
RECT client;
|
||||
GetClientRect(hWnd, &client);
|
||||
xres = client.right - client.left;
|
||||
yres = client.bottom - client.top;
|
||||
|
||||
// try to load D3DX11 first to check whether we have proper runtime support
|
||||
// try to use the dll the plugin was compiled against first - don't bother about debug runtimes
|
||||
hD3DXDll = LoadLibraryA(StringFromFormat("d3dx11_%d.dll", D3DX11_SDK_VERSION).c_str());
|
||||
if (!hD3DXDll)
|
||||
{
|
||||
// if that fails, use the dll which should be available in every SDK which officially supports DX11.
|
||||
hD3DXDll = LoadLibraryA("d3dx11_42.dll");
|
||||
if (!hD3DXDll)
|
||||
{
|
||||
MessageBoxA(NULL, "Failed to load d3dx11_42.dll, update your DX11 runtime, please", "Critical error", MB_OK | MB_ICONERROR);
|
||||
return E_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
NOTICE_LOG(VIDEO, "Successfully loaded d3dx11_42.dll. If you're having trouble, try updating your DX runtime first.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NOTICE_LOG(VIDEO, "Successfully loaded %s.", StringFromFormat("d3dx11_%d.dll", D3DX11_SDK_VERSION).c_str());
|
||||
}
|
||||
|
||||
PD3DX11CompileFromMemory = (D3DX11COMPILEFROMMEMORYTYPE)GetProcAddress(hD3DXDll, "D3DX11CompileFromMemory");
|
||||
if (PD3DX11CompileFromMemory == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11CompileFromMemory!", "Critical error", MB_OK | MB_ICONERROR);
|
||||
|
||||
PD3DX11FilterTexture = (D3DX11FILTERTEXTURETYPE)GetProcAddress(hD3DXDll, "D3DX11FilterTexture");
|
||||
if (PD3DX11FilterTexture == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11FilterTexture!", "Critical error", MB_OK | MB_ICONERROR);
|
||||
|
||||
PD3DX11SaveTextureToFileA = (D3DX11SAVETEXTURETOFILEATYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileA");
|
||||
if (PD3DX11SaveTextureToFileA == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileA!", "Critical error", MB_OK | MB_ICONERROR);
|
||||
|
||||
PD3DX11SaveTextureToFileW = (D3DX11SAVETEXTURETOFILEWTYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileW");
|
||||
if (PD3DX11SaveTextureToFileW == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileW!", "Critical error", MB_OK | MB_ICONERROR);
|
||||
|
||||
// D3DX11 is fine, initialize D3D11
|
||||
IDXGIFactory* factory;
|
||||
IDXGIAdapter* adapter;
|
||||
IDXGIOutput* output;
|
||||
hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
|
||||
if (FAILED(hr)) MessageBox(wnd, _T("Failed to create IDXGIFactory object"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
|
||||
hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// try using the first one
|
||||
hr = factory->EnumAdapters(0, &adapter);
|
||||
if (FAILED(hr)) MessageBox(wnd, _T("Failed to enumerate adapters"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
}
|
||||
|
||||
// TODO: Make this configurable
|
||||
hr = adapter->EnumOutputs(0, &output);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// try using the first one
|
||||
hr = adapter->EnumOutputs(0, &output);
|
||||
if (FAILED(hr)) MessageBox(wnd, _T("Failed to enumerate outputs"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
}
|
||||
|
||||
// this will need to be changed once multisampling gets implemented
|
||||
DXGI_SWAP_CHAIN_DESC swap_chain_desc;
|
||||
memset(&swap_chain_desc, 0, sizeof(swap_chain_desc));
|
||||
swap_chain_desc.BufferCount = 1;
|
||||
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swap_chain_desc.OutputWindow = wnd;
|
||||
swap_chain_desc.SampleDesc.Count = 1;
|
||||
swap_chain_desc.SampleDesc.Quality = 0;
|
||||
swap_chain_desc.Windowed = TRUE;
|
||||
|
||||
DXGI_MODE_DESC mode_desc;
|
||||
memset(&mode_desc, 0, sizeof(mode_desc));
|
||||
mode_desc.Width = xres;
|
||||
mode_desc.Height = yres;
|
||||
mode_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
mode_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
hr = output->FindClosestMatchingMode(&mode_desc, &swap_chain_desc.BufferDesc, NULL);
|
||||
if (FAILED(hr))
|
||||
MessageBox(wnd, _T("Failed to find a supported video mode"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
|
||||
// forcing buffer resolution to xres and yres.. TODO: The new video mode might not actually be supported!
|
||||
swap_chain_desc.BufferDesc.Width = xres;
|
||||
swap_chain_desc.BufferDesc.Height = yres;
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
D3D11_CREATE_DEVICE_FLAG device_flags = (D3D11_CREATE_DEVICE_FLAG)(D3D11_CREATE_DEVICE_DEBUG|D3D11_CREATE_DEVICE_SINGLETHREADED);
|
||||
#else
|
||||
D3D11_CREATE_DEVICE_FLAG device_flags = D3D11_CREATE_DEVICE_SINGLETHREADED;
|
||||
#endif
|
||||
hr = D3D11CreateDeviceAndSwapChain(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, device_flags,
|
||||
supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS,
|
||||
D3D11_SDK_VERSION, &swap_chain_desc, &swapchain, &device,
|
||||
&featlevel, &context);
|
||||
if (FAILED(hr) || !device || !context || !swapchain)
|
||||
{
|
||||
MessageBox(wnd, _T("Failed to initialize Direct3D.\nMake sure your video card supports at least D3D 10.0"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
SAFE_RELEASE(device);
|
||||
SAFE_RELEASE(context);
|
||||
SAFE_RELEASE(swapchain);
|
||||
return E_FAIL;
|
||||
}
|
||||
SetDebugObjectName((ID3D11DeviceChild*)context, "device context");
|
||||
SAFE_RELEASE(factory);
|
||||
SAFE_RELEASE(output);
|
||||
SAFE_RELEASE(adapter);
|
||||
|
||||
ID3D11Texture2D* buf;
|
||||
hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
MessageBox(wnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
SAFE_RELEASE(device);
|
||||
SAFE_RELEASE(context);
|
||||
SAFE_RELEASE(swapchain);
|
||||
return E_FAIL;
|
||||
}
|
||||
backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
|
||||
SAFE_RELEASE(buf);
|
||||
CHECK(backbuf!=NULL, "Create back buffer texture");
|
||||
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetTex(), "backbuffer texture");
|
||||
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetRTV(), "backbuffer render target view");
|
||||
|
||||
context->OMSetRenderTargets(1, &backbuf->GetRTV(), NULL);
|
||||
|
||||
// BGRA textures are easier to deal with in TextureCache, but might not be supported by the hardware
|
||||
UINT format_support;
|
||||
device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &format_support);
|
||||
bgra_textures_supported = (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
|
||||
|
||||
gfxstate = new EmuGfxState;
|
||||
stateman = new StateManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
// unload D3DX11
|
||||
FreeLibrary(hD3DXDll);
|
||||
PD3DX11FilterTexture = NULL;
|
||||
PD3DX11SaveTextureToFileA = NULL;
|
||||
PD3DX11SaveTextureToFileW = NULL;
|
||||
|
||||
// release all bound resources
|
||||
context->ClearState();
|
||||
SAFE_RELEASE(backbuf);
|
||||
SAFE_RELEASE(swapchain);
|
||||
SAFE_DELETE(gfxstate);
|
||||
SAFE_DELETE(stateman);
|
||||
context->Flush(); // immediately destroy device objects
|
||||
|
||||
SAFE_RELEASE(context);
|
||||
ULONG references = device->Release();
|
||||
if (references)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Unreleased references: %i.", references);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOTICE_LOG(VIDEO, "Successfully released all device references!");
|
||||
}
|
||||
device = NULL;
|
||||
}
|
||||
|
||||
/* just returning the 4_0 ones here */
|
||||
const char* VertexShaderVersionString() { return "vs_4_0"; }
|
||||
const char* PixelShaderVersionString() { return "ps_4_0"; }
|
||||
|
||||
D3DTexture2D* &GetBackBuffer() { return backbuf; }
|
||||
unsigned int GetBackBufferWidth() { return xres; }
|
||||
unsigned int GetBackBufferHeight() { return yres; }
|
||||
|
||||
bool BGRATexturesSupported() { return bgra_textures_supported; }
|
||||
|
||||
// Returns the maximum width/height of a texture. This value only depends upon the feature level in DX11
|
||||
unsigned int GetMaxTextureSize()
|
||||
{
|
||||
switch (featlevel)
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
return 16384;
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_10_1:
|
||||
case D3D_FEATURE_LEVEL_10_0:
|
||||
return 8192;
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_9_3:
|
||||
return 4096;
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_9_2:
|
||||
case D3D_FEATURE_LEVEL_9_1:
|
||||
return 2048;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
// release all back buffer references
|
||||
SAFE_RELEASE(backbuf);
|
||||
|
||||
// resize swapchain buffers
|
||||
RECT client;
|
||||
GetClientRect(hWnd, &client);
|
||||
xres = client.right - client.left;
|
||||
yres = client.bottom - client.top;
|
||||
D3D::swapchain->ResizeBuffers(1, xres, yres, DXGI_FORMAT_R8G8B8A8_UNORM, 0);
|
||||
|
||||
// recreate back buffer texture
|
||||
ID3D11Texture2D* buf;
|
||||
HRESULT hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
MessageBox(hWnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
SAFE_RELEASE(device);
|
||||
SAFE_RELEASE(context);
|
||||
SAFE_RELEASE(swapchain);
|
||||
return;
|
||||
}
|
||||
backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
|
||||
SAFE_RELEASE(buf);
|
||||
CHECK(backbuf!=NULL, "Create back buffer texture");
|
||||
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetTex(), "backbuffer texture");
|
||||
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetRTV(), "backbuffer render target view");
|
||||
}
|
||||
|
||||
bool BeginFrame()
|
||||
{
|
||||
if (bFrameInProgress)
|
||||
{
|
||||
PanicAlert("BeginFrame called although a frame is already in progress");
|
||||
return false;
|
||||
}
|
||||
bFrameInProgress = true;
|
||||
return (device != NULL);
|
||||
}
|
||||
|
||||
void EndFrame()
|
||||
{
|
||||
if (!bFrameInProgress)
|
||||
{
|
||||
PanicAlert("EndFrame called although no frame is in progress");
|
||||
return;
|
||||
}
|
||||
bFrameInProgress = false;
|
||||
}
|
||||
|
||||
void Present()
|
||||
{
|
||||
// TODO: Is 1 the correct value for vsyncing?
|
||||
swapchain->Present((UINT)g_ActiveConfig.bVSync, 0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
// Common
|
||||
#include "StringUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
#include "XFStructs.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DTexture.h"
|
||||
#include "DX11_D3DShader.h"
|
||||
#include "DX11_Render.h"
|
||||
|
||||
#include <D3Dcompiler.h>
|
||||
|
||||
#pragma comment(lib, "dxguid.lib")
|
||||
#pragma comment(lib, "d3d11.lib")
|
||||
#pragma comment(lib, "dxgi.lib")
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
HINSTANCE hD3DXDll = NULL;
|
||||
D3DX11COMPILEFROMMEMORYTYPE PD3DX11CompileFromMemory = NULL;
|
||||
D3DX11FILTERTEXTURETYPE PD3DX11FilterTexture = NULL;
|
||||
D3DX11SAVETEXTURETOFILEATYPE PD3DX11SaveTextureToFileA = NULL;
|
||||
D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW = NULL;
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
ID3D11Device* device = NULL;
|
||||
ID3D11DeviceContext* context = NULL;
|
||||
IDXGISwapChain* swapchain = NULL;
|
||||
D3D_FEATURE_LEVEL featlevel;
|
||||
D3DTexture2D* backbuf = NULL;
|
||||
HWND hWnd;
|
||||
|
||||
bool bgra_textures_supported;
|
||||
|
||||
#define NUM_SUPPORTED_FEATURE_LEVELS 3
|
||||
const D3D_FEATURE_LEVEL supported_feature_levels[NUM_SUPPORTED_FEATURE_LEVELS] = {
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
D3D_FEATURE_LEVEL_10_1,
|
||||
D3D_FEATURE_LEVEL_10_0
|
||||
};
|
||||
|
||||
unsigned int xres, yres;
|
||||
|
||||
bool bFrameInProgress = false;
|
||||
|
||||
HRESULT Create(HWND wnd)
|
||||
{
|
||||
hWnd = wnd;
|
||||
HRESULT hr;
|
||||
|
||||
RECT client;
|
||||
GetClientRect(hWnd, &client);
|
||||
xres = client.right - client.left;
|
||||
yres = client.bottom - client.top;
|
||||
|
||||
// try to load D3DX11 first to check whether we have proper runtime support
|
||||
// try to use the dll the plugin was compiled against first - don't bother about debug runtimes
|
||||
hD3DXDll = LoadLibraryA(StringFromFormat("d3dx11_%d.dll", D3DX11_SDK_VERSION).c_str());
|
||||
if (!hD3DXDll)
|
||||
{
|
||||
// if that fails, use the dll which should be available in every SDK which officially supports DX11.
|
||||
hD3DXDll = LoadLibraryA("d3dx11_42.dll");
|
||||
if (!hD3DXDll)
|
||||
{
|
||||
MessageBoxA(NULL, "Failed to load d3dx11_42.dll, update your DX11 runtime, please", "Critical error", MB_OK | MB_ICONERROR);
|
||||
return E_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
NOTICE_LOG(VIDEO, "Successfully loaded d3dx11_42.dll. If you're having trouble, try updating your DX runtime first.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NOTICE_LOG(VIDEO, "Successfully loaded %s.", StringFromFormat("d3dx11_%d.dll", D3DX11_SDK_VERSION).c_str());
|
||||
}
|
||||
|
||||
PD3DX11CompileFromMemory = (D3DX11COMPILEFROMMEMORYTYPE)GetProcAddress(hD3DXDll, "D3DX11CompileFromMemory");
|
||||
if (PD3DX11CompileFromMemory == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11CompileFromMemory!", "Critical error", MB_OK | MB_ICONERROR);
|
||||
|
||||
PD3DX11FilterTexture = (D3DX11FILTERTEXTURETYPE)GetProcAddress(hD3DXDll, "D3DX11FilterTexture");
|
||||
if (PD3DX11FilterTexture == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11FilterTexture!", "Critical error", MB_OK | MB_ICONERROR);
|
||||
|
||||
PD3DX11SaveTextureToFileA = (D3DX11SAVETEXTURETOFILEATYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileA");
|
||||
if (PD3DX11SaveTextureToFileA == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileA!", "Critical error", MB_OK | MB_ICONERROR);
|
||||
|
||||
PD3DX11SaveTextureToFileW = (D3DX11SAVETEXTURETOFILEWTYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileW");
|
||||
if (PD3DX11SaveTextureToFileW == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileW!", "Critical error", MB_OK | MB_ICONERROR);
|
||||
|
||||
// D3DX11 is fine, initialize D3D11
|
||||
IDXGIFactory* factory;
|
||||
IDXGIAdapter* adapter;
|
||||
IDXGIOutput* output;
|
||||
hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
|
||||
if (FAILED(hr)) MessageBox(wnd, _T("Failed to create IDXGIFactory object"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
|
||||
hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// try using the first one
|
||||
hr = factory->EnumAdapters(0, &adapter);
|
||||
if (FAILED(hr)) MessageBox(wnd, _T("Failed to enumerate adapters"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
}
|
||||
|
||||
// TODO: Make this configurable
|
||||
hr = adapter->EnumOutputs(0, &output);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// try using the first one
|
||||
hr = adapter->EnumOutputs(0, &output);
|
||||
if (FAILED(hr)) MessageBox(wnd, _T("Failed to enumerate outputs"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
}
|
||||
|
||||
// this will need to be changed once multisampling gets implemented
|
||||
DXGI_SWAP_CHAIN_DESC swap_chain_desc;
|
||||
memset(&swap_chain_desc, 0, sizeof(swap_chain_desc));
|
||||
swap_chain_desc.BufferCount = 1;
|
||||
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swap_chain_desc.OutputWindow = wnd;
|
||||
swap_chain_desc.SampleDesc.Count = 1;
|
||||
swap_chain_desc.SampleDesc.Quality = 0;
|
||||
swap_chain_desc.Windowed = TRUE;
|
||||
|
||||
DXGI_MODE_DESC mode_desc;
|
||||
memset(&mode_desc, 0, sizeof(mode_desc));
|
||||
mode_desc.Width = xres;
|
||||
mode_desc.Height = yres;
|
||||
mode_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
mode_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
hr = output->FindClosestMatchingMode(&mode_desc, &swap_chain_desc.BufferDesc, NULL);
|
||||
if (FAILED(hr))
|
||||
MessageBox(wnd, _T("Failed to find a supported video mode"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
|
||||
// forcing buffer resolution to xres and yres.. TODO: The new video mode might not actually be supported!
|
||||
swap_chain_desc.BufferDesc.Width = xres;
|
||||
swap_chain_desc.BufferDesc.Height = yres;
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
D3D11_CREATE_DEVICE_FLAG device_flags = (D3D11_CREATE_DEVICE_FLAG)(D3D11_CREATE_DEVICE_DEBUG|D3D11_CREATE_DEVICE_SINGLETHREADED);
|
||||
#else
|
||||
D3D11_CREATE_DEVICE_FLAG device_flags = D3D11_CREATE_DEVICE_SINGLETHREADED;
|
||||
#endif
|
||||
hr = D3D11CreateDeviceAndSwapChain(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, device_flags,
|
||||
supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS,
|
||||
D3D11_SDK_VERSION, &swap_chain_desc, &swapchain, &device,
|
||||
&featlevel, &context);
|
||||
if (FAILED(hr) || !device || !context || !swapchain)
|
||||
{
|
||||
MessageBox(wnd, _T("Failed to initialize Direct3D.\nMake sure your video card supports at least D3D 10.0"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
SAFE_RELEASE(device);
|
||||
SAFE_RELEASE(context);
|
||||
SAFE_RELEASE(swapchain);
|
||||
return E_FAIL;
|
||||
}
|
||||
SetDebugObjectName((ID3D11DeviceChild*)context, "device context");
|
||||
SAFE_RELEASE(factory);
|
||||
SAFE_RELEASE(output);
|
||||
SAFE_RELEASE(adapter);
|
||||
|
||||
ID3D11Texture2D* buf;
|
||||
hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
MessageBox(wnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
SAFE_RELEASE(device);
|
||||
SAFE_RELEASE(context);
|
||||
SAFE_RELEASE(swapchain);
|
||||
return E_FAIL;
|
||||
}
|
||||
backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
|
||||
SAFE_RELEASE(buf);
|
||||
CHECK(backbuf!=NULL, "Create back buffer texture");
|
||||
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetTex(), "backbuffer texture");
|
||||
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetRTV(), "backbuffer render target view");
|
||||
|
||||
context->OMSetRenderTargets(1, &backbuf->GetRTV(), NULL);
|
||||
|
||||
// BGRA textures are easier to deal with in TextureCache, but might not be supported by the hardware
|
||||
UINT format_support;
|
||||
device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &format_support);
|
||||
bgra_textures_supported = (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
|
||||
|
||||
gfxstate = new EmuGfxState;
|
||||
stateman = new StateManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
// unload D3DX11
|
||||
FreeLibrary(hD3DXDll);
|
||||
PD3DX11FilterTexture = NULL;
|
||||
PD3DX11SaveTextureToFileA = NULL;
|
||||
PD3DX11SaveTextureToFileW = NULL;
|
||||
|
||||
// release all bound resources
|
||||
context->ClearState();
|
||||
SAFE_RELEASE(backbuf);
|
||||
SAFE_RELEASE(swapchain);
|
||||
SAFE_DELETE(gfxstate);
|
||||
SAFE_DELETE(stateman);
|
||||
context->Flush(); // immediately destroy device objects
|
||||
|
||||
SAFE_RELEASE(context);
|
||||
ULONG references = device->Release();
|
||||
if (references)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Unreleased references: %i.", references);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOTICE_LOG(VIDEO, "Successfully released all device references!");
|
||||
}
|
||||
device = NULL;
|
||||
}
|
||||
|
||||
/* just returning the 4_0 ones here */
|
||||
const char* VertexShaderVersionString() { return "vs_4_0"; }
|
||||
const char* PixelShaderVersionString() { return "ps_4_0"; }
|
||||
|
||||
D3DTexture2D* &GetBackBuffer() { return backbuf; }
|
||||
unsigned int GetBackBufferWidth() { return xres; }
|
||||
unsigned int GetBackBufferHeight() { return yres; }
|
||||
|
||||
bool BGRATexturesSupported() { return bgra_textures_supported; }
|
||||
|
||||
// Returns the maximum width/height of a texture. This value only depends upon the feature level in DX11
|
||||
unsigned int GetMaxTextureSize()
|
||||
{
|
||||
switch (featlevel)
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
return 16384;
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_10_1:
|
||||
case D3D_FEATURE_LEVEL_10_0:
|
||||
return 8192;
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_9_3:
|
||||
return 4096;
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_9_2:
|
||||
case D3D_FEATURE_LEVEL_9_1:
|
||||
return 2048;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
// release all back buffer references
|
||||
SAFE_RELEASE(backbuf);
|
||||
|
||||
// resize swapchain buffers
|
||||
RECT client;
|
||||
GetClientRect(hWnd, &client);
|
||||
xres = client.right - client.left;
|
||||
yres = client.bottom - client.top;
|
||||
D3D::swapchain->ResizeBuffers(1, xres, yres, DXGI_FORMAT_R8G8B8A8_UNORM, 0);
|
||||
|
||||
// recreate back buffer texture
|
||||
ID3D11Texture2D* buf;
|
||||
HRESULT hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
MessageBox(hWnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
|
||||
SAFE_RELEASE(device);
|
||||
SAFE_RELEASE(context);
|
||||
SAFE_RELEASE(swapchain);
|
||||
return;
|
||||
}
|
||||
backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
|
||||
SAFE_RELEASE(buf);
|
||||
CHECK(backbuf!=NULL, "Create back buffer texture");
|
||||
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetTex(), "backbuffer texture");
|
||||
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetRTV(), "backbuffer render target view");
|
||||
}
|
||||
|
||||
bool BeginFrame()
|
||||
{
|
||||
if (bFrameInProgress)
|
||||
{
|
||||
PanicAlert("BeginFrame called although a frame is already in progress");
|
||||
return false;
|
||||
}
|
||||
bFrameInProgress = true;
|
||||
return (device != NULL);
|
||||
}
|
||||
|
||||
void EndFrame()
|
||||
{
|
||||
if (!bFrameInProgress)
|
||||
{
|
||||
PanicAlert("EndFrame called although no frame is in progress");
|
||||
return;
|
||||
}
|
||||
bFrameInProgress = false;
|
||||
}
|
||||
|
||||
void Present()
|
||||
{
|
||||
// TODO: Is 1 the correct value for vsyncing?
|
||||
swapchain->Present((UINT)g_ActiveConfig.bVSync, 0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
|
|
|
@ -1,96 +1,96 @@
|
|||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
|
||||
// DX11
|
||||
#include <d3dx11.h>
|
||||
#include "DX11_GfxState.h"
|
||||
#include "DX11_D3DBlob.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
#define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; }
|
||||
#define SAFE_DELETE(x) { delete (x); (x) = NULL; }
|
||||
#define SAFE_DELETE_ARRAY(x) { delete[] (x); (x) = NULL; }
|
||||
#define CHECK(cond, Message, ...) if (!(cond)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); }
|
||||
|
||||
class D3DTexture2D;
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
HRESULT Create(HWND wnd);
|
||||
void Close();
|
||||
|
||||
extern ID3D11Device* device;
|
||||
extern ID3D11DeviceContext* context;
|
||||
extern IDXGISwapChain* swapchain;
|
||||
extern bool bFrameInProgress;
|
||||
|
||||
void Reset();
|
||||
bool BeginFrame();
|
||||
void EndFrame();
|
||||
void Present();
|
||||
|
||||
unsigned int GetBackBufferWidth();
|
||||
unsigned int GetBackBufferHeight();
|
||||
D3DTexture2D* &GetBackBuffer();
|
||||
const char* PixelShaderVersionString();
|
||||
const char* VertexShaderVersionString();
|
||||
bool BGRATexturesSupported();
|
||||
|
||||
unsigned int GetMaxTextureSize();
|
||||
|
||||
// Ihis function will assign a name to the given resource.
|
||||
// The DirectX debug layer will make it easier to identify resources that way,
|
||||
// e.g. when listing up all resources who have unreleased references.
|
||||
inline void SetDebugObjectName(ID3D11DeviceChild* resource, const char* name)
|
||||
{
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
resource->SetPrivateData( WKPDID_D3DDebugObjectName, (UINT)strlen(name), name);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// Used to not require the SDK and runtime versions to match:
|
||||
// Linking with d3dx11.lib makes the most recent d3dx11_xx.dll of the
|
||||
// compiler's SDK a requirement, but this plugin works with DX11 runtimes
|
||||
// back to August 2009 even if the plugin was built with June 2010.
|
||||
// Add any d3dx11 functions which you want to use here and load them in Create()
|
||||
typedef HRESULT (WINAPI* D3DX11COMPILEFROMMEMORYTYPE)(LPCSTR, SIZE_T, LPCSTR, const D3D10_SHADER_MACRO*, LPD3D10INCLUDE, LPCSTR, LPCSTR, UINT, UINT, ID3DX11ThreadPump*, ID3D10Blob**, ID3D10Blob**, HRESULT*);
|
||||
typedef HRESULT (WINAPI* D3DX11FILTERTEXTURETYPE)(ID3D11DeviceContext*, ID3D11Resource*, UINT, UINT);
|
||||
typedef HRESULT (WINAPI* D3DX11SAVETEXTURETOFILEATYPE)(ID3D11DeviceContext*, ID3D11Resource*, D3DX11_IMAGE_FILE_FORMAT, LPCSTR);
|
||||
typedef HRESULT (WINAPI* D3DX11SAVETEXTURETOFILEWTYPE)(ID3D11DeviceContext*, ID3D11Resource*, D3DX11_IMAGE_FILE_FORMAT, LPCWSTR);
|
||||
|
||||
extern D3DX11COMPILEFROMMEMORYTYPE PD3DX11CompileFromMemory;
|
||||
extern D3DX11FILTERTEXTURETYPE PD3DX11FilterTexture;
|
||||
extern D3DX11SAVETEXTURETOFILEATYPE PD3DX11SaveTextureToFileA;
|
||||
extern D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW;
|
||||
|
||||
#ifdef UNICODE
|
||||
#define PD3DX11SaveTextureToFile PD3DX11SaveTextureToFileW
|
||||
#else
|
||||
#define PD3DX11SaveTextureToFile PD3DX11SaveTextureToFileA
|
||||
#endif
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
|
||||
// DX11
|
||||
#include <d3dx11.h>
|
||||
#include "DX11_GfxState.h"
|
||||
#include "DX11_D3DBlob.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
#define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; }
|
||||
#define SAFE_DELETE(x) { delete (x); (x) = NULL; }
|
||||
#define SAFE_DELETE_ARRAY(x) { delete[] (x); (x) = NULL; }
|
||||
#define CHECK(cond, Message, ...) if (!(cond)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); }
|
||||
|
||||
class D3DTexture2D;
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
HRESULT Create(HWND wnd);
|
||||
void Close();
|
||||
|
||||
extern ID3D11Device* device;
|
||||
extern ID3D11DeviceContext* context;
|
||||
extern IDXGISwapChain* swapchain;
|
||||
extern bool bFrameInProgress;
|
||||
|
||||
void Reset();
|
||||
bool BeginFrame();
|
||||
void EndFrame();
|
||||
void Present();
|
||||
|
||||
unsigned int GetBackBufferWidth();
|
||||
unsigned int GetBackBufferHeight();
|
||||
D3DTexture2D* &GetBackBuffer();
|
||||
const char* PixelShaderVersionString();
|
||||
const char* VertexShaderVersionString();
|
||||
bool BGRATexturesSupported();
|
||||
|
||||
unsigned int GetMaxTextureSize();
|
||||
|
||||
// Ihis function will assign a name to the given resource.
|
||||
// The DirectX debug layer will make it easier to identify resources that way,
|
||||
// e.g. when listing up all resources who have unreleased references.
|
||||
inline void SetDebugObjectName(ID3D11DeviceChild* resource, const char* name)
|
||||
{
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
resource->SetPrivateData( WKPDID_D3DDebugObjectName, (UINT)strlen(name), name);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// Used to not require the SDK and runtime versions to match:
|
||||
// Linking with d3dx11.lib makes the most recent d3dx11_xx.dll of the
|
||||
// compiler's SDK a requirement, but this plugin works with DX11 runtimes
|
||||
// back to August 2009 even if the plugin was built with June 2010.
|
||||
// Add any d3dx11 functions which you want to use here and load them in Create()
|
||||
typedef HRESULT (WINAPI* D3DX11COMPILEFROMMEMORYTYPE)(LPCSTR, SIZE_T, LPCSTR, const D3D10_SHADER_MACRO*, LPD3D10INCLUDE, LPCSTR, LPCSTR, UINT, UINT, ID3DX11ThreadPump*, ID3D10Blob**, ID3D10Blob**, HRESULT*);
|
||||
typedef HRESULT (WINAPI* D3DX11FILTERTEXTURETYPE)(ID3D11DeviceContext*, ID3D11Resource*, UINT, UINT);
|
||||
typedef HRESULT (WINAPI* D3DX11SAVETEXTURETOFILEATYPE)(ID3D11DeviceContext*, ID3D11Resource*, D3DX11_IMAGE_FILE_FORMAT, LPCSTR);
|
||||
typedef HRESULT (WINAPI* D3DX11SAVETEXTURETOFILEWTYPE)(ID3D11DeviceContext*, ID3D11Resource*, D3DX11_IMAGE_FILE_FORMAT, LPCWSTR);
|
||||
|
||||
extern D3DX11COMPILEFROMMEMORYTYPE PD3DX11CompileFromMemory;
|
||||
extern D3DX11FILTERTEXTURETYPE PD3DX11FilterTexture;
|
||||
extern D3DX11SAVETEXTURETOFILEATYPE PD3DX11SaveTextureToFileA;
|
||||
extern D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW;
|
||||
|
||||
#ifdef UNICODE
|
||||
#define PD3DX11SaveTextureToFile PD3DX11SaveTextureToFileW
|
||||
#else
|
||||
#define PD3DX11SaveTextureToFile PD3DX11SaveTextureToFileA
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -1,68 +1,68 @@
|
|||
// 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 "DX11_D3DBlob.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
D3DBlob::D3DBlob(unsigned int blob_size, const u8* init_data) : ref(1), size(blob_size), blob(NULL)
|
||||
{
|
||||
data = new u8[blob_size];
|
||||
if (init_data) memcpy(data, init_data, size);
|
||||
}
|
||||
|
||||
D3DBlob::D3DBlob(ID3D10Blob* d3dblob) : ref(1)
|
||||
{
|
||||
blob = d3dblob;
|
||||
data = (u8*)blob->GetBufferPointer();
|
||||
size = blob->GetBufferSize();
|
||||
d3dblob->AddRef();
|
||||
}
|
||||
|
||||
D3DBlob::~D3DBlob()
|
||||
{
|
||||
if (blob) blob->Release();
|
||||
else delete[] data;
|
||||
}
|
||||
|
||||
void D3DBlob::AddRef()
|
||||
{
|
||||
++ref;
|
||||
}
|
||||
|
||||
unsigned int D3DBlob::Release()
|
||||
{
|
||||
if (--ref == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
unsigned int D3DBlob::Size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
u8* D3DBlob::Data()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
// 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 "DX11_D3DBlob.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
D3DBlob::D3DBlob(unsigned int blob_size, const u8* init_data) : ref(1), size(blob_size), blob(NULL)
|
||||
{
|
||||
data = new u8[blob_size];
|
||||
if (init_data) memcpy(data, init_data, size);
|
||||
}
|
||||
|
||||
D3DBlob::D3DBlob(ID3D10Blob* d3dblob) : ref(1)
|
||||
{
|
||||
blob = d3dblob;
|
||||
data = (u8*)blob->GetBufferPointer();
|
||||
size = blob->GetBufferSize();
|
||||
d3dblob->AddRef();
|
||||
}
|
||||
|
||||
D3DBlob::~D3DBlob()
|
||||
{
|
||||
if (blob) blob->Release();
|
||||
else delete[] data;
|
||||
}
|
||||
|
||||
void D3DBlob::AddRef()
|
||||
{
|
||||
++ref;
|
||||
}
|
||||
|
||||
unsigned int D3DBlob::Release()
|
||||
{
|
||||
if (--ref == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
unsigned int D3DBlob::Size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
u8* D3DBlob::Data()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,52 +1,52 @@
|
|||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include <d3d11.h>
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
// use this class instead ID3D10Blob or ID3D11Blob whenever possible
|
||||
class D3DBlob
|
||||
{
|
||||
public:
|
||||
// memory will be copied into an own buffer
|
||||
D3DBlob(unsigned int blob_size, const u8* init_data = NULL);
|
||||
|
||||
// d3dblob will be AddRef'd
|
||||
D3DBlob(ID3D10Blob* d3dblob);
|
||||
|
||||
void AddRef();
|
||||
unsigned int Release();
|
||||
|
||||
unsigned int Size();
|
||||
u8* Data();
|
||||
|
||||
private:
|
||||
~D3DBlob();
|
||||
|
||||
unsigned int ref;
|
||||
unsigned int size;
|
||||
|
||||
u8* data;
|
||||
ID3D10Blob* blob;
|
||||
};
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include <d3d11.h>
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
// use this class instead ID3D10Blob or ID3D11Blob whenever possible
|
||||
class D3DBlob
|
||||
{
|
||||
public:
|
||||
// memory will be copied into an own buffer
|
||||
D3DBlob(unsigned int blob_size, const u8* init_data = NULL);
|
||||
|
||||
// d3dblob will be AddRef'd
|
||||
D3DBlob(ID3D10Blob* d3dblob);
|
||||
|
||||
void AddRef();
|
||||
unsigned int Release();
|
||||
|
||||
unsigned int Size();
|
||||
u8* Data();
|
||||
|
||||
private:
|
||||
~D3DBlob();
|
||||
|
||||
unsigned int ref;
|
||||
unsigned int size;
|
||||
|
||||
u8* data;
|
||||
ID3D10Blob* blob;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,150 +1,150 @@
|
|||
// 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 <d3dx11.h>
|
||||
#include <d3dcompiler.h>
|
||||
#include <string>
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "DX11_D3DShader.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
// bytecode->shader
|
||||
ID3D11VertexShader* CreateVertexShaderFromByteCode(void* bytecode, unsigned int len)
|
||||
{
|
||||
ID3D11VertexShader* v_shader;
|
||||
HRESULT hr = D3D::device->CreateVertexShader(bytecode, len, NULL, &v_shader);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("CreateVertexShaderFromByteCode failed from %p (size %d) at %s %d\n", bytecode, len, __FILE__, __LINE__);
|
||||
v_shader = NULL;
|
||||
}
|
||||
return v_shader;
|
||||
}
|
||||
|
||||
// code->bytecode
|
||||
bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob)
|
||||
{
|
||||
ID3D10Blob* shaderBuffer = NULL;
|
||||
ID3D10Blob* errorBuffer = NULL;
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS;
|
||||
#else
|
||||
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_OPTIMIZATION_LEVEL3|D3D10_SHADER_SKIP_VALIDATION;
|
||||
#endif
|
||||
HRESULT hr = PD3DX11CompileFromMemory(code, len, NULL, NULL, NULL, "main", D3D::VertexShaderVersionString(),
|
||||
flags, 0, NULL, &shaderBuffer, &errorBuffer, NULL);
|
||||
|
||||
if (FAILED(hr) || errorBuffer)
|
||||
{
|
||||
std::string msg = (char*)errorBuffer->GetBufferPointer();
|
||||
msg += "\n\n";
|
||||
msg += code;
|
||||
MessageBoxA(0, msg.c_str(), "Error compiling pixel shader", MB_ICONERROR);
|
||||
|
||||
*blob = NULL;
|
||||
errorBuffer->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
*blob = new D3DBlob(shaderBuffer);
|
||||
shaderBuffer->Release();
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
// bytecode->shader
|
||||
ID3D11PixelShader* CreatePixelShaderFromByteCode(void* bytecode, unsigned int len)
|
||||
{
|
||||
ID3D11PixelShader* p_shader;
|
||||
HRESULT hr = D3D::device->CreatePixelShader(bytecode, len, NULL, &p_shader);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("CreatePixelShaderFromByteCode failed at %s %d\n", __FILE__, __LINE__);
|
||||
p_shader = NULL;
|
||||
}
|
||||
return p_shader;
|
||||
}
|
||||
|
||||
// code->bytecode
|
||||
bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob)
|
||||
{
|
||||
ID3D10Blob* shaderBuffer = NULL;
|
||||
ID3D10Blob* errorBuffer = NULL;
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
UINT flags = D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS;
|
||||
#else
|
||||
UINT flags = D3D10_SHADER_OPTIMIZATION_LEVEL3;
|
||||
#endif
|
||||
HRESULT hr = PD3DX11CompileFromMemory(code, len, NULL, NULL, NULL, "main", D3D::PixelShaderVersionString(),
|
||||
flags, 0, NULL, &shaderBuffer, &errorBuffer, NULL);
|
||||
|
||||
if (FAILED(hr) || errorBuffer)
|
||||
{
|
||||
std::string msg = (char*)errorBuffer->GetBufferPointer();
|
||||
msg += "\n\n";
|
||||
msg += code;
|
||||
MessageBoxA(0, msg.c_str(), "Error compiling pixel shader", MB_ICONERROR);
|
||||
|
||||
*blob = NULL;
|
||||
errorBuffer->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
*blob = new D3DBlob(shaderBuffer);
|
||||
shaderBuffer->Release();
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len)
|
||||
{
|
||||
D3DBlob* blob = NULL;
|
||||
if (CompileVertexShader(code, len, &blob))
|
||||
{
|
||||
ID3D11VertexShader* v_shader = CreateVertexShaderFromByteCode(blob);
|
||||
blob->Release();
|
||||
return v_shader;
|
||||
}
|
||||
PanicAlert("Failed to compile and create vertex shader from %p (size %d) at %s %d\n", code, len, __FILE__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code, unsigned int len)
|
||||
{
|
||||
D3DBlob* blob = NULL;
|
||||
CompilePixelShader(code, len, &blob);
|
||||
if (blob)
|
||||
{
|
||||
ID3D11PixelShader* p_shader = CreatePixelShaderFromByteCode(blob);
|
||||
blob->Release();
|
||||
return p_shader;
|
||||
}
|
||||
PanicAlert("Failed to compile and create pixel shader, %s %d\n", __FILE__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
// 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 <d3dx11.h>
|
||||
#include <d3dcompiler.h>
|
||||
#include <string>
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "DX11_D3DShader.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
// bytecode->shader
|
||||
ID3D11VertexShader* CreateVertexShaderFromByteCode(void* bytecode, unsigned int len)
|
||||
{
|
||||
ID3D11VertexShader* v_shader;
|
||||
HRESULT hr = D3D::device->CreateVertexShader(bytecode, len, NULL, &v_shader);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("CreateVertexShaderFromByteCode failed from %p (size %d) at %s %d\n", bytecode, len, __FILE__, __LINE__);
|
||||
v_shader = NULL;
|
||||
}
|
||||
return v_shader;
|
||||
}
|
||||
|
||||
// code->bytecode
|
||||
bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob)
|
||||
{
|
||||
ID3D10Blob* shaderBuffer = NULL;
|
||||
ID3D10Blob* errorBuffer = NULL;
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS;
|
||||
#else
|
||||
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_OPTIMIZATION_LEVEL3|D3D10_SHADER_SKIP_VALIDATION;
|
||||
#endif
|
||||
HRESULT hr = PD3DX11CompileFromMemory(code, len, NULL, NULL, NULL, "main", D3D::VertexShaderVersionString(),
|
||||
flags, 0, NULL, &shaderBuffer, &errorBuffer, NULL);
|
||||
|
||||
if (FAILED(hr) || errorBuffer)
|
||||
{
|
||||
std::string msg = (char*)errorBuffer->GetBufferPointer();
|
||||
msg += "\n\n";
|
||||
msg += code;
|
||||
MessageBoxA(0, msg.c_str(), "Error compiling pixel shader", MB_ICONERROR);
|
||||
|
||||
*blob = NULL;
|
||||
errorBuffer->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
*blob = new D3DBlob(shaderBuffer);
|
||||
shaderBuffer->Release();
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
// bytecode->shader
|
||||
ID3D11PixelShader* CreatePixelShaderFromByteCode(void* bytecode, unsigned int len)
|
||||
{
|
||||
ID3D11PixelShader* p_shader;
|
||||
HRESULT hr = D3D::device->CreatePixelShader(bytecode, len, NULL, &p_shader);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("CreatePixelShaderFromByteCode failed at %s %d\n", __FILE__, __LINE__);
|
||||
p_shader = NULL;
|
||||
}
|
||||
return p_shader;
|
||||
}
|
||||
|
||||
// code->bytecode
|
||||
bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob)
|
||||
{
|
||||
ID3D10Blob* shaderBuffer = NULL;
|
||||
ID3D10Blob* errorBuffer = NULL;
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
UINT flags = D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS;
|
||||
#else
|
||||
UINT flags = D3D10_SHADER_OPTIMIZATION_LEVEL3;
|
||||
#endif
|
||||
HRESULT hr = PD3DX11CompileFromMemory(code, len, NULL, NULL, NULL, "main", D3D::PixelShaderVersionString(),
|
||||
flags, 0, NULL, &shaderBuffer, &errorBuffer, NULL);
|
||||
|
||||
if (FAILED(hr) || errorBuffer)
|
||||
{
|
||||
std::string msg = (char*)errorBuffer->GetBufferPointer();
|
||||
msg += "\n\n";
|
||||
msg += code;
|
||||
MessageBoxA(0, msg.c_str(), "Error compiling pixel shader", MB_ICONERROR);
|
||||
|
||||
*blob = NULL;
|
||||
errorBuffer->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
*blob = new D3DBlob(shaderBuffer);
|
||||
shaderBuffer->Release();
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len)
|
||||
{
|
||||
D3DBlob* blob = NULL;
|
||||
if (CompileVertexShader(code, len, &blob))
|
||||
{
|
||||
ID3D11VertexShader* v_shader = CreateVertexShaderFromByteCode(blob);
|
||||
blob->Release();
|
||||
return v_shader;
|
||||
}
|
||||
PanicAlert("Failed to compile and create vertex shader from %p (size %d) at %s %d\n", code, len, __FILE__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code, unsigned int len)
|
||||
{
|
||||
D3DBlob* blob = NULL;
|
||||
CompilePixelShader(code, len, &blob);
|
||||
if (blob)
|
||||
{
|
||||
ID3D11PixelShader* p_shader = CreatePixelShaderFromByteCode(blob);
|
||||
blob->Release();
|
||||
return p_shader;
|
||||
}
|
||||
PanicAlert("Failed to compile and create pixel shader, %s %d\n", __FILE__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
|
|
|
@ -1,44 +1,44 @@
|
|||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DX11_D3DBase.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
ID3D11VertexShader* CreateVertexShaderFromByteCode(void* bytecode, unsigned int len);
|
||||
ID3D11PixelShader* CreatePixelShaderFromByteCode(void* bytecode, unsigned int len);
|
||||
|
||||
// The returned bytecode buffers should be Release()d.
|
||||
bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob);
|
||||
bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob);
|
||||
|
||||
// Utility functions
|
||||
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len);
|
||||
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code, unsigned int len);
|
||||
|
||||
inline ID3D11VertexShader* CreateVertexShaderFromByteCode(D3DBlob* bytecode) { return CreateVertexShaderFromByteCode(bytecode->Data(), bytecode->Size()); }
|
||||
inline ID3D11PixelShader* CreatePixelShaderFromByteCode(D3DBlob* bytecode) { return CreatePixelShaderFromByteCode(bytecode->Data(), bytecode->Size()); }
|
||||
inline ID3D11VertexShader* CompileAndCreateVertexShader(D3DBlob* code) { return CompileAndCreateVertexShader((const char*)code->Data(), code->Size()); }
|
||||
inline ID3D11PixelShader* CompileAndCreatePixelShader(D3DBlob* code) { return CompileAndCreatePixelShader((const char*)code->Data(), code->Size()); }
|
||||
}
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DX11_D3DBase.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
ID3D11VertexShader* CreateVertexShaderFromByteCode(void* bytecode, unsigned int len);
|
||||
ID3D11PixelShader* CreatePixelShaderFromByteCode(void* bytecode, unsigned int len);
|
||||
|
||||
// The returned bytecode buffers should be Release()d.
|
||||
bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob);
|
||||
bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob);
|
||||
|
||||
// Utility functions
|
||||
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len);
|
||||
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code, unsigned int len);
|
||||
|
||||
inline ID3D11VertexShader* CreateVertexShaderFromByteCode(D3DBlob* bytecode) { return CreateVertexShaderFromByteCode(bytecode->Data(), bytecode->Size()); }
|
||||
inline ID3D11PixelShader* CreatePixelShaderFromByteCode(D3DBlob* bytecode) { return CreatePixelShaderFromByteCode(bytecode->Data(), bytecode->Size()); }
|
||||
inline ID3D11VertexShader* CompileAndCreateVertexShader(D3DBlob* code) { return CompileAndCreateVertexShader((const char*)code->Data(), code->Size()); }
|
||||
inline ID3D11PixelShader* CompileAndCreatePixelShader(D3DBlob* code) { return CompileAndCreatePixelShader((const char*)code->Data(), code->Size()); }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,125 +1,125 @@
|
|||
// 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 <d3dx11.h>
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DTexture.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage)
|
||||
{
|
||||
if (usage == D3D11_USAGE_DYNAMIC)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
HRESULT hr = D3D::context->Map(pTexture, level, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
CHECK(SUCCEEDED(hr), "ID3D11DeviceContext::Map failed! (%x)", hr);
|
||||
if (4 * pitch == map.RowPitch)
|
||||
{
|
||||
memcpy(map.pData, buffer, map.RowPitch * height);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int y = 0; y < height; ++y)
|
||||
memcpy((u8*)map.pData + y * map.RowPitch, (u32*)buffer + y * pitch, map.RowPitch);
|
||||
}
|
||||
D3D::context->Unmap(pTexture, level);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1);
|
||||
D3D::context->UpdateSubresource(pTexture, level, &dest_region, buffer, 4*pitch, 4*pitch*height);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels)
|
||||
{
|
||||
ID3D11Texture2D* pTexture = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
D3D11_CPU_ACCESS_FLAG cpuflags;
|
||||
if (usage == D3D11_USAGE_STAGING)
|
||||
cpuflags = (D3D11_CPU_ACCESS_FLAG)((int)D3D11_CPU_ACCESS_WRITE|(int)D3D11_CPU_ACCESS_READ);
|
||||
else if (usage == D3D11_USAGE_DYNAMIC)
|
||||
cpuflags = D3D11_CPU_ACCESS_WRITE;
|
||||
else
|
||||
cpuflags = (D3D11_CPU_ACCESS_FLAG)0;
|
||||
|
||||
D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(fmt, width, height, 1, levels, bind, usage, cpuflags);
|
||||
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &pTexture);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("Failed to create texture at %s, line %d: hr=%#x\n", __FILE__, __LINE__, hr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
D3DTexture2D* ret = new D3DTexture2D(pTexture, bind);
|
||||
SAFE_RELEASE(pTexture);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void D3DTexture2D::AddRef()
|
||||
{
|
||||
++ref;
|
||||
}
|
||||
|
||||
UINT D3DTexture2D::Release()
|
||||
{
|
||||
--ref;
|
||||
if (ref == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
D3DTexture2D::D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind,
|
||||
DXGI_FORMAT srv_format, DXGI_FORMAT dsv_format, DXGI_FORMAT rtv_format)
|
||||
: ref(1), tex(texptr), srv(NULL), rtv(NULL), dsv(NULL)
|
||||
{
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = CD3D11_SHADER_RESOURCE_VIEW_DESC(D3D11_SRV_DIMENSION_TEXTURE2D, srv_format);
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D, dsv_format);
|
||||
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = CD3D11_RENDER_TARGET_VIEW_DESC(D3D11_RTV_DIMENSION_TEXTURE2D, rtv_format);
|
||||
|
||||
if (bind & D3D11_BIND_SHADER_RESOURCE)
|
||||
D3D::device->CreateShaderResourceView(tex, &srv_desc, &srv);
|
||||
|
||||
if (bind & D3D11_BIND_RENDER_TARGET)
|
||||
D3D::device->CreateRenderTargetView(tex, &rtv_desc, &rtv);
|
||||
|
||||
if (bind & D3D11_BIND_DEPTH_STENCIL)
|
||||
D3D::device->CreateDepthStencilView(tex, &dsv_desc, &dsv);
|
||||
|
||||
tex->AddRef();
|
||||
}
|
||||
|
||||
D3DTexture2D::~D3DTexture2D()
|
||||
{
|
||||
SAFE_RELEASE(srv);
|
||||
SAFE_RELEASE(rtv);
|
||||
SAFE_RELEASE(dsv);
|
||||
SAFE_RELEASE(tex);
|
||||
}
|
||||
|
||||
}
|
||||
// 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 <d3dx11.h>
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DTexture.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage)
|
||||
{
|
||||
if (usage == D3D11_USAGE_DYNAMIC)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
HRESULT hr = D3D::context->Map(pTexture, level, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
CHECK(SUCCEEDED(hr), "ID3D11DeviceContext::Map failed! (%x)", hr);
|
||||
if (4 * pitch == map.RowPitch)
|
||||
{
|
||||
memcpy(map.pData, buffer, map.RowPitch * height);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int y = 0; y < height; ++y)
|
||||
memcpy((u8*)map.pData + y * map.RowPitch, (u32*)buffer + y * pitch, map.RowPitch);
|
||||
}
|
||||
D3D::context->Unmap(pTexture, level);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1);
|
||||
D3D::context->UpdateSubresource(pTexture, level, &dest_region, buffer, 4*pitch, 4*pitch*height);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels)
|
||||
{
|
||||
ID3D11Texture2D* pTexture = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
D3D11_CPU_ACCESS_FLAG cpuflags;
|
||||
if (usage == D3D11_USAGE_STAGING)
|
||||
cpuflags = (D3D11_CPU_ACCESS_FLAG)((int)D3D11_CPU_ACCESS_WRITE|(int)D3D11_CPU_ACCESS_READ);
|
||||
else if (usage == D3D11_USAGE_DYNAMIC)
|
||||
cpuflags = D3D11_CPU_ACCESS_WRITE;
|
||||
else
|
||||
cpuflags = (D3D11_CPU_ACCESS_FLAG)0;
|
||||
|
||||
D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(fmt, width, height, 1, levels, bind, usage, cpuflags);
|
||||
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &pTexture);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("Failed to create texture at %s, line %d: hr=%#x\n", __FILE__, __LINE__, hr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
D3DTexture2D* ret = new D3DTexture2D(pTexture, bind);
|
||||
SAFE_RELEASE(pTexture);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void D3DTexture2D::AddRef()
|
||||
{
|
||||
++ref;
|
||||
}
|
||||
|
||||
UINT D3DTexture2D::Release()
|
||||
{
|
||||
--ref;
|
||||
if (ref == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
D3DTexture2D::D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind,
|
||||
DXGI_FORMAT srv_format, DXGI_FORMAT dsv_format, DXGI_FORMAT rtv_format)
|
||||
: ref(1), tex(texptr), srv(NULL), rtv(NULL), dsv(NULL)
|
||||
{
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = CD3D11_SHADER_RESOURCE_VIEW_DESC(D3D11_SRV_DIMENSION_TEXTURE2D, srv_format);
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D, dsv_format);
|
||||
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = CD3D11_RENDER_TARGET_VIEW_DESC(D3D11_RTV_DIMENSION_TEXTURE2D, rtv_format);
|
||||
|
||||
if (bind & D3D11_BIND_SHADER_RESOURCE)
|
||||
D3D::device->CreateShaderResourceView(tex, &srv_desc, &srv);
|
||||
|
||||
if (bind & D3D11_BIND_RENDER_TARGET)
|
||||
D3D::device->CreateRenderTargetView(tex, &rtv_desc, &rtv);
|
||||
|
||||
if (bind & D3D11_BIND_DEPTH_STENCIL)
|
||||
D3D::device->CreateDepthStencilView(tex, &dsv_desc, &dsv);
|
||||
|
||||
tex->AddRef();
|
||||
}
|
||||
|
||||
D3DTexture2D::~D3DTexture2D()
|
||||
{
|
||||
SAFE_RELEASE(srv);
|
||||
SAFE_RELEASE(rtv);
|
||||
SAFE_RELEASE(dsv);
|
||||
SAFE_RELEASE(tex);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,60 +1,60 @@
|
|||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DX11_D3DBase.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage);
|
||||
}
|
||||
|
||||
class D3DTexture2D
|
||||
{
|
||||
public:
|
||||
// there are two ways to create a D3DTexture2D object:
|
||||
// either create an ID3D11Texture2D object, pass it to the constructor and specify what views to create
|
||||
// or let the texture automatically be created by D3DTexture2D::Create
|
||||
|
||||
D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN);
|
||||
static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1);
|
||||
|
||||
// reference counting, use AddRef() when creating a new reference and Release() it when you don't need it anymore
|
||||
void AddRef();
|
||||
UINT Release();
|
||||
|
||||
ID3D11Texture2D* &GetTex() { return tex; }
|
||||
ID3D11ShaderResourceView* &GetSRV() { return srv; }
|
||||
ID3D11RenderTargetView* &GetRTV() { return rtv; }
|
||||
ID3D11DepthStencilView* &GetDSV() { return dsv; }
|
||||
|
||||
private:
|
||||
~D3DTexture2D();
|
||||
|
||||
ID3D11Texture2D* tex;
|
||||
ID3D11ShaderResourceView* srv;
|
||||
ID3D11RenderTargetView* rtv;
|
||||
ID3D11DepthStencilView* dsv;
|
||||
D3D11_BIND_FLAG bindflags;
|
||||
UINT ref;
|
||||
};
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DX11_D3DBase.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage);
|
||||
}
|
||||
|
||||
class D3DTexture2D
|
||||
{
|
||||
public:
|
||||
// there are two ways to create a D3DTexture2D object:
|
||||
// either create an ID3D11Texture2D object, pass it to the constructor and specify what views to create
|
||||
// or let the texture automatically be created by D3DTexture2D::Create
|
||||
|
||||
D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN);
|
||||
static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1);
|
||||
|
||||
// reference counting, use AddRef() when creating a new reference and Release() it when you don't need it anymore
|
||||
void AddRef();
|
||||
UINT Release();
|
||||
|
||||
ID3D11Texture2D* &GetTex() { return tex; }
|
||||
ID3D11ShaderResourceView* &GetSRV() { return srv; }
|
||||
ID3D11RenderTargetView* &GetRTV() { return rtv; }
|
||||
ID3D11DepthStencilView* &GetDSV() { return dsv; }
|
||||
|
||||
private:
|
||||
~D3DTexture2D();
|
||||
|
||||
ID3D11Texture2D* tex;
|
||||
ID3D11ShaderResourceView* srv;
|
||||
ID3D11RenderTargetView* rtv;
|
||||
ID3D11DepthStencilView* dsv;
|
||||
D3D11_BIND_FLAG bindflags;
|
||||
UINT ref;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,91 +1,91 @@
|
|||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <math.h>
|
||||
#include <MathUtil.h>
|
||||
|
||||
#include "DX11_D3DBase.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
// Font creation flags
|
||||
#define D3DFONT_BOLD 0x0001
|
||||
#define D3DFONT_ITALIC 0x0002
|
||||
|
||||
// Font rendering flags
|
||||
#define D3DFONT_CENTERED 0x0001
|
||||
|
||||
class CD3DFont
|
||||
{
|
||||
ID3D11ShaderResourceView* m_pTexture;
|
||||
ID3D11Buffer* m_pVB;
|
||||
ID3D11InputLayout* m_InputLayout;
|
||||
ID3D11PixelShader* m_pshader;
|
||||
ID3D11VertexShader* m_vshader;
|
||||
ID3D11BlendState* m_blendstate;
|
||||
ID3D11RasterizerState* m_raststate;
|
||||
const int m_dwTexWidth;
|
||||
const int m_dwTexHeight;
|
||||
unsigned int m_LineHeight;
|
||||
float m_fTexCoords[128-32][4];
|
||||
|
||||
public:
|
||||
CD3DFont();
|
||||
// 2D text drawing function
|
||||
// Initializing and destroying device-dependent objects
|
||||
int Init();
|
||||
int Shutdown();
|
||||
int DrawTextScaled(float x, float y,
|
||||
float size,
|
||||
float spacing, u32 dwColor,
|
||||
const char* strText, bool center=true);
|
||||
};
|
||||
|
||||
extern CD3DFont font;
|
||||
|
||||
void InitUtils();
|
||||
void ShutdownUtils();
|
||||
|
||||
void SetPointCopySampler();
|
||||
void SetLinearCopySampler();
|
||||
|
||||
void drawShadedTexQuad(ID3D11ShaderResourceView* texture,
|
||||
const D3D11_RECT* rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
ID3D11PixelShader* PShader,
|
||||
ID3D11VertexShader* VShader,
|
||||
ID3D11InputLayout* layout);
|
||||
void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
|
||||
const MathUtil::Rectangle<float>* rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
const MathUtil::Rectangle<float>* rDest,
|
||||
ID3D11PixelShader* PShader,
|
||||
ID3D11VertexShader* Vshader,
|
||||
ID3D11InputLayout* layout);
|
||||
void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout);
|
||||
void SaveRenderStates();
|
||||
void RestoreRenderStates();
|
||||
}
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <math.h>
|
||||
#include <MathUtil.h>
|
||||
|
||||
#include "DX11_D3DBase.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
// Font creation flags
|
||||
#define D3DFONT_BOLD 0x0001
|
||||
#define D3DFONT_ITALIC 0x0002
|
||||
|
||||
// Font rendering flags
|
||||
#define D3DFONT_CENTERED 0x0001
|
||||
|
||||
class CD3DFont
|
||||
{
|
||||
ID3D11ShaderResourceView* m_pTexture;
|
||||
ID3D11Buffer* m_pVB;
|
||||
ID3D11InputLayout* m_InputLayout;
|
||||
ID3D11PixelShader* m_pshader;
|
||||
ID3D11VertexShader* m_vshader;
|
||||
ID3D11BlendState* m_blendstate;
|
||||
ID3D11RasterizerState* m_raststate;
|
||||
const int m_dwTexWidth;
|
||||
const int m_dwTexHeight;
|
||||
unsigned int m_LineHeight;
|
||||
float m_fTexCoords[128-32][4];
|
||||
|
||||
public:
|
||||
CD3DFont();
|
||||
// 2D text drawing function
|
||||
// Initializing and destroying device-dependent objects
|
||||
int Init();
|
||||
int Shutdown();
|
||||
int DrawTextScaled(float x, float y,
|
||||
float size,
|
||||
float spacing, u32 dwColor,
|
||||
const char* strText, bool center=true);
|
||||
};
|
||||
|
||||
extern CD3DFont font;
|
||||
|
||||
void InitUtils();
|
||||
void ShutdownUtils();
|
||||
|
||||
void SetPointCopySampler();
|
||||
void SetLinearCopySampler();
|
||||
|
||||
void drawShadedTexQuad(ID3D11ShaderResourceView* texture,
|
||||
const D3D11_RECT* rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
ID3D11PixelShader* PShader,
|
||||
ID3D11VertexShader* VShader,
|
||||
ID3D11InputLayout* layout);
|
||||
void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
|
||||
const MathUtil::Rectangle<float>* rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
const MathUtil::Rectangle<float>* rDest,
|
||||
ID3D11PixelShader* PShader,
|
||||
ID3D11VertexShader* Vshader,
|
||||
ID3D11InputLayout* layout);
|
||||
void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout);
|
||||
void SaveRenderStates();
|
||||
void RestoreRenderStates();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,162 +1,162 @@
|
|||
// 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/
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_Render.h"
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DTexture.h"
|
||||
#include "DX11_D3DUtil.h"
|
||||
#include "DX11_FramebufferManager.h"
|
||||
#include "DX11_PixelShaderCache.h"
|
||||
#include "DX11_VertexShaderCache.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
XFBSource FramebufferManager::m_realXFBSource; // used in real XFB mode
|
||||
|
||||
FramebufferManager::EFB FramebufferManager::m_efb;
|
||||
|
||||
D3DTexture2D* &FramebufferManager::GetEFBColorTexture() { return m_efb.color_tex; }
|
||||
ID3D11Texture2D* &FramebufferManager::GetEFBColorStagingBuffer() { return m_efb.color_staging_buf; }
|
||||
|
||||
D3DTexture2D* &FramebufferManager::GetEFBDepthTexture() { return m_efb.depth_tex; }
|
||||
D3DTexture2D* &FramebufferManager::GetEFBDepthReadTexture() { return m_efb.depth_read_texture; }
|
||||
ID3D11Texture2D* &FramebufferManager::GetEFBDepthStagingBuffer() { return m_efb.depth_staging_buf; }
|
||||
|
||||
FramebufferManager::FramebufferManager()
|
||||
{
|
||||
m_efb.color_tex = NULL;
|
||||
m_efb.color_staging_buf = NULL;
|
||||
m_efb.depth_tex = NULL;
|
||||
m_efb.depth_staging_buf = NULL;
|
||||
m_efb.depth_read_texture = NULL;
|
||||
|
||||
m_realXFBSource.tex = NULL;
|
||||
|
||||
unsigned int target_width = Renderer::GetFullTargetWidth();
|
||||
unsigned int target_height = Renderer::GetFullTargetHeight();
|
||||
ID3D11Texture2D* buf;
|
||||
D3D11_TEXTURE2D_DESC texdesc;
|
||||
HRESULT hr;
|
||||
|
||||
// create framebuffer color texture
|
||||
m_efb.color_tex = D3DTexture2D::Create(target_width, target_height,
|
||||
(D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE),
|
||||
D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
CHECK(m_efb.color_tex, "create EFB color texture (size: %dx%d)", target_width, target_height);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetTex(), "EFB color texture");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetRTV(), "EFB color texture render target view");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetSRV(), "EFB color texture shader resource view");
|
||||
|
||||
// create a staging texture for Renderer::AccessEFB
|
||||
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 1, 1, 0,
|
||||
D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_WRITE|D3D11_CPU_ACCESS_READ);
|
||||
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.color_staging_buf);
|
||||
CHECK(SUCCEEDED(hr), "create EFB color staging buffer (hr=%#x)", hr);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_staging_buf, "EFB color staging texture (used for Renderer::AccessEFB)");
|
||||
|
||||
// EFB depth buffer
|
||||
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width,
|
||||
target_height, 1, 1, D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE);
|
||||
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf);
|
||||
CHECK(hr==S_OK, "create EFB depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||
m_efb.depth_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE),
|
||||
DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT);
|
||||
SAFE_RELEASE(buf);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetTex(), "EFB depth texture");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetDSV(), "EFB depth texture depth stencil view");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetSRV(), "EFB depth texture shader resource view");
|
||||
|
||||
// render target for depth buffer access in Renderer::AccessEFB
|
||||
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 4, 4, 1, 1, D3D11_BIND_RENDER_TARGET);
|
||||
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf);
|
||||
CHECK(hr==S_OK, "create EFB depth read texture (hr=%#x)", hr);
|
||||
m_efb.depth_read_texture = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
|
||||
SAFE_RELEASE(buf);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_read_texture->GetTex(), "EFB depth read texture (used in Renderer::AccessEFB)");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_read_texture->GetRTV(), "EFB depth read texture render target view (used in Renderer::AccessEFB)");
|
||||
|
||||
// staging texture to which we copy the data from m_efb.depth_read_texture
|
||||
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 4, 4, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE);
|
||||
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.depth_staging_buf);
|
||||
CHECK(hr==S_OK, "create EFB depth staging buffer (hr=%#x)", hr);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_staging_buf, "EFB depth staging texture (used for Renderer::AccessEFB)");
|
||||
}
|
||||
|
||||
FramebufferManager::~FramebufferManager()
|
||||
{
|
||||
SAFE_RELEASE(m_efb.color_tex);
|
||||
SAFE_RELEASE(m_efb.color_staging_buf);
|
||||
SAFE_RELEASE(m_efb.depth_tex);
|
||||
SAFE_RELEASE(m_efb.depth_staging_buf);
|
||||
SAFE_RELEASE(m_efb.depth_read_texture);
|
||||
|
||||
SAFE_RELEASE(m_realXFBSource.tex);
|
||||
}
|
||||
|
||||
void XFBSource::CopyEFB(const TargetRectangle& efbSource)
|
||||
{
|
||||
// copy EFB data to XFB and restore render target again
|
||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)texWidth, (float)texHeight);
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
D3D::context->OMSetRenderTargets(1, &tex->GetRTV(), NULL);
|
||||
D3D::SetLinearCopySampler();
|
||||
|
||||
D3DTexture2D* const ctex = FramebufferManager::GetEFBColorTexture();
|
||||
|
||||
D3D::drawShadedTexQuad(ctex->GetSRV(), efbSource.AsRECT(),
|
||||
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
|
||||
PixelShaderCache::GetColorCopyProgram(), VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout());
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &ctex->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||
}
|
||||
|
||||
XFBSource::~XFBSource()
|
||||
{
|
||||
tex->Release();
|
||||
}
|
||||
|
||||
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
|
||||
{
|
||||
XFBSource* const xfbs = new XFBSource;
|
||||
xfbs->tex = D3DTexture2D::Create(target_width, target_height,
|
||||
(D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE),
|
||||
D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
|
||||
return xfbs;
|
||||
}
|
||||
|
||||
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
// TODO
|
||||
PanicAlert("copyToRealXFB not implemented, yet\n");
|
||||
}
|
||||
|
||||
const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||
{
|
||||
PanicAlert("getRealXFBSource not implemented, yet\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_Render.h"
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DTexture.h"
|
||||
#include "DX11_D3DUtil.h"
|
||||
#include "DX11_FramebufferManager.h"
|
||||
#include "DX11_PixelShaderCache.h"
|
||||
#include "DX11_VertexShaderCache.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
XFBSource FramebufferManager::m_realXFBSource; // used in real XFB mode
|
||||
|
||||
FramebufferManager::EFB FramebufferManager::m_efb;
|
||||
|
||||
D3DTexture2D* &FramebufferManager::GetEFBColorTexture() { return m_efb.color_tex; }
|
||||
ID3D11Texture2D* &FramebufferManager::GetEFBColorStagingBuffer() { return m_efb.color_staging_buf; }
|
||||
|
||||
D3DTexture2D* &FramebufferManager::GetEFBDepthTexture() { return m_efb.depth_tex; }
|
||||
D3DTexture2D* &FramebufferManager::GetEFBDepthReadTexture() { return m_efb.depth_read_texture; }
|
||||
ID3D11Texture2D* &FramebufferManager::GetEFBDepthStagingBuffer() { return m_efb.depth_staging_buf; }
|
||||
|
||||
FramebufferManager::FramebufferManager()
|
||||
{
|
||||
m_efb.color_tex = NULL;
|
||||
m_efb.color_staging_buf = NULL;
|
||||
m_efb.depth_tex = NULL;
|
||||
m_efb.depth_staging_buf = NULL;
|
||||
m_efb.depth_read_texture = NULL;
|
||||
|
||||
m_realXFBSource.tex = NULL;
|
||||
|
||||
unsigned int target_width = Renderer::GetFullTargetWidth();
|
||||
unsigned int target_height = Renderer::GetFullTargetHeight();
|
||||
ID3D11Texture2D* buf;
|
||||
D3D11_TEXTURE2D_DESC texdesc;
|
||||
HRESULT hr;
|
||||
|
||||
// create framebuffer color texture
|
||||
m_efb.color_tex = D3DTexture2D::Create(target_width, target_height,
|
||||
(D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE),
|
||||
D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
CHECK(m_efb.color_tex, "create EFB color texture (size: %dx%d)", target_width, target_height);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetTex(), "EFB color texture");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetRTV(), "EFB color texture render target view");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetSRV(), "EFB color texture shader resource view");
|
||||
|
||||
// create a staging texture for Renderer::AccessEFB
|
||||
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 1, 1, 0,
|
||||
D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_WRITE|D3D11_CPU_ACCESS_READ);
|
||||
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.color_staging_buf);
|
||||
CHECK(SUCCEEDED(hr), "create EFB color staging buffer (hr=%#x)", hr);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_staging_buf, "EFB color staging texture (used for Renderer::AccessEFB)");
|
||||
|
||||
// EFB depth buffer
|
||||
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width,
|
||||
target_height, 1, 1, D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE);
|
||||
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf);
|
||||
CHECK(hr==S_OK, "create EFB depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||
m_efb.depth_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE),
|
||||
DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT);
|
||||
SAFE_RELEASE(buf);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetTex(), "EFB depth texture");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetDSV(), "EFB depth texture depth stencil view");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetSRV(), "EFB depth texture shader resource view");
|
||||
|
||||
// render target for depth buffer access in Renderer::AccessEFB
|
||||
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 4, 4, 1, 1, D3D11_BIND_RENDER_TARGET);
|
||||
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf);
|
||||
CHECK(hr==S_OK, "create EFB depth read texture (hr=%#x)", hr);
|
||||
m_efb.depth_read_texture = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
|
||||
SAFE_RELEASE(buf);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_read_texture->GetTex(), "EFB depth read texture (used in Renderer::AccessEFB)");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_read_texture->GetRTV(), "EFB depth read texture render target view (used in Renderer::AccessEFB)");
|
||||
|
||||
// staging texture to which we copy the data from m_efb.depth_read_texture
|
||||
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 4, 4, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE);
|
||||
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.depth_staging_buf);
|
||||
CHECK(hr==S_OK, "create EFB depth staging buffer (hr=%#x)", hr);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_staging_buf, "EFB depth staging texture (used for Renderer::AccessEFB)");
|
||||
}
|
||||
|
||||
FramebufferManager::~FramebufferManager()
|
||||
{
|
||||
SAFE_RELEASE(m_efb.color_tex);
|
||||
SAFE_RELEASE(m_efb.color_staging_buf);
|
||||
SAFE_RELEASE(m_efb.depth_tex);
|
||||
SAFE_RELEASE(m_efb.depth_staging_buf);
|
||||
SAFE_RELEASE(m_efb.depth_read_texture);
|
||||
|
||||
SAFE_RELEASE(m_realXFBSource.tex);
|
||||
}
|
||||
|
||||
void XFBSource::CopyEFB(const TargetRectangle& efbSource)
|
||||
{
|
||||
// copy EFB data to XFB and restore render target again
|
||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)texWidth, (float)texHeight);
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
D3D::context->OMSetRenderTargets(1, &tex->GetRTV(), NULL);
|
||||
D3D::SetLinearCopySampler();
|
||||
|
||||
D3DTexture2D* const ctex = FramebufferManager::GetEFBColorTexture();
|
||||
|
||||
D3D::drawShadedTexQuad(ctex->GetSRV(), efbSource.AsRECT(),
|
||||
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
|
||||
PixelShaderCache::GetColorCopyProgram(), VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout());
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &ctex->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||
}
|
||||
|
||||
XFBSource::~XFBSource()
|
||||
{
|
||||
tex->Release();
|
||||
}
|
||||
|
||||
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
|
||||
{
|
||||
XFBSource* const xfbs = new XFBSource;
|
||||
xfbs->tex = D3DTexture2D::Create(target_width, target_height,
|
||||
(D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE),
|
||||
D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
|
||||
return xfbs;
|
||||
}
|
||||
|
||||
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
// TODO
|
||||
PanicAlert("copyToRealXFB not implemented, yet\n");
|
||||
}
|
||||
|
||||
const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||
{
|
||||
PanicAlert("getRealXFBSource not implemented, yet\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,108 +1,108 @@
|
|||
// 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 _DX11_FBMANAGER_D3D_H_
|
||||
#define _DX11_FBMANAGER_D3D_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "DX11_D3DBase.h"
|
||||
|
||||
#include "../FramebufferManager.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
// On the GameCube, the game sends a request for the graphics processor to
|
||||
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
||||
// called the XFB (External Framebuffer). The size and location of the XFB is
|
||||
// decided at the time of the copy, and the format is always YUYV. The video
|
||||
// interface is given a pointer to the XFB, which will be decoded and
|
||||
// displayed on the TV.
|
||||
//
|
||||
// There are two ways for Dolphin to emulate this:
|
||||
//
|
||||
// Real XFB mode:
|
||||
//
|
||||
// Dolphin will behave like the GameCube and encode the EFB to
|
||||
// a portion of GameCube RAM. The emulated video interface will decode the data
|
||||
// for output to the screen.
|
||||
//
|
||||
// Advantages: Behaves exactly like the GameCube.
|
||||
// Disadvantages: Resolution will be limited.
|
||||
//
|
||||
// Virtual XFB mode:
|
||||
//
|
||||
// When a request is made to copy the EFB to an XFB, Dolphin
|
||||
// will remember the RAM location and size of the XFB in a Virtual XFB list.
|
||||
// The video interface will look up the XFB in the list and use the enhanced
|
||||
// data stored there, if available.
|
||||
//
|
||||
// Advantages: Enables high resolution graphics, better than real hardware.
|
||||
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
|
||||
// possible but uncommon), the Virtual XFB will not capture this information.
|
||||
|
||||
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
||||
// virtualize.
|
||||
|
||||
struct XFBSource : public XFBSourceBase
|
||||
{
|
||||
XFBSource() : tex(NULL) {}
|
||||
~XFBSource();
|
||||
|
||||
void CopyEFB(const TargetRectangle& efbSource);
|
||||
|
||||
D3DTexture2D* tex;
|
||||
};
|
||||
|
||||
class FramebufferManager : public ::FramebufferManagerBase
|
||||
{
|
||||
friend struct XFBSource;
|
||||
|
||||
public:
|
||||
FramebufferManager();
|
||||
~FramebufferManager();
|
||||
|
||||
static D3DTexture2D* &GetEFBColorTexture();
|
||||
static ID3D11Texture2D* &GetEFBColorStagingBuffer();
|
||||
|
||||
static D3DTexture2D* &GetEFBDepthTexture();
|
||||
static D3DTexture2D* &GetEFBDepthReadTexture();
|
||||
static ID3D11Texture2D* &GetEFBDepthStagingBuffer();
|
||||
|
||||
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
|
||||
|
||||
private:
|
||||
static void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
static const XFBSource** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||
|
||||
static XFBSource m_realXFBSource; // used in real XFB mode
|
||||
|
||||
static struct EFB
|
||||
{
|
||||
D3DTexture2D* color_tex;
|
||||
ID3D11Texture2D* color_staging_buf;
|
||||
|
||||
D3DTexture2D* depth_tex;
|
||||
ID3D11Texture2D* depth_staging_buf;
|
||||
D3DTexture2D* depth_read_texture;
|
||||
} m_efb;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
// 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 _DX11_FBMANAGER_D3D_H_
|
||||
#define _DX11_FBMANAGER_D3D_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "DX11_D3DBase.h"
|
||||
|
||||
#include "../FramebufferManager.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
// On the GameCube, the game sends a request for the graphics processor to
|
||||
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
||||
// called the XFB (External Framebuffer). The size and location of the XFB is
|
||||
// decided at the time of the copy, and the format is always YUYV. The video
|
||||
// interface is given a pointer to the XFB, which will be decoded and
|
||||
// displayed on the TV.
|
||||
//
|
||||
// There are two ways for Dolphin to emulate this:
|
||||
//
|
||||
// Real XFB mode:
|
||||
//
|
||||
// Dolphin will behave like the GameCube and encode the EFB to
|
||||
// a portion of GameCube RAM. The emulated video interface will decode the data
|
||||
// for output to the screen.
|
||||
//
|
||||
// Advantages: Behaves exactly like the GameCube.
|
||||
// Disadvantages: Resolution will be limited.
|
||||
//
|
||||
// Virtual XFB mode:
|
||||
//
|
||||
// When a request is made to copy the EFB to an XFB, Dolphin
|
||||
// will remember the RAM location and size of the XFB in a Virtual XFB list.
|
||||
// The video interface will look up the XFB in the list and use the enhanced
|
||||
// data stored there, if available.
|
||||
//
|
||||
// Advantages: Enables high resolution graphics, better than real hardware.
|
||||
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
|
||||
// possible but uncommon), the Virtual XFB will not capture this information.
|
||||
|
||||
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
||||
// virtualize.
|
||||
|
||||
struct XFBSource : public XFBSourceBase
|
||||
{
|
||||
XFBSource() : tex(NULL) {}
|
||||
~XFBSource();
|
||||
|
||||
void CopyEFB(const TargetRectangle& efbSource);
|
||||
|
||||
D3DTexture2D* tex;
|
||||
};
|
||||
|
||||
class FramebufferManager : public ::FramebufferManagerBase
|
||||
{
|
||||
friend struct XFBSource;
|
||||
|
||||
public:
|
||||
FramebufferManager();
|
||||
~FramebufferManager();
|
||||
|
||||
static D3DTexture2D* &GetEFBColorTexture();
|
||||
static ID3D11Texture2D* &GetEFBColorStagingBuffer();
|
||||
|
||||
static D3DTexture2D* &GetEFBDepthTexture();
|
||||
static D3DTexture2D* &GetEFBDepthReadTexture();
|
||||
static ID3D11Texture2D* &GetEFBDepthStagingBuffer();
|
||||
|
||||
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
|
||||
|
||||
private:
|
||||
static void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
static const XFBSource** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||
|
||||
static XFBSource m_realXFBSource; // used in real XFB mode
|
||||
|
||||
static struct EFB
|
||||
{
|
||||
D3DTexture2D* color_tex;
|
||||
ID3D11Texture2D* color_staging_buf;
|
||||
|
||||
D3DTexture2D* depth_tex;
|
||||
ID3D11Texture2D* depth_staging_buf;
|
||||
D3DTexture2D* depth_read_texture;
|
||||
} m_efb;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,372 +1,372 @@
|
|||
// 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 "VideoConfig.h"
|
||||
#include "DX11_GfxState.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
EmuGfxState* gfxstate;
|
||||
StateManager* stateman;
|
||||
|
||||
EmuGfxState::EmuGfxState() : vertexshader(NULL), vsbytecode(NULL), pixelshader(NULL), psbytecode(NULL), apply_called(false)
|
||||
{
|
||||
for (unsigned int k = 0;k < 8;k++)
|
||||
{
|
||||
float border[4] = {0.f, 0.f, 0.f, 0.f};
|
||||
shader_resources[k] = NULL;
|
||||
samplerdesc[k] = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, 0.f, 16, D3D11_COMPARISON_ALWAYS, border, -D3D11_FLOAT32_MAX, D3D11_FLOAT32_MAX);
|
||||
if(g_ActiveConfig.iMaxAnisotropy > 1) samplerdesc[k].Filter = D3D11_FILTER_ANISOTROPIC;
|
||||
}
|
||||
|
||||
memset(&blenddesc, 0, sizeof(blenddesc));
|
||||
blenddesc.AlphaToCoverageEnable = FALSE;
|
||||
blenddesc.IndependentBlendEnable = FALSE;
|
||||
blenddesc.RenderTarget[0].BlendEnable = FALSE;
|
||||
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
blenddesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
|
||||
blenddesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
|
||||
blenddesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||
blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
||||
blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
|
||||
memset(&depthdesc, 0, sizeof(depthdesc));
|
||||
depthdesc.DepthEnable = TRUE;
|
||||
depthdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
||||
depthdesc.DepthFunc = D3D11_COMPARISON_LESS;
|
||||
depthdesc.StencilEnable = FALSE;
|
||||
depthdesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
|
||||
depthdesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
|
||||
|
||||
// this probably must be changed once multisampling support gets added
|
||||
rastdesc = CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID, D3D11_CULL_NONE, false, 0, 0.f, 0, false, true, false, false);
|
||||
|
||||
pscbuf = NULL;
|
||||
vscbuf = NULL;
|
||||
vshaderchanged = false;
|
||||
inp_layout = NULL;
|
||||
num_inp_elems = 0;
|
||||
|
||||
pscbufchanged = false;
|
||||
vscbufchanged = false;
|
||||
}
|
||||
|
||||
EmuGfxState::~EmuGfxState()
|
||||
{
|
||||
for (unsigned int k = 0;k < 8;k++)
|
||||
SAFE_RELEASE(shader_resources[k])
|
||||
|
||||
SAFE_RELEASE(vsbytecode);
|
||||
SAFE_RELEASE(psbytecode);
|
||||
SAFE_RELEASE(vertexshader);
|
||||
SAFE_RELEASE(pixelshader);
|
||||
|
||||
SAFE_RELEASE(pscbuf);
|
||||
SAFE_RELEASE(vscbuf);
|
||||
|
||||
SAFE_RELEASE(inp_layout);
|
||||
}
|
||||
|
||||
// TODO: No need to store the whole bytecode, signature might be enough (?)
|
||||
void EmuGfxState::SetVShader(ID3D11VertexShader* shader, D3DBlob* bcode)
|
||||
{
|
||||
// TODO: vshaderchanged actually just needs to be true if the signature changed
|
||||
if (bcode && vsbytecode != bcode) vshaderchanged = true;
|
||||
SAFE_RELEASE(vsbytecode);
|
||||
SAFE_RELEASE(vertexshader);
|
||||
|
||||
if (shader && bcode)
|
||||
{
|
||||
vertexshader = shader;
|
||||
shader->AddRef();
|
||||
vsbytecode = bcode;
|
||||
bcode->AddRef();
|
||||
}
|
||||
else if (shader || bcode)
|
||||
{
|
||||
PanicAlert("Invalid parameters!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void EmuGfxState::SetPShader(ID3D11PixelShader* shader)
|
||||
{
|
||||
if (pixelshader) pixelshader->Release();
|
||||
pixelshader = shader;
|
||||
if (shader) shader->AddRef();
|
||||
}
|
||||
|
||||
void EmuGfxState::SetInputElements(const D3D11_INPUT_ELEMENT_DESC* elems, UINT num)
|
||||
{
|
||||
num_inp_elems = num;
|
||||
memcpy(inp_elems, elems, num*sizeof(D3D11_INPUT_ELEMENT_DESC));
|
||||
}
|
||||
|
||||
void EmuGfxState::SetShaderResource(unsigned int stage, ID3D11ShaderResourceView* srv)
|
||||
{
|
||||
if (shader_resources[stage])
|
||||
shader_resources[stage]->Release();
|
||||
shader_resources[stage] = srv;
|
||||
if (srv)
|
||||
srv->AddRef();
|
||||
}
|
||||
|
||||
void EmuGfxState::ApplyState()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
// input layout (only needs to be updated if the vertex shader signature changed)
|
||||
if (vshaderchanged)
|
||||
{
|
||||
SAFE_RELEASE(inp_layout);
|
||||
hr = D3D::device->CreateInputLayout(inp_elems, num_inp_elems, vsbytecode->Data(), vsbytecode->Size(), &inp_layout);
|
||||
if (FAILED(hr)) PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)inp_layout, "an input layout of EmuGfxState");
|
||||
vshaderchanged = false;
|
||||
}
|
||||
D3D::context->IASetInputLayout(inp_layout);
|
||||
|
||||
// vertex shader
|
||||
// TODO: divide the global variables of the generated shaders into about 5 constant buffers
|
||||
// TODO: improve interaction between EmuGfxState and global state management, so that we don't need to set the constant buffers every time
|
||||
if (!vscbuf)
|
||||
{
|
||||
unsigned int size = ((sizeof(vsconstants))&(~0xf))+0x10; // must be a multiple of 16
|
||||
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
hr = device->CreateBuffer(&cbdesc, NULL, &vscbuf);
|
||||
CHECK(hr==S_OK, "Create vertex shader constant buffer (size=%u)", size);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)vscbuf, "a vertex shader constant buffer of EmuGfxState");
|
||||
}
|
||||
if (vscbufchanged)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
context->Map(vscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, vsconstants, sizeof(vsconstants));
|
||||
context->Unmap(vscbuf, 0);
|
||||
}
|
||||
D3D::context->VSSetConstantBuffers(0, 1, &vscbuf);
|
||||
|
||||
// pixel shader
|
||||
if (!pscbuf)
|
||||
{
|
||||
unsigned int size = ((sizeof(psconstants))&(~0xf))+0x10; // must be a multiple of 16
|
||||
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
device->CreateBuffer(&cbdesc, NULL, &pscbuf);
|
||||
CHECK(hr==S_OK, "Create pixel shader constant buffer (size=%u)", size);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)pscbuf, "a pixel shader constant buffer of EmuGfxState");
|
||||
}
|
||||
if (pscbufchanged)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
context->Map(pscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, psconstants, sizeof(psconstants));
|
||||
context->Unmap(pscbuf, 0);
|
||||
pscbufchanged = false;
|
||||
}
|
||||
D3D::context->PSSetConstantBuffers(0, 1, &pscbuf);
|
||||
|
||||
ID3D11SamplerState* samplerstate[8];
|
||||
for (unsigned int stage = 0; stage < 8; stage++)
|
||||
{
|
||||
if (shader_resources[stage])
|
||||
{
|
||||
if(g_ActiveConfig.iMaxAnisotropy > 1) samplerdesc[stage].Filter = D3D11_FILTER_ANISOTROPIC;
|
||||
hr = D3D::device->CreateSamplerState(&samplerdesc[stage], &samplerstate[stage]);
|
||||
if (FAILED(hr)) PanicAlert("Fail %s %d, stage=%d\n", __FILE__, __LINE__, stage);
|
||||
else SetDebugObjectName((ID3D11DeviceChild*)samplerstate[stage], "a sampler state of EmuGfxState");
|
||||
}
|
||||
else samplerstate[stage] = NULL;
|
||||
}
|
||||
D3D::context->PSSetSamplers(0, 8, samplerstate);
|
||||
for (unsigned int stage = 0; stage < 8; stage++)
|
||||
SAFE_RELEASE(samplerstate[stage]);
|
||||
|
||||
ID3D11BlendState* blstate;
|
||||
hr = device->CreateBlendState(&blenddesc, &blstate);
|
||||
if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
|
||||
stateman->PushBlendState(blstate);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)blstate, "a blend state of EmuGfxState");
|
||||
SAFE_RELEASE(blstate);
|
||||
|
||||
rastdesc.FillMode = (g_ActiveConfig.bWireFrame) ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID;
|
||||
ID3D11RasterizerState* raststate;
|
||||
hr = device->CreateRasterizerState(&rastdesc, &raststate);
|
||||
if (FAILED(hr)) PanicAlert("Failed to create rasterizer state at %s %d\n", __FILE__, __LINE__);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)raststate, "a rasterizer state of EmuGfxState");
|
||||
stateman->PushRasterizerState(raststate);
|
||||
SAFE_RELEASE(raststate);
|
||||
|
||||
ID3D11DepthStencilState* depth_state;
|
||||
hr = device->CreateDepthStencilState(&depthdesc, &depth_state);
|
||||
if (SUCCEEDED(hr)) SetDebugObjectName((ID3D11DeviceChild*)depth_state, "a depth-stencil state of EmuGfxState");
|
||||
else PanicAlert("Failed to create depth state at %s %d\n", __FILE__, __LINE__);
|
||||
D3D::stateman->PushDepthState(depth_state);
|
||||
SAFE_RELEASE(depth_state);
|
||||
|
||||
context->PSSetShader(pixelshader, NULL, 0);
|
||||
context->VSSetShader(vertexshader, NULL, 0);
|
||||
context->PSSetShaderResources(0, 8, shader_resources);
|
||||
|
||||
stateman->Apply();
|
||||
apply_called = true;
|
||||
}
|
||||
|
||||
void EmuGfxState::AlphaPass()
|
||||
{
|
||||
if (!apply_called) ERROR_LOG(VIDEO, "EmuGfxState::AlphaPass called without having called ApplyState before!")
|
||||
else stateman->PopBlendState();
|
||||
|
||||
// pixel shader for alpha pass is different, so update it
|
||||
context->PSSetShader(pixelshader, NULL, 0);
|
||||
|
||||
ID3D11BlendState* blstate;
|
||||
D3D11_BLEND_DESC desc = blenddesc;
|
||||
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALPHA;
|
||||
desc.RenderTarget[0].BlendEnable = FALSE;
|
||||
HRESULT hr = device->CreateBlendState(&desc, &blstate);
|
||||
if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)blstate, "a blend state of EmuGfxState (created during alpha pass)");
|
||||
stateman->PushBlendState(blstate);
|
||||
blstate->Release();
|
||||
|
||||
stateman->Apply();
|
||||
}
|
||||
|
||||
void EmuGfxState::Reset()
|
||||
{
|
||||
for (unsigned int k = 0;k < 8;k++)
|
||||
SAFE_RELEASE(shader_resources[k]);
|
||||
|
||||
context->PSSetShaderResources(0, 8, shader_resources); // unbind all textures
|
||||
if (apply_called)
|
||||
{
|
||||
stateman->PopBlendState();
|
||||
stateman->PopDepthState();
|
||||
stateman->PopRasterizerState();
|
||||
apply_called = false;
|
||||
}
|
||||
}
|
||||
|
||||
void EmuGfxState::SetAlphaBlendEnable(bool enable)
|
||||
{
|
||||
blenddesc.RenderTarget[0].BlendEnable = enable;
|
||||
}
|
||||
|
||||
void EmuGfxState::SetRenderTargetWriteMask(UINT8 mask)
|
||||
{
|
||||
blenddesc.RenderTarget[0].RenderTargetWriteMask = mask;
|
||||
}
|
||||
|
||||
void EmuGfxState::SetSrcBlend(D3D11_BLEND val)
|
||||
{
|
||||
// TODO: Check whether e.g. the dest color check is needed here
|
||||
blenddesc.RenderTarget[0].SrcBlend = val;
|
||||
if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
|
||||
else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA;
|
||||
else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
|
||||
else blenddesc.RenderTarget[0].SrcBlendAlpha = val;
|
||||
}
|
||||
|
||||
void EmuGfxState::SetDestBlend(D3D11_BLEND val)
|
||||
{
|
||||
// TODO: Check whether e.g. the source color check is needed here
|
||||
blenddesc.RenderTarget[0].DestBlend = val;
|
||||
if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_SRC_ALPHA;
|
||||
else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA;
|
||||
else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
|
||||
else blenddesc.RenderTarget[0].DestBlendAlpha = val;
|
||||
}
|
||||
|
||||
void EmuGfxState::SetBlendOp(D3D11_BLEND_OP val)
|
||||
{
|
||||
blenddesc.RenderTarget[0].BlendOp = val;
|
||||
blenddesc.RenderTarget[0].BlendOpAlpha = val;
|
||||
}
|
||||
|
||||
void EmuGfxState::SetSamplerFilter(DWORD stage, D3D11_FILTER filter)
|
||||
{
|
||||
samplerdesc[stage].Filter = filter;
|
||||
}
|
||||
|
||||
template<typename T> AutoState<T>::AutoState(const T* object) : state(object)
|
||||
{
|
||||
((IUnknown*)state)->AddRef();
|
||||
}
|
||||
|
||||
template<typename T> AutoState<T>::AutoState(const AutoState<T> &source)
|
||||
{
|
||||
state = source.GetPtr();
|
||||
((T*)state)->AddRef();
|
||||
}
|
||||
|
||||
template<typename T> AutoState<T>::~AutoState()
|
||||
{
|
||||
if(state) ((T*)state)->Release();
|
||||
state = NULL;
|
||||
}
|
||||
|
||||
StateManager::StateManager() : cur_blendstate(NULL), cur_depthstate(NULL), cur_raststate(NULL) {}
|
||||
|
||||
void StateManager::PushBlendState(const ID3D11BlendState* state) { blendstates.push(AutoBlendState(state)); }
|
||||
void StateManager::PushDepthState(const ID3D11DepthStencilState* state) { depthstates.push(AutoDepthStencilState(state)); }
|
||||
void StateManager::PushRasterizerState(const ID3D11RasterizerState* state) { raststates.push(AutoRasterizerState(state)); }
|
||||
void StateManager::PopBlendState() { blendstates.pop(); }
|
||||
void StateManager::PopDepthState() { depthstates.pop(); }
|
||||
void StateManager::PopRasterizerState() { raststates.pop(); }
|
||||
|
||||
void StateManager::Apply()
|
||||
{
|
||||
if (!blendstates.empty())
|
||||
{
|
||||
if (cur_blendstate != blendstates.top().GetPtr())
|
||||
{
|
||||
cur_blendstate = (ID3D11BlendState*)blendstates.top().GetPtr();
|
||||
D3D::context->OMSetBlendState(cur_blendstate, NULL, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
else ERROR_LOG(VIDEO, "Tried to apply without blend state!");
|
||||
|
||||
if (!depthstates.empty())
|
||||
{
|
||||
if (cur_depthstate != depthstates.top().GetPtr())
|
||||
{
|
||||
cur_depthstate = (ID3D11DepthStencilState*)depthstates.top().GetPtr();
|
||||
D3D::context->OMSetDepthStencilState(cur_depthstate, 0);
|
||||
}
|
||||
}
|
||||
else ERROR_LOG(VIDEO, "Tried to apply without depth state!");
|
||||
|
||||
if (!raststates.empty())
|
||||
{
|
||||
if (cur_raststate != raststates.top().GetPtr())
|
||||
{
|
||||
cur_raststate = (ID3D11RasterizerState*)raststates.top().GetPtr();
|
||||
D3D::context->RSSetState(cur_raststate);
|
||||
}
|
||||
}
|
||||
else ERROR_LOG(VIDEO, "Tried to apply without rasterizer state!");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
// 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 "VideoConfig.h"
|
||||
#include "DX11_GfxState.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
EmuGfxState* gfxstate;
|
||||
StateManager* stateman;
|
||||
|
||||
EmuGfxState::EmuGfxState() : vertexshader(NULL), vsbytecode(NULL), pixelshader(NULL), psbytecode(NULL), apply_called(false)
|
||||
{
|
||||
for (unsigned int k = 0;k < 8;k++)
|
||||
{
|
||||
float border[4] = {0.f, 0.f, 0.f, 0.f};
|
||||
shader_resources[k] = NULL;
|
||||
samplerdesc[k] = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, 0.f, 16, D3D11_COMPARISON_ALWAYS, border, -D3D11_FLOAT32_MAX, D3D11_FLOAT32_MAX);
|
||||
if(g_ActiveConfig.iMaxAnisotropy > 1) samplerdesc[k].Filter = D3D11_FILTER_ANISOTROPIC;
|
||||
}
|
||||
|
||||
memset(&blenddesc, 0, sizeof(blenddesc));
|
||||
blenddesc.AlphaToCoverageEnable = FALSE;
|
||||
blenddesc.IndependentBlendEnable = FALSE;
|
||||
blenddesc.RenderTarget[0].BlendEnable = FALSE;
|
||||
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
blenddesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
|
||||
blenddesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
|
||||
blenddesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||
blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
||||
blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
|
||||
memset(&depthdesc, 0, sizeof(depthdesc));
|
||||
depthdesc.DepthEnable = TRUE;
|
||||
depthdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
||||
depthdesc.DepthFunc = D3D11_COMPARISON_LESS;
|
||||
depthdesc.StencilEnable = FALSE;
|
||||
depthdesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
|
||||
depthdesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
|
||||
|
||||
// this probably must be changed once multisampling support gets added
|
||||
rastdesc = CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID, D3D11_CULL_NONE, false, 0, 0.f, 0, false, true, false, false);
|
||||
|
||||
pscbuf = NULL;
|
||||
vscbuf = NULL;
|
||||
vshaderchanged = false;
|
||||
inp_layout = NULL;
|
||||
num_inp_elems = 0;
|
||||
|
||||
pscbufchanged = false;
|
||||
vscbufchanged = false;
|
||||
}
|
||||
|
||||
EmuGfxState::~EmuGfxState()
|
||||
{
|
||||
for (unsigned int k = 0;k < 8;k++)
|
||||
SAFE_RELEASE(shader_resources[k])
|
||||
|
||||
SAFE_RELEASE(vsbytecode);
|
||||
SAFE_RELEASE(psbytecode);
|
||||
SAFE_RELEASE(vertexshader);
|
||||
SAFE_RELEASE(pixelshader);
|
||||
|
||||
SAFE_RELEASE(pscbuf);
|
||||
SAFE_RELEASE(vscbuf);
|
||||
|
||||
SAFE_RELEASE(inp_layout);
|
||||
}
|
||||
|
||||
// TODO: No need to store the whole bytecode, signature might be enough (?)
|
||||
void EmuGfxState::SetVShader(ID3D11VertexShader* shader, D3DBlob* bcode)
|
||||
{
|
||||
// TODO: vshaderchanged actually just needs to be true if the signature changed
|
||||
if (bcode && vsbytecode != bcode) vshaderchanged = true;
|
||||
SAFE_RELEASE(vsbytecode);
|
||||
SAFE_RELEASE(vertexshader);
|
||||
|
||||
if (shader && bcode)
|
||||
{
|
||||
vertexshader = shader;
|
||||
shader->AddRef();
|
||||
vsbytecode = bcode;
|
||||
bcode->AddRef();
|
||||
}
|
||||
else if (shader || bcode)
|
||||
{
|
||||
PanicAlert("Invalid parameters!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void EmuGfxState::SetPShader(ID3D11PixelShader* shader)
|
||||
{
|
||||
if (pixelshader) pixelshader->Release();
|
||||
pixelshader = shader;
|
||||
if (shader) shader->AddRef();
|
||||
}
|
||||
|
||||
void EmuGfxState::SetInputElements(const D3D11_INPUT_ELEMENT_DESC* elems, UINT num)
|
||||
{
|
||||
num_inp_elems = num;
|
||||
memcpy(inp_elems, elems, num*sizeof(D3D11_INPUT_ELEMENT_DESC));
|
||||
}
|
||||
|
||||
void EmuGfxState::SetShaderResource(unsigned int stage, ID3D11ShaderResourceView* srv)
|
||||
{
|
||||
if (shader_resources[stage])
|
||||
shader_resources[stage]->Release();
|
||||
shader_resources[stage] = srv;
|
||||
if (srv)
|
||||
srv->AddRef();
|
||||
}
|
||||
|
||||
void EmuGfxState::ApplyState()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
// input layout (only needs to be updated if the vertex shader signature changed)
|
||||
if (vshaderchanged)
|
||||
{
|
||||
SAFE_RELEASE(inp_layout);
|
||||
hr = D3D::device->CreateInputLayout(inp_elems, num_inp_elems, vsbytecode->Data(), vsbytecode->Size(), &inp_layout);
|
||||
if (FAILED(hr)) PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)inp_layout, "an input layout of EmuGfxState");
|
||||
vshaderchanged = false;
|
||||
}
|
||||
D3D::context->IASetInputLayout(inp_layout);
|
||||
|
||||
// vertex shader
|
||||
// TODO: divide the global variables of the generated shaders into about 5 constant buffers
|
||||
// TODO: improve interaction between EmuGfxState and global state management, so that we don't need to set the constant buffers every time
|
||||
if (!vscbuf)
|
||||
{
|
||||
unsigned int size = ((sizeof(vsconstants))&(~0xf))+0x10; // must be a multiple of 16
|
||||
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
hr = device->CreateBuffer(&cbdesc, NULL, &vscbuf);
|
||||
CHECK(hr==S_OK, "Create vertex shader constant buffer (size=%u)", size);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)vscbuf, "a vertex shader constant buffer of EmuGfxState");
|
||||
}
|
||||
if (vscbufchanged)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
context->Map(vscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, vsconstants, sizeof(vsconstants));
|
||||
context->Unmap(vscbuf, 0);
|
||||
}
|
||||
D3D::context->VSSetConstantBuffers(0, 1, &vscbuf);
|
||||
|
||||
// pixel shader
|
||||
if (!pscbuf)
|
||||
{
|
||||
unsigned int size = ((sizeof(psconstants))&(~0xf))+0x10; // must be a multiple of 16
|
||||
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
device->CreateBuffer(&cbdesc, NULL, &pscbuf);
|
||||
CHECK(hr==S_OK, "Create pixel shader constant buffer (size=%u)", size);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)pscbuf, "a pixel shader constant buffer of EmuGfxState");
|
||||
}
|
||||
if (pscbufchanged)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
context->Map(pscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, psconstants, sizeof(psconstants));
|
||||
context->Unmap(pscbuf, 0);
|
||||
pscbufchanged = false;
|
||||
}
|
||||
D3D::context->PSSetConstantBuffers(0, 1, &pscbuf);
|
||||
|
||||
ID3D11SamplerState* samplerstate[8];
|
||||
for (unsigned int stage = 0; stage < 8; stage++)
|
||||
{
|
||||
if (shader_resources[stage])
|
||||
{
|
||||
if(g_ActiveConfig.iMaxAnisotropy > 1) samplerdesc[stage].Filter = D3D11_FILTER_ANISOTROPIC;
|
||||
hr = D3D::device->CreateSamplerState(&samplerdesc[stage], &samplerstate[stage]);
|
||||
if (FAILED(hr)) PanicAlert("Fail %s %d, stage=%d\n", __FILE__, __LINE__, stage);
|
||||
else SetDebugObjectName((ID3D11DeviceChild*)samplerstate[stage], "a sampler state of EmuGfxState");
|
||||
}
|
||||
else samplerstate[stage] = NULL;
|
||||
}
|
||||
D3D::context->PSSetSamplers(0, 8, samplerstate);
|
||||
for (unsigned int stage = 0; stage < 8; stage++)
|
||||
SAFE_RELEASE(samplerstate[stage]);
|
||||
|
||||
ID3D11BlendState* blstate;
|
||||
hr = device->CreateBlendState(&blenddesc, &blstate);
|
||||
if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
|
||||
stateman->PushBlendState(blstate);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)blstate, "a blend state of EmuGfxState");
|
||||
SAFE_RELEASE(blstate);
|
||||
|
||||
rastdesc.FillMode = (g_ActiveConfig.bWireFrame) ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID;
|
||||
ID3D11RasterizerState* raststate;
|
||||
hr = device->CreateRasterizerState(&rastdesc, &raststate);
|
||||
if (FAILED(hr)) PanicAlert("Failed to create rasterizer state at %s %d\n", __FILE__, __LINE__);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)raststate, "a rasterizer state of EmuGfxState");
|
||||
stateman->PushRasterizerState(raststate);
|
||||
SAFE_RELEASE(raststate);
|
||||
|
||||
ID3D11DepthStencilState* depth_state;
|
||||
hr = device->CreateDepthStencilState(&depthdesc, &depth_state);
|
||||
if (SUCCEEDED(hr)) SetDebugObjectName((ID3D11DeviceChild*)depth_state, "a depth-stencil state of EmuGfxState");
|
||||
else PanicAlert("Failed to create depth state at %s %d\n", __FILE__, __LINE__);
|
||||
D3D::stateman->PushDepthState(depth_state);
|
||||
SAFE_RELEASE(depth_state);
|
||||
|
||||
context->PSSetShader(pixelshader, NULL, 0);
|
||||
context->VSSetShader(vertexshader, NULL, 0);
|
||||
context->PSSetShaderResources(0, 8, shader_resources);
|
||||
|
||||
stateman->Apply();
|
||||
apply_called = true;
|
||||
}
|
||||
|
||||
void EmuGfxState::AlphaPass()
|
||||
{
|
||||
if (!apply_called) ERROR_LOG(VIDEO, "EmuGfxState::AlphaPass called without having called ApplyState before!")
|
||||
else stateman->PopBlendState();
|
||||
|
||||
// pixel shader for alpha pass is different, so update it
|
||||
context->PSSetShader(pixelshader, NULL, 0);
|
||||
|
||||
ID3D11BlendState* blstate;
|
||||
D3D11_BLEND_DESC desc = blenddesc;
|
||||
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALPHA;
|
||||
desc.RenderTarget[0].BlendEnable = FALSE;
|
||||
HRESULT hr = device->CreateBlendState(&desc, &blstate);
|
||||
if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)blstate, "a blend state of EmuGfxState (created during alpha pass)");
|
||||
stateman->PushBlendState(blstate);
|
||||
blstate->Release();
|
||||
|
||||
stateman->Apply();
|
||||
}
|
||||
|
||||
void EmuGfxState::Reset()
|
||||
{
|
||||
for (unsigned int k = 0;k < 8;k++)
|
||||
SAFE_RELEASE(shader_resources[k]);
|
||||
|
||||
context->PSSetShaderResources(0, 8, shader_resources); // unbind all textures
|
||||
if (apply_called)
|
||||
{
|
||||
stateman->PopBlendState();
|
||||
stateman->PopDepthState();
|
||||
stateman->PopRasterizerState();
|
||||
apply_called = false;
|
||||
}
|
||||
}
|
||||
|
||||
void EmuGfxState::SetAlphaBlendEnable(bool enable)
|
||||
{
|
||||
blenddesc.RenderTarget[0].BlendEnable = enable;
|
||||
}
|
||||
|
||||
void EmuGfxState::SetRenderTargetWriteMask(UINT8 mask)
|
||||
{
|
||||
blenddesc.RenderTarget[0].RenderTargetWriteMask = mask;
|
||||
}
|
||||
|
||||
void EmuGfxState::SetSrcBlend(D3D11_BLEND val)
|
||||
{
|
||||
// TODO: Check whether e.g. the dest color check is needed here
|
||||
blenddesc.RenderTarget[0].SrcBlend = val;
|
||||
if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
|
||||
else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA;
|
||||
else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
|
||||
else blenddesc.RenderTarget[0].SrcBlendAlpha = val;
|
||||
}
|
||||
|
||||
void EmuGfxState::SetDestBlend(D3D11_BLEND val)
|
||||
{
|
||||
// TODO: Check whether e.g. the source color check is needed here
|
||||
blenddesc.RenderTarget[0].DestBlend = val;
|
||||
if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_SRC_ALPHA;
|
||||
else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA;
|
||||
else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
|
||||
else blenddesc.RenderTarget[0].DestBlendAlpha = val;
|
||||
}
|
||||
|
||||
void EmuGfxState::SetBlendOp(D3D11_BLEND_OP val)
|
||||
{
|
||||
blenddesc.RenderTarget[0].BlendOp = val;
|
||||
blenddesc.RenderTarget[0].BlendOpAlpha = val;
|
||||
}
|
||||
|
||||
void EmuGfxState::SetSamplerFilter(DWORD stage, D3D11_FILTER filter)
|
||||
{
|
||||
samplerdesc[stage].Filter = filter;
|
||||
}
|
||||
|
||||
template<typename T> AutoState<T>::AutoState(const T* object) : state(object)
|
||||
{
|
||||
((IUnknown*)state)->AddRef();
|
||||
}
|
||||
|
||||
template<typename T> AutoState<T>::AutoState(const AutoState<T> &source)
|
||||
{
|
||||
state = source.GetPtr();
|
||||
((T*)state)->AddRef();
|
||||
}
|
||||
|
||||
template<typename T> AutoState<T>::~AutoState()
|
||||
{
|
||||
if(state) ((T*)state)->Release();
|
||||
state = NULL;
|
||||
}
|
||||
|
||||
StateManager::StateManager() : cur_blendstate(NULL), cur_depthstate(NULL), cur_raststate(NULL) {}
|
||||
|
||||
void StateManager::PushBlendState(const ID3D11BlendState* state) { blendstates.push(AutoBlendState(state)); }
|
||||
void StateManager::PushDepthState(const ID3D11DepthStencilState* state) { depthstates.push(AutoDepthStencilState(state)); }
|
||||
void StateManager::PushRasterizerState(const ID3D11RasterizerState* state) { raststates.push(AutoRasterizerState(state)); }
|
||||
void StateManager::PopBlendState() { blendstates.pop(); }
|
||||
void StateManager::PopDepthState() { depthstates.pop(); }
|
||||
void StateManager::PopRasterizerState() { raststates.pop(); }
|
||||
|
||||
void StateManager::Apply()
|
||||
{
|
||||
if (!blendstates.empty())
|
||||
{
|
||||
if (cur_blendstate != blendstates.top().GetPtr())
|
||||
{
|
||||
cur_blendstate = (ID3D11BlendState*)blendstates.top().GetPtr();
|
||||
D3D::context->OMSetBlendState(cur_blendstate, NULL, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
else ERROR_LOG(VIDEO, "Tried to apply without blend state!");
|
||||
|
||||
if (!depthstates.empty())
|
||||
{
|
||||
if (cur_depthstate != depthstates.top().GetPtr())
|
||||
{
|
||||
cur_depthstate = (ID3D11DepthStencilState*)depthstates.top().GetPtr();
|
||||
D3D::context->OMSetDepthStencilState(cur_depthstate, 0);
|
||||
}
|
||||
}
|
||||
else ERROR_LOG(VIDEO, "Tried to apply without depth state!");
|
||||
|
||||
if (!raststates.empty())
|
||||
{
|
||||
if (cur_raststate != raststates.top().GetPtr())
|
||||
{
|
||||
cur_raststate = (ID3D11RasterizerState*)raststates.top().GetPtr();
|
||||
D3D::context->RSSetState(cur_raststate);
|
||||
}
|
||||
}
|
||||
else ERROR_LOG(VIDEO, "Tried to apply without rasterizer state!");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
|
|
|
@ -1,142 +1,142 @@
|
|||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stack>
|
||||
|
||||
// VideoCommon
|
||||
#include "VertexShaderGen.h"
|
||||
#include "PixelShaderGen.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DBlob.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
// stores the pipeline state to use when calling VertexManager::Flush()
|
||||
class EmuGfxState
|
||||
{
|
||||
public:
|
||||
EmuGfxState();
|
||||
~EmuGfxState();
|
||||
|
||||
void SetVShader(ID3D11VertexShader* shader, D3DBlob* bcode);
|
||||
void SetPShader(ID3D11PixelShader* shader);
|
||||
void SetInputElements(const D3D11_INPUT_ELEMENT_DESC* elems, UINT num);
|
||||
void SetShaderResource(unsigned int stage, ID3D11ShaderResourceView* srv);
|
||||
|
||||
void ApplyState(); // apply current state
|
||||
void AlphaPass(); // only modify the current state to enable the alpha pass
|
||||
void Reset();
|
||||
|
||||
// blend state
|
||||
void SetAlphaBlendEnable(bool enable);
|
||||
void SetRenderTargetWriteMask(UINT8 mask);
|
||||
void SetSrcBlend(D3D11_BLEND val);
|
||||
void SetDestBlend(D3D11_BLEND val);
|
||||
void SetBlendOp(D3D11_BLEND_OP val);
|
||||
|
||||
// sampler states
|
||||
void SetSamplerFilter(DWORD stage, D3D11_FILTER filter);
|
||||
|
||||
// TODO: add methods for changing the other states instead of modifying them directly
|
||||
|
||||
D3D11_SAMPLER_DESC samplerdesc[8];
|
||||
D3D11_RASTERIZER_DESC rastdesc;
|
||||
D3D11_DEPTH_STENCIL_DESC depthdesc;
|
||||
|
||||
float psconstants[C_PENVCONST_END*4];
|
||||
float vsconstants[C_VENVCONST_END*4];
|
||||
bool vscbufchanged;
|
||||
bool pscbufchanged;
|
||||
|
||||
private:
|
||||
ID3D11VertexShader* vertexshader;
|
||||
D3DBlob* vsbytecode;
|
||||
ID3D11PixelShader* pixelshader;
|
||||
D3DBlob* psbytecode;
|
||||
bool vshaderchanged;
|
||||
|
||||
ID3D11Buffer* vscbuf;
|
||||
ID3D11Buffer* pscbuf;
|
||||
|
||||
ID3D11InputLayout* inp_layout;
|
||||
D3D11_INPUT_ELEMENT_DESC inp_elems[32];
|
||||
int num_inp_elems;
|
||||
|
||||
ID3D11ShaderResourceView* shader_resources[8];
|
||||
D3D11_BLEND_DESC blenddesc;
|
||||
|
||||
bool apply_called;
|
||||
};
|
||||
|
||||
template<typename T> class AutoState
|
||||
{
|
||||
public:
|
||||
AutoState(const T* object);
|
||||
AutoState(const AutoState<T> &source);
|
||||
~AutoState();
|
||||
|
||||
const inline T* GetPtr() const { return state; }
|
||||
|
||||
private:
|
||||
const T* state;
|
||||
};
|
||||
|
||||
typedef AutoState<ID3D11BlendState> AutoBlendState;
|
||||
typedef AutoState<ID3D11DepthStencilState> AutoDepthStencilState;
|
||||
typedef AutoState<ID3D11RasterizerState> AutoRasterizerState;
|
||||
|
||||
class StateManager
|
||||
{
|
||||
public:
|
||||
StateManager();
|
||||
|
||||
// call any of these to change the affected states
|
||||
void PushBlendState(const ID3D11BlendState* state);
|
||||
void PushDepthState(const ID3D11DepthStencilState* state);
|
||||
void PushRasterizerState(const ID3D11RasterizerState* state);
|
||||
|
||||
// call these after drawing
|
||||
void PopBlendState();
|
||||
void PopDepthState();
|
||||
void PopRasterizerState();
|
||||
|
||||
// call this before any drawing operation if states could have changed meanwhile
|
||||
void Apply();
|
||||
|
||||
private:
|
||||
std::stack<AutoBlendState> blendstates;
|
||||
std::stack<AutoDepthStencilState> depthstates;
|
||||
std::stack<AutoRasterizerState> raststates;
|
||||
ID3D11BlendState* cur_blendstate;
|
||||
ID3D11DepthStencilState* cur_depthstate;
|
||||
ID3D11RasterizerState* cur_raststate;
|
||||
};
|
||||
|
||||
extern EmuGfxState* gfxstate;
|
||||
extern StateManager* stateman;
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stack>
|
||||
|
||||
// VideoCommon
|
||||
#include "VertexShaderGen.h"
|
||||
#include "PixelShaderGen.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DBlob.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
// stores the pipeline state to use when calling VertexManager::Flush()
|
||||
class EmuGfxState
|
||||
{
|
||||
public:
|
||||
EmuGfxState();
|
||||
~EmuGfxState();
|
||||
|
||||
void SetVShader(ID3D11VertexShader* shader, D3DBlob* bcode);
|
||||
void SetPShader(ID3D11PixelShader* shader);
|
||||
void SetInputElements(const D3D11_INPUT_ELEMENT_DESC* elems, UINT num);
|
||||
void SetShaderResource(unsigned int stage, ID3D11ShaderResourceView* srv);
|
||||
|
||||
void ApplyState(); // apply current state
|
||||
void AlphaPass(); // only modify the current state to enable the alpha pass
|
||||
void Reset();
|
||||
|
||||
// blend state
|
||||
void SetAlphaBlendEnable(bool enable);
|
||||
void SetRenderTargetWriteMask(UINT8 mask);
|
||||
void SetSrcBlend(D3D11_BLEND val);
|
||||
void SetDestBlend(D3D11_BLEND val);
|
||||
void SetBlendOp(D3D11_BLEND_OP val);
|
||||
|
||||
// sampler states
|
||||
void SetSamplerFilter(DWORD stage, D3D11_FILTER filter);
|
||||
|
||||
// TODO: add methods for changing the other states instead of modifying them directly
|
||||
|
||||
D3D11_SAMPLER_DESC samplerdesc[8];
|
||||
D3D11_RASTERIZER_DESC rastdesc;
|
||||
D3D11_DEPTH_STENCIL_DESC depthdesc;
|
||||
|
||||
float psconstants[C_PENVCONST_END*4];
|
||||
float vsconstants[C_VENVCONST_END*4];
|
||||
bool vscbufchanged;
|
||||
bool pscbufchanged;
|
||||
|
||||
private:
|
||||
ID3D11VertexShader* vertexshader;
|
||||
D3DBlob* vsbytecode;
|
||||
ID3D11PixelShader* pixelshader;
|
||||
D3DBlob* psbytecode;
|
||||
bool vshaderchanged;
|
||||
|
||||
ID3D11Buffer* vscbuf;
|
||||
ID3D11Buffer* pscbuf;
|
||||
|
||||
ID3D11InputLayout* inp_layout;
|
||||
D3D11_INPUT_ELEMENT_DESC inp_elems[32];
|
||||
int num_inp_elems;
|
||||
|
||||
ID3D11ShaderResourceView* shader_resources[8];
|
||||
D3D11_BLEND_DESC blenddesc;
|
||||
|
||||
bool apply_called;
|
||||
};
|
||||
|
||||
template<typename T> class AutoState
|
||||
{
|
||||
public:
|
||||
AutoState(const T* object);
|
||||
AutoState(const AutoState<T> &source);
|
||||
~AutoState();
|
||||
|
||||
const inline T* GetPtr() const { return state; }
|
||||
|
||||
private:
|
||||
const T* state;
|
||||
};
|
||||
|
||||
typedef AutoState<ID3D11BlendState> AutoBlendState;
|
||||
typedef AutoState<ID3D11DepthStencilState> AutoDepthStencilState;
|
||||
typedef AutoState<ID3D11RasterizerState> AutoRasterizerState;
|
||||
|
||||
class StateManager
|
||||
{
|
||||
public:
|
||||
StateManager();
|
||||
|
||||
// call any of these to change the affected states
|
||||
void PushBlendState(const ID3D11BlendState* state);
|
||||
void PushDepthState(const ID3D11DepthStencilState* state);
|
||||
void PushRasterizerState(const ID3D11RasterizerState* state);
|
||||
|
||||
// call these after drawing
|
||||
void PopBlendState();
|
||||
void PopDepthState();
|
||||
void PopRasterizerState();
|
||||
|
||||
// call this before any drawing operation if states could have changed meanwhile
|
||||
void Apply();
|
||||
|
||||
private:
|
||||
std::stack<AutoBlendState> blendstates;
|
||||
std::stack<AutoDepthStencilState> depthstates;
|
||||
std::stack<AutoRasterizerState> raststates;
|
||||
ID3D11BlendState* cur_blendstate;
|
||||
ID3D11DepthStencilState* cur_depthstate;
|
||||
ID3D11RasterizerState* cur_raststate;
|
||||
};
|
||||
|
||||
extern EmuGfxState* gfxstate;
|
||||
extern StateManager* stateman;
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
|
|
|
@ -1,150 +1,150 @@
|
|||
|
||||
// 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/
|
||||
|
||||
// Common
|
||||
#include "MemoryUtil.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "Profiler.h"
|
||||
#include "CPMemory.h"
|
||||
#include "VertexShaderGen.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_VertexShaderCache.h"
|
||||
#include "DX11_VertexManager.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
class D3DVertexFormat : public NativeVertexFormat
|
||||
{
|
||||
D3D11_INPUT_ELEMENT_DESC m_elems[32];
|
||||
UINT m_num_elems;
|
||||
|
||||
public:
|
||||
D3DVertexFormat() : m_num_elems(0) {}
|
||||
void Initialize(const PortableVertexDeclaration &_vtx_decl);
|
||||
void SetupVertexPointers() const;
|
||||
};
|
||||
|
||||
NativeVertexFormat* VertexManager::CreateNativeVertexFormat()
|
||||
{
|
||||
return new D3DVertexFormat;
|
||||
}
|
||||
|
||||
DXGI_FORMAT VarToD3D(VarType t, int size)
|
||||
{
|
||||
DXGI_FORMAT retval = DXGI_FORMAT_UNKNOWN;
|
||||
static const DXGI_FORMAT lookup1[5] = {
|
||||
DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R32_FLOAT
|
||||
};
|
||||
static const DXGI_FORMAT lookup2[5] = {
|
||||
DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R32G32_FLOAT
|
||||
};
|
||||
static const DXGI_FORMAT lookup3[5] = {
|
||||
DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32_FLOAT
|
||||
};
|
||||
static const DXGI_FORMAT lookup4[5] = {
|
||||
DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||
};
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 1: retval = lookup1[t]; break;
|
||||
case 2: retval = lookup2[t]; break;
|
||||
case 3: retval = lookup3[t]; break;
|
||||
case 4: retval = lookup4[t]; break;
|
||||
default: break;
|
||||
}
|
||||
if (retval == DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
PanicAlert("VarToD3D: Invalid type/size combo %i , %i", (int)t, size);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
|
||||
{
|
||||
vertex_stride = _vtx_decl.stride;
|
||||
memset(m_elems, 0, sizeof(m_elems));
|
||||
|
||||
m_elems[m_num_elems].SemanticName = "POSITION";
|
||||
m_elems[m_num_elems].AlignedByteOffset = 0;
|
||||
m_elems[m_num_elems].Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (_vtx_decl.normal_offset[i] > 0)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "NORMAL";
|
||||
m_elems[m_num_elems].SemanticIndex = i;
|
||||
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.normal_offset[i];
|
||||
m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.normal_gl_type, _vtx_decl.normal_gl_size);
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (_vtx_decl.color_offset[i] > 0)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "COLOR";
|
||||
m_elems[m_num_elems].SemanticIndex = i;
|
||||
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.color_offset[i];
|
||||
m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.color_gl_type, 4);
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (_vtx_decl.texcoord_offset[i] > 0)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "TEXCOORD";
|
||||
m_elems[m_num_elems].SemanticIndex = i;
|
||||
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.texcoord_offset[i];
|
||||
m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.texcoord_gl_type[i], _vtx_decl.texcoord_size[i]);
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
}
|
||||
|
||||
if (_vtx_decl.posmtx_offset != -1)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "BLENDINDICES";
|
||||
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.posmtx_offset;
|
||||
m_elems[m_num_elems].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
}
|
||||
|
||||
void D3DVertexFormat::SetupVertexPointers() const
|
||||
{
|
||||
D3D::gfxstate->SetInputElements(m_elems, m_num_elems);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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/
|
||||
|
||||
// Common
|
||||
#include "MemoryUtil.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "Profiler.h"
|
||||
#include "CPMemory.h"
|
||||
#include "VertexShaderGen.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_VertexShaderCache.h"
|
||||
#include "DX11_VertexManager.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
class D3DVertexFormat : public NativeVertexFormat
|
||||
{
|
||||
D3D11_INPUT_ELEMENT_DESC m_elems[32];
|
||||
UINT m_num_elems;
|
||||
|
||||
public:
|
||||
D3DVertexFormat() : m_num_elems(0) {}
|
||||
void Initialize(const PortableVertexDeclaration &_vtx_decl);
|
||||
void SetupVertexPointers() const;
|
||||
};
|
||||
|
||||
NativeVertexFormat* VertexManager::CreateNativeVertexFormat()
|
||||
{
|
||||
return new D3DVertexFormat;
|
||||
}
|
||||
|
||||
DXGI_FORMAT VarToD3D(VarType t, int size)
|
||||
{
|
||||
DXGI_FORMAT retval = DXGI_FORMAT_UNKNOWN;
|
||||
static const DXGI_FORMAT lookup1[5] = {
|
||||
DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R32_FLOAT
|
||||
};
|
||||
static const DXGI_FORMAT lookup2[5] = {
|
||||
DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R32G32_FLOAT
|
||||
};
|
||||
static const DXGI_FORMAT lookup3[5] = {
|
||||
DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32_FLOAT
|
||||
};
|
||||
static const DXGI_FORMAT lookup4[5] = {
|
||||
DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||
};
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 1: retval = lookup1[t]; break;
|
||||
case 2: retval = lookup2[t]; break;
|
||||
case 3: retval = lookup3[t]; break;
|
||||
case 4: retval = lookup4[t]; break;
|
||||
default: break;
|
||||
}
|
||||
if (retval == DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
PanicAlert("VarToD3D: Invalid type/size combo %i , %i", (int)t, size);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
|
||||
{
|
||||
vertex_stride = _vtx_decl.stride;
|
||||
memset(m_elems, 0, sizeof(m_elems));
|
||||
|
||||
m_elems[m_num_elems].SemanticName = "POSITION";
|
||||
m_elems[m_num_elems].AlignedByteOffset = 0;
|
||||
m_elems[m_num_elems].Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (_vtx_decl.normal_offset[i] > 0)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "NORMAL";
|
||||
m_elems[m_num_elems].SemanticIndex = i;
|
||||
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.normal_offset[i];
|
||||
m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.normal_gl_type, _vtx_decl.normal_gl_size);
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (_vtx_decl.color_offset[i] > 0)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "COLOR";
|
||||
m_elems[m_num_elems].SemanticIndex = i;
|
||||
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.color_offset[i];
|
||||
m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.color_gl_type, 4);
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (_vtx_decl.texcoord_offset[i] > 0)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "TEXCOORD";
|
||||
m_elems[m_num_elems].SemanticIndex = i;
|
||||
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.texcoord_offset[i];
|
||||
m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.texcoord_gl_type[i], _vtx_decl.texcoord_size[i]);
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
}
|
||||
|
||||
if (_vtx_decl.posmtx_offset != -1)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "BLENDINDICES";
|
||||
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.posmtx_offset;
|
||||
m_elems[m_num_elems].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
}
|
||||
|
||||
void D3DVertexFormat::SetupVertexPointers() const
|
||||
{
|
||||
D3D::gfxstate->SetInputElements(m_elems, m_num_elems);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,306 +1,306 @@
|
|||
// 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/
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
#include "LinearDiskCache.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "BPMemory.h"
|
||||
#include "XFMemory.h"
|
||||
#include "ImageWrite.h"
|
||||
#include "PixelShaderGen.h"
|
||||
#include "PixelShaderManager.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DShader.h"
|
||||
#include "DX11_PixelShaderCache.h"
|
||||
|
||||
#include <D3Dcompiler.h>
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
|
||||
const PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry;
|
||||
|
||||
LinearDiskCache g_ps_disk_cache;
|
||||
|
||||
ID3D11PixelShader* s_ColorMatrixProgram = NULL;
|
||||
ID3D11PixelShader* s_ColorCopyProgram = NULL;
|
||||
ID3D11PixelShader* s_DepthMatrixProgram = NULL;
|
||||
ID3D11PixelShader* s_ClearProgram = NULL;
|
||||
|
||||
const char clear_program_code[] = {
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : SV_Target,\n"
|
||||
"in float4 pos : SV_Position,\n"
|
||||
"in float4 incol0 : COLOR0){\n"
|
||||
"ocol0 = incol0;\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
const char color_copy_program_code[] = {
|
||||
"sampler samp0 : register(s0);\n"
|
||||
"Texture2D Tex0 : register(t0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : SV_Target,\n"
|
||||
"in float4 pos : SV_Position,\n"
|
||||
"in float2 uv0 : TEXCOORD0){\n"
|
||||
"ocol0 = Tex0.Sample(samp0,uv0);\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
const char color_matrix_program_code[] = {
|
||||
"sampler samp0 : register(s0);\n"
|
||||
"Texture2D Tex0 : register(t0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : SV_Target,\n"
|
||||
"in float4 pos : SV_Position,\n"
|
||||
" in float2 uv0 : TEXCOORD0){\n"
|
||||
"float4 texcol = Tex0.Sample(samp0,uv0);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
const char depth_matrix_program[] = {
|
||||
"sampler samp0 : register(s0);\n"
|
||||
"Texture2D Tex0 : register(t0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : SV_Target,\n"
|
||||
" in float4 pos : SV_Position,\n"
|
||||
" in float2 uv0 : TEXCOORD0){\n"
|
||||
"float4 texcol = Tex0.Sample(samp0,uv0);\n"
|
||||
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
|
||||
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::GetColorMatrixProgram()
|
||||
{
|
||||
return s_ColorMatrixProgram;
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::GetDepthMatrixProgram()
|
||||
{
|
||||
return s_DepthMatrixProgram;
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::GetColorCopyProgram()
|
||||
{
|
||||
return s_ColorCopyProgram;
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::GetClearProgram()
|
||||
{
|
||||
return s_ClearProgram;
|
||||
}
|
||||
|
||||
// HACK to avoid some invasive VideoCommon changes
|
||||
// these values are hardcoded, they depend on internal D3DCompile behavior; TODO: Solve this with D3DReflect or something
|
||||
// offset given in floats, table index is float4
|
||||
unsigned int ps_constant_offset_table[] = {
|
||||
0, 4, 8, 12, // C_COLORS, 16
|
||||
16, 20, 24, 28, // C_KCOLORS, 16
|
||||
32, // C_ALPHA, 4
|
||||
36, 40, 44, 48, 52, 56, 60, 64, // C_TEXDIMS, 32
|
||||
68, 72, // C_ZBIAS, 8
|
||||
76, 80, // C_INDTEXSCALE, 8
|
||||
84, 88, 92, 96, 100, 104, // C_INDTEXMTX, 24
|
||||
108, 112, // C_FOG, 8
|
||||
116, 120, 124 ,128, // C_COLORMATRIX, 16
|
||||
132, 136, 140, 144, 148, // C_PLIGHTS0, 20
|
||||
152, 156, 160, 164, 168, // C_PLIGHTS1, 20
|
||||
172, 176, 180, 184, 188, // C_PLIGHTS2, 20
|
||||
192, 196, 200, 204, 208, // C_PLIGHTS3, 20
|
||||
212, 216, 220, 224, 228, // C_PLIGHTS4, 20
|
||||
232, 236, 240, 244, 248, // C_PLIGHTS5, 20
|
||||
252, 256, 260, 264, 268, // C_PLIGHTS6, 20
|
||||
272, 276, 280, 284, 288, // C_PLIGHTS7, 20
|
||||
292, 296, 300, 304, // C_PMATERIALS, 16
|
||||
};
|
||||
void PixelShaderCache::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number] ] = f1;
|
||||
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+1] = f2;
|
||||
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+2] = f3;
|
||||
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+3] = f4;
|
||||
D3D::gfxstate->pscbufchanged = true;
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float* f)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4);
|
||||
D3D::gfxstate->pscbufchanged = true;
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float* f)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4*count);
|
||||
D3D::gfxstate->pscbufchanged = true;
|
||||
}
|
||||
|
||||
// this class will load the precompiled shaders into our cache
|
||||
class PixelShaderCacheInserter : public LinearDiskCacheReader
|
||||
{
|
||||
public:
|
||||
void Read(const u8* key, int key_size, const u8* value, int value_size)
|
||||
{
|
||||
PIXELSHADERUID uid;
|
||||
if (key_size != sizeof(uid)) {
|
||||
ERROR_LOG(VIDEO, "Wrong key size in pixel shader cache");
|
||||
return;
|
||||
}
|
||||
memcpy(&uid, key, key_size);
|
||||
PixelShaderCache::InsertByteCode(uid, (void*)value, value_size);
|
||||
}
|
||||
};
|
||||
|
||||
PixelShaderCache::PixelShaderCache()
|
||||
{
|
||||
// used when drawing clear quads
|
||||
s_ClearProgram = D3D::CompileAndCreatePixelShader(clear_program_code, sizeof(clear_program_code));
|
||||
CHECK(s_ClearProgram!=NULL, "Create clear pixel shader");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "clear pixel shader");
|
||||
|
||||
// used when copying/resolving the color buffer
|
||||
s_ColorCopyProgram = D3D::CompileAndCreatePixelShader(color_copy_program_code, sizeof(color_copy_program_code));
|
||||
CHECK(s_ColorCopyProgram!=NULL, "Create color copy pixel shader");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "color copy pixel shader");
|
||||
|
||||
// used for color conversion
|
||||
s_ColorMatrixProgram = D3D::CompileAndCreatePixelShader(color_matrix_program_code, sizeof(color_matrix_program_code));
|
||||
CHECK(s_ColorMatrixProgram!=NULL, "Create color matrix pixel shader");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "color matrix pixel shader");
|
||||
|
||||
// used for depth copy
|
||||
s_DepthMatrixProgram = D3D::CompileAndCreatePixelShader(depth_matrix_program, sizeof(depth_matrix_program));
|
||||
CHECK(s_DepthMatrixProgram!=NULL, "Create depth matrix pixel shader");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "depth matrix pixel shader");
|
||||
|
||||
Clear();
|
||||
|
||||
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
|
||||
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
|
||||
|
||||
char cache_filename[MAX_PATH];
|
||||
sprintf(cache_filename, "%sdx11-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
|
||||
PixelShaderCacheInserter inserter;
|
||||
g_ps_disk_cache.OpenAndRead(cache_filename, &inserter);
|
||||
}
|
||||
|
||||
// ONLY to be used during shutdown.
|
||||
void PixelShaderCache::Clear()
|
||||
{
|
||||
for (PSCache::iterator iter = PixelShaders.begin(); iter != PixelShaders.end(); iter++)
|
||||
iter->second.Destroy();
|
||||
PixelShaders.clear();
|
||||
}
|
||||
|
||||
PixelShaderCache::~PixelShaderCache()
|
||||
{
|
||||
SAFE_RELEASE(s_ColorMatrixProgram);
|
||||
SAFE_RELEASE(s_ColorCopyProgram);
|
||||
SAFE_RELEASE(s_DepthMatrixProgram);
|
||||
SAFE_RELEASE(s_ClearProgram);
|
||||
|
||||
Clear();
|
||||
g_ps_disk_cache.Sync();
|
||||
g_ps_disk_cache.Close();
|
||||
}
|
||||
|
||||
bool PixelShaderCache::SetShader(bool dstAlpha)
|
||||
{
|
||||
PIXELSHADERUID uid;
|
||||
GetPixelShaderId(&uid, dstAlpha);
|
||||
|
||||
// check if the shader is already set
|
||||
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
|
||||
{
|
||||
PSCache::const_iterator iter = PixelShaders.find(uid);
|
||||
return (iter != PixelShaders.end() && iter->second.shader);
|
||||
}
|
||||
|
||||
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
|
||||
|
||||
// check if the shader is already in the cache
|
||||
PSCache::iterator iter = PixelShaders.find(uid);
|
||||
if (iter != PixelShaders.end())
|
||||
{
|
||||
iter->second.frameCount = frameCount;
|
||||
const PSCacheEntry &entry = iter->second;
|
||||
last_entry = &entry;
|
||||
|
||||
D3D::gfxstate->SetPShader(entry.shader);
|
||||
return (entry.shader != NULL);
|
||||
}
|
||||
|
||||
// need to compile a new shader
|
||||
const char* code = GeneratePixelShaderCode(dstAlpha, API_D3D11);
|
||||
|
||||
D3DBlob* pbytecode;
|
||||
if (!D3D::CompilePixelShader(code, (unsigned int)strlen(code), &pbytecode))
|
||||
{
|
||||
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
|
||||
return false;
|
||||
}
|
||||
|
||||
// insert the bytecode into the caches
|
||||
g_ps_disk_cache.Append((u8*)&uid, sizeof(uid), (const u8*)pbytecode->Data(), pbytecode->Size());
|
||||
g_ps_disk_cache.Sync();
|
||||
|
||||
bool result = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size());
|
||||
D3D::gfxstate->SetPShader(last_entry->shader);
|
||||
pbytecode->Release();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, void* bytecode, unsigned int bytecodelen)
|
||||
{
|
||||
ID3D11PixelShader* shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
|
||||
if (shader == NULL)
|
||||
{
|
||||
PanicAlert("Failed to create pixel shader at %s %d\n", __FILE__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
// TODO: Somehow make the debug name a bit more specific
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a pixel shader of PixelShaderCache");
|
||||
|
||||
// make an entry in the table
|
||||
PSCacheEntry newentry;
|
||||
newentry.shader = shader;
|
||||
newentry.frameCount = frameCount;
|
||||
PixelShaders[uid] = newentry;
|
||||
last_entry = &PixelShaders[uid];
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, PixelShaders.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
#include "LinearDiskCache.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "BPMemory.h"
|
||||
#include "XFMemory.h"
|
||||
#include "ImageWrite.h"
|
||||
#include "PixelShaderGen.h"
|
||||
#include "PixelShaderManager.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DShader.h"
|
||||
#include "DX11_PixelShaderCache.h"
|
||||
|
||||
#include <D3Dcompiler.h>
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
|
||||
const PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry;
|
||||
|
||||
LinearDiskCache g_ps_disk_cache;
|
||||
|
||||
ID3D11PixelShader* s_ColorMatrixProgram = NULL;
|
||||
ID3D11PixelShader* s_ColorCopyProgram = NULL;
|
||||
ID3D11PixelShader* s_DepthMatrixProgram = NULL;
|
||||
ID3D11PixelShader* s_ClearProgram = NULL;
|
||||
|
||||
const char clear_program_code[] = {
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : SV_Target,\n"
|
||||
"in float4 pos : SV_Position,\n"
|
||||
"in float4 incol0 : COLOR0){\n"
|
||||
"ocol0 = incol0;\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
const char color_copy_program_code[] = {
|
||||
"sampler samp0 : register(s0);\n"
|
||||
"Texture2D Tex0 : register(t0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : SV_Target,\n"
|
||||
"in float4 pos : SV_Position,\n"
|
||||
"in float2 uv0 : TEXCOORD0){\n"
|
||||
"ocol0 = Tex0.Sample(samp0,uv0);\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
const char color_matrix_program_code[] = {
|
||||
"sampler samp0 : register(s0);\n"
|
||||
"Texture2D Tex0 : register(t0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : SV_Target,\n"
|
||||
"in float4 pos : SV_Position,\n"
|
||||
" in float2 uv0 : TEXCOORD0){\n"
|
||||
"float4 texcol = Tex0.Sample(samp0,uv0);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
const char depth_matrix_program[] = {
|
||||
"sampler samp0 : register(s0);\n"
|
||||
"Texture2D Tex0 : register(t0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : SV_Target,\n"
|
||||
" in float4 pos : SV_Position,\n"
|
||||
" in float2 uv0 : TEXCOORD0){\n"
|
||||
"float4 texcol = Tex0.Sample(samp0,uv0);\n"
|
||||
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
|
||||
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::GetColorMatrixProgram()
|
||||
{
|
||||
return s_ColorMatrixProgram;
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::GetDepthMatrixProgram()
|
||||
{
|
||||
return s_DepthMatrixProgram;
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::GetColorCopyProgram()
|
||||
{
|
||||
return s_ColorCopyProgram;
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::GetClearProgram()
|
||||
{
|
||||
return s_ClearProgram;
|
||||
}
|
||||
|
||||
// HACK to avoid some invasive VideoCommon changes
|
||||
// these values are hardcoded, they depend on internal D3DCompile behavior; TODO: Solve this with D3DReflect or something
|
||||
// offset given in floats, table index is float4
|
||||
unsigned int ps_constant_offset_table[] = {
|
||||
0, 4, 8, 12, // C_COLORS, 16
|
||||
16, 20, 24, 28, // C_KCOLORS, 16
|
||||
32, // C_ALPHA, 4
|
||||
36, 40, 44, 48, 52, 56, 60, 64, // C_TEXDIMS, 32
|
||||
68, 72, // C_ZBIAS, 8
|
||||
76, 80, // C_INDTEXSCALE, 8
|
||||
84, 88, 92, 96, 100, 104, // C_INDTEXMTX, 24
|
||||
108, 112, // C_FOG, 8
|
||||
116, 120, 124 ,128, // C_COLORMATRIX, 16
|
||||
132, 136, 140, 144, 148, // C_PLIGHTS0, 20
|
||||
152, 156, 160, 164, 168, // C_PLIGHTS1, 20
|
||||
172, 176, 180, 184, 188, // C_PLIGHTS2, 20
|
||||
192, 196, 200, 204, 208, // C_PLIGHTS3, 20
|
||||
212, 216, 220, 224, 228, // C_PLIGHTS4, 20
|
||||
232, 236, 240, 244, 248, // C_PLIGHTS5, 20
|
||||
252, 256, 260, 264, 268, // C_PLIGHTS6, 20
|
||||
272, 276, 280, 284, 288, // C_PLIGHTS7, 20
|
||||
292, 296, 300, 304, // C_PMATERIALS, 16
|
||||
};
|
||||
void PixelShaderCache::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number] ] = f1;
|
||||
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+1] = f2;
|
||||
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+2] = f3;
|
||||
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+3] = f4;
|
||||
D3D::gfxstate->pscbufchanged = true;
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float* f)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4);
|
||||
D3D::gfxstate->pscbufchanged = true;
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float* f)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4*count);
|
||||
D3D::gfxstate->pscbufchanged = true;
|
||||
}
|
||||
|
||||
// this class will load the precompiled shaders into our cache
|
||||
class PixelShaderCacheInserter : public LinearDiskCacheReader
|
||||
{
|
||||
public:
|
||||
void Read(const u8* key, int key_size, const u8* value, int value_size)
|
||||
{
|
||||
PIXELSHADERUID uid;
|
||||
if (key_size != sizeof(uid)) {
|
||||
ERROR_LOG(VIDEO, "Wrong key size in pixel shader cache");
|
||||
return;
|
||||
}
|
||||
memcpy(&uid, key, key_size);
|
||||
PixelShaderCache::InsertByteCode(uid, (void*)value, value_size);
|
||||
}
|
||||
};
|
||||
|
||||
PixelShaderCache::PixelShaderCache()
|
||||
{
|
||||
// used when drawing clear quads
|
||||
s_ClearProgram = D3D::CompileAndCreatePixelShader(clear_program_code, sizeof(clear_program_code));
|
||||
CHECK(s_ClearProgram!=NULL, "Create clear pixel shader");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "clear pixel shader");
|
||||
|
||||
// used when copying/resolving the color buffer
|
||||
s_ColorCopyProgram = D3D::CompileAndCreatePixelShader(color_copy_program_code, sizeof(color_copy_program_code));
|
||||
CHECK(s_ColorCopyProgram!=NULL, "Create color copy pixel shader");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "color copy pixel shader");
|
||||
|
||||
// used for color conversion
|
||||
s_ColorMatrixProgram = D3D::CompileAndCreatePixelShader(color_matrix_program_code, sizeof(color_matrix_program_code));
|
||||
CHECK(s_ColorMatrixProgram!=NULL, "Create color matrix pixel shader");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "color matrix pixel shader");
|
||||
|
||||
// used for depth copy
|
||||
s_DepthMatrixProgram = D3D::CompileAndCreatePixelShader(depth_matrix_program, sizeof(depth_matrix_program));
|
||||
CHECK(s_DepthMatrixProgram!=NULL, "Create depth matrix pixel shader");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "depth matrix pixel shader");
|
||||
|
||||
Clear();
|
||||
|
||||
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
|
||||
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
|
||||
|
||||
char cache_filename[MAX_PATH];
|
||||
sprintf(cache_filename, "%sdx11-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
|
||||
PixelShaderCacheInserter inserter;
|
||||
g_ps_disk_cache.OpenAndRead(cache_filename, &inserter);
|
||||
}
|
||||
|
||||
// ONLY to be used during shutdown.
|
||||
void PixelShaderCache::Clear()
|
||||
{
|
||||
for (PSCache::iterator iter = PixelShaders.begin(); iter != PixelShaders.end(); iter++)
|
||||
iter->second.Destroy();
|
||||
PixelShaders.clear();
|
||||
}
|
||||
|
||||
PixelShaderCache::~PixelShaderCache()
|
||||
{
|
||||
SAFE_RELEASE(s_ColorMatrixProgram);
|
||||
SAFE_RELEASE(s_ColorCopyProgram);
|
||||
SAFE_RELEASE(s_DepthMatrixProgram);
|
||||
SAFE_RELEASE(s_ClearProgram);
|
||||
|
||||
Clear();
|
||||
g_ps_disk_cache.Sync();
|
||||
g_ps_disk_cache.Close();
|
||||
}
|
||||
|
||||
bool PixelShaderCache::SetShader(bool dstAlpha)
|
||||
{
|
||||
PIXELSHADERUID uid;
|
||||
GetPixelShaderId(&uid, dstAlpha);
|
||||
|
||||
// check if the shader is already set
|
||||
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
|
||||
{
|
||||
PSCache::const_iterator iter = PixelShaders.find(uid);
|
||||
return (iter != PixelShaders.end() && iter->second.shader);
|
||||
}
|
||||
|
||||
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
|
||||
|
||||
// check if the shader is already in the cache
|
||||
PSCache::iterator iter = PixelShaders.find(uid);
|
||||
if (iter != PixelShaders.end())
|
||||
{
|
||||
iter->second.frameCount = frameCount;
|
||||
const PSCacheEntry &entry = iter->second;
|
||||
last_entry = &entry;
|
||||
|
||||
D3D::gfxstate->SetPShader(entry.shader);
|
||||
return (entry.shader != NULL);
|
||||
}
|
||||
|
||||
// need to compile a new shader
|
||||
const char* code = GeneratePixelShaderCode(dstAlpha, API_D3D11);
|
||||
|
||||
D3DBlob* pbytecode;
|
||||
if (!D3D::CompilePixelShader(code, (unsigned int)strlen(code), &pbytecode))
|
||||
{
|
||||
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
|
||||
return false;
|
||||
}
|
||||
|
||||
// insert the bytecode into the caches
|
||||
g_ps_disk_cache.Append((u8*)&uid, sizeof(uid), (const u8*)pbytecode->Data(), pbytecode->Size());
|
||||
g_ps_disk_cache.Sync();
|
||||
|
||||
bool result = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size());
|
||||
D3D::gfxstate->SetPShader(last_entry->shader);
|
||||
pbytecode->Release();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, void* bytecode, unsigned int bytecodelen)
|
||||
{
|
||||
ID3D11PixelShader* shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
|
||||
if (shader == NULL)
|
||||
{
|
||||
PanicAlert("Failed to create pixel shader at %s %d\n", __FILE__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
// TODO: Somehow make the debug name a bit more specific
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a pixel shader of PixelShaderCache");
|
||||
|
||||
// make an entry in the table
|
||||
PSCacheEntry newentry;
|
||||
newentry.shader = shader;
|
||||
newentry.frameCount = frameCount;
|
||||
PixelShaders[uid] = newentry;
|
||||
last_entry = &PixelShaders[uid];
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, PixelShaders.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,74 +1,74 @@
|
|||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
#include "LinearDiskCache.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "PixelShaderGen.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
|
||||
#include "../PixelShaderCache.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
class PixelShaderCache : public ::PixelShaderCacheBase
|
||||
{
|
||||
public:
|
||||
PixelShaderCache();
|
||||
~PixelShaderCache();
|
||||
|
||||
void Clear();
|
||||
|
||||
bool SetShader(bool dstAlpha);
|
||||
static bool InsertByteCode(const PIXELSHADERUID &uid, void* bytecode, unsigned int bytecodelen);
|
||||
|
||||
static ID3D11PixelShader* GetColorMatrixProgram();
|
||||
static ID3D11PixelShader* GetColorCopyProgram();
|
||||
static ID3D11PixelShader* GetDepthMatrixProgram();
|
||||
static ID3D11PixelShader* GetClearProgram();
|
||||
|
||||
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetPSConstant4fv(unsigned int const_number, const float *f);
|
||||
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
|
||||
|
||||
private:
|
||||
struct PSCacheEntry
|
||||
{
|
||||
ID3D11PixelShader* shader;
|
||||
int frameCount;
|
||||
|
||||
PSCacheEntry() : shader(NULL), frameCount(0) {}
|
||||
void Destroy() { SAFE_RELEASE(shader); }
|
||||
};
|
||||
|
||||
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
|
||||
|
||||
static PSCache PixelShaders;
|
||||
static const PSCacheEntry* last_entry;
|
||||
};
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
#include "LinearDiskCache.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "PixelShaderGen.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
|
||||
#include "../PixelShaderCache.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
class PixelShaderCache : public ::PixelShaderCacheBase
|
||||
{
|
||||
public:
|
||||
PixelShaderCache();
|
||||
~PixelShaderCache();
|
||||
|
||||
void Clear();
|
||||
|
||||
bool SetShader(bool dstAlpha);
|
||||
static bool InsertByteCode(const PIXELSHADERUID &uid, void* bytecode, unsigned int bytecodelen);
|
||||
|
||||
static ID3D11PixelShader* GetColorMatrixProgram();
|
||||
static ID3D11PixelShader* GetColorCopyProgram();
|
||||
static ID3D11PixelShader* GetDepthMatrixProgram();
|
||||
static ID3D11PixelShader* GetClearProgram();
|
||||
|
||||
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetPSConstant4fv(unsigned int const_number, const float *f);
|
||||
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
|
||||
|
||||
private:
|
||||
struct PSCacheEntry
|
||||
{
|
||||
ID3D11PixelShader* shader;
|
||||
int frameCount;
|
||||
|
||||
PSCacheEntry() : shader(NULL), frameCount(0) {}
|
||||
void Destroy() { SAFE_RELEASE(shader); }
|
||||
};
|
||||
|
||||
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
|
||||
|
||||
static PSCache PixelShaders;
|
||||
static const PSCacheEntry* last_entry;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,52 +1,52 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "MathUtil.h"
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "Renderer.h"
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
class Renderer : public ::RendererBase
|
||||
{
|
||||
public:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
||||
// What's the real difference between these? Too similar names.
|
||||
void ResetAPIState();
|
||||
void RestoreAPIState();
|
||||
|
||||
static void SetupDeviceObjects();
|
||||
static void TeardownDeviceObjects();
|
||||
|
||||
void SetColorMask();
|
||||
void SetBlendMode(bool forceUpdate);
|
||||
bool SetScissorRect();
|
||||
|
||||
void SetGenerationMode();
|
||||
void SetDepthMode();
|
||||
void SetLogicOpMode();
|
||||
void SetSamplerState(int stage,int texindex);
|
||||
|
||||
u32 AccessEFB(EFBAccessType type, int x, int y);
|
||||
|
||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
|
||||
void UpdateViewport();
|
||||
|
||||
// virtual funcs used by RendererBase::Swap
|
||||
void PrepareXFBCopy(const TargetRectangle &dst_rect);
|
||||
void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
|
||||
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc);
|
||||
void EndFrame();
|
||||
void Present();
|
||||
bool CheckForResize();
|
||||
void GetBackBufferSize(int* w, int* h);
|
||||
void RecreateFramebufferManger();
|
||||
void BeginFrame();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MathUtil.h"
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "Renderer.h"
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
class Renderer : public ::RendererBase
|
||||
{
|
||||
public:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
||||
// What's the real difference between these? Too similar names.
|
||||
void ResetAPIState();
|
||||
void RestoreAPIState();
|
||||
|
||||
static void SetupDeviceObjects();
|
||||
static void TeardownDeviceObjects();
|
||||
|
||||
void SetColorMask();
|
||||
void SetBlendMode(bool forceUpdate);
|
||||
bool SetScissorRect();
|
||||
|
||||
void SetGenerationMode();
|
||||
void SetDepthMode();
|
||||
void SetLogicOpMode();
|
||||
void SetSamplerState(int stage,int texindex);
|
||||
|
||||
u32 AccessEFB(EFBAccessType type, int x, int y);
|
||||
|
||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
|
||||
void UpdateViewport();
|
||||
|
||||
// virtual funcs used by RendererBase::Swap
|
||||
void PrepareXFBCopy(const TargetRectangle &dst_rect);
|
||||
void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
|
||||
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc);
|
||||
void EndFrame();
|
||||
void Present();
|
||||
bool CheckForResize();
|
||||
void GetBackBufferSize(int* w, int* h);
|
||||
void RecreateFramebufferManger();
|
||||
void BeginFrame();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,230 +1,230 @@
|
|||
// 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 <d3dx11.h>
|
||||
|
||||
// Common
|
||||
#include "CommonPaths.h"
|
||||
#include "FileUtil.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "Hash.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
#include "Statistics.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "TextureDecoder.h"
|
||||
#include "HiresTextures.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DTexture.h"
|
||||
#include "DX11_D3DUtil.h"
|
||||
#include "DX11_FramebufferManager.h"
|
||||
#include "DX11_PixelShaderCache.h"
|
||||
#include "DX11_VertexShaderCache.h"
|
||||
#include "DX11_TextureCache.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
ID3D11BlendState* efbcopyblendstate = NULL;
|
||||
ID3D11RasterizerState* efbcopyraststate = NULL;
|
||||
ID3D11DepthStencilState* efbcopydepthstate = NULL;
|
||||
ID3D11Buffer* efbcopycbuf[20] = {};
|
||||
|
||||
TextureCache::TCacheEntry::~TCacheEntry()
|
||||
{
|
||||
SAFE_RELEASE(texture);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, expanded_width, level, usage);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect)
|
||||
{
|
||||
// stretch picture with increased internal resolution
|
||||
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)Scaledw, (float)Scaledh);
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
|
||||
// set transformation
|
||||
if (NULL == efbcopycbuf[cbufid])
|
||||
{
|
||||
const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(20 * sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT);
|
||||
D3D11_SUBRESOURCE_DATA data;
|
||||
data.pSysMem = colmat;
|
||||
HRESULT hr = D3D::device->CreateBuffer(&cbdesc, &data, &efbcopycbuf[cbufid]);
|
||||
CHECK(SUCCEEDED(hr), "Create efb copy constant buffer %d", cbufid);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopycbuf[cbufid], "a constant buffer used in TextureCache::CopyRenderTargetToTexture");
|
||||
}
|
||||
D3D::context->PSSetConstantBuffers(0, 1, &efbcopycbuf[cbufid]);
|
||||
|
||||
const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(source_rect);
|
||||
// TODO: try targetSource.asRECT();
|
||||
const D3D11_RECT sourcerect = CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom);
|
||||
|
||||
// Use linear filtering if (bScaleByHalf), use point filtering otherwise
|
||||
if (bScaleByHalf)
|
||||
D3D::SetLinearCopySampler();
|
||||
else
|
||||
D3D::SetPointCopySampler();
|
||||
|
||||
D3D::stateman->PushBlendState(efbcopyblendstate);
|
||||
D3D::stateman->PushRasterizerState(efbcopyraststate);
|
||||
D3D::stateman->PushDepthState(efbcopydepthstate);
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), NULL);
|
||||
|
||||
D3D::drawShadedTexQuad(
|
||||
(bFromZBuffer) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(),
|
||||
&sourcerect, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight(),
|
||||
(bFromZBuffer) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram(),
|
||||
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||
|
||||
D3D::stateman->PopBlendState();
|
||||
D3D::stateman->PopDepthState();
|
||||
D3D::stateman->PopRasterizerState();
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Bind(unsigned int stage)
|
||||
{
|
||||
D3D::gfxstate->SetShaderResource(stage, texture->GetSRV());
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
||||
unsigned int height, unsigned int expanded_width,
|
||||
unsigned int tex_levels, PC_TexFormat pcfmt)
|
||||
{
|
||||
D3D11_SUBRESOURCE_DATA srdata;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA *data = NULL;
|
||||
D3D11_CPU_ACCESS_FLAG cpu_access = (D3D11_CPU_ACCESS_FLAG)0;
|
||||
D3D11_USAGE usage = D3D11_USAGE_DEFAULT;
|
||||
|
||||
// TODO: temp
|
||||
tex_levels = 1;
|
||||
|
||||
if (1 == tex_levels)
|
||||
{
|
||||
cpu_access = D3D11_CPU_ACCESS_WRITE;
|
||||
usage = D3D11_USAGE_DYNAMIC;
|
||||
|
||||
srdata.pSysMem = temp;
|
||||
srdata.SysMemPitch = 4 * expanded_width;
|
||||
data = &srdata;
|
||||
}
|
||||
|
||||
const D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
width, height, 1, tex_levels, D3D11_BIND_SHADER_RESOURCE, usage, cpu_access);
|
||||
|
||||
ID3D11Texture2D *pTexture;
|
||||
HRESULT hr = D3D::device->CreateTexture2D(&texdesc, data, &pTexture);
|
||||
CHECK(SUCCEEDED(hr), "Create texture of the TextureCache");
|
||||
|
||||
TCacheEntry* const entry = new TCacheEntry(new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE));
|
||||
entry->usage = usage;
|
||||
|
||||
// TODO: silly debug names
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry->texture->GetTex(), "a texture of the TextureCache");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry->texture->GetSRV(), "shader resource view of a texture of the TextureCache");
|
||||
|
||||
// wuts this?
|
||||
//if (0 == tex_levels)
|
||||
// PD3DX11FilterTexture(D3D::context, entry->texture->GetTex(), 0, D3DX11_DEFAULT);
|
||||
|
||||
// TODO: this good?
|
||||
//if (1 != tex_levels)
|
||||
// entry->Load(width, height, expanded_width, 0);
|
||||
|
||||
SAFE_RELEASE(pTexture);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h)
|
||||
{
|
||||
return new TCacheEntry(D3DTexture2D::Create(scaled_tex_w, scaled_tex_h,
|
||||
(D3D11_BIND_FLAG)((int)D3D11_BIND_RENDER_TARGET | (int)D3D11_BIND_SHADER_RESOURCE),
|
||||
D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM));
|
||||
}
|
||||
|
||||
TextureCache::TextureCache()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D3D11_BLEND_DESC blenddesc;
|
||||
blenddesc.AlphaToCoverageEnable = FALSE;
|
||||
blenddesc.IndependentBlendEnable = FALSE;
|
||||
blenddesc.RenderTarget[0].BlendEnable = FALSE;
|
||||
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
blenddesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
|
||||
blenddesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
|
||||
blenddesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||
blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
||||
blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
hr = D3D::device->CreateBlendState(&blenddesc, &efbcopyblendstate);
|
||||
CHECK(hr==S_OK, "Create blend state for CopyRenderTargetToTexture");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopyblendstate, "blend state used in CopyRenderTargetToTexture");
|
||||
|
||||
D3D11_DEPTH_STENCIL_DESC depthdesc;
|
||||
depthdesc.DepthEnable = FALSE;
|
||||
depthdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
||||
depthdesc.DepthFunc = D3D11_COMPARISON_LESS;
|
||||
depthdesc.StencilEnable = FALSE;
|
||||
depthdesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
|
||||
depthdesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
|
||||
hr = D3D::device->CreateDepthStencilState(&depthdesc, &efbcopydepthstate);
|
||||
CHECK(hr==S_OK, "Create depth state for CopyRenderTargetToTexture");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopydepthstate, "depth stencil state used in CopyRenderTargetToTexture");
|
||||
|
||||
D3D11_RASTERIZER_DESC rastdesc;
|
||||
rastdesc.CullMode = D3D11_CULL_NONE;
|
||||
rastdesc.FillMode = D3D11_FILL_SOLID;
|
||||
rastdesc.FrontCounterClockwise = false;
|
||||
rastdesc.DepthBias = false;
|
||||
rastdesc.DepthBiasClamp = 0;
|
||||
rastdesc.SlopeScaledDepthBias = 0;
|
||||
rastdesc.DepthClipEnable = false;
|
||||
rastdesc.ScissorEnable = false;
|
||||
rastdesc.MultisampleEnable = false;
|
||||
rastdesc.AntialiasedLineEnable = false;
|
||||
hr = D3D::device->CreateRasterizerState(&rastdesc, &efbcopyraststate);
|
||||
CHECK(hr==S_OK, "Create rasterizer state for CopyRenderTargetToTexture");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopyraststate, "rasterizer state used in CopyRenderTargetToTexture");
|
||||
}
|
||||
|
||||
TextureCache::~TextureCache()
|
||||
{
|
||||
SAFE_RELEASE(efbcopyblendstate);
|
||||
SAFE_RELEASE(efbcopyraststate);
|
||||
SAFE_RELEASE(efbcopydepthstate);
|
||||
|
||||
for (unsigned int k = 0; k < 20; ++k)
|
||||
SAFE_RELEASE(efbcopycbuf[k]);
|
||||
}
|
||||
|
||||
}
|
||||
// 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 <d3dx11.h>
|
||||
|
||||
// Common
|
||||
#include "CommonPaths.h"
|
||||
#include "FileUtil.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "Hash.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
#include "Statistics.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "TextureDecoder.h"
|
||||
#include "HiresTextures.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DTexture.h"
|
||||
#include "DX11_D3DUtil.h"
|
||||
#include "DX11_FramebufferManager.h"
|
||||
#include "DX11_PixelShaderCache.h"
|
||||
#include "DX11_VertexShaderCache.h"
|
||||
#include "DX11_TextureCache.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
ID3D11BlendState* efbcopyblendstate = NULL;
|
||||
ID3D11RasterizerState* efbcopyraststate = NULL;
|
||||
ID3D11DepthStencilState* efbcopydepthstate = NULL;
|
||||
ID3D11Buffer* efbcopycbuf[20] = {};
|
||||
|
||||
TextureCache::TCacheEntry::~TCacheEntry()
|
||||
{
|
||||
SAFE_RELEASE(texture);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, expanded_width, level, usage);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect)
|
||||
{
|
||||
// stretch picture with increased internal resolution
|
||||
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)Scaledw, (float)Scaledh);
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
|
||||
// set transformation
|
||||
if (NULL == efbcopycbuf[cbufid])
|
||||
{
|
||||
const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(20 * sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT);
|
||||
D3D11_SUBRESOURCE_DATA data;
|
||||
data.pSysMem = colmat;
|
||||
HRESULT hr = D3D::device->CreateBuffer(&cbdesc, &data, &efbcopycbuf[cbufid]);
|
||||
CHECK(SUCCEEDED(hr), "Create efb copy constant buffer %d", cbufid);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopycbuf[cbufid], "a constant buffer used in TextureCache::CopyRenderTargetToTexture");
|
||||
}
|
||||
D3D::context->PSSetConstantBuffers(0, 1, &efbcopycbuf[cbufid]);
|
||||
|
||||
const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(source_rect);
|
||||
// TODO: try targetSource.asRECT();
|
||||
const D3D11_RECT sourcerect = CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom);
|
||||
|
||||
// Use linear filtering if (bScaleByHalf), use point filtering otherwise
|
||||
if (bScaleByHalf)
|
||||
D3D::SetLinearCopySampler();
|
||||
else
|
||||
D3D::SetPointCopySampler();
|
||||
|
||||
D3D::stateman->PushBlendState(efbcopyblendstate);
|
||||
D3D::stateman->PushRasterizerState(efbcopyraststate);
|
||||
D3D::stateman->PushDepthState(efbcopydepthstate);
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), NULL);
|
||||
|
||||
D3D::drawShadedTexQuad(
|
||||
(bFromZBuffer) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(),
|
||||
&sourcerect, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight(),
|
||||
(bFromZBuffer) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram(),
|
||||
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||
|
||||
D3D::stateman->PopBlendState();
|
||||
D3D::stateman->PopDepthState();
|
||||
D3D::stateman->PopRasterizerState();
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Bind(unsigned int stage)
|
||||
{
|
||||
D3D::gfxstate->SetShaderResource(stage, texture->GetSRV());
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
||||
unsigned int height, unsigned int expanded_width,
|
||||
unsigned int tex_levels, PC_TexFormat pcfmt)
|
||||
{
|
||||
D3D11_SUBRESOURCE_DATA srdata;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA *data = NULL;
|
||||
D3D11_CPU_ACCESS_FLAG cpu_access = (D3D11_CPU_ACCESS_FLAG)0;
|
||||
D3D11_USAGE usage = D3D11_USAGE_DEFAULT;
|
||||
|
||||
// TODO: temp
|
||||
tex_levels = 1;
|
||||
|
||||
if (1 == tex_levels)
|
||||
{
|
||||
cpu_access = D3D11_CPU_ACCESS_WRITE;
|
||||
usage = D3D11_USAGE_DYNAMIC;
|
||||
|
||||
srdata.pSysMem = temp;
|
||||
srdata.SysMemPitch = 4 * expanded_width;
|
||||
data = &srdata;
|
||||
}
|
||||
|
||||
const D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
width, height, 1, tex_levels, D3D11_BIND_SHADER_RESOURCE, usage, cpu_access);
|
||||
|
||||
ID3D11Texture2D *pTexture;
|
||||
HRESULT hr = D3D::device->CreateTexture2D(&texdesc, data, &pTexture);
|
||||
CHECK(SUCCEEDED(hr), "Create texture of the TextureCache");
|
||||
|
||||
TCacheEntry* const entry = new TCacheEntry(new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE));
|
||||
entry->usage = usage;
|
||||
|
||||
// TODO: silly debug names
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry->texture->GetTex(), "a texture of the TextureCache");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry->texture->GetSRV(), "shader resource view of a texture of the TextureCache");
|
||||
|
||||
// wuts this?
|
||||
//if (0 == tex_levels)
|
||||
// PD3DX11FilterTexture(D3D::context, entry->texture->GetTex(), 0, D3DX11_DEFAULT);
|
||||
|
||||
// TODO: this good?
|
||||
//if (1 != tex_levels)
|
||||
// entry->Load(width, height, expanded_width, 0);
|
||||
|
||||
SAFE_RELEASE(pTexture);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h)
|
||||
{
|
||||
return new TCacheEntry(D3DTexture2D::Create(scaled_tex_w, scaled_tex_h,
|
||||
(D3D11_BIND_FLAG)((int)D3D11_BIND_RENDER_TARGET | (int)D3D11_BIND_SHADER_RESOURCE),
|
||||
D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM));
|
||||
}
|
||||
|
||||
TextureCache::TextureCache()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D3D11_BLEND_DESC blenddesc;
|
||||
blenddesc.AlphaToCoverageEnable = FALSE;
|
||||
blenddesc.IndependentBlendEnable = FALSE;
|
||||
blenddesc.RenderTarget[0].BlendEnable = FALSE;
|
||||
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
blenddesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
|
||||
blenddesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
|
||||
blenddesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||
blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
||||
blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
hr = D3D::device->CreateBlendState(&blenddesc, &efbcopyblendstate);
|
||||
CHECK(hr==S_OK, "Create blend state for CopyRenderTargetToTexture");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopyblendstate, "blend state used in CopyRenderTargetToTexture");
|
||||
|
||||
D3D11_DEPTH_STENCIL_DESC depthdesc;
|
||||
depthdesc.DepthEnable = FALSE;
|
||||
depthdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
||||
depthdesc.DepthFunc = D3D11_COMPARISON_LESS;
|
||||
depthdesc.StencilEnable = FALSE;
|
||||
depthdesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
|
||||
depthdesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
|
||||
hr = D3D::device->CreateDepthStencilState(&depthdesc, &efbcopydepthstate);
|
||||
CHECK(hr==S_OK, "Create depth state for CopyRenderTargetToTexture");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopydepthstate, "depth stencil state used in CopyRenderTargetToTexture");
|
||||
|
||||
D3D11_RASTERIZER_DESC rastdesc;
|
||||
rastdesc.CullMode = D3D11_CULL_NONE;
|
||||
rastdesc.FillMode = D3D11_FILL_SOLID;
|
||||
rastdesc.FrontCounterClockwise = false;
|
||||
rastdesc.DepthBias = false;
|
||||
rastdesc.DepthBiasClamp = 0;
|
||||
rastdesc.SlopeScaledDepthBias = 0;
|
||||
rastdesc.DepthClipEnable = false;
|
||||
rastdesc.ScissorEnable = false;
|
||||
rastdesc.MultisampleEnable = false;
|
||||
rastdesc.AntialiasedLineEnable = false;
|
||||
hr = D3D::device->CreateRasterizerState(&rastdesc, &efbcopyraststate);
|
||||
CHECK(hr==S_OK, "Create rasterizer state for CopyRenderTargetToTexture");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopyraststate, "rasterizer state used in CopyRenderTargetToTexture");
|
||||
}
|
||||
|
||||
TextureCache::~TextureCache()
|
||||
{
|
||||
SAFE_RELEASE(efbcopyblendstate);
|
||||
SAFE_RELEASE(efbcopyraststate);
|
||||
SAFE_RELEASE(efbcopydepthstate);
|
||||
|
||||
for (unsigned int k = 0; k < 20; ++k)
|
||||
SAFE_RELEASE(efbcopycbuf[k]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,66 +1,66 @@
|
|||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoCommon.h"
|
||||
#include "BPMemory.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DTexture.h"
|
||||
|
||||
#include "../TextureCache.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
class TextureCache : public ::TextureCacheBase
|
||||
{
|
||||
public:
|
||||
struct TCacheEntry : TCacheEntryBase
|
||||
{
|
||||
D3DTexture2D* texture;
|
||||
|
||||
D3D11_USAGE usage;
|
||||
|
||||
TCacheEntry(D3DTexture2D* _texture) : texture(_texture) {}
|
||||
~TCacheEntry();
|
||||
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level);
|
||||
|
||||
void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect);
|
||||
|
||||
void Bind(unsigned int stage);
|
||||
};
|
||||
|
||||
TextureCache();
|
||||
~TextureCache();
|
||||
|
||||
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt);
|
||||
|
||||
TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h);
|
||||
|
||||
void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, unsigned int bScaleByHalf, const EFBRectangle &source_rect);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoCommon.h"
|
||||
#include "BPMemory.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DTexture.h"
|
||||
|
||||
#include "../TextureCache.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
class TextureCache : public ::TextureCacheBase
|
||||
{
|
||||
public:
|
||||
struct TCacheEntry : TCacheEntryBase
|
||||
{
|
||||
D3DTexture2D* texture;
|
||||
|
||||
D3D11_USAGE usage;
|
||||
|
||||
TCacheEntry(D3DTexture2D* _texture) : texture(_texture) {}
|
||||
~TCacheEntry();
|
||||
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level);
|
||||
|
||||
void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect);
|
||||
|
||||
void Bind(unsigned int stage);
|
||||
};
|
||||
|
||||
TextureCache();
|
||||
~TextureCache();
|
||||
|
||||
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt);
|
||||
|
||||
TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h);
|
||||
|
||||
void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, unsigned int bScaleByHalf, const EFBRectangle &source_rect);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,194 +1,194 @@
|
|||
// 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 <string>
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "Fifo.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "NativeVertexWriter.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DShader.h"
|
||||
#include "DX11_D3DUtil.h"
|
||||
#include "DX11_VertexManager.h"
|
||||
#include "DX11_VertexShaderCache.h"
|
||||
#include "DX11_PixelShaderCache.h"
|
||||
#include "DX11_TextureCache.h"
|
||||
#include "DX11_FramebufferManager.h"
|
||||
#include "DX11_Render.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
//using std::string;
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
using namespace D3D;
|
||||
|
||||
ID3D11Buffer* indexbuffers[NUM_INDEXBUFFERS] = {};
|
||||
ID3D11Buffer* vertexbuffers[NUM_VERTEXBUFFERS] = {};
|
||||
|
||||
// TODO: these seem ugly
|
||||
inline ID3D11Buffer* GetSuitableIndexBuffer(const u32 minsize)
|
||||
{
|
||||
for (u32 k = 0; k < NUM_INDEXBUFFERS - 1; ++k)
|
||||
if (minsize > (((u32)MAXIBUFFERSIZE) >> k))
|
||||
return indexbuffers[k];
|
||||
return indexbuffers[NUM_INDEXBUFFERS - 1];
|
||||
}
|
||||
|
||||
inline ID3D11Buffer* GetSuitableVertexBuffer(const u32 minsize)
|
||||
{
|
||||
for (u32 k = 0; k < NUM_VERTEXBUFFERS - 1; ++k)
|
||||
if (minsize > (((u32)MAXVBUFFERSIZE) >> (k + 1)))
|
||||
return vertexbuffers[k];
|
||||
return vertexbuffers[NUM_VERTEXBUFFERS - 1];
|
||||
}
|
||||
|
||||
void CreateDeviceObjects()
|
||||
{
|
||||
D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(MAXIBUFFERSIZE * 2,
|
||||
D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
for (u32 k = 0; k < NUM_INDEXBUFFERS; ++k, bufdesc.ByteWidth >>= 1)
|
||||
{
|
||||
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, indexbuffers + k)),
|
||||
"Failed to create index buffer [%i].", k);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)indexbuffers[k], "an index buffer of VertexManager");
|
||||
}
|
||||
|
||||
bufdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bufdesc.ByteWidth = MAXVBUFFERSIZE;
|
||||
for (u32 k = 0; k < NUM_VERTEXBUFFERS; ++k, bufdesc.ByteWidth >>= 1)
|
||||
{
|
||||
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, vertexbuffers + k)),
|
||||
"Failed to create vertex buffer [%i].", k);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)vertexbuffers[k], "a vertex buffer of VertexManager");
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyDeviceObjects()
|
||||
{
|
||||
for (u32 k = 0; k < NUM_INDEXBUFFERS; ++k)
|
||||
SAFE_RELEASE(indexbuffers[k]);
|
||||
|
||||
for (u32 k = 0; k < NUM_VERTEXBUFFERS; ++k)
|
||||
SAFE_RELEASE(vertexbuffers[k]);
|
||||
}
|
||||
|
||||
VertexManager::VertexManager()
|
||||
{
|
||||
CreateDeviceObjects();
|
||||
}
|
||||
|
||||
VertexManager::~VertexManager()
|
||||
{
|
||||
DestroyDeviceObjects();
|
||||
ResetBuffer();
|
||||
}
|
||||
|
||||
void VertexManager::Draw(u32 stride, bool alphapass)
|
||||
{
|
||||
static const UINT bufoffset = 0;
|
||||
const UINT bufstride = stride;
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
ID3D11Buffer* const vertexbuffer = GetSuitableVertexBuffer((u32)(s_pCurBufferPointer - LocalVBuffer));
|
||||
|
||||
if (alphapass)
|
||||
{
|
||||
gfxstate->AlphaPass();
|
||||
}
|
||||
else
|
||||
{
|
||||
context->Map(vertexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, LocalVBuffer, (u32)(s_pCurBufferPointer - LocalVBuffer));
|
||||
context->Unmap(vertexbuffer, 0);
|
||||
|
||||
gfxstate->ApplyState();
|
||||
}
|
||||
|
||||
D3D::context->IASetVertexBuffers(0, 1, &vertexbuffer, &bufstride, &bufoffset);
|
||||
|
||||
if (IndexGenerator::GetNumTriangles() > 0)
|
||||
{
|
||||
u32 indexbuffersize = IndexGenerator::GetTriangleindexLen();
|
||||
ID3D11Buffer* indexbuffer = GetSuitableIndexBuffer(2*indexbuffersize);
|
||||
if (!alphapass)
|
||||
{
|
||||
D3D::context->Map(indexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, TIBuffer, 2*indexbuffersize);
|
||||
D3D::context->Unmap(indexbuffer, 0);
|
||||
}
|
||||
|
||||
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
D3D::context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R16_UINT, 0);
|
||||
|
||||
D3D::context->DrawIndexed(indexbuffersize, 0, 0);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumLines() > 0)
|
||||
{
|
||||
u32 indexbuffersize = IndexGenerator::GetLineindexLen();
|
||||
ID3D11Buffer* indexbuffer = GetSuitableIndexBuffer(2*indexbuffersize);
|
||||
if (!alphapass)
|
||||
{
|
||||
D3D::context->Map(indexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, LIBuffer, 2*indexbuffersize);
|
||||
D3D::context->Unmap(indexbuffer, 0);
|
||||
}
|
||||
|
||||
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
|
||||
D3D::context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R16_UINT, 0);
|
||||
|
||||
D3D::context->DrawIndexed(indexbuffersize, 0, 0);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumPoints() > 0)
|
||||
{
|
||||
u32 indexbuffersize = IndexGenerator::GetPointindexLen();
|
||||
ID3D11Buffer* indexbuffer = GetSuitableIndexBuffer(2*indexbuffersize);
|
||||
if (!alphapass)
|
||||
{
|
||||
D3D::context->Map(indexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, PIBuffer, 2*indexbuffersize);
|
||||
D3D::context->Unmap(indexbuffer, 0);
|
||||
}
|
||||
|
||||
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
|
||||
D3D::context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R16_UINT, 0);
|
||||
|
||||
D3D::context->DrawIndexed(indexbuffersize, 0, 0);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// 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 <string>
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "Fifo.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "NativeVertexWriter.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DShader.h"
|
||||
#include "DX11_D3DUtil.h"
|
||||
#include "DX11_VertexManager.h"
|
||||
#include "DX11_VertexShaderCache.h"
|
||||
#include "DX11_PixelShaderCache.h"
|
||||
#include "DX11_TextureCache.h"
|
||||
#include "DX11_FramebufferManager.h"
|
||||
#include "DX11_Render.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
//using std::string;
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
using namespace D3D;
|
||||
|
||||
ID3D11Buffer* indexbuffers[NUM_INDEXBUFFERS] = {};
|
||||
ID3D11Buffer* vertexbuffers[NUM_VERTEXBUFFERS] = {};
|
||||
|
||||
// TODO: these seem ugly
|
||||
inline ID3D11Buffer* GetSuitableIndexBuffer(const u32 minsize)
|
||||
{
|
||||
for (u32 k = 0; k < NUM_INDEXBUFFERS - 1; ++k)
|
||||
if (minsize > (((u32)MAXIBUFFERSIZE) >> k))
|
||||
return indexbuffers[k];
|
||||
return indexbuffers[NUM_INDEXBUFFERS - 1];
|
||||
}
|
||||
|
||||
inline ID3D11Buffer* GetSuitableVertexBuffer(const u32 minsize)
|
||||
{
|
||||
for (u32 k = 0; k < NUM_VERTEXBUFFERS - 1; ++k)
|
||||
if (minsize > (((u32)MAXVBUFFERSIZE) >> (k + 1)))
|
||||
return vertexbuffers[k];
|
||||
return vertexbuffers[NUM_VERTEXBUFFERS - 1];
|
||||
}
|
||||
|
||||
void CreateDeviceObjects()
|
||||
{
|
||||
D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(MAXIBUFFERSIZE * 2,
|
||||
D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
for (u32 k = 0; k < NUM_INDEXBUFFERS; ++k, bufdesc.ByteWidth >>= 1)
|
||||
{
|
||||
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, indexbuffers + k)),
|
||||
"Failed to create index buffer [%i].", k);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)indexbuffers[k], "an index buffer of VertexManager");
|
||||
}
|
||||
|
||||
bufdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bufdesc.ByteWidth = MAXVBUFFERSIZE;
|
||||
for (u32 k = 0; k < NUM_VERTEXBUFFERS; ++k, bufdesc.ByteWidth >>= 1)
|
||||
{
|
||||
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, vertexbuffers + k)),
|
||||
"Failed to create vertex buffer [%i].", k);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)vertexbuffers[k], "a vertex buffer of VertexManager");
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyDeviceObjects()
|
||||
{
|
||||
for (u32 k = 0; k < NUM_INDEXBUFFERS; ++k)
|
||||
SAFE_RELEASE(indexbuffers[k]);
|
||||
|
||||
for (u32 k = 0; k < NUM_VERTEXBUFFERS; ++k)
|
||||
SAFE_RELEASE(vertexbuffers[k]);
|
||||
}
|
||||
|
||||
VertexManager::VertexManager()
|
||||
{
|
||||
CreateDeviceObjects();
|
||||
}
|
||||
|
||||
VertexManager::~VertexManager()
|
||||
{
|
||||
DestroyDeviceObjects();
|
||||
ResetBuffer();
|
||||
}
|
||||
|
||||
void VertexManager::Draw(u32 stride, bool alphapass)
|
||||
{
|
||||
static const UINT bufoffset = 0;
|
||||
const UINT bufstride = stride;
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
ID3D11Buffer* const vertexbuffer = GetSuitableVertexBuffer((u32)(s_pCurBufferPointer - LocalVBuffer));
|
||||
|
||||
if (alphapass)
|
||||
{
|
||||
gfxstate->AlphaPass();
|
||||
}
|
||||
else
|
||||
{
|
||||
context->Map(vertexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, LocalVBuffer, (u32)(s_pCurBufferPointer - LocalVBuffer));
|
||||
context->Unmap(vertexbuffer, 0);
|
||||
|
||||
gfxstate->ApplyState();
|
||||
}
|
||||
|
||||
D3D::context->IASetVertexBuffers(0, 1, &vertexbuffer, &bufstride, &bufoffset);
|
||||
|
||||
if (IndexGenerator::GetNumTriangles() > 0)
|
||||
{
|
||||
u32 indexbuffersize = IndexGenerator::GetTriangleindexLen();
|
||||
ID3D11Buffer* indexbuffer = GetSuitableIndexBuffer(2*indexbuffersize);
|
||||
if (!alphapass)
|
||||
{
|
||||
D3D::context->Map(indexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, TIBuffer, 2*indexbuffersize);
|
||||
D3D::context->Unmap(indexbuffer, 0);
|
||||
}
|
||||
|
||||
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
D3D::context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R16_UINT, 0);
|
||||
|
||||
D3D::context->DrawIndexed(indexbuffersize, 0, 0);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumLines() > 0)
|
||||
{
|
||||
u32 indexbuffersize = IndexGenerator::GetLineindexLen();
|
||||
ID3D11Buffer* indexbuffer = GetSuitableIndexBuffer(2*indexbuffersize);
|
||||
if (!alphapass)
|
||||
{
|
||||
D3D::context->Map(indexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, LIBuffer, 2*indexbuffersize);
|
||||
D3D::context->Unmap(indexbuffer, 0);
|
||||
}
|
||||
|
||||
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
|
||||
D3D::context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R16_UINT, 0);
|
||||
|
||||
D3D::context->DrawIndexed(indexbuffersize, 0, 0);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumPoints() > 0)
|
||||
{
|
||||
u32 indexbuffersize = IndexGenerator::GetPointindexLen();
|
||||
ID3D11Buffer* indexbuffer = GetSuitableIndexBuffer(2*indexbuffersize);
|
||||
if (!alphapass)
|
||||
{
|
||||
D3D::context->Map(indexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, PIBuffer, 2*indexbuffersize);
|
||||
D3D::context->Unmap(indexbuffer, 0);
|
||||
}
|
||||
|
||||
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
|
||||
D3D::context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R16_UINT, 0);
|
||||
|
||||
D3D::context->DrawIndexed(indexbuffersize, 0, 0);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,49 +1,49 @@
|
|||
// 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 _DX11_VERTEXMANAGER_H
|
||||
#define _DX11_VERTEXMANAGER_H
|
||||
|
||||
#include "CPMemory.h"
|
||||
#include "VertexLoader.h"
|
||||
|
||||
#include "../VertexManager.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
// TODO: find sensible values for these two
|
||||
NUM_VERTEXBUFFERS = 8,
|
||||
NUM_INDEXBUFFERS = 10,
|
||||
};
|
||||
|
||||
class VertexManager : public ::VertexManagerBase
|
||||
{
|
||||
public:
|
||||
VertexManager();
|
||||
~VertexManager();
|
||||
|
||||
void Draw(u32 stride, bool alphapass);
|
||||
|
||||
NativeVertexFormat* CreateNativeVertexFormat();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
// 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 _DX11_VERTEXMANAGER_H
|
||||
#define _DX11_VERTEXMANAGER_H
|
||||
|
||||
#include "CPMemory.h"
|
||||
#include "VertexLoader.h"
|
||||
|
||||
#include "../VertexManager.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
// TODO: find sensible values for these two
|
||||
NUM_VERTEXBUFFERS = 8,
|
||||
NUM_INDEXBUFFERS = 10,
|
||||
};
|
||||
|
||||
class VertexManager : public ::VertexManagerBase
|
||||
{
|
||||
public:
|
||||
VertexManager();
|
||||
~VertexManager();
|
||||
|
||||
void Draw(u32 stride, bool alphapass);
|
||||
|
||||
NativeVertexFormat* CreateNativeVertexFormat();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,283 +1,283 @@
|
|||
// 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 <map>
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
#include "LinearDiskCache.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "BPMemory.h"
|
||||
#include "XFMemory.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DShader.h"
|
||||
#include "DX11_VertexShaderCache.h"
|
||||
#include "DX11_Render.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
VertexShaderCache::VSCache VertexShaderCache::vshaders;
|
||||
const VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry;
|
||||
|
||||
static ID3D11VertexShader* SimpleVertexShader = NULL;
|
||||
static ID3D11VertexShader* ClearVertexShader = NULL;
|
||||
static ID3D11InputLayout* SimpleLayout = NULL;
|
||||
static ID3D11InputLayout* ClearLayout = NULL;
|
||||
|
||||
LinearDiskCache g_vs_disk_cache;
|
||||
|
||||
ID3D11VertexShader* VertexShaderCache::GetSimpleVertexShader() { return SimpleVertexShader; }
|
||||
ID3D11VertexShader* VertexShaderCache::GetClearVertexShader() { return ClearVertexShader; }
|
||||
ID3D11InputLayout* VertexShaderCache::GetSimpleInputLayout() { return SimpleLayout; }
|
||||
ID3D11InputLayout* VertexShaderCache::GetClearInputLayout() { return ClearLayout; }
|
||||
|
||||
// maps the constant numbers to float indices in the constant buffer
|
||||
unsigned int vs_constant_offset_table[C_VENVCONST_END];
|
||||
void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number] ] = f1;
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+1] = f2;
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+2] = f3;
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+3] = f4;
|
||||
D3D::gfxstate->vscbufchanged = true;
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float* f)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4);
|
||||
D3D::gfxstate->vscbufchanged = true;
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]], f+3*i, sizeof(float)*3);
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]+3] = 0.f;
|
||||
}
|
||||
D3D::gfxstate->vscbufchanged = true;
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4*count);
|
||||
D3D::gfxstate->vscbufchanged = true;
|
||||
}
|
||||
|
||||
// this class will load the precompiled shaders into our cache
|
||||
class VertexShaderCacheInserter : public LinearDiskCacheReader {
|
||||
public:
|
||||
void Read(const u8* key, int key_size, const u8* value, int value_size)
|
||||
{
|
||||
VERTEXSHADERUID uid;
|
||||
if (key_size != sizeof(uid))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Wrong key size in vertex shader cache");
|
||||
return;
|
||||
}
|
||||
memcpy(&uid, key, key_size);
|
||||
|
||||
D3DBlob* blob = new D3DBlob(value_size, value);
|
||||
VertexShaderCache::InsertByteCode(uid, blob);
|
||||
blob->Release();
|
||||
}
|
||||
};
|
||||
|
||||
const char simple_shader_code[] = {
|
||||
"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float2 vTexCoord : TEXCOORD0;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;\n"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vTexCoord = inTEX0;\n"
|
||||
"return OUT;\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
const char clear_shader_code[] = {
|
||||
"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float4 vColor0 : COLOR0;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;\n"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vColor0 = inColor0;\n"
|
||||
"return OUT;\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
VertexShaderCache::VertexShaderCache()
|
||||
{
|
||||
const D3D11_INPUT_ELEMENT_DESC simpleelems[2] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
const D3D11_INPUT_ELEMENT_DESC clearelems[2] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
D3DBlob* blob;
|
||||
D3D::CompileVertexShader(simple_shader_code, sizeof(simple_shader_code), &blob);
|
||||
D3D::device->CreateInputLayout(simpleelems, 2, blob->Data(), blob->Size(), &SimpleLayout);
|
||||
SimpleVertexShader = D3D::CreateVertexShaderFromByteCode(blob);
|
||||
if (SimpleLayout == NULL || SimpleVertexShader == NULL) PanicAlert("Failed to create simple vertex shader or input layout at %s %d\n", __FILE__, __LINE__);
|
||||
blob->Release();
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleVertexShader, "simple vertex shader");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleLayout, "simple input layout");
|
||||
|
||||
D3D::CompileVertexShader(clear_shader_code, sizeof(clear_shader_code), &blob);
|
||||
D3D::device->CreateInputLayout(clearelems, 2, blob->Data(), blob->Size(), &ClearLayout);
|
||||
ClearVertexShader = D3D::CreateVertexShaderFromByteCode(blob);
|
||||
if (ClearLayout == NULL || ClearVertexShader == NULL) PanicAlert("Failed to create clear vertex shader or input layout at %s %d\n", __FILE__, __LINE__);
|
||||
blob->Release();
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearVertexShader, "clear vertex shader");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearLayout, "clear input layout");
|
||||
|
||||
Clear();
|
||||
|
||||
// these values are hardcoded, they depend on internal D3DCompile behavior
|
||||
// TODO: Do this with D3DReflect or something instead
|
||||
unsigned int k;
|
||||
for (k = 0;k < 6;k++) vs_constant_offset_table[C_POSNORMALMATRIX+k] = 0+4*k;
|
||||
for (k = 0;k < 4;k++) vs_constant_offset_table[C_PROJECTION+k] = 24+4*k;
|
||||
for (k = 0;k < 4;k++) vs_constant_offset_table[C_MATERIALS+k] = 40+4*k;
|
||||
for (k = 0;k < 40;k++) vs_constant_offset_table[C_LIGHTS+k] = 56+4*k;
|
||||
for (k = 0;k < 24;k++) vs_constant_offset_table[C_TEXMATRICES+k] = 216+4*k;
|
||||
for (k = 0;k < 64;k++) vs_constant_offset_table[C_TRANSFORMMATRICES+k] = 312+4*k;
|
||||
for (k = 0;k < 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;
|
||||
|
||||
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
|
||||
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
|
||||
|
||||
char cache_filename[MAX_PATH];
|
||||
sprintf(cache_filename, "%sdx11-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
|
||||
VertexShaderCacheInserter inserter;
|
||||
g_vs_disk_cache.OpenAndRead(cache_filename, &inserter);
|
||||
}
|
||||
|
||||
void VertexShaderCache::Clear()
|
||||
{
|
||||
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter)
|
||||
iter->second.Destroy();
|
||||
vshaders.clear();
|
||||
}
|
||||
|
||||
VertexShaderCache::~VertexShaderCache()
|
||||
{
|
||||
SAFE_RELEASE(SimpleVertexShader);
|
||||
SAFE_RELEASE(ClearVertexShader);
|
||||
|
||||
SAFE_RELEASE(SimpleLayout);
|
||||
SAFE_RELEASE(ClearLayout);
|
||||
|
||||
Clear();
|
||||
g_vs_disk_cache.Sync();
|
||||
g_vs_disk_cache.Close();
|
||||
}
|
||||
|
||||
bool VertexShaderCache::SetShader(u32 components)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
VERTEXSHADERUID uid;
|
||||
GetVertexShaderId(&uid, components);
|
||||
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
|
||||
return (vshaders[uid].shader != NULL);
|
||||
|
||||
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
|
||||
|
||||
VSCache::iterator iter;
|
||||
iter = vshaders.find(uid);
|
||||
if (iter != vshaders.end())
|
||||
{
|
||||
iter->second.frameCount = frameCount;
|
||||
const VSCacheEntry &entry = iter->second;
|
||||
last_entry = &entry;
|
||||
|
||||
if (entry.shader) D3D::gfxstate->SetVShader(entry.shader, iter->second.bytecode);
|
||||
return (entry.shader != NULL);
|
||||
}
|
||||
|
||||
const char* code = GenerateVertexShaderCode(components, API_D3D11);
|
||||
|
||||
D3DBlob* pbytecode = NULL;
|
||||
D3D::CompileVertexShader(code, (int)strlen(code), &pbytecode);
|
||||
|
||||
if (pbytecode == NULL)
|
||||
{
|
||||
PanicAlert("Failed to compile Vertex Shader %s %d:\n\n%s", __FILE__, __LINE__, code);
|
||||
return false;
|
||||
}
|
||||
g_vs_disk_cache.Append((u8*)&uid, sizeof(uid), (const u8*)pbytecode->Data(), pbytecode->Size());
|
||||
g_vs_disk_cache.Sync();
|
||||
|
||||
bool result = InsertByteCode(uid, pbytecode);
|
||||
D3D::gfxstate->SetVShader(last_entry->shader, last_entry->bytecode);
|
||||
pbytecode->Release();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, D3DBlob* bcodeblob)
|
||||
{
|
||||
ID3D11VertexShader* shader = D3D::CreateVertexShaderFromByteCode(bcodeblob);
|
||||
if (shader == NULL)
|
||||
{
|
||||
PanicAlert("Failed to create vertex shader from %p size %d at %s %d\n", bcodeblob->Data(), bcodeblob->Size(), __FILE__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
// TODO: Somehow make the debug name a bit more specific
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a vertex shader of VertexShaderCache");
|
||||
|
||||
// Make an entry in the table
|
||||
VSCacheEntry entry;
|
||||
entry.shader = shader;
|
||||
entry.frameCount = frameCount;
|
||||
entry.SetByteCode(bcodeblob);
|
||||
|
||||
vshaders[uid] = entry;
|
||||
last_entry = &vshaders[uid];
|
||||
|
||||
INCSTAT(stats.numVertexShadersCreated);
|
||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
// 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 <map>
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
#include "LinearDiskCache.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "BPMemory.h"
|
||||
#include "XFMemory.h"
|
||||
|
||||
// DX11
|
||||
#include "DX11_D3DBase.h"
|
||||
#include "DX11_D3DShader.h"
|
||||
#include "DX11_VertexShaderCache.h"
|
||||
#include "DX11_Render.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
VertexShaderCache::VSCache VertexShaderCache::vshaders;
|
||||
const VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry;
|
||||
|
||||
static ID3D11VertexShader* SimpleVertexShader = NULL;
|
||||
static ID3D11VertexShader* ClearVertexShader = NULL;
|
||||
static ID3D11InputLayout* SimpleLayout = NULL;
|
||||
static ID3D11InputLayout* ClearLayout = NULL;
|
||||
|
||||
LinearDiskCache g_vs_disk_cache;
|
||||
|
||||
ID3D11VertexShader* VertexShaderCache::GetSimpleVertexShader() { return SimpleVertexShader; }
|
||||
ID3D11VertexShader* VertexShaderCache::GetClearVertexShader() { return ClearVertexShader; }
|
||||
ID3D11InputLayout* VertexShaderCache::GetSimpleInputLayout() { return SimpleLayout; }
|
||||
ID3D11InputLayout* VertexShaderCache::GetClearInputLayout() { return ClearLayout; }
|
||||
|
||||
// maps the constant numbers to float indices in the constant buffer
|
||||
unsigned int vs_constant_offset_table[C_VENVCONST_END];
|
||||
void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number] ] = f1;
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+1] = f2;
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+2] = f3;
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+3] = f4;
|
||||
D3D::gfxstate->vscbufchanged = true;
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float* f)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4);
|
||||
D3D::gfxstate->vscbufchanged = true;
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]], f+3*i, sizeof(float)*3);
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]+3] = 0.f;
|
||||
}
|
||||
D3D::gfxstate->vscbufchanged = true;
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4*count);
|
||||
D3D::gfxstate->vscbufchanged = true;
|
||||
}
|
||||
|
||||
// this class will load the precompiled shaders into our cache
|
||||
class VertexShaderCacheInserter : public LinearDiskCacheReader {
|
||||
public:
|
||||
void Read(const u8* key, int key_size, const u8* value, int value_size)
|
||||
{
|
||||
VERTEXSHADERUID uid;
|
||||
if (key_size != sizeof(uid))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Wrong key size in vertex shader cache");
|
||||
return;
|
||||
}
|
||||
memcpy(&uid, key, key_size);
|
||||
|
||||
D3DBlob* blob = new D3DBlob(value_size, value);
|
||||
VertexShaderCache::InsertByteCode(uid, blob);
|
||||
blob->Release();
|
||||
}
|
||||
};
|
||||
|
||||
const char simple_shader_code[] = {
|
||||
"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float2 vTexCoord : TEXCOORD0;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;\n"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vTexCoord = inTEX0;\n"
|
||||
"return OUT;\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
const char clear_shader_code[] = {
|
||||
"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float4 vColor0 : COLOR0;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;\n"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vColor0 = inColor0;\n"
|
||||
"return OUT;\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
VertexShaderCache::VertexShaderCache()
|
||||
{
|
||||
const D3D11_INPUT_ELEMENT_DESC simpleelems[2] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
const D3D11_INPUT_ELEMENT_DESC clearelems[2] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
D3DBlob* blob;
|
||||
D3D::CompileVertexShader(simple_shader_code, sizeof(simple_shader_code), &blob);
|
||||
D3D::device->CreateInputLayout(simpleelems, 2, blob->Data(), blob->Size(), &SimpleLayout);
|
||||
SimpleVertexShader = D3D::CreateVertexShaderFromByteCode(blob);
|
||||
if (SimpleLayout == NULL || SimpleVertexShader == NULL) PanicAlert("Failed to create simple vertex shader or input layout at %s %d\n", __FILE__, __LINE__);
|
||||
blob->Release();
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleVertexShader, "simple vertex shader");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleLayout, "simple input layout");
|
||||
|
||||
D3D::CompileVertexShader(clear_shader_code, sizeof(clear_shader_code), &blob);
|
||||
D3D::device->CreateInputLayout(clearelems, 2, blob->Data(), blob->Size(), &ClearLayout);
|
||||
ClearVertexShader = D3D::CreateVertexShaderFromByteCode(blob);
|
||||
if (ClearLayout == NULL || ClearVertexShader == NULL) PanicAlert("Failed to create clear vertex shader or input layout at %s %d\n", __FILE__, __LINE__);
|
||||
blob->Release();
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearVertexShader, "clear vertex shader");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearLayout, "clear input layout");
|
||||
|
||||
Clear();
|
||||
|
||||
// these values are hardcoded, they depend on internal D3DCompile behavior
|
||||
// TODO: Do this with D3DReflect or something instead
|
||||
unsigned int k;
|
||||
for (k = 0;k < 6;k++) vs_constant_offset_table[C_POSNORMALMATRIX+k] = 0+4*k;
|
||||
for (k = 0;k < 4;k++) vs_constant_offset_table[C_PROJECTION+k] = 24+4*k;
|
||||
for (k = 0;k < 4;k++) vs_constant_offset_table[C_MATERIALS+k] = 40+4*k;
|
||||
for (k = 0;k < 40;k++) vs_constant_offset_table[C_LIGHTS+k] = 56+4*k;
|
||||
for (k = 0;k < 24;k++) vs_constant_offset_table[C_TEXMATRICES+k] = 216+4*k;
|
||||
for (k = 0;k < 64;k++) vs_constant_offset_table[C_TRANSFORMMATRICES+k] = 312+4*k;
|
||||
for (k = 0;k < 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;
|
||||
|
||||
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
|
||||
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
|
||||
|
||||
char cache_filename[MAX_PATH];
|
||||
sprintf(cache_filename, "%sdx11-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
|
||||
VertexShaderCacheInserter inserter;
|
||||
g_vs_disk_cache.OpenAndRead(cache_filename, &inserter);
|
||||
}
|
||||
|
||||
void VertexShaderCache::Clear()
|
||||
{
|
||||
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter)
|
||||
iter->second.Destroy();
|
||||
vshaders.clear();
|
||||
}
|
||||
|
||||
VertexShaderCache::~VertexShaderCache()
|
||||
{
|
||||
SAFE_RELEASE(SimpleVertexShader);
|
||||
SAFE_RELEASE(ClearVertexShader);
|
||||
|
||||
SAFE_RELEASE(SimpleLayout);
|
||||
SAFE_RELEASE(ClearLayout);
|
||||
|
||||
Clear();
|
||||
g_vs_disk_cache.Sync();
|
||||
g_vs_disk_cache.Close();
|
||||
}
|
||||
|
||||
bool VertexShaderCache::SetShader(u32 components)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
VERTEXSHADERUID uid;
|
||||
GetVertexShaderId(&uid, components);
|
||||
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
|
||||
return (vshaders[uid].shader != NULL);
|
||||
|
||||
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
|
||||
|
||||
VSCache::iterator iter;
|
||||
iter = vshaders.find(uid);
|
||||
if (iter != vshaders.end())
|
||||
{
|
||||
iter->second.frameCount = frameCount;
|
||||
const VSCacheEntry &entry = iter->second;
|
||||
last_entry = &entry;
|
||||
|
||||
if (entry.shader) D3D::gfxstate->SetVShader(entry.shader, iter->second.bytecode);
|
||||
return (entry.shader != NULL);
|
||||
}
|
||||
|
||||
const char* code = GenerateVertexShaderCode(components, API_D3D11);
|
||||
|
||||
D3DBlob* pbytecode = NULL;
|
||||
D3D::CompileVertexShader(code, (int)strlen(code), &pbytecode);
|
||||
|
||||
if (pbytecode == NULL)
|
||||
{
|
||||
PanicAlert("Failed to compile Vertex Shader %s %d:\n\n%s", __FILE__, __LINE__, code);
|
||||
return false;
|
||||
}
|
||||
g_vs_disk_cache.Append((u8*)&uid, sizeof(uid), (const u8*)pbytecode->Data(), pbytecode->Size());
|
||||
g_vs_disk_cache.Sync();
|
||||
|
||||
bool result = InsertByteCode(uid, pbytecode);
|
||||
D3D::gfxstate->SetVShader(last_entry->shader, last_entry->bytecode);
|
||||
pbytecode->Release();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, D3DBlob* bcodeblob)
|
||||
{
|
||||
ID3D11VertexShader* shader = D3D::CreateVertexShaderFromByteCode(bcodeblob);
|
||||
if (shader == NULL)
|
||||
{
|
||||
PanicAlert("Failed to create vertex shader from %p size %d at %s %d\n", bcodeblob->Data(), bcodeblob->Size(), __FILE__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
// TODO: Somehow make the debug name a bit more specific
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a vertex shader of VertexShaderCache");
|
||||
|
||||
// Make an entry in the table
|
||||
VSCacheEntry entry;
|
||||
entry.shader = shader;
|
||||
entry.frameCount = frameCount;
|
||||
entry.SetByteCode(bcodeblob);
|
||||
|
||||
vshaders[uid] = entry;
|
||||
last_entry = &vshaders[uid];
|
||||
|
||||
INCSTAT(stats.numVertexShadersCreated);
|
||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,80 +1,80 @@
|
|||
// 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 _DX11_VERTEXSHADERCACHE_H
|
||||
#define _DX11_VERTEXSHADERCACHE_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "VertexShaderGen.h"
|
||||
#include "DX11_D3DBase.h"
|
||||
|
||||
#include "../VertexShaderCache.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
class VertexShaderCache : public ::VertexShaderCacheBase
|
||||
{
|
||||
public:
|
||||
VertexShaderCache();
|
||||
~VertexShaderCache();
|
||||
|
||||
static void Clear();
|
||||
bool SetShader(u32 components);
|
||||
|
||||
static ID3D11VertexShader* GetSimpleVertexShader();
|
||||
static ID3D11VertexShader* GetClearVertexShader();
|
||||
static ID3D11InputLayout* GetSimpleInputLayout();
|
||||
static ID3D11InputLayout* GetClearInputLayout();
|
||||
|
||||
static bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, D3DBlob* bcodeblob);
|
||||
|
||||
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetVSConstant4fv(unsigned int const_number, const float* f);
|
||||
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f);
|
||||
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f);
|
||||
|
||||
private:
|
||||
struct VSCacheEntry
|
||||
{
|
||||
ID3D11VertexShader* shader;
|
||||
D3DBlob* bytecode; // needed to initialize the input layout
|
||||
int frameCount;
|
||||
|
||||
VSCacheEntry() : shader(NULL), bytecode(NULL), frameCount(0) {}
|
||||
void SetByteCode(D3DBlob* blob)
|
||||
{
|
||||
SAFE_RELEASE(bytecode);
|
||||
bytecode = blob;
|
||||
blob->AddRef();
|
||||
}
|
||||
void Destroy()
|
||||
{
|
||||
SAFE_RELEASE(shader);
|
||||
SAFE_RELEASE(bytecode);
|
||||
}
|
||||
};
|
||||
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
|
||||
|
||||
static VSCache vshaders;
|
||||
static const VSCacheEntry* last_entry;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _VERTEXSHADERCACHE_H
|
||||
// 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 _DX11_VERTEXSHADERCACHE_H
|
||||
#define _DX11_VERTEXSHADERCACHE_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "VertexShaderGen.h"
|
||||
#include "DX11_D3DBase.h"
|
||||
|
||||
#include "../VertexShaderCache.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
class VertexShaderCache : public ::VertexShaderCacheBase
|
||||
{
|
||||
public:
|
||||
VertexShaderCache();
|
||||
~VertexShaderCache();
|
||||
|
||||
static void Clear();
|
||||
bool SetShader(u32 components);
|
||||
|
||||
static ID3D11VertexShader* GetSimpleVertexShader();
|
||||
static ID3D11VertexShader* GetClearVertexShader();
|
||||
static ID3D11InputLayout* GetSimpleInputLayout();
|
||||
static ID3D11InputLayout* GetClearInputLayout();
|
||||
|
||||
static bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, D3DBlob* bcodeblob);
|
||||
|
||||
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetVSConstant4fv(unsigned int const_number, const float* f);
|
||||
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f);
|
||||
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f);
|
||||
|
||||
private:
|
||||
struct VSCacheEntry
|
||||
{
|
||||
ID3D11VertexShader* shader;
|
||||
D3DBlob* bytecode; // needed to initialize the input layout
|
||||
int frameCount;
|
||||
|
||||
VSCacheEntry() : shader(NULL), bytecode(NULL), frameCount(0) {}
|
||||
void SetByteCode(D3DBlob* blob)
|
||||
{
|
||||
SAFE_RELEASE(bytecode);
|
||||
bytecode = blob;
|
||||
blob->AddRef();
|
||||
}
|
||||
void Destroy()
|
||||
{
|
||||
SAFE_RELEASE(shader);
|
||||
SAFE_RELEASE(bytecode);
|
||||
}
|
||||
};
|
||||
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
|
||||
|
||||
static VSCache vshaders;
|
||||
static const VSCacheEntry* last_entry;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _VERTEXSHADERCACHE_H
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,165 +1,165 @@
|
|||
// 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 _D3DBASE_H
|
||||
#define _D3DBASE_H
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
#define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; }
|
||||
#define SAFE_DELETE(x) { delete (x); (x) = NULL; }
|
||||
|
||||
// From http://developer.amd.com/gpu_assets/Advanced%20DX9%20Capabilities%20for%20ATI%20Radeon%20Cards.pdf
|
||||
// Magic FourCC's to unlock undocumented D3D9 features:
|
||||
|
||||
// Z texture formats
|
||||
#define FOURCC_INTZ ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')))
|
||||
#define FOURCC_RAWZ ((D3DFORMAT)(MAKEFOURCC('R','A','W','Z')))
|
||||
#define FOURCC_DF24 ((D3DFORMAT)(MAKEFOURCC('D','F','2','4')))
|
||||
#define FOURCC_DF16 ((D3DFORMAT)(MAKEFOURCC('D','F','1','6')))
|
||||
|
||||
// Depth buffer resolve:
|
||||
#define FOURCC_RESZ ((D3DFORMAT)(MAKEFOURCC('R','E','S','Z')))
|
||||
#define RESZ_CODE 0x7fa05000
|
||||
|
||||
// Null render target to do Z-only shadow maps: (probably not useful for Dolphin)
|
||||
#define FOURCC_NULL ((D3DFORMAT)(MAKEFOURCC('N','U','L','L')))
|
||||
|
||||
bool IsATIDevice();
|
||||
HRESULT Init();
|
||||
HRESULT Create(int adapter, HWND wnd, int resolution, int aa_mode, bool auto_depth);
|
||||
void Close();
|
||||
void Shutdown();
|
||||
|
||||
// Direct access to the device.
|
||||
extern LPDIRECT3DDEVICE9 dev;
|
||||
extern bool bFrameInProgress;
|
||||
|
||||
void Reset();
|
||||
bool BeginFrame();
|
||||
void EndFrame();
|
||||
void Present();
|
||||
bool CanUseINTZ();
|
||||
|
||||
int GetBackBufferWidth();
|
||||
int GetBackBufferHeight();
|
||||
LPDIRECT3DSURFACE9 GetBackBufferSurface();
|
||||
LPDIRECT3DSURFACE9 GetBackBufferDepthSurface();
|
||||
LPDIRECT3DVERTEXBUFFER9 GetquadVB();
|
||||
LPDIRECT3DVERTEXDECLARATION9 GetBasicvertexDecl();
|
||||
const D3DCAPS9 &GetCaps();
|
||||
const char *PixelShaderVersionString();
|
||||
const char *VertexShaderVersionString();
|
||||
void ShowD3DError(HRESULT err);
|
||||
|
||||
// The following are "filtered" versions of the corresponding D3Ddev-> functions.
|
||||
void SetTexture(DWORD Stage, IDirect3DBaseTexture9 *pTexture);
|
||||
void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value);
|
||||
void RefreshRenderState(D3DRENDERSTATETYPE State);
|
||||
void ChangeRenderState(D3DRENDERSTATETYPE State, DWORD Value);
|
||||
|
||||
void SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
|
||||
void RefreshTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type);
|
||||
void ChangeTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
|
||||
|
||||
void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
|
||||
void RefreshSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type);
|
||||
void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
|
||||
|
||||
void RefreshVertexDeclaration();
|
||||
void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl);
|
||||
|
||||
void RefreshVertexShader();
|
||||
void SetVertexShader(LPDIRECT3DVERTEXSHADER9 shader);
|
||||
|
||||
void RefreshPixelShader();
|
||||
void SetPixelShader(LPDIRECT3DPIXELSHADER9 shader);
|
||||
|
||||
void ApplyCachedState();
|
||||
|
||||
// Utility functions for vendor specific hacks. So far, just the one.
|
||||
void EnableAlphaToCoverage();
|
||||
|
||||
struct Resolution
|
||||
{
|
||||
char name[32];
|
||||
int xres;
|
||||
int yres;
|
||||
std::set<D3DFORMAT> bitdepths;
|
||||
std::set<int> refreshes;
|
||||
};
|
||||
|
||||
struct AALevel
|
||||
{
|
||||
AALevel(const char *n, D3DMULTISAMPLE_TYPE m, int q) {
|
||||
strncpy(name, n, 32);
|
||||
name[31] = '\0';
|
||||
ms_setting = m;
|
||||
qual_setting = q;
|
||||
}
|
||||
char name[32];
|
||||
D3DMULTISAMPLE_TYPE ms_setting;
|
||||
int qual_setting;
|
||||
};
|
||||
|
||||
struct Adapter
|
||||
{
|
||||
D3DADAPTER_IDENTIFIER9 ident;
|
||||
std::vector<Resolution> resolutions;
|
||||
std::vector<AALevel> aa_levels;
|
||||
bool supports_alpha_to_coverage;
|
||||
|
||||
// Magic render targets, see the top of this file.
|
||||
bool supports_intz;
|
||||
bool supports_rawz;
|
||||
bool supports_resz;
|
||||
bool supports_null;
|
||||
};
|
||||
|
||||
const Adapter &GetAdapter(int i);
|
||||
const Adapter &GetCurAdapter();
|
||||
int GetNumAdapters();
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// Used to not require the SDK and runtime versions to match:
|
||||
// Linking with d3dx9.lib makes the most recent d3dx9_xx.dll of the
|
||||
// compiler's SDK an actually unnecessary requirement.
|
||||
// Add any d3dx9 functions which you want to use here and load them in LoadD3DX9()
|
||||
typedef HRESULT (WINAPI* D3DXSAVESURFACETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DSURFACE9, CONST PALETTEENTRY*, CONST RECT*);
|
||||
typedef HRESULT (WINAPI* D3DXSAVETEXTURETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DBASETEXTURE9, CONST PALETTEENTRY*);
|
||||
typedef HRESULT (WINAPI* D3DXCOMPILESHADERTYPE)(LPCSTR, UINT, CONST D3DXMACRO*, LPD3DXINCLUDE, LPCSTR, LPCSTR, DWORD, LPD3DXBUFFER*, LPD3DXBUFFER*, LPD3DXCONSTANTTABLE*);
|
||||
|
||||
extern D3DXSAVESURFACETOFILEATYPE PD3DXSaveSurfaceToFileA;
|
||||
extern D3DXSAVETEXTURETOFILEATYPE PD3DXSaveTextureToFileA;
|
||||
extern D3DXCOMPILESHADERTYPE PD3DXCompileShader;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
// 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 _D3DBASE_H
|
||||
#define _D3DBASE_H
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
#define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; }
|
||||
#define SAFE_DELETE(x) { delete (x); (x) = NULL; }
|
||||
|
||||
// From http://developer.amd.com/gpu_assets/Advanced%20DX9%20Capabilities%20for%20ATI%20Radeon%20Cards.pdf
|
||||
// Magic FourCC's to unlock undocumented D3D9 features:
|
||||
|
||||
// Z texture formats
|
||||
#define FOURCC_INTZ ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')))
|
||||
#define FOURCC_RAWZ ((D3DFORMAT)(MAKEFOURCC('R','A','W','Z')))
|
||||
#define FOURCC_DF24 ((D3DFORMAT)(MAKEFOURCC('D','F','2','4')))
|
||||
#define FOURCC_DF16 ((D3DFORMAT)(MAKEFOURCC('D','F','1','6')))
|
||||
|
||||
// Depth buffer resolve:
|
||||
#define FOURCC_RESZ ((D3DFORMAT)(MAKEFOURCC('R','E','S','Z')))
|
||||
#define RESZ_CODE 0x7fa05000
|
||||
|
||||
// Null render target to do Z-only shadow maps: (probably not useful for Dolphin)
|
||||
#define FOURCC_NULL ((D3DFORMAT)(MAKEFOURCC('N','U','L','L')))
|
||||
|
||||
bool IsATIDevice();
|
||||
HRESULT Init();
|
||||
HRESULT Create(int adapter, HWND wnd, int resolution, int aa_mode, bool auto_depth);
|
||||
void Close();
|
||||
void Shutdown();
|
||||
|
||||
// Direct access to the device.
|
||||
extern LPDIRECT3DDEVICE9 dev;
|
||||
extern bool bFrameInProgress;
|
||||
|
||||
void Reset();
|
||||
bool BeginFrame();
|
||||
void EndFrame();
|
||||
void Present();
|
||||
bool CanUseINTZ();
|
||||
|
||||
int GetBackBufferWidth();
|
||||
int GetBackBufferHeight();
|
||||
LPDIRECT3DSURFACE9 GetBackBufferSurface();
|
||||
LPDIRECT3DSURFACE9 GetBackBufferDepthSurface();
|
||||
LPDIRECT3DVERTEXBUFFER9 GetquadVB();
|
||||
LPDIRECT3DVERTEXDECLARATION9 GetBasicvertexDecl();
|
||||
const D3DCAPS9 &GetCaps();
|
||||
const char *PixelShaderVersionString();
|
||||
const char *VertexShaderVersionString();
|
||||
void ShowD3DError(HRESULT err);
|
||||
|
||||
// The following are "filtered" versions of the corresponding D3Ddev-> functions.
|
||||
void SetTexture(DWORD Stage, IDirect3DBaseTexture9 *pTexture);
|
||||
void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value);
|
||||
void RefreshRenderState(D3DRENDERSTATETYPE State);
|
||||
void ChangeRenderState(D3DRENDERSTATETYPE State, DWORD Value);
|
||||
|
||||
void SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
|
||||
void RefreshTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type);
|
||||
void ChangeTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
|
||||
|
||||
void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
|
||||
void RefreshSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type);
|
||||
void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
|
||||
|
||||
void RefreshVertexDeclaration();
|
||||
void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl);
|
||||
|
||||
void RefreshVertexShader();
|
||||
void SetVertexShader(LPDIRECT3DVERTEXSHADER9 shader);
|
||||
|
||||
void RefreshPixelShader();
|
||||
void SetPixelShader(LPDIRECT3DPIXELSHADER9 shader);
|
||||
|
||||
void ApplyCachedState();
|
||||
|
||||
// Utility functions for vendor specific hacks. So far, just the one.
|
||||
void EnableAlphaToCoverage();
|
||||
|
||||
struct Resolution
|
||||
{
|
||||
char name[32];
|
||||
int xres;
|
||||
int yres;
|
||||
std::set<D3DFORMAT> bitdepths;
|
||||
std::set<int> refreshes;
|
||||
};
|
||||
|
||||
struct AALevel
|
||||
{
|
||||
AALevel(const char *n, D3DMULTISAMPLE_TYPE m, int q) {
|
||||
strncpy(name, n, 32);
|
||||
name[31] = '\0';
|
||||
ms_setting = m;
|
||||
qual_setting = q;
|
||||
}
|
||||
char name[32];
|
||||
D3DMULTISAMPLE_TYPE ms_setting;
|
||||
int qual_setting;
|
||||
};
|
||||
|
||||
struct Adapter
|
||||
{
|
||||
D3DADAPTER_IDENTIFIER9 ident;
|
||||
std::vector<Resolution> resolutions;
|
||||
std::vector<AALevel> aa_levels;
|
||||
bool supports_alpha_to_coverage;
|
||||
|
||||
// Magic render targets, see the top of this file.
|
||||
bool supports_intz;
|
||||
bool supports_rawz;
|
||||
bool supports_resz;
|
||||
bool supports_null;
|
||||
};
|
||||
|
||||
const Adapter &GetAdapter(int i);
|
||||
const Adapter &GetCurAdapter();
|
||||
int GetNumAdapters();
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// Used to not require the SDK and runtime versions to match:
|
||||
// Linking with d3dx9.lib makes the most recent d3dx9_xx.dll of the
|
||||
// compiler's SDK an actually unnecessary requirement.
|
||||
// Add any d3dx9 functions which you want to use here and load them in LoadD3DX9()
|
||||
typedef HRESULT (WINAPI* D3DXSAVESURFACETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DSURFACE9, CONST PALETTEENTRY*, CONST RECT*);
|
||||
typedef HRESULT (WINAPI* D3DXSAVETEXTURETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DBASETEXTURE9, CONST PALETTEENTRY*);
|
||||
typedef HRESULT (WINAPI* D3DXCOMPILESHADERTYPE)(LPCSTR, UINT, CONST D3DXMACRO*, LPD3DXINCLUDE, LPCSTR, LPCSTR, DWORD, LPD3DXBUFFER*, LPD3DXBUFFER*, LPD3DXCONSTANTTABLE*);
|
||||
|
||||
extern D3DXSAVESURFACETOFILEATYPE PD3DXSaveSurfaceToFileA;
|
||||
extern D3DXSAVETEXTURETOFILEATYPE PD3DXSaveTextureToFileA;
|
||||
extern D3DXCOMPILESHADERTYPE PD3DXCompileShader;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,150 +1,150 @@
|
|||
// 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 <d3dx9.h>
|
||||
#include <string>
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "DX9_D3DShader.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
// Bytecode->shader.
|
||||
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len)
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 v_shader;
|
||||
HRESULT hr = D3D::dev->CreateVertexShader((DWORD *)bytecode, &v_shader);
|
||||
if (FAILED(hr))
|
||||
v_shader = 0;
|
||||
return v_shader;
|
||||
}
|
||||
|
||||
// Code->bytecode.
|
||||
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
|
||||
{
|
||||
//try to compile
|
||||
LPD3DXBUFFER shaderBuffer = 0;
|
||||
LPD3DXBUFFER errorBuffer = 0;
|
||||
HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::VertexShaderVersionString(),
|
||||
0, &shaderBuffer, &errorBuffer, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
//compilation error
|
||||
if (g_ActiveConfig.bShowShaderErrors) {
|
||||
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
||||
hello += "\n\n";
|
||||
hello += code;
|
||||
MessageBoxA(0, hello.c_str(), "Error compiling vertex shader", MB_ICONERROR);
|
||||
}
|
||||
*bytecode = 0;
|
||||
*bytecodelen = 0;
|
||||
}
|
||||
else if (SUCCEEDED(hr))
|
||||
{
|
||||
*bytecodelen = shaderBuffer->GetBufferSize();
|
||||
*bytecode = new u8[*bytecodelen];
|
||||
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
|
||||
}
|
||||
|
||||
//cleanup
|
||||
if (shaderBuffer)
|
||||
shaderBuffer->Release();
|
||||
if (errorBuffer)
|
||||
errorBuffer->Release();
|
||||
return SUCCEEDED(hr) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
// Bytecode->shader.
|
||||
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len)
|
||||
{
|
||||
LPDIRECT3DPIXELSHADER9 p_shader;
|
||||
HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)bytecode, &p_shader);
|
||||
if (FAILED(hr))
|
||||
p_shader = 0;
|
||||
return p_shader;
|
||||
}
|
||||
|
||||
|
||||
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
|
||||
{
|
||||
LPD3DXBUFFER shaderBuffer = 0;
|
||||
LPD3DXBUFFER errorBuffer = 0;
|
||||
|
||||
// Someone:
|
||||
// For some reason, I had this kind of errors : "Shader uses texture addressing operations
|
||||
// in a dependency chain that is too complex for the target shader model (ps_2_0) to handle."
|
||||
HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::PixelShaderVersionString(),
|
||||
0, &shaderBuffer, &errorBuffer, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (g_ActiveConfig.bShowShaderErrors) {
|
||||
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
||||
hello += "\n\n";
|
||||
hello += code;
|
||||
MessageBoxA(0, hello.c_str(), "Error compiling pixel shader", MB_ICONERROR);
|
||||
}
|
||||
*bytecode = 0;
|
||||
*bytecodelen = 0;
|
||||
}
|
||||
else if (SUCCEEDED(hr))
|
||||
{
|
||||
*bytecodelen = shaderBuffer->GetBufferSize();
|
||||
*bytecode = new u8[*bytecodelen];
|
||||
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
|
||||
}
|
||||
|
||||
//cleanup
|
||||
if (shaderBuffer)
|
||||
shaderBuffer->Release();
|
||||
if (errorBuffer)
|
||||
errorBuffer->Release();
|
||||
return SUCCEEDED(hr) ? true : false;
|
||||
}
|
||||
|
||||
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len) {
|
||||
u8 *bytecode;
|
||||
int bytecodelen;
|
||||
if (CompileVertexShader(code, len, &bytecode, &bytecodelen)) {
|
||||
LPDIRECT3DVERTEXSHADER9 v_shader = CreateVertexShaderFromByteCode(bytecode, len);
|
||||
delete [] bytecode;
|
||||
return v_shader;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len) {
|
||||
u8 *bytecode;
|
||||
int bytecodelen;
|
||||
if (CompilePixelShader(code, len, &bytecode, &bytecodelen)) {
|
||||
LPDIRECT3DPIXELSHADER9 p_shader = CreatePixelShaderFromByteCode(bytecode, len);
|
||||
delete [] bytecode;
|
||||
return p_shader;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
// 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 <d3dx9.h>
|
||||
#include <string>
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "DX9_D3DShader.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
// Bytecode->shader.
|
||||
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len)
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 v_shader;
|
||||
HRESULT hr = D3D::dev->CreateVertexShader((DWORD *)bytecode, &v_shader);
|
||||
if (FAILED(hr))
|
||||
v_shader = 0;
|
||||
return v_shader;
|
||||
}
|
||||
|
||||
// Code->bytecode.
|
||||
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
|
||||
{
|
||||
//try to compile
|
||||
LPD3DXBUFFER shaderBuffer = 0;
|
||||
LPD3DXBUFFER errorBuffer = 0;
|
||||
HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::VertexShaderVersionString(),
|
||||
0, &shaderBuffer, &errorBuffer, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
//compilation error
|
||||
if (g_ActiveConfig.bShowShaderErrors) {
|
||||
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
||||
hello += "\n\n";
|
||||
hello += code;
|
||||
MessageBoxA(0, hello.c_str(), "Error compiling vertex shader", MB_ICONERROR);
|
||||
}
|
||||
*bytecode = 0;
|
||||
*bytecodelen = 0;
|
||||
}
|
||||
else if (SUCCEEDED(hr))
|
||||
{
|
||||
*bytecodelen = shaderBuffer->GetBufferSize();
|
||||
*bytecode = new u8[*bytecodelen];
|
||||
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
|
||||
}
|
||||
|
||||
//cleanup
|
||||
if (shaderBuffer)
|
||||
shaderBuffer->Release();
|
||||
if (errorBuffer)
|
||||
errorBuffer->Release();
|
||||
return SUCCEEDED(hr) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
// Bytecode->shader.
|
||||
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len)
|
||||
{
|
||||
LPDIRECT3DPIXELSHADER9 p_shader;
|
||||
HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)bytecode, &p_shader);
|
||||
if (FAILED(hr))
|
||||
p_shader = 0;
|
||||
return p_shader;
|
||||
}
|
||||
|
||||
|
||||
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
|
||||
{
|
||||
LPD3DXBUFFER shaderBuffer = 0;
|
||||
LPD3DXBUFFER errorBuffer = 0;
|
||||
|
||||
// Someone:
|
||||
// For some reason, I had this kind of errors : "Shader uses texture addressing operations
|
||||
// in a dependency chain that is too complex for the target shader model (ps_2_0) to handle."
|
||||
HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::PixelShaderVersionString(),
|
||||
0, &shaderBuffer, &errorBuffer, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (g_ActiveConfig.bShowShaderErrors) {
|
||||
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
||||
hello += "\n\n";
|
||||
hello += code;
|
||||
MessageBoxA(0, hello.c_str(), "Error compiling pixel shader", MB_ICONERROR);
|
||||
}
|
||||
*bytecode = 0;
|
||||
*bytecodelen = 0;
|
||||
}
|
||||
else if (SUCCEEDED(hr))
|
||||
{
|
||||
*bytecodelen = shaderBuffer->GetBufferSize();
|
||||
*bytecode = new u8[*bytecodelen];
|
||||
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
|
||||
}
|
||||
|
||||
//cleanup
|
||||
if (shaderBuffer)
|
||||
shaderBuffer->Release();
|
||||
if (errorBuffer)
|
||||
errorBuffer->Release();
|
||||
return SUCCEEDED(hr) ? true : false;
|
||||
}
|
||||
|
||||
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len) {
|
||||
u8 *bytecode;
|
||||
int bytecodelen;
|
||||
if (CompileVertexShader(code, len, &bytecode, &bytecodelen)) {
|
||||
LPDIRECT3DVERTEXSHADER9 v_shader = CreateVertexShaderFromByteCode(bytecode, len);
|
||||
delete [] bytecode;
|
||||
return v_shader;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len) {
|
||||
u8 *bytecode;
|
||||
int bytecodelen;
|
||||
if (CompilePixelShader(code, len, &bytecode, &bytecodelen)) {
|
||||
LPDIRECT3DPIXELSHADER9 p_shader = CreatePixelShaderFromByteCode(bytecode, len);
|
||||
delete [] bytecode;
|
||||
return p_shader;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
|
|
|
@ -1,39 +1,39 @@
|
|||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len);
|
||||
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len);
|
||||
|
||||
// The returned bytecode buffers should be delete[]-d.
|
||||
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
|
||||
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
|
||||
|
||||
// Utility functions
|
||||
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len);
|
||||
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len);
|
||||
}
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len);
|
||||
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len);
|
||||
|
||||
// The returned bytecode buffers should be delete[]-d.
|
||||
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
|
||||
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
|
||||
|
||||
// Utility functions
|
||||
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len);
|
||||
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,275 +1,275 @@
|
|||
// 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 "DX9_D3DBase.h"
|
||||
#include "DX9_D3DTexture.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int levels)
|
||||
{
|
||||
u32* pBuffer = (u32*)buffer;
|
||||
LPDIRECT3DTEXTURE9 pTexture;
|
||||
|
||||
// crazy bitmagic, sorry :)
|
||||
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
|
||||
bool bExpand = false;
|
||||
|
||||
if (fmt == D3DFMT_A8P8) {
|
||||
fmt = D3DFMT_A8L8;
|
||||
bExpand = true;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
// TODO(ector): Allow mipmaps for non-pow textures on newer cards?
|
||||
// TODO(ector): Use the game-specified mipmaps?
|
||||
if (levels > 0)
|
||||
hr = dev->CreateTexture(width, height, levels, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
else
|
||||
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return 0;
|
||||
int level = 0;
|
||||
D3DLOCKED_RECT Lock;
|
||||
pTexture->LockRect(level, &Lock, NULL, 0);
|
||||
switch (fmt)
|
||||
{
|
||||
case D3DFMT_L8:
|
||||
case D3DFMT_A8:
|
||||
case D3DFMT_A4L4:
|
||||
{
|
||||
const u8 *pIn = buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_R5G6B5:
|
||||
{
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_A8L8:
|
||||
{
|
||||
if (bExpand) { // I8
|
||||
const u8 *pIn = buffer;
|
||||
// TODO(XK): Find a better way that does not involve either unpacking
|
||||
// or downsampling (i.e. A4L4)
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
for(int i = 0; i < width * 2; i += 2) {
|
||||
pBits[i] = pIn[i / 2];
|
||||
pBits[i + 1] = pIn[i / 2];
|
||||
}
|
||||
pIn += pitch;
|
||||
}
|
||||
} else { // IA8
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_A8R8G8B8:
|
||||
{
|
||||
if(pitch * 4 == Lock.Pitch && !swap_r_b)
|
||||
{
|
||||
memcpy(Lock.pBits,buffer,Lock.Pitch*height);
|
||||
}
|
||||
else
|
||||
{
|
||||
u32* pIn = pBuffer;
|
||||
if (!swap_r_b) {
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 4);
|
||||
pIn += pitch;
|
||||
}
|
||||
} else {
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8 *pIn8 = (u8 *)pIn;
|
||||
u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
for (int x = 0; x < width * 4; x += 4) {
|
||||
pBits[x + 0] = pIn8[x + 2];
|
||||
pBits[x + 1] = pIn8[x + 1];
|
||||
pBits[x + 2] = pIn8[x + 0];
|
||||
pBits[x + 3] = pIn8[x + 3];
|
||||
}
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_DXT1:
|
||||
memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
|
||||
break;
|
||||
default:
|
||||
PanicAlert("D3D: Invalid texture format %i", fmt);
|
||||
}
|
||||
pTexture->UnlockRect(level);
|
||||
return pTexture;
|
||||
}
|
||||
|
||||
LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 pTexture;
|
||||
// crazy bitmagic, sorry :)
|
||||
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
|
||||
bool bExpand = false;
|
||||
HRESULT hr;
|
||||
// TODO(ector): Allow mipmaps for non-pow textures on newer cards?
|
||||
// TODO(ector): Use the game-specified mipmaps?
|
||||
if (!isPow2)
|
||||
hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
else
|
||||
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return 0;
|
||||
return pTexture;
|
||||
}
|
||||
|
||||
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level)
|
||||
{
|
||||
u32* pBuffer = (u32*)buffer;
|
||||
D3DLOCKED_RECT Lock;
|
||||
pTexture->LockRect(level, &Lock, NULL, 0);
|
||||
u32* pIn = pBuffer;
|
||||
|
||||
bool bExpand = false;
|
||||
|
||||
if (fmt == D3DFMT_A8P8) {
|
||||
fmt = D3DFMT_A8L8;
|
||||
bExpand = true;
|
||||
}
|
||||
switch (fmt)
|
||||
{
|
||||
case D3DFMT_A8R8G8B8:
|
||||
if(pitch * 4 == Lock.Pitch && !swap_r_b)
|
||||
{
|
||||
memcpy(Lock.pBits, pBuffer, Lock.Pitch*height);
|
||||
}
|
||||
else if (!swap_r_b)
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 4);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8 *pIn8 = (u8 *)pIn;
|
||||
u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
for (int x = 0; x < width * 4; x += 4)
|
||||
{
|
||||
pBits[x + 0] = pIn8[x + 2];
|
||||
pBits[x + 1] = pIn8[x + 1];
|
||||
pBits[x + 2] = pIn8[x + 0];
|
||||
pBits[x + 3] = pIn8[x + 3];
|
||||
}
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_L8:
|
||||
case D3DFMT_A8:
|
||||
case D3DFMT_A4L4:
|
||||
{
|
||||
const u8 *pIn = buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_R5G6B5:
|
||||
{
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_A8L8:
|
||||
{
|
||||
if (bExpand) { // I8
|
||||
const u8 *pIn = buffer;
|
||||
// TODO(XK): Find a better way that does not involve either unpacking
|
||||
// or downsampling (i.e. A4L4)
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
for(int i = 0; i < width * 2; i += 2) {
|
||||
pBits[i] = pIn[i / 2];
|
||||
pBits[i + 1] = pIn[i / 2];
|
||||
}
|
||||
pIn += pitch;
|
||||
}
|
||||
} else { // IA8
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_DXT1:
|
||||
memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
|
||||
break;
|
||||
}
|
||||
pTexture->UnlockRect(level);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
// 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 "DX9_D3DBase.h"
|
||||
#include "DX9_D3DTexture.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int levels)
|
||||
{
|
||||
u32* pBuffer = (u32*)buffer;
|
||||
LPDIRECT3DTEXTURE9 pTexture;
|
||||
|
||||
// crazy bitmagic, sorry :)
|
||||
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
|
||||
bool bExpand = false;
|
||||
|
||||
if (fmt == D3DFMT_A8P8) {
|
||||
fmt = D3DFMT_A8L8;
|
||||
bExpand = true;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
// TODO(ector): Allow mipmaps for non-pow textures on newer cards?
|
||||
// TODO(ector): Use the game-specified mipmaps?
|
||||
if (levels > 0)
|
||||
hr = dev->CreateTexture(width, height, levels, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
else
|
||||
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return 0;
|
||||
int level = 0;
|
||||
D3DLOCKED_RECT Lock;
|
||||
pTexture->LockRect(level, &Lock, NULL, 0);
|
||||
switch (fmt)
|
||||
{
|
||||
case D3DFMT_L8:
|
||||
case D3DFMT_A8:
|
||||
case D3DFMT_A4L4:
|
||||
{
|
||||
const u8 *pIn = buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_R5G6B5:
|
||||
{
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_A8L8:
|
||||
{
|
||||
if (bExpand) { // I8
|
||||
const u8 *pIn = buffer;
|
||||
// TODO(XK): Find a better way that does not involve either unpacking
|
||||
// or downsampling (i.e. A4L4)
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
for(int i = 0; i < width * 2; i += 2) {
|
||||
pBits[i] = pIn[i / 2];
|
||||
pBits[i + 1] = pIn[i / 2];
|
||||
}
|
||||
pIn += pitch;
|
||||
}
|
||||
} else { // IA8
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_A8R8G8B8:
|
||||
{
|
||||
if(pitch * 4 == Lock.Pitch && !swap_r_b)
|
||||
{
|
||||
memcpy(Lock.pBits,buffer,Lock.Pitch*height);
|
||||
}
|
||||
else
|
||||
{
|
||||
u32* pIn = pBuffer;
|
||||
if (!swap_r_b) {
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 4);
|
||||
pIn += pitch;
|
||||
}
|
||||
} else {
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8 *pIn8 = (u8 *)pIn;
|
||||
u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
for (int x = 0; x < width * 4; x += 4) {
|
||||
pBits[x + 0] = pIn8[x + 2];
|
||||
pBits[x + 1] = pIn8[x + 1];
|
||||
pBits[x + 2] = pIn8[x + 0];
|
||||
pBits[x + 3] = pIn8[x + 3];
|
||||
}
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_DXT1:
|
||||
memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
|
||||
break;
|
||||
default:
|
||||
PanicAlert("D3D: Invalid texture format %i", fmt);
|
||||
}
|
||||
pTexture->UnlockRect(level);
|
||||
return pTexture;
|
||||
}
|
||||
|
||||
LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 pTexture;
|
||||
// crazy bitmagic, sorry :)
|
||||
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
|
||||
bool bExpand = false;
|
||||
HRESULT hr;
|
||||
// TODO(ector): Allow mipmaps for non-pow textures on newer cards?
|
||||
// TODO(ector): Use the game-specified mipmaps?
|
||||
if (!isPow2)
|
||||
hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
else
|
||||
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return 0;
|
||||
return pTexture;
|
||||
}
|
||||
|
||||
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level)
|
||||
{
|
||||
u32* pBuffer = (u32*)buffer;
|
||||
D3DLOCKED_RECT Lock;
|
||||
pTexture->LockRect(level, &Lock, NULL, 0);
|
||||
u32* pIn = pBuffer;
|
||||
|
||||
bool bExpand = false;
|
||||
|
||||
if (fmt == D3DFMT_A8P8) {
|
||||
fmt = D3DFMT_A8L8;
|
||||
bExpand = true;
|
||||
}
|
||||
switch (fmt)
|
||||
{
|
||||
case D3DFMT_A8R8G8B8:
|
||||
if(pitch * 4 == Lock.Pitch && !swap_r_b)
|
||||
{
|
||||
memcpy(Lock.pBits, pBuffer, Lock.Pitch*height);
|
||||
}
|
||||
else if (!swap_r_b)
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 4);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8 *pIn8 = (u8 *)pIn;
|
||||
u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
for (int x = 0; x < width * 4; x += 4)
|
||||
{
|
||||
pBits[x + 0] = pIn8[x + 2];
|
||||
pBits[x + 1] = pIn8[x + 1];
|
||||
pBits[x + 2] = pIn8[x + 0];
|
||||
pBits[x + 3] = pIn8[x + 3];
|
||||
}
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_L8:
|
||||
case D3DFMT_A8:
|
||||
case D3DFMT_A4L4:
|
||||
{
|
||||
const u8 *pIn = buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_R5G6B5:
|
||||
{
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_A8L8:
|
||||
{
|
||||
if (bExpand) { // I8
|
||||
const u8 *pIn = buffer;
|
||||
// TODO(XK): Find a better way that does not involve either unpacking
|
||||
// or downsampling (i.e. A4L4)
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
for(int i = 0; i < width * 2; i += 2) {
|
||||
pBits[i] = pIn[i / 2];
|
||||
pBits[i + 1] = pIn[i / 2];
|
||||
}
|
||||
pIn += pitch;
|
||||
}
|
||||
} else { // IA8
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_DXT1:
|
||||
memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
|
||||
break;
|
||||
}
|
||||
pTexture->UnlockRect(level);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt = D3DFMT_A8R8G8B8, bool swap_r_b = false, int levels = 1);
|
||||
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level = 0);
|
||||
LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height);
|
||||
LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height);
|
||||
LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt);
|
||||
}
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt = D3DFMT_A8R8G8B8, bool swap_r_b = false, int levels = 1);
|
||||
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level = 0);
|
||||
LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height);
|
||||
LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height);
|
||||
LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,447 +1,447 @@
|
|||
// 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 "Common.h"
|
||||
#include "StringUtil.h"
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "DX9_D3DUtil.h"
|
||||
#include "DX9_Render.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
CD3DFont font;
|
||||
|
||||
#define MAX_NUM_VERTICES 50*6
|
||||
struct FONT2DVERTEX {
|
||||
float x,y,z;
|
||||
float rhw;
|
||||
u32 color;
|
||||
float tu, tv;
|
||||
};
|
||||
|
||||
#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
||||
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1)
|
||||
|
||||
inline FONT2DVERTEX InitFont2DVertex(float x, float y, u32 color, float tu, float tv)
|
||||
{
|
||||
FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv;
|
||||
return v;
|
||||
}
|
||||
|
||||
CD3DFont::CD3DFont()
|
||||
{
|
||||
m_pTexture = NULL;
|
||||
m_pVB = NULL;
|
||||
}
|
||||
|
||||
enum {m_dwTexWidth = 512, m_dwTexHeight = 512};
|
||||
|
||||
int CD3DFont::Init()
|
||||
{
|
||||
// Create vertex buffer for the letters
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = dev->CreateVertexBuffer(MAX_NUM_VERTICES*sizeof(FONT2DVERTEX),
|
||||
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &m_pVB, NULL)))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
m_fTextScale = 1.0f; // Draw fonts into texture without scaling
|
||||
|
||||
// Prepare to create a bitmap
|
||||
int *pBitmapBits;
|
||||
BITMAPINFO bmi;
|
||||
ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
|
||||
bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
|
||||
// Create a DC and a bitmap for the font
|
||||
HDC hDC = CreateCompatibleDC(NULL);
|
||||
HBITMAP hbmBitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (VOID**)&pBitmapBits, NULL, 0);
|
||||
SetMapMode(hDC, MM_TEXT);
|
||||
|
||||
// Create a font. By specifying ANTIALIASED_QUALITY, we might get an
|
||||
// antialiased font, but this is not guaranteed.
|
||||
// We definitely don't want to get it cleartype'd, anyway.
|
||||
int m_dwFontHeight = 24;
|
||||
int nHeight = -MulDiv(m_dwFontHeight, int(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72);
|
||||
int dwBold = FW_NORMAL; ///FW_BOLD
|
||||
HFONT hFont = CreateFont(nHeight, 0, 0, 0, dwBold, 0,
|
||||
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
|
||||
VARIABLE_PITCH, _T("Tahoma"));
|
||||
if (NULL == hFont)
|
||||
return E_FAIL;
|
||||
|
||||
HGDIOBJ hOldbmBitmap = SelectObject(hDC, hbmBitmap);
|
||||
HGDIOBJ hOldFont = SelectObject(hDC, hFont);
|
||||
|
||||
// Set text properties
|
||||
SetTextColor(hDC, 0xFFFFFF);
|
||||
SetBkColor (hDC, 0);
|
||||
SetTextAlign(hDC, TA_TOP);
|
||||
|
||||
// Loop through all printable character and output them to the bitmap..
|
||||
// Meanwhile, keep track of the corresponding tex coords for each character.
|
||||
int x = 0, y = 0;
|
||||
char str[2] = "\0";
|
||||
for (int c = 0; c < 127 - 32; c++)
|
||||
{
|
||||
str[0] = c + 32;
|
||||
SIZE size;
|
||||
GetTextExtentPoint32A(hDC, str, 1, &size);
|
||||
if ((int)(x+size.cx+1) > m_dwTexWidth)
|
||||
{
|
||||
x = 0;
|
||||
y += size.cy + 1;
|
||||
}
|
||||
|
||||
ExtTextOutA(hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL);
|
||||
m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth;
|
||||
m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight;
|
||||
m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth;
|
||||
m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight;
|
||||
|
||||
x += size.cx + 3; //3 to work around annoying ij conflict (part of the j ends up with the i)
|
||||
}
|
||||
|
||||
// Create a new texture for the font
|
||||
hr = dev->CreateTexture(m_dwTexWidth, m_dwTexHeight, 1, D3DUSAGE_DYNAMIC,
|
||||
D3DFMT_A4R4G4B4, D3DPOOL_DEFAULT, &m_pTexture, NULL);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("Failed to create font texture");
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Lock the surface and write the alpha values for the set pixels
|
||||
D3DLOCKED_RECT d3dlr;
|
||||
m_pTexture->LockRect(0, &d3dlr, 0, D3DLOCK_DISCARD);
|
||||
int bAlpha; // 4-bit measure of pixel intensity
|
||||
|
||||
for (y = 0; y < m_dwTexHeight; y++)
|
||||
{
|
||||
u16 *pDst16 = (u16*)((u8 *)d3dlr.pBits + y * d3dlr.Pitch);
|
||||
for (x = 0; x < m_dwTexWidth; x++)
|
||||
{
|
||||
bAlpha = ((pBitmapBits[m_dwTexWidth * y + x] & 0xff) >> 4);
|
||||
pDst16[x] = (bAlpha << 12) | 0x0fff;
|
||||
}
|
||||
}
|
||||
|
||||
// Done updating texture, so clean up used objects
|
||||
m_pTexture->UnlockRect(0);
|
||||
|
||||
SelectObject(hDC, hOldbmBitmap);
|
||||
DeleteObject(hbmBitmap);
|
||||
|
||||
SelectObject(hDC, hOldFont);
|
||||
DeleteObject(hFont);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int CD3DFont::Shutdown()
|
||||
{
|
||||
m_pVB->Release();
|
||||
m_pVB = NULL;
|
||||
m_pTexture->Release();
|
||||
m_pTexture = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
const int RS[6][2] =
|
||||
{
|
||||
{D3DRS_ALPHABLENDENABLE, TRUE},
|
||||
{D3DRS_SRCBLEND, D3DBLEND_SRCALPHA},
|
||||
{D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA},
|
||||
{D3DRS_CULLMODE, D3DCULL_NONE},
|
||||
{D3DRS_ZENABLE, FALSE},
|
||||
{D3DRS_FOGENABLE, FALSE},
|
||||
};
|
||||
const int TS[6][2] =
|
||||
{
|
||||
{D3DTSS_COLOROP, D3DTOP_MODULATE},
|
||||
{D3DTSS_COLORARG1, D3DTA_TEXTURE},
|
||||
{D3DTSS_COLORARG2, D3DTA_DIFFUSE },
|
||||
{D3DTSS_ALPHAOP, D3DTOP_MODULATE },
|
||||
{D3DTSS_ALPHAARG1, D3DTA_TEXTURE },
|
||||
{D3DTSS_ALPHAARG2, D3DTA_DIFFUSE },
|
||||
};
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 ps_old = NULL;
|
||||
static LPDIRECT3DVERTEXSHADER9 vs_old = NULL;
|
||||
|
||||
void RestoreShaders()
|
||||
{
|
||||
D3D::SetTexture(0, 0);
|
||||
D3D::RefreshVertexDeclaration();
|
||||
D3D::RefreshPixelShader();
|
||||
D3D::RefreshVertexShader();
|
||||
}
|
||||
|
||||
void RestoreRenderStates()
|
||||
{
|
||||
RestoreShaders();
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
D3D::RefreshRenderState((_D3DRENDERSTATETYPE)RS[i][0]);
|
||||
D3D::RefreshTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]));
|
||||
}
|
||||
}
|
||||
|
||||
void CD3DFont::SetRenderStates()
|
||||
{
|
||||
D3D::SetTexture(0, m_pTexture);
|
||||
|
||||
dev->SetPixelShader(0);
|
||||
dev->SetVertexShader(0);
|
||||
|
||||
dev->SetFVF(D3DFVF_FONT2DVERTEX);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
D3D::ChangeRenderState((_D3DRENDERSTATETYPE)RS[i][0], RS[i][1]);
|
||||
D3D::ChangeTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CD3DFont::DrawTextScaled(float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const char* strText, bool center)
|
||||
{
|
||||
if (!m_pVB)
|
||||
return 0;
|
||||
|
||||
SetRenderStates();
|
||||
dev->SetStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX));
|
||||
|
||||
float vpWidth = 1;
|
||||
float vpHeight = 1;
|
||||
|
||||
float sx = x*vpWidth-0.5f;
|
||||
float sy = y*vpHeight-0.5f;
|
||||
|
||||
float fStartX = sx;
|
||||
|
||||
float invLineHeight = 1.0f / ((m_fTexCoords[0][3] - m_fTexCoords[0][1]) * m_dwTexHeight);
|
||||
// Fill vertex buffer
|
||||
FONT2DVERTEX* pVertices;
|
||||
int dwNumTriangles = 0L;
|
||||
m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
|
||||
|
||||
const char *oldstrText=strText;
|
||||
//First, let's measure the text
|
||||
float tw=0;
|
||||
float mx=0;
|
||||
float maxx=0;
|
||||
|
||||
while (*strText)
|
||||
{
|
||||
char c = *strText++;
|
||||
|
||||
if (c == ('\n'))
|
||||
mx = 0;
|
||||
if (c < (' '))
|
||||
continue;
|
||||
|
||||
float tx1 = m_fTexCoords[c-32][0];
|
||||
float tx2 = m_fTexCoords[c-32][2];
|
||||
|
||||
float w = (tx2-tx1)*m_dwTexWidth;
|
||||
w *= (fXScale*vpHeight)*invLineHeight;
|
||||
mx += w + spacing*fXScale*vpWidth;
|
||||
if (mx > maxx) maxx = mx;
|
||||
}
|
||||
|
||||
float offset = -maxx/2;
|
||||
strText = oldstrText;
|
||||
//Then let's draw it
|
||||
if (center)
|
||||
{
|
||||
sx+=offset;
|
||||
fStartX+=offset;
|
||||
}
|
||||
|
||||
float wScale = (fXScale*vpHeight)*invLineHeight;
|
||||
float hScale = (fYScale*vpHeight)*invLineHeight;
|
||||
|
||||
while (*strText)
|
||||
{
|
||||
char c = *strText++;
|
||||
|
||||
if (c == ('\n'))
|
||||
{
|
||||
sx = fStartX;
|
||||
sy += fYScale*vpHeight;
|
||||
}
|
||||
if (c < (' '))
|
||||
continue;
|
||||
|
||||
c-=32;
|
||||
float tx1 = m_fTexCoords[c][0];
|
||||
float ty1 = m_fTexCoords[c][1];
|
||||
float tx2 = m_fTexCoords[c][2];
|
||||
float ty2 = m_fTexCoords[c][3];
|
||||
|
||||
float w = (tx2-tx1)*m_dwTexWidth;
|
||||
float h = (ty2-ty1)*m_dwTexHeight;
|
||||
|
||||
w *= wScale;
|
||||
h *= hScale;
|
||||
|
||||
FONT2DVERTEX v[6];
|
||||
v[0] = InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2);
|
||||
v[1] = InitFont2DVertex(sx, sy, dwColor, tx1, ty1);
|
||||
v[2] = InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2);
|
||||
v[3] = InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1);
|
||||
v[4] = v[2];
|
||||
v[5] = v[1];
|
||||
|
||||
memcpy(pVertices, v, 6*sizeof(FONT2DVERTEX));
|
||||
|
||||
pVertices+=6;
|
||||
dwNumTriangles += 2;
|
||||
|
||||
if (dwNumTriangles * 3 > (MAX_NUM_VERTICES - 6))
|
||||
{
|
||||
// Unlock, render, and relock the vertex buffer
|
||||
m_pVB->Unlock();
|
||||
dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles);
|
||||
m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
|
||||
dwNumTriangles = 0;
|
||||
}
|
||||
|
||||
sx += w + spacing*fXScale*vpWidth;
|
||||
}
|
||||
|
||||
// Unlock and render the vertex buffer
|
||||
m_pVB->Unlock();
|
||||
if (dwNumTriangles > 0)
|
||||
dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles);
|
||||
RestoreRenderStates();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2)
|
||||
{
|
||||
struct Q2DVertex { float x,y,z,rhw;u32 color;float u,v,w,h; } coords[4] = {
|
||||
{x1-0.5f, y1-0.5f, 0, 1, color, u1, v1},
|
||||
{x2-0.5f, y1-0.5f, 0, 1, color, u2, v1},
|
||||
{x2-0.5f, y2-0.5f, 0, 1, color, u2, v2},
|
||||
{x1-0.5f, y2-0.5f, 0, 1, color, u1, v2},
|
||||
};
|
||||
dev->SetPixelShader(0);
|
||||
dev->SetVertexShader(0);
|
||||
dev->SetVertexDeclaration(NULL);
|
||||
dev->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
void drawShadedTexQuad(IDirect3DTexture9 *texture,
|
||||
const RECT *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
int DestWidth,
|
||||
int DestHeight,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader)
|
||||
{
|
||||
float sw = 1.0f /(float) SourceWidth;
|
||||
float sh = 1.0f /(float) SourceHeight;
|
||||
float dw = 1.0f /(float) DestWidth;
|
||||
float dh = 1.0f /(float) DestHeight;
|
||||
float u1=((float)rSource->left) * sw;
|
||||
float u2=((float)rSource->right) * sw;
|
||||
float v1=((float)rSource->top) * sh;
|
||||
float v2=((float)rSource->bottom) * sh;
|
||||
|
||||
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,L,T,R,B; } coords[4] = {
|
||||
{-1.0f - dw,-1.0f + dh, 0.0f,1.0f, u1, v2, sw, sh,u1,v1,u2,v2},
|
||||
{-1.0f - dw, 1.0f + dh, 0.0f,1.0f, u1, v1, sw, sh,u1,v1,u2,v2},
|
||||
{ 1.0f - dw,-1.0f + dh, 0.0f,1.0f, u2, v2, sw, sh,u1,v1,u2,v2},
|
||||
{ 1.0f - dw, 1.0f + dh, 0.0f,1.0f, u2, v1, sw, sh,u1,v1,u2,v2}
|
||||
};
|
||||
dev->SetVertexShader(Vshader);
|
||||
dev->SetPixelShader(PShader);
|
||||
D3D::SetTexture(0, texture);
|
||||
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2));
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
|
||||
const MathUtil::Rectangle<float> *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
const MathUtil::Rectangle<float> *rDest,
|
||||
int DestWidth,
|
||||
int DestHeight,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader)
|
||||
{
|
||||
float sw = 1.0f /(float) SourceWidth;
|
||||
float sh = 1.0f /(float) SourceHeight;
|
||||
float dw = 1.0f /(float) DestWidth;
|
||||
float dh = 1.0f /(float) DestHeight;
|
||||
float u1= rSource->left * sw;
|
||||
float u2= rSource->right * sw;
|
||||
float v1= rSource->top * sh;
|
||||
float v2= rSource->bottom * sh;
|
||||
|
||||
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,L,T,R,B; } coords[4] = {
|
||||
{ rDest->left - dw , rDest->top + dh, 1.0f,1.0f, u1, v2, sw, sh,u1,v1,u2,v2},
|
||||
{ rDest->left - dw , rDest->bottom + dh, 1.0f,1.0f, u1, v1, sw, sh,u1,v1,u2,v2},
|
||||
{ rDest->right - dw , rDest->top + dh, 1.0f,1.0f, u2, v2, sw, sh,u1,v1,u2,v2},
|
||||
{ rDest->right - dw , rDest->bottom + dh, 1.0f,1.0f, u2, v1, sw, sh,u1,v1,u2,v2}
|
||||
};
|
||||
dev->SetVertexShader(Vshader);
|
||||
dev->SetPixelShader(PShader);
|
||||
D3D::SetTexture(0, texture);
|
||||
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2));
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader)
|
||||
{
|
||||
struct Q2DVertex { float x,y,z,rhw;u32 color;} coords[4] = {
|
||||
{-1.0f, 1.0f, z, 1.0f, Color},
|
||||
{ 1.0f, 1.0f, z, 1.0f, Color},
|
||||
{ 1.0f, -1.0f, z, 1.0f, Color},
|
||||
{-1.0f, -1.0f, z, 1.0f, Color}
|
||||
};
|
||||
dev->SetVertexShader(Vshader);
|
||||
dev->SetPixelShader(PShader);
|
||||
dev->SetFVF(D3DFVF_XYZW | D3DFVF_DIFFUSE);
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
// 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 "Common.h"
|
||||
#include "StringUtil.h"
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "DX9_D3DUtil.h"
|
||||
#include "DX9_Render.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
CD3DFont font;
|
||||
|
||||
#define MAX_NUM_VERTICES 50*6
|
||||
struct FONT2DVERTEX {
|
||||
float x,y,z;
|
||||
float rhw;
|
||||
u32 color;
|
||||
float tu, tv;
|
||||
};
|
||||
|
||||
#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
||||
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1)
|
||||
|
||||
inline FONT2DVERTEX InitFont2DVertex(float x, float y, u32 color, float tu, float tv)
|
||||
{
|
||||
FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv;
|
||||
return v;
|
||||
}
|
||||
|
||||
CD3DFont::CD3DFont()
|
||||
{
|
||||
m_pTexture = NULL;
|
||||
m_pVB = NULL;
|
||||
}
|
||||
|
||||
enum {m_dwTexWidth = 512, m_dwTexHeight = 512};
|
||||
|
||||
int CD3DFont::Init()
|
||||
{
|
||||
// Create vertex buffer for the letters
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = dev->CreateVertexBuffer(MAX_NUM_VERTICES*sizeof(FONT2DVERTEX),
|
||||
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &m_pVB, NULL)))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
m_fTextScale = 1.0f; // Draw fonts into texture without scaling
|
||||
|
||||
// Prepare to create a bitmap
|
||||
int *pBitmapBits;
|
||||
BITMAPINFO bmi;
|
||||
ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
|
||||
bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
|
||||
// Create a DC and a bitmap for the font
|
||||
HDC hDC = CreateCompatibleDC(NULL);
|
||||
HBITMAP hbmBitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (VOID**)&pBitmapBits, NULL, 0);
|
||||
SetMapMode(hDC, MM_TEXT);
|
||||
|
||||
// Create a font. By specifying ANTIALIASED_QUALITY, we might get an
|
||||
// antialiased font, but this is not guaranteed.
|
||||
// We definitely don't want to get it cleartype'd, anyway.
|
||||
int m_dwFontHeight = 24;
|
||||
int nHeight = -MulDiv(m_dwFontHeight, int(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72);
|
||||
int dwBold = FW_NORMAL; ///FW_BOLD
|
||||
HFONT hFont = CreateFont(nHeight, 0, 0, 0, dwBold, 0,
|
||||
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
|
||||
VARIABLE_PITCH, _T("Tahoma"));
|
||||
if (NULL == hFont)
|
||||
return E_FAIL;
|
||||
|
||||
HGDIOBJ hOldbmBitmap = SelectObject(hDC, hbmBitmap);
|
||||
HGDIOBJ hOldFont = SelectObject(hDC, hFont);
|
||||
|
||||
// Set text properties
|
||||
SetTextColor(hDC, 0xFFFFFF);
|
||||
SetBkColor (hDC, 0);
|
||||
SetTextAlign(hDC, TA_TOP);
|
||||
|
||||
// Loop through all printable character and output them to the bitmap..
|
||||
// Meanwhile, keep track of the corresponding tex coords for each character.
|
||||
int x = 0, y = 0;
|
||||
char str[2] = "\0";
|
||||
for (int c = 0; c < 127 - 32; c++)
|
||||
{
|
||||
str[0] = c + 32;
|
||||
SIZE size;
|
||||
GetTextExtentPoint32A(hDC, str, 1, &size);
|
||||
if ((int)(x+size.cx+1) > m_dwTexWidth)
|
||||
{
|
||||
x = 0;
|
||||
y += size.cy + 1;
|
||||
}
|
||||
|
||||
ExtTextOutA(hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL);
|
||||
m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth;
|
||||
m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight;
|
||||
m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth;
|
||||
m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight;
|
||||
|
||||
x += size.cx + 3; //3 to work around annoying ij conflict (part of the j ends up with the i)
|
||||
}
|
||||
|
||||
// Create a new texture for the font
|
||||
hr = dev->CreateTexture(m_dwTexWidth, m_dwTexHeight, 1, D3DUSAGE_DYNAMIC,
|
||||
D3DFMT_A4R4G4B4, D3DPOOL_DEFAULT, &m_pTexture, NULL);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("Failed to create font texture");
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Lock the surface and write the alpha values for the set pixels
|
||||
D3DLOCKED_RECT d3dlr;
|
||||
m_pTexture->LockRect(0, &d3dlr, 0, D3DLOCK_DISCARD);
|
||||
int bAlpha; // 4-bit measure of pixel intensity
|
||||
|
||||
for (y = 0; y < m_dwTexHeight; y++)
|
||||
{
|
||||
u16 *pDst16 = (u16*)((u8 *)d3dlr.pBits + y * d3dlr.Pitch);
|
||||
for (x = 0; x < m_dwTexWidth; x++)
|
||||
{
|
||||
bAlpha = ((pBitmapBits[m_dwTexWidth * y + x] & 0xff) >> 4);
|
||||
pDst16[x] = (bAlpha << 12) | 0x0fff;
|
||||
}
|
||||
}
|
||||
|
||||
// Done updating texture, so clean up used objects
|
||||
m_pTexture->UnlockRect(0);
|
||||
|
||||
SelectObject(hDC, hOldbmBitmap);
|
||||
DeleteObject(hbmBitmap);
|
||||
|
||||
SelectObject(hDC, hOldFont);
|
||||
DeleteObject(hFont);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int CD3DFont::Shutdown()
|
||||
{
|
||||
m_pVB->Release();
|
||||
m_pVB = NULL;
|
||||
m_pTexture->Release();
|
||||
m_pTexture = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
const int RS[6][2] =
|
||||
{
|
||||
{D3DRS_ALPHABLENDENABLE, TRUE},
|
||||
{D3DRS_SRCBLEND, D3DBLEND_SRCALPHA},
|
||||
{D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA},
|
||||
{D3DRS_CULLMODE, D3DCULL_NONE},
|
||||
{D3DRS_ZENABLE, FALSE},
|
||||
{D3DRS_FOGENABLE, FALSE},
|
||||
};
|
||||
const int TS[6][2] =
|
||||
{
|
||||
{D3DTSS_COLOROP, D3DTOP_MODULATE},
|
||||
{D3DTSS_COLORARG1, D3DTA_TEXTURE},
|
||||
{D3DTSS_COLORARG2, D3DTA_DIFFUSE },
|
||||
{D3DTSS_ALPHAOP, D3DTOP_MODULATE },
|
||||
{D3DTSS_ALPHAARG1, D3DTA_TEXTURE },
|
||||
{D3DTSS_ALPHAARG2, D3DTA_DIFFUSE },
|
||||
};
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 ps_old = NULL;
|
||||
static LPDIRECT3DVERTEXSHADER9 vs_old = NULL;
|
||||
|
||||
void RestoreShaders()
|
||||
{
|
||||
D3D::SetTexture(0, 0);
|
||||
D3D::RefreshVertexDeclaration();
|
||||
D3D::RefreshPixelShader();
|
||||
D3D::RefreshVertexShader();
|
||||
}
|
||||
|
||||
void RestoreRenderStates()
|
||||
{
|
||||
RestoreShaders();
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
D3D::RefreshRenderState((_D3DRENDERSTATETYPE)RS[i][0]);
|
||||
D3D::RefreshTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]));
|
||||
}
|
||||
}
|
||||
|
||||
void CD3DFont::SetRenderStates()
|
||||
{
|
||||
D3D::SetTexture(0, m_pTexture);
|
||||
|
||||
dev->SetPixelShader(0);
|
||||
dev->SetVertexShader(0);
|
||||
|
||||
dev->SetFVF(D3DFVF_FONT2DVERTEX);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
D3D::ChangeRenderState((_D3DRENDERSTATETYPE)RS[i][0], RS[i][1]);
|
||||
D3D::ChangeTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CD3DFont::DrawTextScaled(float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const char* strText, bool center)
|
||||
{
|
||||
if (!m_pVB)
|
||||
return 0;
|
||||
|
||||
SetRenderStates();
|
||||
dev->SetStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX));
|
||||
|
||||
float vpWidth = 1;
|
||||
float vpHeight = 1;
|
||||
|
||||
float sx = x*vpWidth-0.5f;
|
||||
float sy = y*vpHeight-0.5f;
|
||||
|
||||
float fStartX = sx;
|
||||
|
||||
float invLineHeight = 1.0f / ((m_fTexCoords[0][3] - m_fTexCoords[0][1]) * m_dwTexHeight);
|
||||
// Fill vertex buffer
|
||||
FONT2DVERTEX* pVertices;
|
||||
int dwNumTriangles = 0L;
|
||||
m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
|
||||
|
||||
const char *oldstrText=strText;
|
||||
//First, let's measure the text
|
||||
float tw=0;
|
||||
float mx=0;
|
||||
float maxx=0;
|
||||
|
||||
while (*strText)
|
||||
{
|
||||
char c = *strText++;
|
||||
|
||||
if (c == ('\n'))
|
||||
mx = 0;
|
||||
if (c < (' '))
|
||||
continue;
|
||||
|
||||
float tx1 = m_fTexCoords[c-32][0];
|
||||
float tx2 = m_fTexCoords[c-32][2];
|
||||
|
||||
float w = (tx2-tx1)*m_dwTexWidth;
|
||||
w *= (fXScale*vpHeight)*invLineHeight;
|
||||
mx += w + spacing*fXScale*vpWidth;
|
||||
if (mx > maxx) maxx = mx;
|
||||
}
|
||||
|
||||
float offset = -maxx/2;
|
||||
strText = oldstrText;
|
||||
//Then let's draw it
|
||||
if (center)
|
||||
{
|
||||
sx+=offset;
|
||||
fStartX+=offset;
|
||||
}
|
||||
|
||||
float wScale = (fXScale*vpHeight)*invLineHeight;
|
||||
float hScale = (fYScale*vpHeight)*invLineHeight;
|
||||
|
||||
while (*strText)
|
||||
{
|
||||
char c = *strText++;
|
||||
|
||||
if (c == ('\n'))
|
||||
{
|
||||
sx = fStartX;
|
||||
sy += fYScale*vpHeight;
|
||||
}
|
||||
if (c < (' '))
|
||||
continue;
|
||||
|
||||
c-=32;
|
||||
float tx1 = m_fTexCoords[c][0];
|
||||
float ty1 = m_fTexCoords[c][1];
|
||||
float tx2 = m_fTexCoords[c][2];
|
||||
float ty2 = m_fTexCoords[c][3];
|
||||
|
||||
float w = (tx2-tx1)*m_dwTexWidth;
|
||||
float h = (ty2-ty1)*m_dwTexHeight;
|
||||
|
||||
w *= wScale;
|
||||
h *= hScale;
|
||||
|
||||
FONT2DVERTEX v[6];
|
||||
v[0] = InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2);
|
||||
v[1] = InitFont2DVertex(sx, sy, dwColor, tx1, ty1);
|
||||
v[2] = InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2);
|
||||
v[3] = InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1);
|
||||
v[4] = v[2];
|
||||
v[5] = v[1];
|
||||
|
||||
memcpy(pVertices, v, 6*sizeof(FONT2DVERTEX));
|
||||
|
||||
pVertices+=6;
|
||||
dwNumTriangles += 2;
|
||||
|
||||
if (dwNumTriangles * 3 > (MAX_NUM_VERTICES - 6))
|
||||
{
|
||||
// Unlock, render, and relock the vertex buffer
|
||||
m_pVB->Unlock();
|
||||
dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles);
|
||||
m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
|
||||
dwNumTriangles = 0;
|
||||
}
|
||||
|
||||
sx += w + spacing*fXScale*vpWidth;
|
||||
}
|
||||
|
||||
// Unlock and render the vertex buffer
|
||||
m_pVB->Unlock();
|
||||
if (dwNumTriangles > 0)
|
||||
dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles);
|
||||
RestoreRenderStates();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2)
|
||||
{
|
||||
struct Q2DVertex { float x,y,z,rhw;u32 color;float u,v,w,h; } coords[4] = {
|
||||
{x1-0.5f, y1-0.5f, 0, 1, color, u1, v1},
|
||||
{x2-0.5f, y1-0.5f, 0, 1, color, u2, v1},
|
||||
{x2-0.5f, y2-0.5f, 0, 1, color, u2, v2},
|
||||
{x1-0.5f, y2-0.5f, 0, 1, color, u1, v2},
|
||||
};
|
||||
dev->SetPixelShader(0);
|
||||
dev->SetVertexShader(0);
|
||||
dev->SetVertexDeclaration(NULL);
|
||||
dev->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
void drawShadedTexQuad(IDirect3DTexture9 *texture,
|
||||
const RECT *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
int DestWidth,
|
||||
int DestHeight,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader)
|
||||
{
|
||||
float sw = 1.0f /(float) SourceWidth;
|
||||
float sh = 1.0f /(float) SourceHeight;
|
||||
float dw = 1.0f /(float) DestWidth;
|
||||
float dh = 1.0f /(float) DestHeight;
|
||||
float u1=((float)rSource->left) * sw;
|
||||
float u2=((float)rSource->right) * sw;
|
||||
float v1=((float)rSource->top) * sh;
|
||||
float v2=((float)rSource->bottom) * sh;
|
||||
|
||||
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,L,T,R,B; } coords[4] = {
|
||||
{-1.0f - dw,-1.0f + dh, 0.0f,1.0f, u1, v2, sw, sh,u1,v1,u2,v2},
|
||||
{-1.0f - dw, 1.0f + dh, 0.0f,1.0f, u1, v1, sw, sh,u1,v1,u2,v2},
|
||||
{ 1.0f - dw,-1.0f + dh, 0.0f,1.0f, u2, v2, sw, sh,u1,v1,u2,v2},
|
||||
{ 1.0f - dw, 1.0f + dh, 0.0f,1.0f, u2, v1, sw, sh,u1,v1,u2,v2}
|
||||
};
|
||||
dev->SetVertexShader(Vshader);
|
||||
dev->SetPixelShader(PShader);
|
||||
D3D::SetTexture(0, texture);
|
||||
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2));
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
|
||||
const MathUtil::Rectangle<float> *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
const MathUtil::Rectangle<float> *rDest,
|
||||
int DestWidth,
|
||||
int DestHeight,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader)
|
||||
{
|
||||
float sw = 1.0f /(float) SourceWidth;
|
||||
float sh = 1.0f /(float) SourceHeight;
|
||||
float dw = 1.0f /(float) DestWidth;
|
||||
float dh = 1.0f /(float) DestHeight;
|
||||
float u1= rSource->left * sw;
|
||||
float u2= rSource->right * sw;
|
||||
float v1= rSource->top * sh;
|
||||
float v2= rSource->bottom * sh;
|
||||
|
||||
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,L,T,R,B; } coords[4] = {
|
||||
{ rDest->left - dw , rDest->top + dh, 1.0f,1.0f, u1, v2, sw, sh,u1,v1,u2,v2},
|
||||
{ rDest->left - dw , rDest->bottom + dh, 1.0f,1.0f, u1, v1, sw, sh,u1,v1,u2,v2},
|
||||
{ rDest->right - dw , rDest->top + dh, 1.0f,1.0f, u2, v2, sw, sh,u1,v1,u2,v2},
|
||||
{ rDest->right - dw , rDest->bottom + dh, 1.0f,1.0f, u2, v1, sw, sh,u1,v1,u2,v2}
|
||||
};
|
||||
dev->SetVertexShader(Vshader);
|
||||
dev->SetPixelShader(PShader);
|
||||
D3D::SetTexture(0, texture);
|
||||
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2));
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader)
|
||||
{
|
||||
struct Q2DVertex { float x,y,z,rhw;u32 color;} coords[4] = {
|
||||
{-1.0f, 1.0f, z, 1.0f, Color},
|
||||
{ 1.0f, 1.0f, z, 1.0f, Color},
|
||||
{ 1.0f, -1.0f, z, 1.0f, Color},
|
||||
{-1.0f, -1.0f, z, 1.0f, Color}
|
||||
};
|
||||
dev->SetVertexShader(Vshader);
|
||||
dev->SetPixelShader(PShader);
|
||||
dev->SetFVF(D3DFVF_XYZW | D3DFVF_DIFFUSE);
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
|
|
|
@ -1,88 +1,88 @@
|
|||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include <math.h>
|
||||
#include <MathUtil.h>
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
// Font creation flags
|
||||
#define D3DFONT_BOLD 0x0001
|
||||
#define D3DFONT_ITALIC 0x0002
|
||||
|
||||
// Font rendering flags
|
||||
#define D3DFONT_CENTERED 0x0001
|
||||
|
||||
//a cut-down variant of the DXSDK CD3DFont class
|
||||
class CD3DFont
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 m_pTexture; // The d3d texture for this font
|
||||
LPDIRECT3DVERTEXBUFFER9 m_pVB; // VertexBuffer for rendering text
|
||||
//int m_dwTexWidth; // Texture dimensions
|
||||
//int m_dwTexHeight;
|
||||
float m_fTextScale;
|
||||
float m_fTexCoords[128-32][4];
|
||||
|
||||
public:
|
||||
CD3DFont();
|
||||
// 2D (no longer 3D) text drawing function
|
||||
// Initializing and destroying device-dependent objects
|
||||
void SetRenderStates();
|
||||
int Init();
|
||||
int Shutdown();
|
||||
int DrawTextScaled( float x, float y,
|
||||
float fXScale, float fYScale,
|
||||
float spacing, u32 dwColor,
|
||||
const char* strText, bool center=true );
|
||||
|
||||
|
||||
// Constructor / destructor
|
||||
//~CD3DFont();
|
||||
};
|
||||
|
||||
extern CD3DFont font;
|
||||
|
||||
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1=0, float v1=0, float u2=1, float v2=1);
|
||||
void drawShadedTexQuad(IDirect3DTexture9 *texture,
|
||||
const RECT *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
int DestWidth,
|
||||
int DestHeight,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader);
|
||||
void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
|
||||
const MathUtil::Rectangle<float> *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
const MathUtil::Rectangle<float> *rDest,
|
||||
int DestWidth,
|
||||
int DestHeight,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader);
|
||||
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader);
|
||||
void SaveRenderStates();
|
||||
void RestoreRenderStates();
|
||||
}
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include <math.h>
|
||||
#include <MathUtil.h>
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
// Font creation flags
|
||||
#define D3DFONT_BOLD 0x0001
|
||||
#define D3DFONT_ITALIC 0x0002
|
||||
|
||||
// Font rendering flags
|
||||
#define D3DFONT_CENTERED 0x0001
|
||||
|
||||
//a cut-down variant of the DXSDK CD3DFont class
|
||||
class CD3DFont
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 m_pTexture; // The d3d texture for this font
|
||||
LPDIRECT3DVERTEXBUFFER9 m_pVB; // VertexBuffer for rendering text
|
||||
//int m_dwTexWidth; // Texture dimensions
|
||||
//int m_dwTexHeight;
|
||||
float m_fTextScale;
|
||||
float m_fTexCoords[128-32][4];
|
||||
|
||||
public:
|
||||
CD3DFont();
|
||||
// 2D (no longer 3D) text drawing function
|
||||
// Initializing and destroying device-dependent objects
|
||||
void SetRenderStates();
|
||||
int Init();
|
||||
int Shutdown();
|
||||
int DrawTextScaled( float x, float y,
|
||||
float fXScale, float fYScale,
|
||||
float spacing, u32 dwColor,
|
||||
const char* strText, bool center=true );
|
||||
|
||||
|
||||
// Constructor / destructor
|
||||
//~CD3DFont();
|
||||
};
|
||||
|
||||
extern CD3DFont font;
|
||||
|
||||
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1=0, float v1=0, float u2=1, float v2=1);
|
||||
void drawShadedTexQuad(IDirect3DTexture9 *texture,
|
||||
const RECT *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
int DestWidth,
|
||||
int DestHeight,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader);
|
||||
void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
|
||||
const MathUtil::Rectangle<float> *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
const MathUtil::Rectangle<float> *rDest,
|
||||
int DestWidth,
|
||||
int DestHeight,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader);
|
||||
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader);
|
||||
void SaveRenderStates();
|
||||
void RestoreRenderStates();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,285 +1,285 @@
|
|||
// 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 "DX9_D3DBase.h"
|
||||
#include "DX9_Render.h"
|
||||
#include "DX9_FramebufferManager.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "DX9_PixelShaderCache.h"
|
||||
#include "DX9_VertexShaderCache.h"
|
||||
#include "DX9_TextureConverter.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
#undef CHECK
|
||||
#define CHECK(hr, Message, ...) if (FAILED(hr)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); }
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
XFBSource FramebufferManager::m_realXFBSource;
|
||||
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_color_texture;
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_colorRead_texture;
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_depth_texture;
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_depthRead_texture;
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_surface;
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_surface;
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_ReadBuffer;
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_ReadBuffer;
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_OffScreenReadBuffer;
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_OffScreenReadBuffer;
|
||||
|
||||
D3DFORMAT FramebufferManager::s_efb_color_surface_Format;
|
||||
D3DFORMAT FramebufferManager::s_efb_depth_surface_Format;
|
||||
D3DFORMAT FramebufferManager::s_efb_depth_ReadBuffer_Format;
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorRTSurface()
|
||||
{
|
||||
return s_efb_color_surface;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthRTSurface()
|
||||
{
|
||||
return s_efb_depth_surface;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorOffScreenRTSurface()
|
||||
{
|
||||
return s_efb_color_OffScreenReadBuffer;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthOffScreenRTSurface()
|
||||
{
|
||||
return s_efb_depth_OffScreenReadBuffer;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorReadSurface()
|
||||
{
|
||||
return s_efb_color_ReadBuffer;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthReadSurface()
|
||||
{
|
||||
return s_efb_depth_ReadBuffer;
|
||||
}
|
||||
|
||||
D3DFORMAT FramebufferManager::GetEFBDepthRTSurfaceFormat()
|
||||
{
|
||||
return s_efb_depth_surface_Format;
|
||||
}
|
||||
|
||||
D3DFORMAT FramebufferManager::GetEFBDepthReadSurfaceFormat()
|
||||
{
|
||||
return s_efb_depth_ReadBuffer_Format;
|
||||
}
|
||||
|
||||
D3DFORMAT FramebufferManager::GetEFBColorRTSurfaceFormat()
|
||||
{
|
||||
return s_efb_color_surface_Format;
|
||||
}
|
||||
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
|
||||
{
|
||||
return s_efb_color_texture;
|
||||
}
|
||||
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBDepthTexture(const EFBRectangle &sourceRc)
|
||||
{
|
||||
return s_efb_depth_texture;
|
||||
}
|
||||
|
||||
FramebufferManager::FramebufferManager()
|
||||
{
|
||||
s_efb_color_texture = NULL;
|
||||
LPDIRECT3DTEXTURE9 s_efb_colorRead_texture = NULL;
|
||||
LPDIRECT3DTEXTURE9 s_efb_depth_texture = NULL;
|
||||
LPDIRECT3DTEXTURE9 s_efb_depthRead_texture = NULL;
|
||||
|
||||
LPDIRECT3DSURFACE9 s_efb_depth_surface = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_color_surface = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer = NULL;
|
||||
|
||||
D3DFORMAT s_efb_color_surface_Format = D3DFMT_FORCE_DWORD;
|
||||
D3DFORMAT s_efb_depth_surface_Format = D3DFMT_FORCE_DWORD;
|
||||
D3DFORMAT s_efb_depth_ReadBuffer_Format = D3DFMT_FORCE_DWORD;
|
||||
m_realXFBSource.texture = NULL;
|
||||
|
||||
// Simplest possible setup to start with.
|
||||
int target_width = Renderer::GetFullTargetWidth();
|
||||
int target_height = Renderer::GetFullTargetHeight();
|
||||
|
||||
s_efb_color_surface_Format = D3DFMT_A8R8G8B8;
|
||||
// Get the framebuffer texture
|
||||
HRESULT hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb_color_texture, NULL);
|
||||
if(s_efb_color_texture)
|
||||
{
|
||||
hr = s_efb_color_texture->GetSurfaceLevel(0, &s_efb_color_surface);
|
||||
}
|
||||
CHECK(hr, "Create color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||
hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb_colorRead_texture, NULL);
|
||||
CHECK(hr, "Create Color Read Texture (hr=%#x)", hr);
|
||||
if(s_efb_colorRead_texture)
|
||||
{
|
||||
s_efb_colorRead_texture->GetSurfaceLevel(0, &s_efb_color_ReadBuffer);
|
||||
}
|
||||
// Create an offscreen surface that we can lock to retrieve the data
|
||||
hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, s_efb_color_surface_Format, D3DPOOL_SYSTEMMEM, &s_efb_color_OffScreenReadBuffer, NULL);
|
||||
CHECK(hr, "Create offscreen color surface (hr=%#x)", hr);
|
||||
|
||||
// Select a Z-buffer format with hardware support
|
||||
D3DFORMAT *DepthTexFormats = new D3DFORMAT[5];
|
||||
DepthTexFormats[0] = FOURCC_INTZ;
|
||||
DepthTexFormats[1] = FOURCC_DF24;
|
||||
DepthTexFormats[2] = FOURCC_RAWZ;
|
||||
DepthTexFormats[3] = FOURCC_DF16;
|
||||
DepthTexFormats[4] = D3DFMT_D24X8;
|
||||
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
s_efb_depth_surface_Format = DepthTexFormats[i];
|
||||
// Create the framebuffer depth texture
|
||||
hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_DEPTHSTENCIL, s_efb_depth_surface_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb_depth_texture, NULL);
|
||||
if (!FAILED(hr))
|
||||
break;
|
||||
}
|
||||
CHECK(hr, "Framebuffer depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||
// Get the Surface
|
||||
if(s_efb_depth_texture)
|
||||
{
|
||||
s_efb_depth_texture->GetSurfaceLevel(0, &s_efb_depth_surface);
|
||||
}
|
||||
// Create a 4x4 pixel texture to work as a buffer for peeking
|
||||
if(s_efb_depth_surface_Format == FOURCC_RAWZ || s_efb_depth_surface_Format == D3DFMT_D24X8)
|
||||
{
|
||||
DepthTexFormats[0] = D3DFMT_A8R8G8B8;
|
||||
}
|
||||
else
|
||||
{
|
||||
DepthTexFormats[0] = D3DFMT_R32F;
|
||||
}
|
||||
DepthTexFormats[1] = D3DFMT_A8R8G8B8;
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
s_efb_depth_ReadBuffer_Format = DepthTexFormats[i];
|
||||
// Get the framebuffer Depth texture
|
||||
hr = D3D::dev->CreateTexture(4, 4, 1, D3DUSAGE_RENDERTARGET, s_efb_depth_ReadBuffer_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb_depthRead_texture, NULL);
|
||||
if (!FAILED(hr))
|
||||
break;
|
||||
}
|
||||
|
||||
CHECK(hr, "Create depth read texture (hr=%#x)", hr);
|
||||
if(s_efb_depthRead_texture)
|
||||
{
|
||||
s_efb_depthRead_texture->GetSurfaceLevel(0, &s_efb_depth_ReadBuffer);
|
||||
}
|
||||
// Create an offscreen surface that we can lock to retrieve the data
|
||||
hr = D3D::dev->CreateOffscreenPlainSurface(4, 4, s_efb_depth_ReadBuffer_Format, D3DPOOL_SYSTEMMEM, &s_efb_depth_OffScreenReadBuffer, NULL);
|
||||
CHECK(hr, "Create depth offscreen surface (hr=%#x)", hr);
|
||||
delete [] DepthTexFormats;
|
||||
}
|
||||
|
||||
FramebufferManager::~FramebufferManager()
|
||||
{
|
||||
SAFE_RELEASE(s_efb_depth_surface);
|
||||
SAFE_RELEASE(s_efb_color_surface);
|
||||
SAFE_RELEASE(s_efb_color_ReadBuffer);
|
||||
SAFE_RELEASE(s_efb_depth_ReadBuffer);
|
||||
SAFE_RELEASE(s_efb_color_OffScreenReadBuffer);
|
||||
SAFE_RELEASE(s_efb_depth_OffScreenReadBuffer);
|
||||
SAFE_RELEASE(s_efb_color_texture);
|
||||
SAFE_RELEASE(s_efb_colorRead_texture);
|
||||
SAFE_RELEASE(s_efb_depth_texture);
|
||||
SAFE_RELEASE(s_efb_depthRead_texture);
|
||||
|
||||
if (m_realXFBSource.texture)
|
||||
m_realXFBSource.texture->Release();
|
||||
m_realXFBSource.texture = NULL;
|
||||
}
|
||||
|
||||
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
// TODO:
|
||||
|
||||
//u8* xfb_in_ram = Memory_GetPtr(xfbAddr);
|
||||
//if (!xfb_in_ram)
|
||||
//{
|
||||
// WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
|
||||
// return;
|
||||
//}
|
||||
|
||||
//TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc);
|
||||
//TextureConverter::EncodeToRamYUYV(GetEFBColorTexture(sourceRc), targetRc, xfb_in_ram, fbWidth, fbHeight);
|
||||
}
|
||||
|
||||
const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||
{
|
||||
return NULL;
|
||||
|
||||
// TODO:
|
||||
//xfbCount = 1;
|
||||
|
||||
//m_realXFBSource.texWidth = fbWidth;
|
||||
//m_realXFBSource.texHeight = fbHeight;
|
||||
|
||||
//m_realXFBSource.srcAddr = xfbAddr;
|
||||
//m_realXFBSource.srcWidth = fbWidth;
|
||||
//m_realXFBSource.srcHeight = fbHeight;
|
||||
|
||||
//if (!m_realXFBSource.texture)
|
||||
//{
|
||||
// D3D::dev->CreateTexture(fbWidth, fbHeight, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
||||
// D3DPOOL_DEFAULT, &m_realXFBSource.texture, NULL);
|
||||
//}
|
||||
|
||||
//// Decode YUYV data from GameCube RAM
|
||||
//TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture);
|
||||
|
||||
//m_overlappingXFBArray[0] = &m_realXFBSource;
|
||||
|
||||
//return &m_overlappingXFBArray[0];
|
||||
}
|
||||
|
||||
XFBSourceBase *FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
|
||||
{
|
||||
XFBSource* const xfbs = new XFBSource;
|
||||
D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &xfbs->texture, NULL);
|
||||
|
||||
return xfbs;
|
||||
}
|
||||
|
||||
XFBSource::~XFBSource()
|
||||
{
|
||||
texture->Release();
|
||||
}
|
||||
|
||||
void XFBSource::CopyEFB(const TargetRectangle& efbSource)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// 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 "DX9_D3DBase.h"
|
||||
#include "DX9_Render.h"
|
||||
#include "DX9_FramebufferManager.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "DX9_PixelShaderCache.h"
|
||||
#include "DX9_VertexShaderCache.h"
|
||||
#include "DX9_TextureConverter.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
#undef CHECK
|
||||
#define CHECK(hr, Message, ...) if (FAILED(hr)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); }
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
XFBSource FramebufferManager::m_realXFBSource;
|
||||
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_color_texture;
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_colorRead_texture;
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_depth_texture;
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_depthRead_texture;
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_surface;
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_surface;
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_ReadBuffer;
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_ReadBuffer;
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_OffScreenReadBuffer;
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_OffScreenReadBuffer;
|
||||
|
||||
D3DFORMAT FramebufferManager::s_efb_color_surface_Format;
|
||||
D3DFORMAT FramebufferManager::s_efb_depth_surface_Format;
|
||||
D3DFORMAT FramebufferManager::s_efb_depth_ReadBuffer_Format;
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorRTSurface()
|
||||
{
|
||||
return s_efb_color_surface;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthRTSurface()
|
||||
{
|
||||
return s_efb_depth_surface;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorOffScreenRTSurface()
|
||||
{
|
||||
return s_efb_color_OffScreenReadBuffer;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthOffScreenRTSurface()
|
||||
{
|
||||
return s_efb_depth_OffScreenReadBuffer;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorReadSurface()
|
||||
{
|
||||
return s_efb_color_ReadBuffer;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthReadSurface()
|
||||
{
|
||||
return s_efb_depth_ReadBuffer;
|
||||
}
|
||||
|
||||
D3DFORMAT FramebufferManager::GetEFBDepthRTSurfaceFormat()
|
||||
{
|
||||
return s_efb_depth_surface_Format;
|
||||
}
|
||||
|
||||
D3DFORMAT FramebufferManager::GetEFBDepthReadSurfaceFormat()
|
||||
{
|
||||
return s_efb_depth_ReadBuffer_Format;
|
||||
}
|
||||
|
||||
D3DFORMAT FramebufferManager::GetEFBColorRTSurfaceFormat()
|
||||
{
|
||||
return s_efb_color_surface_Format;
|
||||
}
|
||||
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
|
||||
{
|
||||
return s_efb_color_texture;
|
||||
}
|
||||
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBDepthTexture(const EFBRectangle &sourceRc)
|
||||
{
|
||||
return s_efb_depth_texture;
|
||||
}
|
||||
|
||||
FramebufferManager::FramebufferManager()
|
||||
{
|
||||
s_efb_color_texture = NULL;
|
||||
LPDIRECT3DTEXTURE9 s_efb_colorRead_texture = NULL;
|
||||
LPDIRECT3DTEXTURE9 s_efb_depth_texture = NULL;
|
||||
LPDIRECT3DTEXTURE9 s_efb_depthRead_texture = NULL;
|
||||
|
||||
LPDIRECT3DSURFACE9 s_efb_depth_surface = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_color_surface = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer = NULL;
|
||||
|
||||
D3DFORMAT s_efb_color_surface_Format = D3DFMT_FORCE_DWORD;
|
||||
D3DFORMAT s_efb_depth_surface_Format = D3DFMT_FORCE_DWORD;
|
||||
D3DFORMAT s_efb_depth_ReadBuffer_Format = D3DFMT_FORCE_DWORD;
|
||||
m_realXFBSource.texture = NULL;
|
||||
|
||||
// Simplest possible setup to start with.
|
||||
int target_width = Renderer::GetFullTargetWidth();
|
||||
int target_height = Renderer::GetFullTargetHeight();
|
||||
|
||||
s_efb_color_surface_Format = D3DFMT_A8R8G8B8;
|
||||
// Get the framebuffer texture
|
||||
HRESULT hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb_color_texture, NULL);
|
||||
if(s_efb_color_texture)
|
||||
{
|
||||
hr = s_efb_color_texture->GetSurfaceLevel(0, &s_efb_color_surface);
|
||||
}
|
||||
CHECK(hr, "Create color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||
hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb_colorRead_texture, NULL);
|
||||
CHECK(hr, "Create Color Read Texture (hr=%#x)", hr);
|
||||
if(s_efb_colorRead_texture)
|
||||
{
|
||||
s_efb_colorRead_texture->GetSurfaceLevel(0, &s_efb_color_ReadBuffer);
|
||||
}
|
||||
// Create an offscreen surface that we can lock to retrieve the data
|
||||
hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, s_efb_color_surface_Format, D3DPOOL_SYSTEMMEM, &s_efb_color_OffScreenReadBuffer, NULL);
|
||||
CHECK(hr, "Create offscreen color surface (hr=%#x)", hr);
|
||||
|
||||
// Select a Z-buffer format with hardware support
|
||||
D3DFORMAT *DepthTexFormats = new D3DFORMAT[5];
|
||||
DepthTexFormats[0] = FOURCC_INTZ;
|
||||
DepthTexFormats[1] = FOURCC_DF24;
|
||||
DepthTexFormats[2] = FOURCC_RAWZ;
|
||||
DepthTexFormats[3] = FOURCC_DF16;
|
||||
DepthTexFormats[4] = D3DFMT_D24X8;
|
||||
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
s_efb_depth_surface_Format = DepthTexFormats[i];
|
||||
// Create the framebuffer depth texture
|
||||
hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_DEPTHSTENCIL, s_efb_depth_surface_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb_depth_texture, NULL);
|
||||
if (!FAILED(hr))
|
||||
break;
|
||||
}
|
||||
CHECK(hr, "Framebuffer depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||
// Get the Surface
|
||||
if(s_efb_depth_texture)
|
||||
{
|
||||
s_efb_depth_texture->GetSurfaceLevel(0, &s_efb_depth_surface);
|
||||
}
|
||||
// Create a 4x4 pixel texture to work as a buffer for peeking
|
||||
if(s_efb_depth_surface_Format == FOURCC_RAWZ || s_efb_depth_surface_Format == D3DFMT_D24X8)
|
||||
{
|
||||
DepthTexFormats[0] = D3DFMT_A8R8G8B8;
|
||||
}
|
||||
else
|
||||
{
|
||||
DepthTexFormats[0] = D3DFMT_R32F;
|
||||
}
|
||||
DepthTexFormats[1] = D3DFMT_A8R8G8B8;
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
s_efb_depth_ReadBuffer_Format = DepthTexFormats[i];
|
||||
// Get the framebuffer Depth texture
|
||||
hr = D3D::dev->CreateTexture(4, 4, 1, D3DUSAGE_RENDERTARGET, s_efb_depth_ReadBuffer_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb_depthRead_texture, NULL);
|
||||
if (!FAILED(hr))
|
||||
break;
|
||||
}
|
||||
|
||||
CHECK(hr, "Create depth read texture (hr=%#x)", hr);
|
||||
if(s_efb_depthRead_texture)
|
||||
{
|
||||
s_efb_depthRead_texture->GetSurfaceLevel(0, &s_efb_depth_ReadBuffer);
|
||||
}
|
||||
// Create an offscreen surface that we can lock to retrieve the data
|
||||
hr = D3D::dev->CreateOffscreenPlainSurface(4, 4, s_efb_depth_ReadBuffer_Format, D3DPOOL_SYSTEMMEM, &s_efb_depth_OffScreenReadBuffer, NULL);
|
||||
CHECK(hr, "Create depth offscreen surface (hr=%#x)", hr);
|
||||
delete [] DepthTexFormats;
|
||||
}
|
||||
|
||||
FramebufferManager::~FramebufferManager()
|
||||
{
|
||||
SAFE_RELEASE(s_efb_depth_surface);
|
||||
SAFE_RELEASE(s_efb_color_surface);
|
||||
SAFE_RELEASE(s_efb_color_ReadBuffer);
|
||||
SAFE_RELEASE(s_efb_depth_ReadBuffer);
|
||||
SAFE_RELEASE(s_efb_color_OffScreenReadBuffer);
|
||||
SAFE_RELEASE(s_efb_depth_OffScreenReadBuffer);
|
||||
SAFE_RELEASE(s_efb_color_texture);
|
||||
SAFE_RELEASE(s_efb_colorRead_texture);
|
||||
SAFE_RELEASE(s_efb_depth_texture);
|
||||
SAFE_RELEASE(s_efb_depthRead_texture);
|
||||
|
||||
if (m_realXFBSource.texture)
|
||||
m_realXFBSource.texture->Release();
|
||||
m_realXFBSource.texture = NULL;
|
||||
}
|
||||
|
||||
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
// TODO:
|
||||
|
||||
//u8* xfb_in_ram = Memory_GetPtr(xfbAddr);
|
||||
//if (!xfb_in_ram)
|
||||
//{
|
||||
// WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
|
||||
// return;
|
||||
//}
|
||||
|
||||
//TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc);
|
||||
//TextureConverter::EncodeToRamYUYV(GetEFBColorTexture(sourceRc), targetRc, xfb_in_ram, fbWidth, fbHeight);
|
||||
}
|
||||
|
||||
const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||
{
|
||||
return NULL;
|
||||
|
||||
// TODO:
|
||||
//xfbCount = 1;
|
||||
|
||||
//m_realXFBSource.texWidth = fbWidth;
|
||||
//m_realXFBSource.texHeight = fbHeight;
|
||||
|
||||
//m_realXFBSource.srcAddr = xfbAddr;
|
||||
//m_realXFBSource.srcWidth = fbWidth;
|
||||
//m_realXFBSource.srcHeight = fbHeight;
|
||||
|
||||
//if (!m_realXFBSource.texture)
|
||||
//{
|
||||
// D3D::dev->CreateTexture(fbWidth, fbHeight, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
||||
// D3DPOOL_DEFAULT, &m_realXFBSource.texture, NULL);
|
||||
//}
|
||||
|
||||
//// Decode YUYV data from GameCube RAM
|
||||
//TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture);
|
||||
|
||||
//m_overlappingXFBArray[0] = &m_realXFBSource;
|
||||
|
||||
//return &m_overlappingXFBArray[0];
|
||||
}
|
||||
|
||||
XFBSourceBase *FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
|
||||
{
|
||||
XFBSource* const xfbs = new XFBSource;
|
||||
D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &xfbs->texture, NULL);
|
||||
|
||||
return xfbs;
|
||||
}
|
||||
|
||||
XFBSource::~XFBSource()
|
||||
{
|
||||
texture->Release();
|
||||
}
|
||||
|
||||
void XFBSource::CopyEFB(const TargetRectangle& efbSource)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,130 +1,130 @@
|
|||
// 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 _FRAMEBUFFERMANAGER_D3D_H_
|
||||
#define _FRAMEBUFFERMANAGER_D3D_H_
|
||||
|
||||
#include <list>
|
||||
#include "DX9_D3DBase.h"
|
||||
|
||||
#include "../FramebufferManager.h"
|
||||
|
||||
// On the GameCube, the game sends a request for the graphics processor to
|
||||
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
||||
// called the XFB (External Framebuffer). The size and location of the XFB is
|
||||
// decided at the time of the copy, and the format is always YUYV. The video
|
||||
// interface is given a pointer to the XFB, which will be decoded and
|
||||
// displayed on the TV.
|
||||
//
|
||||
// There are two ways for Dolphin to emulate this:
|
||||
//
|
||||
// Real XFB mode:
|
||||
//
|
||||
// Dolphin will behave like the GameCube and encode the EFB to
|
||||
// a portion of GameCube RAM. The emulated video interface will decode the data
|
||||
// for output to the screen.
|
||||
//
|
||||
// Advantages: Behaves exactly like the GameCube.
|
||||
// Disadvantages: Resolution will be limited.
|
||||
//
|
||||
// Virtual XFB mode:
|
||||
//
|
||||
// When a request is made to copy the EFB to an XFB, Dolphin
|
||||
// will remember the RAM location and size of the XFB in a Virtual XFB list.
|
||||
// The video interface will look up the XFB in the list and use the enhanced
|
||||
// data stored there, if available.
|
||||
//
|
||||
// Advantages: Enables high resolution graphics, better than real hardware.
|
||||
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
|
||||
// possible but uncommon), the Virtual XFB will not capture this information.
|
||||
|
||||
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
||||
// virtualize.
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
const int MAX_VIRTUAL_XFB = 8;
|
||||
|
||||
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
||||
{
|
||||
return !((aLower >= bUpper) || (bLower >= aUpper));
|
||||
}
|
||||
|
||||
struct XFBSource : public XFBSourceBase
|
||||
{
|
||||
XFBSource() : texture(NULL) {}
|
||||
~XFBSource();
|
||||
|
||||
void CopyEFB(const TargetRectangle& efbSource);
|
||||
|
||||
LPDIRECT3DTEXTURE9 texture;
|
||||
};
|
||||
|
||||
class FramebufferManager : public ::FramebufferManagerBase
|
||||
{
|
||||
public:
|
||||
FramebufferManager();
|
||||
~FramebufferManager();
|
||||
|
||||
void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
|
||||
XFBSourceBase *CreateXFBSource(unsigned int target_width, unsigned int target_height);
|
||||
|
||||
static LPDIRECT3DTEXTURE9 GetEFBColorTexture(const EFBRectangle& sourceRc);
|
||||
static LPDIRECT3DTEXTURE9 GetEFBDepthTexture(const EFBRectangle& sourceRc);
|
||||
|
||||
static LPDIRECT3DSURFACE9 GetEFBColorRTSurface();
|
||||
static LPDIRECT3DSURFACE9 GetEFBDepthRTSurface();
|
||||
static LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface();
|
||||
static LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface();
|
||||
static D3DFORMAT GetEFBDepthRTSurfaceFormat();
|
||||
static D3DFORMAT GetEFBColorRTSurfaceFormat();
|
||||
static D3DFORMAT GetEFBDepthReadSurfaceFormat();
|
||||
static LPDIRECT3DSURFACE9 GetEFBColorReadSurface();
|
||||
static LPDIRECT3DSURFACE9 GetEFBDepthReadSurface();
|
||||
|
||||
private:
|
||||
|
||||
void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
const XFBSource** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||
|
||||
static XFBSource m_realXFBSource; // Only used in Real XFB mode
|
||||
|
||||
const XFBSource* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
||||
|
||||
static LPDIRECT3DTEXTURE9 s_efb_color_texture;//Texture thats contains the color data of the render target
|
||||
static LPDIRECT3DTEXTURE9 s_efb_colorRead_texture;//1 pixel texture for temporal data store
|
||||
static LPDIRECT3DTEXTURE9 s_efb_depth_texture;//Texture thats contains the depth data of the render target
|
||||
static LPDIRECT3DTEXTURE9 s_efb_depthRead_texture;//4 pixel texture for temporal data store
|
||||
|
||||
static LPDIRECT3DSURFACE9 s_efb_depth_surface;//Depth Surface
|
||||
static LPDIRECT3DSURFACE9 s_efb_color_surface;//Color Surface
|
||||
static LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer;//Surface 0 of s_efb_colorRead_texture
|
||||
static LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer;//Surface 0 of s_efb_depthRead_texture
|
||||
static LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
|
||||
static LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
|
||||
|
||||
static D3DFORMAT s_efb_color_surface_Format;//Format of the color Surface
|
||||
static D3DFORMAT s_efb_depth_surface_Format;//Format of the Depth Surface
|
||||
static D3DFORMAT s_efb_depth_ReadBuffer_Format;//Format of the Depth color Read Surface
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
// 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 _FRAMEBUFFERMANAGER_D3D_H_
|
||||
#define _FRAMEBUFFERMANAGER_D3D_H_
|
||||
|
||||
#include <list>
|
||||
#include "DX9_D3DBase.h"
|
||||
|
||||
#include "../FramebufferManager.h"
|
||||
|
||||
// On the GameCube, the game sends a request for the graphics processor to
|
||||
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
||||
// called the XFB (External Framebuffer). The size and location of the XFB is
|
||||
// decided at the time of the copy, and the format is always YUYV. The video
|
||||
// interface is given a pointer to the XFB, which will be decoded and
|
||||
// displayed on the TV.
|
||||
//
|
||||
// There are two ways for Dolphin to emulate this:
|
||||
//
|
||||
// Real XFB mode:
|
||||
//
|
||||
// Dolphin will behave like the GameCube and encode the EFB to
|
||||
// a portion of GameCube RAM. The emulated video interface will decode the data
|
||||
// for output to the screen.
|
||||
//
|
||||
// Advantages: Behaves exactly like the GameCube.
|
||||
// Disadvantages: Resolution will be limited.
|
||||
//
|
||||
// Virtual XFB mode:
|
||||
//
|
||||
// When a request is made to copy the EFB to an XFB, Dolphin
|
||||
// will remember the RAM location and size of the XFB in a Virtual XFB list.
|
||||
// The video interface will look up the XFB in the list and use the enhanced
|
||||
// data stored there, if available.
|
||||
//
|
||||
// Advantages: Enables high resolution graphics, better than real hardware.
|
||||
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
|
||||
// possible but uncommon), the Virtual XFB will not capture this information.
|
||||
|
||||
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
||||
// virtualize.
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
const int MAX_VIRTUAL_XFB = 8;
|
||||
|
||||
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
||||
{
|
||||
return !((aLower >= bUpper) || (bLower >= aUpper));
|
||||
}
|
||||
|
||||
struct XFBSource : public XFBSourceBase
|
||||
{
|
||||
XFBSource() : texture(NULL) {}
|
||||
~XFBSource();
|
||||
|
||||
void CopyEFB(const TargetRectangle& efbSource);
|
||||
|
||||
LPDIRECT3DTEXTURE9 texture;
|
||||
};
|
||||
|
||||
class FramebufferManager : public ::FramebufferManagerBase
|
||||
{
|
||||
public:
|
||||
FramebufferManager();
|
||||
~FramebufferManager();
|
||||
|
||||
void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
|
||||
XFBSourceBase *CreateXFBSource(unsigned int target_width, unsigned int target_height);
|
||||
|
||||
static LPDIRECT3DTEXTURE9 GetEFBColorTexture(const EFBRectangle& sourceRc);
|
||||
static LPDIRECT3DTEXTURE9 GetEFBDepthTexture(const EFBRectangle& sourceRc);
|
||||
|
||||
static LPDIRECT3DSURFACE9 GetEFBColorRTSurface();
|
||||
static LPDIRECT3DSURFACE9 GetEFBDepthRTSurface();
|
||||
static LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface();
|
||||
static LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface();
|
||||
static D3DFORMAT GetEFBDepthRTSurfaceFormat();
|
||||
static D3DFORMAT GetEFBColorRTSurfaceFormat();
|
||||
static D3DFORMAT GetEFBDepthReadSurfaceFormat();
|
||||
static LPDIRECT3DSURFACE9 GetEFBColorReadSurface();
|
||||
static LPDIRECT3DSURFACE9 GetEFBDepthReadSurface();
|
||||
|
||||
private:
|
||||
|
||||
void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
const XFBSource** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||
|
||||
static XFBSource m_realXFBSource; // Only used in Real XFB mode
|
||||
|
||||
const XFBSource* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
||||
|
||||
static LPDIRECT3DTEXTURE9 s_efb_color_texture;//Texture thats contains the color data of the render target
|
||||
static LPDIRECT3DTEXTURE9 s_efb_colorRead_texture;//1 pixel texture for temporal data store
|
||||
static LPDIRECT3DTEXTURE9 s_efb_depth_texture;//Texture thats contains the depth data of the render target
|
||||
static LPDIRECT3DTEXTURE9 s_efb_depthRead_texture;//4 pixel texture for temporal data store
|
||||
|
||||
static LPDIRECT3DSURFACE9 s_efb_depth_surface;//Depth Surface
|
||||
static LPDIRECT3DSURFACE9 s_efb_color_surface;//Color Surface
|
||||
static LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer;//Surface 0 of s_efb_colorRead_texture
|
||||
static LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer;//Surface 0 of s_efb_depthRead_texture
|
||||
static LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
|
||||
static LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
|
||||
|
||||
static D3DFORMAT s_efb_color_surface_Format;//Format of the color Surface
|
||||
static D3DFORMAT s_efb_depth_surface_Format;//Format of the Depth Surface
|
||||
static D3DFORMAT s_efb_depth_ReadBuffer_Format;//Format of the Depth color Read Surface
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,178 +1,178 @@
|
|||
|
||||
// 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 "DX9_D3DBase.h"
|
||||
|
||||
#include "Profiler.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
#include "CPMemory.h"
|
||||
|
||||
#include "DX9_VertexManager.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class D3DVertexFormat : public NativeVertexFormat
|
||||
{
|
||||
LPDIRECT3DVERTEXDECLARATION9 d3d_decl;
|
||||
|
||||
public:
|
||||
D3DVertexFormat();
|
||||
~D3DVertexFormat();
|
||||
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
|
||||
virtual void SetupVertexPointers() const;
|
||||
};
|
||||
|
||||
NativeVertexFormat *VertexManager::CreateNativeVertexFormat()
|
||||
{
|
||||
return new D3DVertexFormat();
|
||||
}
|
||||
|
||||
D3DVertexFormat::D3DVertexFormat() : d3d_decl(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
D3DVertexFormat::~D3DVertexFormat()
|
||||
{
|
||||
if (d3d_decl)
|
||||
{
|
||||
d3d_decl->Release();
|
||||
d3d_decl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
D3DDECLTYPE VarToD3D(VarType t, int size)
|
||||
{
|
||||
if (t < 0 || t > 4) {
|
||||
PanicAlert("VarToD3D: Invalid VarType %i", t);
|
||||
}
|
||||
static const D3DDECLTYPE lookup1[5] = {
|
||||
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT1,
|
||||
};
|
||||
static const D3DDECLTYPE lookup2[5] = {
|
||||
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_SHORT2N, D3DDECLTYPE_USHORT2N, D3DDECLTYPE_FLOAT2,
|
||||
};
|
||||
static const D3DDECLTYPE lookup3[5] = {
|
||||
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT3,
|
||||
};
|
||||
// Sadly, D3D9 has no SBYTE4N. D3D10 does, though.
|
||||
static const D3DDECLTYPE lookup4[5] = {
|
||||
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UBYTE4N, D3DDECLTYPE_SHORT4N, D3DDECLTYPE_USHORT4N, D3DDECLTYPE_FLOAT4,
|
||||
};
|
||||
D3DDECLTYPE retval = D3DDECLTYPE_UNUSED;
|
||||
switch (size) {
|
||||
case 1: retval = lookup1[t]; break;
|
||||
case 2: retval = lookup2[t]; break;
|
||||
case 3: retval = lookup3[t]; break;
|
||||
case 4: retval = lookup4[t]; break;
|
||||
default: PanicAlert("VarToD3D: size wrong (%i)", size); break;
|
||||
}
|
||||
if (retval == D3DDECLTYPE_UNUSED) {
|
||||
PanicAlert("VarToD3D: Invalid type/size combo %i , %i", (int)t, size);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
|
||||
{
|
||||
vertex_stride = _vtx_decl.stride;
|
||||
|
||||
D3DVERTEXELEMENT9 *elems = new D3DVERTEXELEMENT9[32];
|
||||
memset(elems, 0, sizeof(D3DVERTEXELEMENT9) * 32);
|
||||
|
||||
// There's only one stream and it's 0, so the above memset takes care of that - no need to set Stream.
|
||||
// Same for method.
|
||||
|
||||
// So, here we go. First position:
|
||||
int elem_idx = 0;
|
||||
elems[elem_idx].Offset = 0; // Positions are always first, at position 0. Always float3.
|
||||
elems[elem_idx].Type = D3DDECLTYPE_FLOAT3;
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_POSITION;
|
||||
++elem_idx;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (_vtx_decl.normal_offset[i] > 0)
|
||||
{
|
||||
elems[elem_idx].Offset = _vtx_decl.normal_offset[i];
|
||||
elems[elem_idx].Type = VarToD3D(_vtx_decl.normal_gl_type, _vtx_decl.normal_gl_size);
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_NORMAL;
|
||||
elems[elem_idx].UsageIndex = i;
|
||||
++elem_idx;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (_vtx_decl.color_offset[i] > 0)
|
||||
{
|
||||
elems[elem_idx].Offset = _vtx_decl.color_offset[i];
|
||||
elems[elem_idx].Type = VarToD3D(_vtx_decl.color_gl_type, 4);
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_COLOR;
|
||||
elems[elem_idx].UsageIndex = i;
|
||||
++elem_idx;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (_vtx_decl.texcoord_offset[i] > 0)
|
||||
{
|
||||
elems[elem_idx].Offset = _vtx_decl.texcoord_offset[i];
|
||||
elems[elem_idx].Type = VarToD3D(_vtx_decl.texcoord_gl_type[i], _vtx_decl.texcoord_size[i]);
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_TEXCOORD;
|
||||
elems[elem_idx].UsageIndex = i;
|
||||
++elem_idx;
|
||||
}
|
||||
}
|
||||
|
||||
if (_vtx_decl.posmtx_offset != -1)
|
||||
{
|
||||
elems[elem_idx].Offset = _vtx_decl.posmtx_offset;
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_BLENDINDICES;
|
||||
elems[elem_idx].Type = D3DDECLTYPE_D3DCOLOR;
|
||||
elems[elem_idx].UsageIndex = 0;
|
||||
++elem_idx;
|
||||
}
|
||||
|
||||
// End marker
|
||||
elems[elem_idx].Stream = 0xff;
|
||||
elems[elem_idx].Type = D3DDECLTYPE_UNUSED;
|
||||
++elem_idx;
|
||||
|
||||
if (FAILED(D3D::dev->CreateVertexDeclaration(elems, &d3d_decl)))
|
||||
{
|
||||
PanicAlert("Failed to create D3D vertex declaration!");
|
||||
return;
|
||||
}
|
||||
delete [] elems;
|
||||
}
|
||||
|
||||
void D3DVertexFormat::SetupVertexPointers() const
|
||||
{
|
||||
if (d3d_decl)
|
||||
D3D::SetVertexDeclaration(d3d_decl);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "invalid d3d decl");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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 "DX9_D3DBase.h"
|
||||
|
||||
#include "Profiler.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
#include "CPMemory.h"
|
||||
|
||||
#include "DX9_VertexManager.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class D3DVertexFormat : public NativeVertexFormat
|
||||
{
|
||||
LPDIRECT3DVERTEXDECLARATION9 d3d_decl;
|
||||
|
||||
public:
|
||||
D3DVertexFormat();
|
||||
~D3DVertexFormat();
|
||||
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
|
||||
virtual void SetupVertexPointers() const;
|
||||
};
|
||||
|
||||
NativeVertexFormat *VertexManager::CreateNativeVertexFormat()
|
||||
{
|
||||
return new D3DVertexFormat();
|
||||
}
|
||||
|
||||
D3DVertexFormat::D3DVertexFormat() : d3d_decl(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
D3DVertexFormat::~D3DVertexFormat()
|
||||
{
|
||||
if (d3d_decl)
|
||||
{
|
||||
d3d_decl->Release();
|
||||
d3d_decl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
D3DDECLTYPE VarToD3D(VarType t, int size)
|
||||
{
|
||||
if (t < 0 || t > 4) {
|
||||
PanicAlert("VarToD3D: Invalid VarType %i", t);
|
||||
}
|
||||
static const D3DDECLTYPE lookup1[5] = {
|
||||
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT1,
|
||||
};
|
||||
static const D3DDECLTYPE lookup2[5] = {
|
||||
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_SHORT2N, D3DDECLTYPE_USHORT2N, D3DDECLTYPE_FLOAT2,
|
||||
};
|
||||
static const D3DDECLTYPE lookup3[5] = {
|
||||
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT3,
|
||||
};
|
||||
// Sadly, D3D9 has no SBYTE4N. D3D10 does, though.
|
||||
static const D3DDECLTYPE lookup4[5] = {
|
||||
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UBYTE4N, D3DDECLTYPE_SHORT4N, D3DDECLTYPE_USHORT4N, D3DDECLTYPE_FLOAT4,
|
||||
};
|
||||
D3DDECLTYPE retval = D3DDECLTYPE_UNUSED;
|
||||
switch (size) {
|
||||
case 1: retval = lookup1[t]; break;
|
||||
case 2: retval = lookup2[t]; break;
|
||||
case 3: retval = lookup3[t]; break;
|
||||
case 4: retval = lookup4[t]; break;
|
||||
default: PanicAlert("VarToD3D: size wrong (%i)", size); break;
|
||||
}
|
||||
if (retval == D3DDECLTYPE_UNUSED) {
|
||||
PanicAlert("VarToD3D: Invalid type/size combo %i , %i", (int)t, size);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
|
||||
{
|
||||
vertex_stride = _vtx_decl.stride;
|
||||
|
||||
D3DVERTEXELEMENT9 *elems = new D3DVERTEXELEMENT9[32];
|
||||
memset(elems, 0, sizeof(D3DVERTEXELEMENT9) * 32);
|
||||
|
||||
// There's only one stream and it's 0, so the above memset takes care of that - no need to set Stream.
|
||||
// Same for method.
|
||||
|
||||
// So, here we go. First position:
|
||||
int elem_idx = 0;
|
||||
elems[elem_idx].Offset = 0; // Positions are always first, at position 0. Always float3.
|
||||
elems[elem_idx].Type = D3DDECLTYPE_FLOAT3;
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_POSITION;
|
||||
++elem_idx;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (_vtx_decl.normal_offset[i] > 0)
|
||||
{
|
||||
elems[elem_idx].Offset = _vtx_decl.normal_offset[i];
|
||||
elems[elem_idx].Type = VarToD3D(_vtx_decl.normal_gl_type, _vtx_decl.normal_gl_size);
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_NORMAL;
|
||||
elems[elem_idx].UsageIndex = i;
|
||||
++elem_idx;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (_vtx_decl.color_offset[i] > 0)
|
||||
{
|
||||
elems[elem_idx].Offset = _vtx_decl.color_offset[i];
|
||||
elems[elem_idx].Type = VarToD3D(_vtx_decl.color_gl_type, 4);
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_COLOR;
|
||||
elems[elem_idx].UsageIndex = i;
|
||||
++elem_idx;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (_vtx_decl.texcoord_offset[i] > 0)
|
||||
{
|
||||
elems[elem_idx].Offset = _vtx_decl.texcoord_offset[i];
|
||||
elems[elem_idx].Type = VarToD3D(_vtx_decl.texcoord_gl_type[i], _vtx_decl.texcoord_size[i]);
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_TEXCOORD;
|
||||
elems[elem_idx].UsageIndex = i;
|
||||
++elem_idx;
|
||||
}
|
||||
}
|
||||
|
||||
if (_vtx_decl.posmtx_offset != -1)
|
||||
{
|
||||
elems[elem_idx].Offset = _vtx_decl.posmtx_offset;
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_BLENDINDICES;
|
||||
elems[elem_idx].Type = D3DDECLTYPE_D3DCOLOR;
|
||||
elems[elem_idx].UsageIndex = 0;
|
||||
++elem_idx;
|
||||
}
|
||||
|
||||
// End marker
|
||||
elems[elem_idx].Stream = 0xff;
|
||||
elems[elem_idx].Type = D3DDECLTYPE_UNUSED;
|
||||
++elem_idx;
|
||||
|
||||
if (FAILED(D3D::dev->CreateVertexDeclaration(elems, &d3d_decl)))
|
||||
{
|
||||
PanicAlert("Failed to create D3D vertex declaration!");
|
||||
return;
|
||||
}
|
||||
delete [] elems;
|
||||
}
|
||||
|
||||
void D3DVertexFormat::SetupVertexPointers() const
|
||||
{
|
||||
if (d3d_decl)
|
||||
D3D::SetVertexDeclaration(d3d_decl);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "invalid d3d decl");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,392 +1,392 @@
|
|||
// 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 <map>
|
||||
#include <set>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Hash.h"
|
||||
#include "FileUtil.h"
|
||||
#include "LinearDiskCache.h"
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "DX9_D3DShader.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "PixelShaderGen.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "DX9_PixelShaderCache.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "BPMemory.h"
|
||||
#include "XFMemory.h"
|
||||
#include "ImageWrite.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
//#include "Debugger/Debugger.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
|
||||
const PixelShaderCache::PSCacheEntry *PixelShaderCache::last_entry;
|
||||
|
||||
static LinearDiskCache g_ps_disk_cache;
|
||||
static std::set<u32> unique_shaders;
|
||||
|
||||
#define MAX_SSAA_SHADERS 3
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 s_ColorMatrixProgram[MAX_SSAA_SHADERS];
|
||||
static LPDIRECT3DPIXELSHADER9 s_ColorCopyProgram[MAX_SSAA_SHADERS];
|
||||
static LPDIRECT3DPIXELSHADER9 s_DepthMatrixProgram[MAX_SSAA_SHADERS];
|
||||
static LPDIRECT3DPIXELSHADER9 s_ClearProgram = 0;
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorMatrixProgram(int SSAAMode)
|
||||
{
|
||||
return s_ColorMatrixProgram[SSAAMode % MAX_SSAA_SHADERS];
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetDepthMatrixProgram(int SSAAMode)
|
||||
{
|
||||
return s_DepthMatrixProgram[SSAAMode % MAX_SSAA_SHADERS];
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorCopyProgram(int SSAAMode)
|
||||
{
|
||||
return s_ColorCopyProgram[SSAAMode % MAX_SSAA_SHADERS];
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetClearProgram()
|
||||
{
|
||||
return s_ClearProgram;
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
float f[4] = { f1, f2, f3, f4 };
|
||||
D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
D3D::dev->SetPixelShaderConstantF(const_number, f, count);
|
||||
}
|
||||
|
||||
class PixelShaderCacheInserter : public LinearDiskCacheReader {
|
||||
public:
|
||||
void Read(const u8 *key, int key_size, const u8 *value, int value_size)
|
||||
{
|
||||
PIXELSHADERUID uid;
|
||||
if (key_size != sizeof(uid)) {
|
||||
ERROR_LOG(VIDEO, "Wrong key size in pixel shader cache");
|
||||
return;
|
||||
}
|
||||
memcpy(&uid, key, key_size);
|
||||
PixelShaderCache::InsertByteCode(uid, value, value_size, false);
|
||||
}
|
||||
};
|
||||
|
||||
PixelShaderCache::PixelShaderCache()
|
||||
{
|
||||
//program used for clear screen
|
||||
char pprog[3072];
|
||||
sprintf(pprog, "void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
" in float4 incol0 : COLOR0){\n"
|
||||
"ocol0 = incol0;\n"
|
||||
"}\n");
|
||||
s_ClearProgram = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//Used for Copy/resolve the color buffer
|
||||
//1 Sample
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float2 uv0 : TEXCOORD0){\n"
|
||||
"ocol0 = tex2D(samp0,uv0);\n"
|
||||
"}\n");
|
||||
s_ColorCopyProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//1 Samples SSAA
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float4 uv1 : TEXCOORD1){\n"
|
||||
"ocol0 = tex2D(samp0,uv0.xy);\n"
|
||||
"}\n");
|
||||
s_ColorCopyProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//4 Samples SSAA
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float4 uv1 : TEXCOORD1,\n"
|
||||
"in float4 uv2 : TEXCOORD2,\n"
|
||||
"in float4 uv3 : TEXCOORD3){\n"
|
||||
"ocol0 = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25;\n"
|
||||
"}\n");
|
||||
s_ColorCopyProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
|
||||
|
||||
//Color conversion Programs
|
||||
//1 sample
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
" in float2 uv0 : TEXCOORD0){\n"
|
||||
"float4 texcol = tex2D(samp0,uv0);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n",C_COLORMATRIX);
|
||||
s_ColorMatrixProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//1 samples SSAA
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float4 uv1 : TEXCOORD1){\n"
|
||||
"float4 texcol = tex2D(samp0,uv0.xy);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n",C_COLORMATRIX);
|
||||
s_ColorMatrixProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//4 samples SSAA
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float4 uv1 : TEXCOORD1,\n"
|
||||
"in float4 uv2 : TEXCOORD2,\n"
|
||||
"in float4 uv3 : TEXCOORD3){\n"
|
||||
"float4 texcol = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25f;\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n",C_COLORMATRIX);
|
||||
s_ColorMatrixProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//Depth copy programs
|
||||
//1 sample
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
" in float2 uv0 : TEXCOORD0){\n"
|
||||
"float4 texcol = tex2D(samp0,uv0);\n"
|
||||
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
|
||||
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n",C_COLORMATRIX);
|
||||
s_DepthMatrixProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//1 sample SSAA
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float4 uv1 : TEXCOORD1){\n"
|
||||
"float4 texcol = tex2D(samp0,uv0.xy);\n"
|
||||
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
|
||||
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n",C_COLORMATRIX);
|
||||
s_DepthMatrixProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//4 sample SSAA
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float4 uv1 : TEXCOORD1,\n"
|
||||
"in float4 uv2 : TEXCOORD2,\n"
|
||||
"in float4 uv3 : TEXCOORD3){\n"
|
||||
"float4 texcol = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25f;\n"
|
||||
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
|
||||
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n",C_COLORMATRIX);
|
||||
s_DepthMatrixProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
Clear();
|
||||
|
||||
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
|
||||
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
|
||||
|
||||
SETSTAT(stats.numPixelShadersCreated, 0);
|
||||
SETSTAT(stats.numPixelShadersAlive, 0);
|
||||
|
||||
char cache_filename[MAX_PATH];
|
||||
sprintf(cache_filename, "%sdx9-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
|
||||
PixelShaderCacheInserter inserter;
|
||||
int read_items = g_ps_disk_cache.OpenAndRead(cache_filename, &inserter);
|
||||
}
|
||||
|
||||
// ONLY to be used during shutdown.
|
||||
void PixelShaderCache::Clear()
|
||||
{
|
||||
PSCache::iterator iter = PixelShaders.begin();
|
||||
for (; iter != PixelShaders.end(); ++iter)
|
||||
iter->second.Destroy();
|
||||
PixelShaders.clear();
|
||||
|
||||
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
|
||||
}
|
||||
|
||||
PixelShaderCache::~PixelShaderCache()
|
||||
{
|
||||
for(int i = 0;i < MAX_SSAA_SHADERS; i++)
|
||||
{
|
||||
if (s_ColorMatrixProgram[i]) s_ColorMatrixProgram[i]->Release();
|
||||
s_ColorMatrixProgram[i] = NULL;
|
||||
if (s_ColorCopyProgram[i]) s_ColorCopyProgram[i]->Release();
|
||||
s_ColorCopyProgram[i] = NULL;
|
||||
if (s_DepthMatrixProgram[i]) s_DepthMatrixProgram[i]->Release();
|
||||
s_DepthMatrixProgram[i] = NULL;
|
||||
}
|
||||
if (s_ClearProgram) s_ClearProgram->Release();
|
||||
s_ClearProgram = NULL;
|
||||
|
||||
Clear();
|
||||
g_ps_disk_cache.Sync();
|
||||
g_ps_disk_cache.Close();
|
||||
|
||||
unique_shaders.clear();
|
||||
}
|
||||
|
||||
bool PixelShaderCache::SetShader(bool dstAlpha)
|
||||
{
|
||||
PIXELSHADERUID uid;
|
||||
GetPixelShaderId(&uid, dstAlpha);
|
||||
|
||||
// Is the shader already set?
|
||||
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
|
||||
{
|
||||
PSCache::const_iterator iter = PixelShaders.find(uid);
|
||||
if (iter != PixelShaders.end() && iter->second.shader)
|
||||
return true; // Sure, we're done.
|
||||
else
|
||||
return false; // ?? something is wrong.
|
||||
}
|
||||
|
||||
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
|
||||
|
||||
// Is the shader already in the cache?
|
||||
PSCache::iterator iter;
|
||||
iter = PixelShaders.find(uid);
|
||||
if (iter != PixelShaders.end())
|
||||
{
|
||||
iter->second.frameCount = frameCount;
|
||||
const PSCacheEntry &entry = iter->second;
|
||||
last_entry = &entry;
|
||||
|
||||
if (entry.shader)
|
||||
{
|
||||
D3D::SetPixelShader(entry.shader);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// OK, need to generate and compile it.
|
||||
const char *code = GeneratePixelShaderCode(dstAlpha, API_D3D9);
|
||||
|
||||
u32 code_hash = HashAdler32((const u8 *)code, strlen(code));
|
||||
unique_shaders.insert(code_hash);
|
||||
SETSTAT(stats.numUniquePixelShaders, unique_shaders.size());
|
||||
|
||||
#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), counter++);
|
||||
|
||||
SaveData(szTemp, code);
|
||||
}
|
||||
#endif
|
||||
|
||||
u8 *bytecode = 0;
|
||||
int bytecodelen = 0;
|
||||
if (!D3D::CompilePixelShader(code, (int)strlen(code), &bytecode, &bytecodelen)) {
|
||||
if (g_ActiveConfig.bShowShaderErrors)
|
||||
{
|
||||
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
|
||||
SaveData(szTemp, code);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Here we have the UID and the byte code. Insert it into the disk cache.
|
||||
g_ps_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen);
|
||||
g_ps_disk_cache.Sync();
|
||||
|
||||
// And insert it into the shader cache.
|
||||
bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
|
||||
delete [] bytecode;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) {
|
||||
LPDIRECT3DPIXELSHADER9 shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
|
||||
|
||||
// Make an entry in the table
|
||||
PSCacheEntry newentry;
|
||||
newentry.shader = shader;
|
||||
newentry.frameCount = frameCount;
|
||||
PixelShaders[uid] = newentry;
|
||||
last_entry = &PixelShaders[uid];
|
||||
|
||||
if (!shader) {
|
||||
// INCSTAT(stats.numPixelShadersFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, (int)PixelShaders.size());
|
||||
if (activate)
|
||||
{
|
||||
D3D::SetPixelShader(shader);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string PixelShaderCache::GetCurrentShaderCode()
|
||||
{
|
||||
if (last_entry)
|
||||
return last_entry->code;
|
||||
else
|
||||
return "(no shader)\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
// 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 <map>
|
||||
#include <set>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Hash.h"
|
||||
#include "FileUtil.h"
|
||||
#include "LinearDiskCache.h"
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "DX9_D3DShader.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "PixelShaderGen.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "DX9_PixelShaderCache.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "BPMemory.h"
|
||||
#include "XFMemory.h"
|
||||
#include "ImageWrite.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
//#include "Debugger/Debugger.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
|
||||
const PixelShaderCache::PSCacheEntry *PixelShaderCache::last_entry;
|
||||
|
||||
static LinearDiskCache g_ps_disk_cache;
|
||||
static std::set<u32> unique_shaders;
|
||||
|
||||
#define MAX_SSAA_SHADERS 3
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 s_ColorMatrixProgram[MAX_SSAA_SHADERS];
|
||||
static LPDIRECT3DPIXELSHADER9 s_ColorCopyProgram[MAX_SSAA_SHADERS];
|
||||
static LPDIRECT3DPIXELSHADER9 s_DepthMatrixProgram[MAX_SSAA_SHADERS];
|
||||
static LPDIRECT3DPIXELSHADER9 s_ClearProgram = 0;
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorMatrixProgram(int SSAAMode)
|
||||
{
|
||||
return s_ColorMatrixProgram[SSAAMode % MAX_SSAA_SHADERS];
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetDepthMatrixProgram(int SSAAMode)
|
||||
{
|
||||
return s_DepthMatrixProgram[SSAAMode % MAX_SSAA_SHADERS];
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorCopyProgram(int SSAAMode)
|
||||
{
|
||||
return s_ColorCopyProgram[SSAAMode % MAX_SSAA_SHADERS];
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetClearProgram()
|
||||
{
|
||||
return s_ClearProgram;
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
float f[4] = { f1, f2, f3, f4 };
|
||||
D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
D3D::dev->SetPixelShaderConstantF(const_number, f, count);
|
||||
}
|
||||
|
||||
class PixelShaderCacheInserter : public LinearDiskCacheReader {
|
||||
public:
|
||||
void Read(const u8 *key, int key_size, const u8 *value, int value_size)
|
||||
{
|
||||
PIXELSHADERUID uid;
|
||||
if (key_size != sizeof(uid)) {
|
||||
ERROR_LOG(VIDEO, "Wrong key size in pixel shader cache");
|
||||
return;
|
||||
}
|
||||
memcpy(&uid, key, key_size);
|
||||
PixelShaderCache::InsertByteCode(uid, value, value_size, false);
|
||||
}
|
||||
};
|
||||
|
||||
PixelShaderCache::PixelShaderCache()
|
||||
{
|
||||
//program used for clear screen
|
||||
char pprog[3072];
|
||||
sprintf(pprog, "void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
" in float4 incol0 : COLOR0){\n"
|
||||
"ocol0 = incol0;\n"
|
||||
"}\n");
|
||||
s_ClearProgram = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//Used for Copy/resolve the color buffer
|
||||
//1 Sample
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float2 uv0 : TEXCOORD0){\n"
|
||||
"ocol0 = tex2D(samp0,uv0);\n"
|
||||
"}\n");
|
||||
s_ColorCopyProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//1 Samples SSAA
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float4 uv1 : TEXCOORD1){\n"
|
||||
"ocol0 = tex2D(samp0,uv0.xy);\n"
|
||||
"}\n");
|
||||
s_ColorCopyProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//4 Samples SSAA
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float4 uv1 : TEXCOORD1,\n"
|
||||
"in float4 uv2 : TEXCOORD2,\n"
|
||||
"in float4 uv3 : TEXCOORD3){\n"
|
||||
"ocol0 = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25;\n"
|
||||
"}\n");
|
||||
s_ColorCopyProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
|
||||
|
||||
//Color conversion Programs
|
||||
//1 sample
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
" in float2 uv0 : TEXCOORD0){\n"
|
||||
"float4 texcol = tex2D(samp0,uv0);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n",C_COLORMATRIX);
|
||||
s_ColorMatrixProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//1 samples SSAA
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float4 uv1 : TEXCOORD1){\n"
|
||||
"float4 texcol = tex2D(samp0,uv0.xy);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n",C_COLORMATRIX);
|
||||
s_ColorMatrixProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//4 samples SSAA
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float4 uv1 : TEXCOORD1,\n"
|
||||
"in float4 uv2 : TEXCOORD2,\n"
|
||||
"in float4 uv3 : TEXCOORD3){\n"
|
||||
"float4 texcol = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25f;\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n",C_COLORMATRIX);
|
||||
s_ColorMatrixProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//Depth copy programs
|
||||
//1 sample
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
" in float2 uv0 : TEXCOORD0){\n"
|
||||
"float4 texcol = tex2D(samp0,uv0);\n"
|
||||
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
|
||||
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n",C_COLORMATRIX);
|
||||
s_DepthMatrixProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//1 sample SSAA
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float4 uv1 : TEXCOORD1){\n"
|
||||
"float4 texcol = tex2D(samp0,uv0.xy);\n"
|
||||
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
|
||||
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n",C_COLORMATRIX);
|
||||
s_DepthMatrixProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
//4 sample SSAA
|
||||
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float4 uv1 : TEXCOORD1,\n"
|
||||
"in float4 uv2 : TEXCOORD2,\n"
|
||||
"in float4 uv3 : TEXCOORD3){\n"
|
||||
"float4 texcol = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25f;\n"
|
||||
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
|
||||
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
|
||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||
"}\n",C_COLORMATRIX);
|
||||
s_DepthMatrixProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
|
||||
Clear();
|
||||
|
||||
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
|
||||
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
|
||||
|
||||
SETSTAT(stats.numPixelShadersCreated, 0);
|
||||
SETSTAT(stats.numPixelShadersAlive, 0);
|
||||
|
||||
char cache_filename[MAX_PATH];
|
||||
sprintf(cache_filename, "%sdx9-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
|
||||
PixelShaderCacheInserter inserter;
|
||||
int read_items = g_ps_disk_cache.OpenAndRead(cache_filename, &inserter);
|
||||
}
|
||||
|
||||
// ONLY to be used during shutdown.
|
||||
void PixelShaderCache::Clear()
|
||||
{
|
||||
PSCache::iterator iter = PixelShaders.begin();
|
||||
for (; iter != PixelShaders.end(); ++iter)
|
||||
iter->second.Destroy();
|
||||
PixelShaders.clear();
|
||||
|
||||
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
|
||||
}
|
||||
|
||||
PixelShaderCache::~PixelShaderCache()
|
||||
{
|
||||
for(int i = 0;i < MAX_SSAA_SHADERS; i++)
|
||||
{
|
||||
if (s_ColorMatrixProgram[i]) s_ColorMatrixProgram[i]->Release();
|
||||
s_ColorMatrixProgram[i] = NULL;
|
||||
if (s_ColorCopyProgram[i]) s_ColorCopyProgram[i]->Release();
|
||||
s_ColorCopyProgram[i] = NULL;
|
||||
if (s_DepthMatrixProgram[i]) s_DepthMatrixProgram[i]->Release();
|
||||
s_DepthMatrixProgram[i] = NULL;
|
||||
}
|
||||
if (s_ClearProgram) s_ClearProgram->Release();
|
||||
s_ClearProgram = NULL;
|
||||
|
||||
Clear();
|
||||
g_ps_disk_cache.Sync();
|
||||
g_ps_disk_cache.Close();
|
||||
|
||||
unique_shaders.clear();
|
||||
}
|
||||
|
||||
bool PixelShaderCache::SetShader(bool dstAlpha)
|
||||
{
|
||||
PIXELSHADERUID uid;
|
||||
GetPixelShaderId(&uid, dstAlpha);
|
||||
|
||||
// Is the shader already set?
|
||||
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
|
||||
{
|
||||
PSCache::const_iterator iter = PixelShaders.find(uid);
|
||||
if (iter != PixelShaders.end() && iter->second.shader)
|
||||
return true; // Sure, we're done.
|
||||
else
|
||||
return false; // ?? something is wrong.
|
||||
}
|
||||
|
||||
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
|
||||
|
||||
// Is the shader already in the cache?
|
||||
PSCache::iterator iter;
|
||||
iter = PixelShaders.find(uid);
|
||||
if (iter != PixelShaders.end())
|
||||
{
|
||||
iter->second.frameCount = frameCount;
|
||||
const PSCacheEntry &entry = iter->second;
|
||||
last_entry = &entry;
|
||||
|
||||
if (entry.shader)
|
||||
{
|
||||
D3D::SetPixelShader(entry.shader);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// OK, need to generate and compile it.
|
||||
const char *code = GeneratePixelShaderCode(dstAlpha, API_D3D9);
|
||||
|
||||
u32 code_hash = HashAdler32((const u8 *)code, strlen(code));
|
||||
unique_shaders.insert(code_hash);
|
||||
SETSTAT(stats.numUniquePixelShaders, unique_shaders.size());
|
||||
|
||||
#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), counter++);
|
||||
|
||||
SaveData(szTemp, code);
|
||||
}
|
||||
#endif
|
||||
|
||||
u8 *bytecode = 0;
|
||||
int bytecodelen = 0;
|
||||
if (!D3D::CompilePixelShader(code, (int)strlen(code), &bytecode, &bytecodelen)) {
|
||||
if (g_ActiveConfig.bShowShaderErrors)
|
||||
{
|
||||
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
|
||||
SaveData(szTemp, code);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Here we have the UID and the byte code. Insert it into the disk cache.
|
||||
g_ps_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen);
|
||||
g_ps_disk_cache.Sync();
|
||||
|
||||
// And insert it into the shader cache.
|
||||
bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
|
||||
delete [] bytecode;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) {
|
||||
LPDIRECT3DPIXELSHADER9 shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
|
||||
|
||||
// Make an entry in the table
|
||||
PSCacheEntry newentry;
|
||||
newentry.shader = shader;
|
||||
newentry.frameCount = frameCount;
|
||||
PixelShaders[uid] = newentry;
|
||||
last_entry = &PixelShaders[uid];
|
||||
|
||||
if (!shader) {
|
||||
// INCSTAT(stats.numPixelShadersFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, (int)PixelShaders.size());
|
||||
if (activate)
|
||||
{
|
||||
D3D::SetPixelShader(shader);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string PixelShaderCache::GetCurrentShaderCode()
|
||||
{
|
||||
if (last_entry)
|
||||
return last_entry->code;
|
||||
else
|
||||
return "(no shader)\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -1,89 +1,89 @@
|
|||
// 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 "Common.h"
|
||||
#include "LinearDiskCache.h"
|
||||
#include "DX9_D3DBase.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "PixelShaderGen.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
#include "../PixelShaderCache.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
typedef u32 tevhash;
|
||||
|
||||
tevhash GetCurrentTEV();
|
||||
|
||||
class PixelShaderCache : public ::PixelShaderCacheBase
|
||||
{
|
||||
private:
|
||||
struct PSCacheEntry
|
||||
{
|
||||
LPDIRECT3DPIXELSHADER9 shader;
|
||||
bool owns_shader;
|
||||
int frameCount;
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string code;
|
||||
#endif
|
||||
PSCacheEntry() : shader(NULL), owns_shader(true), frameCount(0) {}
|
||||
void Destroy()
|
||||
{
|
||||
if (shader && owns_shader)
|
||||
shader->Release();
|
||||
shader = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
|
||||
|
||||
static PSCache PixelShaders;
|
||||
static const PSCacheEntry *last_entry;
|
||||
static void Clear();
|
||||
|
||||
public:
|
||||
PixelShaderCache();
|
||||
~PixelShaderCache();
|
||||
|
||||
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetPSConstant4fv(unsigned int const_number, const float* f);
|
||||
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float* f);
|
||||
|
||||
bool SetShader(bool dstAlpha);
|
||||
|
||||
static bool InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
|
||||
static LPDIRECT3DPIXELSHADER9 GetColorMatrixProgram(int SSAAMode);
|
||||
static LPDIRECT3DPIXELSHADER9 GetColorCopyProgram(int SSAAMode);
|
||||
static LPDIRECT3DPIXELSHADER9 GetDepthMatrixProgram(int SSAAMode);
|
||||
static LPDIRECT3DPIXELSHADER9 GetClearProgram();
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
static std::string GetCurrentShaderCode();
|
||||
#endif
|
||||
static LPDIRECT3DPIXELSHADER9 CompileCgShader(const char *pstrprogram);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _PIXELSHADERCACHE_H
|
||||
// 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 "Common.h"
|
||||
#include "LinearDiskCache.h"
|
||||
#include "DX9_D3DBase.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "PixelShaderGen.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
#include "../PixelShaderCache.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
typedef u32 tevhash;
|
||||
|
||||
tevhash GetCurrentTEV();
|
||||
|
||||
class PixelShaderCache : public ::PixelShaderCacheBase
|
||||
{
|
||||
private:
|
||||
struct PSCacheEntry
|
||||
{
|
||||
LPDIRECT3DPIXELSHADER9 shader;
|
||||
bool owns_shader;
|
||||
int frameCount;
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string code;
|
||||
#endif
|
||||
PSCacheEntry() : shader(NULL), owns_shader(true), frameCount(0) {}
|
||||
void Destroy()
|
||||
{
|
||||
if (shader && owns_shader)
|
||||
shader->Release();
|
||||
shader = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
|
||||
|
||||
static PSCache PixelShaders;
|
||||
static const PSCacheEntry *last_entry;
|
||||
static void Clear();
|
||||
|
||||
public:
|
||||
PixelShaderCache();
|
||||
~PixelShaderCache();
|
||||
|
||||
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetPSConstant4fv(unsigned int const_number, const float* f);
|
||||
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float* f);
|
||||
|
||||
bool SetShader(bool dstAlpha);
|
||||
|
||||
static bool InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
|
||||
static LPDIRECT3DPIXELSHADER9 GetColorMatrixProgram(int SSAAMode);
|
||||
static LPDIRECT3DPIXELSHADER9 GetColorCopyProgram(int SSAAMode);
|
||||
static LPDIRECT3DPIXELSHADER9 GetDepthMatrixProgram(int SSAAMode);
|
||||
static LPDIRECT3DPIXELSHADER9 GetClearProgram();
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
static std::string GetCurrentShaderCode();
|
||||
#endif
|
||||
static LPDIRECT3DPIXELSHADER9 CompileCgShader(const char *pstrprogram);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _PIXELSHADERCACHE_H
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,58 +1,58 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "MathUtil.h"
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "Renderer.h"
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class Renderer : public ::RendererBase
|
||||
{
|
||||
public:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
||||
void ResetAPIState();
|
||||
void RestoreAPIState();
|
||||
|
||||
static void SetupDeviceObjects();
|
||||
static void TeardownDeviceObjects();
|
||||
|
||||
void SetColorMask();
|
||||
void SetBlendMode(bool forceUpdate);
|
||||
bool SetScissorRect();
|
||||
|
||||
void SetGenerationMode();
|
||||
void SetDepthMode();
|
||||
void SetLogicOpMode();
|
||||
void SetSamplerState(int stage,int texindex);
|
||||
void SetDitherMode();
|
||||
void SetLineWidth();
|
||||
|
||||
u32 AccessEFB(EFBAccessType type, int x, int y);
|
||||
|
||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
|
||||
void UpdateViewport();
|
||||
|
||||
// virtual funcs used by RendererBase::Swap
|
||||
void PrepareXFBCopy(const TargetRectangle &dst_rect);
|
||||
void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
|
||||
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc);
|
||||
void EndFrame();
|
||||
void Present();
|
||||
bool CheckForResize();
|
||||
void GetBackBufferSize(int* w, int* h);
|
||||
void RecreateFramebufferManger();
|
||||
void BeginFrame();
|
||||
|
||||
void Swap(u32, FieldType, u32, u32, const EFBRectangle&);
|
||||
|
||||
private:
|
||||
static bool IS_AMD;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MathUtil.h"
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "Renderer.h"
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class Renderer : public ::RendererBase
|
||||
{
|
||||
public:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
||||
void ResetAPIState();
|
||||
void RestoreAPIState();
|
||||
|
||||
static void SetupDeviceObjects();
|
||||
static void TeardownDeviceObjects();
|
||||
|
||||
void SetColorMask();
|
||||
void SetBlendMode(bool forceUpdate);
|
||||
bool SetScissorRect();
|
||||
|
||||
void SetGenerationMode();
|
||||
void SetDepthMode();
|
||||
void SetLogicOpMode();
|
||||
void SetSamplerState(int stage,int texindex);
|
||||
void SetDitherMode();
|
||||
void SetLineWidth();
|
||||
|
||||
u32 AccessEFB(EFBAccessType type, int x, int y);
|
||||
|
||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
|
||||
void UpdateViewport();
|
||||
|
||||
// virtual funcs used by RendererBase::Swap
|
||||
void PrepareXFBCopy(const TargetRectangle &dst_rect);
|
||||
void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
|
||||
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc);
|
||||
void EndFrame();
|
||||
void Present();
|
||||
bool CheckForResize();
|
||||
void GetBackBufferSize(int* w, int* h);
|
||||
void RecreateFramebufferManger();
|
||||
void BeginFrame();
|
||||
|
||||
void Swap(u32, FieldType, u32, u32, const EFBRectangle&);
|
||||
|
||||
private:
|
||||
static bool IS_AMD;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,207 +1,207 @@
|
|||
// 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 <d3dx9.h>
|
||||
|
||||
#include "Statistics.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "Hash.h"
|
||||
|
||||
#include "CommonPaths.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "DX9_D3DTexture.h"
|
||||
#include "DX9_D3DUtil.h"
|
||||
#include "DX9_FramebufferManager.h"
|
||||
#include "DX9_PixelShaderCache.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "DX9_VertexShaderCache.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
#include "DX9_Render.h"
|
||||
|
||||
#include "TextureDecoder.h"
|
||||
#include "DX9_TextureCache.h"
|
||||
#include "HiresTextures.h"
|
||||
#include "DX9_TextureConverter.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
//#include "debugger/debugger.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
TextureCache::TCacheEntry::TCacheEntry(LPDIRECT3DTEXTURE9 _texture)
|
||||
: texture(_texture), isDynamic(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntry::~TCacheEntry()
|
||||
{
|
||||
texture->Release();
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
D3D::ReplaceTexture2D(texture, temp, width, height, expanded_width, d3d_fmt, swap_r_b, level);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect)
|
||||
{
|
||||
LPDIRECT3DSURFACE9 Rendersurf = NULL;
|
||||
texture->GetSurfaceLevel(0, &Rendersurf);
|
||||
D3D::dev->SetDepthStencilSurface(NULL);
|
||||
D3D::dev->SetRenderTarget(0, Rendersurf);
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
|
||||
// Stretch picture with increased internal resolution
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = Scaledw;
|
||||
vp.Height = Scaledh;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
RECT destrect;
|
||||
destrect.bottom = Scaledh;
|
||||
destrect.left = 0;
|
||||
destrect.right = Scaledw;
|
||||
destrect.top = 0;
|
||||
|
||||
const float* const fConstAdd = colmat + 16; // fConstAdd is the last 4 floats of colmat
|
||||
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
|
||||
TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect);
|
||||
RECT sourcerect;
|
||||
sourcerect.bottom = targetSource.bottom;
|
||||
sourcerect.left = targetSource.left;
|
||||
sourcerect.right = targetSource.right;
|
||||
sourcerect.top = targetSource.top;
|
||||
|
||||
if (bFromZBuffer)
|
||||
{
|
||||
if (bScaleByHalf || g_ActiveConfig.iMultisampleMode)
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
}
|
||||
|
||||
const LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ?
|
||||
FramebufferManager::GetEFBDepthTexture(source_rect) :
|
||||
FramebufferManager::GetEFBColorTexture(source_rect);
|
||||
|
||||
D3DFORMAT bformat = FramebufferManager::GetEFBDepthRTSurfaceFormat();
|
||||
int SSAAMode = g_ActiveConfig.iMultisampleMode;
|
||||
|
||||
D3D::drawShadedTexQuad(read_texture, &sourcerect,
|
||||
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
|
||||
Scaledw, Scaledh,
|
||||
((bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8) && bFromZBuffer) ?
|
||||
PixelShaderCache::GetDepthMatrixProgram(SSAAMode) :
|
||||
PixelShaderCache::GetColorMatrixProgram(SSAAMode),
|
||||
VertexShaderCache::GetSimpleVertexShader(SSAAMode));
|
||||
|
||||
Rendersurf->Release();
|
||||
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
||||
D3D::SetTexture(0,NULL);
|
||||
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Bind(unsigned int stage)
|
||||
{
|
||||
D3D::SetTexture(stage, texture);
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt)
|
||||
{
|
||||
D3DFORMAT d3d_fmt;
|
||||
bool swap_r_b = false;
|
||||
|
||||
switch (pcfmt)
|
||||
{
|
||||
case PC_TEX_FMT_BGRA32:
|
||||
d3d_fmt = D3DFMT_A8R8G8B8;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_RGBA32:
|
||||
d3d_fmt = D3DFMT_A8R8G8B8;
|
||||
swap_r_b = true;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_RGB565:
|
||||
d3d_fmt = D3DFMT_R5G6B5;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_IA4_AS_IA8:
|
||||
d3d_fmt = D3DFMT_A8L8;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_I8:
|
||||
case PC_TEX_FMT_I4_AS_I8:
|
||||
// A hack which means the format is a packed
|
||||
// 8-bit intensity texture. It is unpacked
|
||||
// to A8L8 in D3DTexture.cpp
|
||||
d3d_fmt = D3DFMT_A8P8;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_IA8:
|
||||
d3d_fmt = D3DFMT_A8L8;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_DXT1:
|
||||
d3d_fmt = D3DFMT_DXT1;
|
||||
break;
|
||||
}
|
||||
|
||||
TCacheEntry* entry = new TCacheEntry(D3D::CreateTexture2D(temp, width, height, expanded_width, d3d_fmt, swap_r_b, tex_levels));
|
||||
entry->swap_r_b = swap_r_b;
|
||||
entry->d3d_fmt = d3d_fmt;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 texture;
|
||||
D3D::dev->CreateTexture(scaled_tex_w, scaled_tex_h, 1, D3DUSAGE_RENDERTARGET,
|
||||
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
|
||||
|
||||
return new TCacheEntry(texture);
|
||||
}
|
||||
|
||||
}
|
||||
// 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 <d3dx9.h>
|
||||
|
||||
#include "Statistics.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "Hash.h"
|
||||
|
||||
#include "CommonPaths.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "DX9_D3DTexture.h"
|
||||
#include "DX9_D3DUtil.h"
|
||||
#include "DX9_FramebufferManager.h"
|
||||
#include "DX9_PixelShaderCache.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "DX9_VertexShaderCache.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
#include "DX9_Render.h"
|
||||
|
||||
#include "TextureDecoder.h"
|
||||
#include "DX9_TextureCache.h"
|
||||
#include "HiresTextures.h"
|
||||
#include "DX9_TextureConverter.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
//#include "debugger/debugger.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
TextureCache::TCacheEntry::TCacheEntry(LPDIRECT3DTEXTURE9 _texture)
|
||||
: texture(_texture), isDynamic(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntry::~TCacheEntry()
|
||||
{
|
||||
texture->Release();
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
D3D::ReplaceTexture2D(texture, temp, width, height, expanded_width, d3d_fmt, swap_r_b, level);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect)
|
||||
{
|
||||
LPDIRECT3DSURFACE9 Rendersurf = NULL;
|
||||
texture->GetSurfaceLevel(0, &Rendersurf);
|
||||
D3D::dev->SetDepthStencilSurface(NULL);
|
||||
D3D::dev->SetRenderTarget(0, Rendersurf);
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
|
||||
// Stretch picture with increased internal resolution
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = Scaledw;
|
||||
vp.Height = Scaledh;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
RECT destrect;
|
||||
destrect.bottom = Scaledh;
|
||||
destrect.left = 0;
|
||||
destrect.right = Scaledw;
|
||||
destrect.top = 0;
|
||||
|
||||
const float* const fConstAdd = colmat + 16; // fConstAdd is the last 4 floats of colmat
|
||||
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
|
||||
TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect);
|
||||
RECT sourcerect;
|
||||
sourcerect.bottom = targetSource.bottom;
|
||||
sourcerect.left = targetSource.left;
|
||||
sourcerect.right = targetSource.right;
|
||||
sourcerect.top = targetSource.top;
|
||||
|
||||
if (bFromZBuffer)
|
||||
{
|
||||
if (bScaleByHalf || g_ActiveConfig.iMultisampleMode)
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
}
|
||||
|
||||
const LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ?
|
||||
FramebufferManager::GetEFBDepthTexture(source_rect) :
|
||||
FramebufferManager::GetEFBColorTexture(source_rect);
|
||||
|
||||
D3DFORMAT bformat = FramebufferManager::GetEFBDepthRTSurfaceFormat();
|
||||
int SSAAMode = g_ActiveConfig.iMultisampleMode;
|
||||
|
||||
D3D::drawShadedTexQuad(read_texture, &sourcerect,
|
||||
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
|
||||
Scaledw, Scaledh,
|
||||
((bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8) && bFromZBuffer) ?
|
||||
PixelShaderCache::GetDepthMatrixProgram(SSAAMode) :
|
||||
PixelShaderCache::GetColorMatrixProgram(SSAAMode),
|
||||
VertexShaderCache::GetSimpleVertexShader(SSAAMode));
|
||||
|
||||
Rendersurf->Release();
|
||||
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
||||
D3D::SetTexture(0,NULL);
|
||||
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Bind(unsigned int stage)
|
||||
{
|
||||
D3D::SetTexture(stage, texture);
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt)
|
||||
{
|
||||
D3DFORMAT d3d_fmt;
|
||||
bool swap_r_b = false;
|
||||
|
||||
switch (pcfmt)
|
||||
{
|
||||
case PC_TEX_FMT_BGRA32:
|
||||
d3d_fmt = D3DFMT_A8R8G8B8;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_RGBA32:
|
||||
d3d_fmt = D3DFMT_A8R8G8B8;
|
||||
swap_r_b = true;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_RGB565:
|
||||
d3d_fmt = D3DFMT_R5G6B5;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_IA4_AS_IA8:
|
||||
d3d_fmt = D3DFMT_A8L8;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_I8:
|
||||
case PC_TEX_FMT_I4_AS_I8:
|
||||
// A hack which means the format is a packed
|
||||
// 8-bit intensity texture. It is unpacked
|
||||
// to A8L8 in D3DTexture.cpp
|
||||
d3d_fmt = D3DFMT_A8P8;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_IA8:
|
||||
d3d_fmt = D3DFMT_A8L8;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_DXT1:
|
||||
d3d_fmt = D3DFMT_DXT1;
|
||||
break;
|
||||
}
|
||||
|
||||
TCacheEntry* entry = new TCacheEntry(D3D::CreateTexture2D(temp, width, height, expanded_width, d3d_fmt, swap_r_b, tex_levels));
|
||||
entry->swap_r_b = swap_r_b;
|
||||
entry->d3d_fmt = d3d_fmt;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 texture;
|
||||
D3D::dev->CreateTexture(scaled_tex_w, scaled_tex_h, 1, D3DUSAGE_RENDERTARGET,
|
||||
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
|
||||
|
||||
return new TCacheEntry(texture);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,67 +1,67 @@
|
|||
// 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 _TEXTURECACHE_H
|
||||
#define _TEXTURECACHE_H
|
||||
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "VideoCommon.h"
|
||||
#include "BPMemory.h"
|
||||
|
||||
#include "../TextureCache.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class TextureCache : public TextureCacheBase
|
||||
{
|
||||
public:
|
||||
struct TCacheEntry : TCacheEntryBase
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 texture;
|
||||
|
||||
D3DFORMAT d3d_fmt;
|
||||
bool swap_r_b;
|
||||
bool isDynamic; // mofified from cpu
|
||||
|
||||
TCacheEntry(LPDIRECT3DTEXTURE9 _texture);
|
||||
~TCacheEntry();
|
||||
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int levels);
|
||||
|
||||
void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect);
|
||||
|
||||
void Bind(unsigned int stage);
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt);
|
||||
|
||||
TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
// 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 _TEXTURECACHE_H
|
||||
#define _TEXTURECACHE_H
|
||||
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "VideoCommon.h"
|
||||
#include "BPMemory.h"
|
||||
|
||||
#include "../TextureCache.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class TextureCache : public TextureCacheBase
|
||||
{
|
||||
public:
|
||||
struct TCacheEntry : TCacheEntryBase
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 texture;
|
||||
|
||||
D3DFORMAT d3d_fmt;
|
||||
bool swap_r_b;
|
||||
bool isDynamic; // mofified from cpu
|
||||
|
||||
TCacheEntry(LPDIRECT3DTEXTURE9 _texture);
|
||||
~TCacheEntry();
|
||||
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int levels);
|
||||
|
||||
void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect);
|
||||
|
||||
void Bind(unsigned int stage);
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt);
|
||||
|
||||
TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,53 +1,53 @@
|
|||
// 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 _TEXTURECONVERTER_H_
|
||||
#define _TEXTURECONVERTER_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "DX9_D3DTexture.h"
|
||||
#include "DX9_D3DUtil.h"
|
||||
#include "DX9_D3DShader.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
// Converts textures between formats
|
||||
// TODO: support multiple texture formats
|
||||
namespace TextureConverter
|
||||
{
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
|
||||
u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
|
||||
|
||||
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight);
|
||||
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture);
|
||||
|
||||
u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 SourceW, u32 SourceH,float MValueX,float MValueY,float Xstride, float Ystride , bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // _TEXTURECONVERTER_H_
|
||||
// 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 _TEXTURECONVERTER_H_
|
||||
#define _TEXTURECONVERTER_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "DX9_D3DTexture.h"
|
||||
#include "DX9_D3DUtil.h"
|
||||
#include "DX9_D3DShader.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
// Converts textures between formats
|
||||
// TODO: support multiple texture formats
|
||||
namespace TextureConverter
|
||||
{
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
|
||||
u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
|
||||
|
||||
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight);
|
||||
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture);
|
||||
|
||||
u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 SourceW, u32 SourceH,float MValueX,float MValueY,float Xstride, float Ystride , bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // _TEXTURECONVERTER_H_
|
||||
|
|
|
@ -1,135 +1,135 @@
|
|||
// 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 "Common.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "Fifo.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "DX9_VertexManager.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "DX9_VertexShaderCache.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "DX9_PixelShaderCache.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "NativeVertexWriter.h"
|
||||
#include "DX9_TextureCache.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
|
||||
//#include "debugger/debugger.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
using namespace D3D;
|
||||
|
||||
// internal state for loading vertices
|
||||
extern NativeVertexFormat *g_nativeVertexFmt;
|
||||
|
||||
inline void DumpBadShaders()
|
||||
{
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string error_shaders;
|
||||
error_shaders.append(VertexShaderCache::GetCurrentShaderCode());
|
||||
error_shaders.append(PixelShaderCache::GetCurrentShaderCode());
|
||||
char filename[512] = "bad_shader_combo_0.txt";
|
||||
int which = 0;
|
||||
while (File::Exists(filename))
|
||||
{
|
||||
which++;
|
||||
sprintf(filename, "bad_shader_combo_%i.txt", which);
|
||||
}
|
||||
File::WriteStringToFile(true, error_shaders, filename);
|
||||
PanicAlert("DrawIndexedPrimitiveUP failed. Shaders written to %s", filename);
|
||||
#endif
|
||||
}
|
||||
|
||||
void VertexManager::Draw(u32 stride, bool alphapass)
|
||||
{
|
||||
if (alphapass)
|
||||
{
|
||||
DWORD write = 0;
|
||||
if (false == g_pixel_shader_cache->SetShader(true))
|
||||
{
|
||||
//DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
|
||||
//goto shader_fail;
|
||||
return;
|
||||
}
|
||||
// update alpha only
|
||||
D3D::ChangeRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA);
|
||||
D3D::ChangeRenderState(D3DRS_ALPHABLENDENABLE, false);
|
||||
}
|
||||
|
||||
if (IndexGenerator::GetNumTriangles() > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
D3DPT_TRIANGLELIST,
|
||||
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumTriangles(),
|
||||
TIBuffer,
|
||||
D3DFMT_INDEX16,
|
||||
LocalVBuffer,
|
||||
stride)))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumLines() > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
D3DPT_LINELIST,
|
||||
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumLines(),
|
||||
LIBuffer,
|
||||
D3DFMT_INDEX16,
|
||||
LocalVBuffer,
|
||||
stride)))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumPoints() > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
D3DPT_POINTLIST,
|
||||
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumPoints(),
|
||||
PIBuffer,
|
||||
D3DFMT_INDEX16,
|
||||
LocalVBuffer,
|
||||
stride)))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
|
||||
if (alphapass)
|
||||
{
|
||||
D3D::RefreshRenderState(D3DRS_COLORWRITEENABLE);
|
||||
D3D::RefreshRenderState(D3DRS_ALPHABLENDENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
// 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 "Common.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "Fifo.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "DX9_VertexManager.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "DX9_VertexShaderCache.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "DX9_PixelShaderCache.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "NativeVertexWriter.h"
|
||||
#include "DX9_TextureCache.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
|
||||
//#include "debugger/debugger.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
using namespace D3D;
|
||||
|
||||
// internal state for loading vertices
|
||||
extern NativeVertexFormat *g_nativeVertexFmt;
|
||||
|
||||
inline void DumpBadShaders()
|
||||
{
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string error_shaders;
|
||||
error_shaders.append(VertexShaderCache::GetCurrentShaderCode());
|
||||
error_shaders.append(PixelShaderCache::GetCurrentShaderCode());
|
||||
char filename[512] = "bad_shader_combo_0.txt";
|
||||
int which = 0;
|
||||
while (File::Exists(filename))
|
||||
{
|
||||
which++;
|
||||
sprintf(filename, "bad_shader_combo_%i.txt", which);
|
||||
}
|
||||
File::WriteStringToFile(true, error_shaders, filename);
|
||||
PanicAlert("DrawIndexedPrimitiveUP failed. Shaders written to %s", filename);
|
||||
#endif
|
||||
}
|
||||
|
||||
void VertexManager::Draw(u32 stride, bool alphapass)
|
||||
{
|
||||
if (alphapass)
|
||||
{
|
||||
DWORD write = 0;
|
||||
if (false == g_pixel_shader_cache->SetShader(true))
|
||||
{
|
||||
//DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
|
||||
//goto shader_fail;
|
||||
return;
|
||||
}
|
||||
// update alpha only
|
||||
D3D::ChangeRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA);
|
||||
D3D::ChangeRenderState(D3DRS_ALPHABLENDENABLE, false);
|
||||
}
|
||||
|
||||
if (IndexGenerator::GetNumTriangles() > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
D3DPT_TRIANGLELIST,
|
||||
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumTriangles(),
|
||||
TIBuffer,
|
||||
D3DFMT_INDEX16,
|
||||
LocalVBuffer,
|
||||
stride)))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumLines() > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
D3DPT_LINELIST,
|
||||
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumLines(),
|
||||
LIBuffer,
|
||||
D3DFMT_INDEX16,
|
||||
LocalVBuffer,
|
||||
stride)))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumPoints() > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
D3DPT_POINTLIST,
|
||||
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumPoints(),
|
||||
PIBuffer,
|
||||
D3DFMT_INDEX16,
|
||||
LocalVBuffer,
|
||||
stride)))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
|
||||
if (alphapass)
|
||||
{
|
||||
D3D::RefreshRenderState(D3DRS_COLORWRITEENABLE);
|
||||
D3D::RefreshRenderState(D3DRS_ALPHABLENDENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -1,39 +1,39 @@
|
|||
// 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 _VERTEXMANAGER_H
|
||||
#define _VERTEXMANAGER_H
|
||||
|
||||
#include "CPMemory.h"
|
||||
#include "VertexLoader.h"
|
||||
|
||||
#include "../VertexManager.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class VertexManager : public ::VertexManagerBase
|
||||
{
|
||||
public:
|
||||
void Draw(u32 stride, bool alphapass);
|
||||
|
||||
NativeVertexFormat* CreateNativeVertexFormat();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
// 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 _VERTEXMANAGER_H
|
||||
#define _VERTEXMANAGER_H
|
||||
|
||||
#include "CPMemory.h"
|
||||
#include "VertexLoader.h"
|
||||
|
||||
#include "../VertexManager.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class VertexManager : public ::VertexManagerBase
|
||||
{
|
||||
public:
|
||||
void Draw(u32 stride, bool alphapass);
|
||||
|
||||
NativeVertexFormat* CreateNativeVertexFormat();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,302 +1,302 @@
|
|||
// 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 <map>
|
||||
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
#include "LinearDiskCache.h"
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "DX9_D3DShader.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "DX9_VertexShaderCache.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "BPMemory.h"
|
||||
#include "XFMemory.h"
|
||||
|
||||
//#include "debugger/debugger.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
VertexShaderCache::VSCache VertexShaderCache::vshaders;
|
||||
const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry;
|
||||
|
||||
#define MAX_SSAA_SHADERS 3
|
||||
|
||||
static LPDIRECT3DVERTEXSHADER9 SimpleVertexShader[MAX_SSAA_SHADERS];
|
||||
static LPDIRECT3DVERTEXSHADER9 ClearVertexShader;
|
||||
|
||||
LinearDiskCache g_vs_disk_cache;
|
||||
|
||||
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetSimpleVertexShader(int level)
|
||||
{
|
||||
return SimpleVertexShader[level % MAX_SSAA_SHADERS];
|
||||
}
|
||||
|
||||
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetClearVertexShader()
|
||||
{
|
||||
return ClearVertexShader;
|
||||
}
|
||||
|
||||
|
||||
void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
const float f[4] = { f1, f2, f3, f4 };
|
||||
D3D::dev->SetVertexShaderConstantF(const_number, f, 1);
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
D3D::dev->SetVertexShaderConstantF(const_number, f, 1);
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
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;
|
||||
}
|
||||
D3D::dev->SetVertexShaderConstantF(const_number, buf, count);
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
D3D::dev->SetVertexShaderConstantF(const_number, f, count);
|
||||
}
|
||||
|
||||
class VertexShaderCacheInserter : public LinearDiskCacheReader {
|
||||
public:
|
||||
void Read(const u8 *key, int key_size, const u8 *value, int value_size)
|
||||
{
|
||||
VERTEXSHADERUID uid;
|
||||
if (key_size != sizeof(uid)) {
|
||||
ERROR_LOG(VIDEO, "Wrong key size in vertex shader cache");
|
||||
return;
|
||||
}
|
||||
memcpy(&uid, key, key_size);
|
||||
VertexShaderCache::InsertByteCode(uid, value, value_size, false);
|
||||
}
|
||||
};
|
||||
|
||||
VertexShaderCache::VertexShaderCache()
|
||||
{
|
||||
char* vProg = new char[2048];
|
||||
sprintf(vProg,"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float2 vTexCoord : TEXCOORD0;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;\n"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vTexCoord = inTEX0;\n"
|
||||
"return OUT;\n"
|
||||
"}\n");
|
||||
|
||||
SimpleVertexShader[0] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
|
||||
|
||||
sprintf(vProg,"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float4 vColor0 : COLOR0;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;\n"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vColor0 = inColor0;\n"
|
||||
"return OUT;\n"
|
||||
"}\n");
|
||||
|
||||
ClearVertexShader = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
|
||||
|
||||
sprintf(vProg, "struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float4 vTexCoord : TEXCOORD0;\n"
|
||||
"float4 vTexCoord1 : TEXCOORD1;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float4 inTEX2 : TEXCOORD2)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vTexCoord = inTEX0.xyyx;\n"
|
||||
"OUT.vTexCoord1 = inTEX2;\n"
|
||||
"return OUT;\n"
|
||||
"}\n");
|
||||
SimpleVertexShader[1] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
|
||||
|
||||
sprintf(vProg, "struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float4 vTexCoord : TEXCOORD0;\n"
|
||||
"float4 vTexCoord1 : TEXCOORD1;\n"
|
||||
"float4 vTexCoord2 : TEXCOORD2;\n"
|
||||
"float4 vTexCoord3 : TEXCOORD3;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float4 inTEX2 : TEXCOORD2)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vTexCoord = inTEX0.xyyx;\n"
|
||||
"OUT.vTexCoord1 = inTEX0.xyyx + (float4(-1.0f,-0.5f, 1.0f,-0.5f) * inTEX1.xyyx);\n"
|
||||
"OUT.vTexCoord2 = inTEX0.xyyx + (float4( 1.0f, 0.5f,-1.0f, 0.5f) * inTEX1.xyyx);\n"
|
||||
"OUT.vTexCoord3 = inTEX2;\n"
|
||||
"return OUT;\n"
|
||||
"}\n");
|
||||
SimpleVertexShader[2] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
|
||||
|
||||
Clear();
|
||||
delete [] vProg;
|
||||
|
||||
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
|
||||
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
|
||||
|
||||
SETSTAT(stats.numVertexShadersCreated, 0);
|
||||
SETSTAT(stats.numVertexShadersAlive, 0);
|
||||
|
||||
char cache_filename[MAX_PATH];
|
||||
sprintf(cache_filename, "%sdx9-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
|
||||
VertexShaderCacheInserter inserter;
|
||||
int read_items = g_vs_disk_cache.OpenAndRead(cache_filename, &inserter);
|
||||
}
|
||||
|
||||
void VertexShaderCache::Clear()
|
||||
{
|
||||
VSCache::iterator
|
||||
iter = vshaders.begin(),
|
||||
vsend = vshaders.end();
|
||||
for (; iter != vsend; ++iter)
|
||||
iter->second.Destroy();
|
||||
|
||||
vshaders.clear();
|
||||
|
||||
memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid));
|
||||
}
|
||||
|
||||
VertexShaderCache::~VertexShaderCache()
|
||||
{
|
||||
for (int i = 0; i < MAX_SSAA_SHADERS; i++)
|
||||
{
|
||||
if (SimpleVertexShader[i])
|
||||
SimpleVertexShader[i]->Release();
|
||||
SimpleVertexShader[i] = NULL;
|
||||
}
|
||||
|
||||
if (ClearVertexShader)
|
||||
ClearVertexShader->Release();
|
||||
|
||||
ClearVertexShader = NULL;
|
||||
|
||||
g_vs_disk_cache.Sync();
|
||||
g_vs_disk_cache.Close();
|
||||
}
|
||||
|
||||
bool VertexShaderCache::SetShader(u32 components)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
VERTEXSHADERUID uid;
|
||||
GetVertexShaderId(&uid, components);
|
||||
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
|
||||
{
|
||||
if (vshaders[uid].shader)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
|
||||
|
||||
VSCache::iterator iter;
|
||||
iter = vshaders.find(uid);
|
||||
if (iter != vshaders.end())
|
||||
{
|
||||
iter->second.frameCount = frameCount;
|
||||
const VSCacheEntry &entry = iter->second;
|
||||
last_entry = &entry;
|
||||
|
||||
//DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
|
||||
if (entry.shader)
|
||||
{
|
||||
D3D::SetVertexShader(entry.shader);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *code = GenerateVertexShaderCode(components, API_D3D9);
|
||||
u8 *bytecode;
|
||||
int bytecodelen;
|
||||
if (!D3D::CompileVertexShader(code, (int)strlen(code), &bytecode, &bytecodelen))
|
||||
{
|
||||
if (g_ActiveConfig.bShowShaderErrors)
|
||||
{
|
||||
PanicAlert("Failed to compile Vertex Shader:\n\n%s", code);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
g_vs_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen);
|
||||
g_vs_disk_cache.Sync();
|
||||
|
||||
bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
|
||||
delete [] bytecode;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) {
|
||||
LPDIRECT3DVERTEXSHADER9 shader = D3D::CreateVertexShaderFromByteCode(bytecode, bytecodelen);
|
||||
|
||||
// Make an entry in the table
|
||||
VSCacheEntry entry;
|
||||
entry.shader = shader;
|
||||
entry.frameCount = frameCount;
|
||||
|
||||
vshaders[uid] = entry;
|
||||
last_entry = &vshaders[uid];
|
||||
if (!shader)
|
||||
return false;
|
||||
|
||||
INCSTAT(stats.numVertexShadersCreated);
|
||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
||||
if (activate)
|
||||
{
|
||||
D3D::SetVertexShader(shader);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string VertexShaderCache::GetCurrentShaderCode()
|
||||
{
|
||||
return "(N/A)\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
// 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 <map>
|
||||
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
#include "LinearDiskCache.h"
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "DX9_D3DShader.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "DX9_VertexShaderCache.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "BPMemory.h"
|
||||
#include "XFMemory.h"
|
||||
|
||||
//#include "debugger/debugger.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
VertexShaderCache::VSCache VertexShaderCache::vshaders;
|
||||
const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry;
|
||||
|
||||
#define MAX_SSAA_SHADERS 3
|
||||
|
||||
static LPDIRECT3DVERTEXSHADER9 SimpleVertexShader[MAX_SSAA_SHADERS];
|
||||
static LPDIRECT3DVERTEXSHADER9 ClearVertexShader;
|
||||
|
||||
LinearDiskCache g_vs_disk_cache;
|
||||
|
||||
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetSimpleVertexShader(int level)
|
||||
{
|
||||
return SimpleVertexShader[level % MAX_SSAA_SHADERS];
|
||||
}
|
||||
|
||||
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetClearVertexShader()
|
||||
{
|
||||
return ClearVertexShader;
|
||||
}
|
||||
|
||||
|
||||
void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
const float f[4] = { f1, f2, f3, f4 };
|
||||
D3D::dev->SetVertexShaderConstantF(const_number, f, 1);
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
D3D::dev->SetVertexShaderConstantF(const_number, f, 1);
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
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;
|
||||
}
|
||||
D3D::dev->SetVertexShaderConstantF(const_number, buf, count);
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
D3D::dev->SetVertexShaderConstantF(const_number, f, count);
|
||||
}
|
||||
|
||||
class VertexShaderCacheInserter : public LinearDiskCacheReader {
|
||||
public:
|
||||
void Read(const u8 *key, int key_size, const u8 *value, int value_size)
|
||||
{
|
||||
VERTEXSHADERUID uid;
|
||||
if (key_size != sizeof(uid)) {
|
||||
ERROR_LOG(VIDEO, "Wrong key size in vertex shader cache");
|
||||
return;
|
||||
}
|
||||
memcpy(&uid, key, key_size);
|
||||
VertexShaderCache::InsertByteCode(uid, value, value_size, false);
|
||||
}
|
||||
};
|
||||
|
||||
VertexShaderCache::VertexShaderCache()
|
||||
{
|
||||
char* vProg = new char[2048];
|
||||
sprintf(vProg,"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float2 vTexCoord : TEXCOORD0;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;\n"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vTexCoord = inTEX0;\n"
|
||||
"return OUT;\n"
|
||||
"}\n");
|
||||
|
||||
SimpleVertexShader[0] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
|
||||
|
||||
sprintf(vProg,"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float4 vColor0 : COLOR0;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;\n"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vColor0 = inColor0;\n"
|
||||
"return OUT;\n"
|
||||
"}\n");
|
||||
|
||||
ClearVertexShader = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
|
||||
|
||||
sprintf(vProg, "struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float4 vTexCoord : TEXCOORD0;\n"
|
||||
"float4 vTexCoord1 : TEXCOORD1;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float4 inTEX2 : TEXCOORD2)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vTexCoord = inTEX0.xyyx;\n"
|
||||
"OUT.vTexCoord1 = inTEX2;\n"
|
||||
"return OUT;\n"
|
||||
"}\n");
|
||||
SimpleVertexShader[1] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
|
||||
|
||||
sprintf(vProg, "struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float4 vTexCoord : TEXCOORD0;\n"
|
||||
"float4 vTexCoord1 : TEXCOORD1;\n"
|
||||
"float4 vTexCoord2 : TEXCOORD2;\n"
|
||||
"float4 vTexCoord3 : TEXCOORD3;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float4 inTEX2 : TEXCOORD2)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vTexCoord = inTEX0.xyyx;\n"
|
||||
"OUT.vTexCoord1 = inTEX0.xyyx + (float4(-1.0f,-0.5f, 1.0f,-0.5f) * inTEX1.xyyx);\n"
|
||||
"OUT.vTexCoord2 = inTEX0.xyyx + (float4( 1.0f, 0.5f,-1.0f, 0.5f) * inTEX1.xyyx);\n"
|
||||
"OUT.vTexCoord3 = inTEX2;\n"
|
||||
"return OUT;\n"
|
||||
"}\n");
|
||||
SimpleVertexShader[2] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
|
||||
|
||||
Clear();
|
||||
delete [] vProg;
|
||||
|
||||
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
|
||||
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
|
||||
|
||||
SETSTAT(stats.numVertexShadersCreated, 0);
|
||||
SETSTAT(stats.numVertexShadersAlive, 0);
|
||||
|
||||
char cache_filename[MAX_PATH];
|
||||
sprintf(cache_filename, "%sdx9-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
|
||||
VertexShaderCacheInserter inserter;
|
||||
int read_items = g_vs_disk_cache.OpenAndRead(cache_filename, &inserter);
|
||||
}
|
||||
|
||||
void VertexShaderCache::Clear()
|
||||
{
|
||||
VSCache::iterator
|
||||
iter = vshaders.begin(),
|
||||
vsend = vshaders.end();
|
||||
for (; iter != vsend; ++iter)
|
||||
iter->second.Destroy();
|
||||
|
||||
vshaders.clear();
|
||||
|
||||
memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid));
|
||||
}
|
||||
|
||||
VertexShaderCache::~VertexShaderCache()
|
||||
{
|
||||
for (int i = 0; i < MAX_SSAA_SHADERS; i++)
|
||||
{
|
||||
if (SimpleVertexShader[i])
|
||||
SimpleVertexShader[i]->Release();
|
||||
SimpleVertexShader[i] = NULL;
|
||||
}
|
||||
|
||||
if (ClearVertexShader)
|
||||
ClearVertexShader->Release();
|
||||
|
||||
ClearVertexShader = NULL;
|
||||
|
||||
g_vs_disk_cache.Sync();
|
||||
g_vs_disk_cache.Close();
|
||||
}
|
||||
|
||||
bool VertexShaderCache::SetShader(u32 components)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
VERTEXSHADERUID uid;
|
||||
GetVertexShaderId(&uid, components);
|
||||
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
|
||||
{
|
||||
if (vshaders[uid].shader)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
|
||||
|
||||
VSCache::iterator iter;
|
||||
iter = vshaders.find(uid);
|
||||
if (iter != vshaders.end())
|
||||
{
|
||||
iter->second.frameCount = frameCount;
|
||||
const VSCacheEntry &entry = iter->second;
|
||||
last_entry = &entry;
|
||||
|
||||
//DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
|
||||
if (entry.shader)
|
||||
{
|
||||
D3D::SetVertexShader(entry.shader);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *code = GenerateVertexShaderCode(components, API_D3D9);
|
||||
u8 *bytecode;
|
||||
int bytecodelen;
|
||||
if (!D3D::CompileVertexShader(code, (int)strlen(code), &bytecode, &bytecodelen))
|
||||
{
|
||||
if (g_ActiveConfig.bShowShaderErrors)
|
||||
{
|
||||
PanicAlert("Failed to compile Vertex Shader:\n\n%s", code);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
g_vs_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen);
|
||||
g_vs_disk_cache.Sync();
|
||||
|
||||
bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
|
||||
delete [] bytecode;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) {
|
||||
LPDIRECT3DVERTEXSHADER9 shader = D3D::CreateVertexShaderFromByteCode(bytecode, bytecodelen);
|
||||
|
||||
// Make an entry in the table
|
||||
VSCacheEntry entry;
|
||||
entry.shader = shader;
|
||||
entry.frameCount = frameCount;
|
||||
|
||||
vshaders[uid] = entry;
|
||||
last_entry = &vshaders[uid];
|
||||
if (!shader)
|
||||
return false;
|
||||
|
||||
INCSTAT(stats.numVertexShadersCreated);
|
||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
||||
if (activate)
|
||||
{
|
||||
D3D::SetVertexShader(shader);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string VertexShaderCache::GetCurrentShaderCode()
|
||||
{
|
||||
return "(N/A)\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -1,81 +1,81 @@
|
|||
// 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 "DX9_D3DBase.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
#include "../VertexShaderCache.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class VertexShaderCache : public ::VertexShaderCacheBase
|
||||
{
|
||||
private:
|
||||
struct VSCacheEntry
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 shader;
|
||||
int frameCount;
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string code;
|
||||
#endif
|
||||
VSCacheEntry() : shader(NULL), frameCount(0) {}
|
||||
void Destroy()
|
||||
{
|
||||
if (shader)
|
||||
shader->Release();
|
||||
shader = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
|
||||
|
||||
static VSCache vshaders;
|
||||
static const VSCacheEntry *last_entry;
|
||||
static void Clear();
|
||||
|
||||
public:
|
||||
VertexShaderCache();
|
||||
~VertexShaderCache();
|
||||
|
||||
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetVSConstant4fv(unsigned int const_number, const float *f);
|
||||
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f);
|
||||
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
|
||||
|
||||
bool SetShader(u32 components);
|
||||
|
||||
static LPDIRECT3DVERTEXSHADER9 GetSimpleVertexShader(int level);
|
||||
static LPDIRECT3DVERTEXSHADER9 GetClearVertexShader();
|
||||
static bool InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
static std::string GetCurrentShaderCode();
|
||||
#endif
|
||||
static LPDIRECT3DVERTEXSHADER9 CompileCgShader(const char *pstrprogram);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _VERTEXSHADERCACHE_H
|
||||
// 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 "DX9_D3DBase.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "DX9_D3DBase.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
#include "../VertexShaderCache.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class VertexShaderCache : public ::VertexShaderCacheBase
|
||||
{
|
||||
private:
|
||||
struct VSCacheEntry
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 shader;
|
||||
int frameCount;
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string code;
|
||||
#endif
|
||||
VSCacheEntry() : shader(NULL), frameCount(0) {}
|
||||
void Destroy()
|
||||
{
|
||||
if (shader)
|
||||
shader->Release();
|
||||
shader = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
|
||||
|
||||
static VSCache vshaders;
|
||||
static const VSCacheEntry *last_entry;
|
||||
static void Clear();
|
||||
|
||||
public:
|
||||
VertexShaderCache();
|
||||
~VertexShaderCache();
|
||||
|
||||
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetVSConstant4fv(unsigned int const_number, const float *f);
|
||||
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f);
|
||||
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
|
||||
|
||||
bool SetShader(u32 components);
|
||||
|
||||
static LPDIRECT3DVERTEXSHADER9 GetSimpleVertexShader(int level);
|
||||
static LPDIRECT3DVERTEXSHADER9 GetClearVertexShader();
|
||||
static bool InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
static std::string GetCurrentShaderCode();
|
||||
#endif
|
||||
static LPDIRECT3DVERTEXSHADER9 CompileCgShader(const char *pstrprogram);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _VERTEXSHADERCACHE_H
|
||||
|
|
|
@ -1,233 +1,233 @@
|
|||
|
||||
#include <windows.h>
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
#include "Fifo.h"
|
||||
|
||||
#include "EmuWindow.h"
|
||||
|
||||
int OSDChoice = 0 , OSDTime = 0, OSDInternalW = 0, OSDInternalH = 0;
|
||||
|
||||
namespace EmuWindow
|
||||
{
|
||||
|
||||
HWND m_hWnd = NULL;
|
||||
HWND m_hParent = NULL;
|
||||
HINSTANCE m_hInstance = NULL;
|
||||
WNDCLASSEX wndClass;
|
||||
const TCHAR m_szClassName[] = _T("DolphinEmuWnd");
|
||||
int g_winstyle;
|
||||
static volatile bool s_sizing;
|
||||
|
||||
bool IsSizing()
|
||||
{
|
||||
return s_sizing;
|
||||
}
|
||||
|
||||
HWND GetWnd()
|
||||
{
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
HWND GetParentWnd()
|
||||
{
|
||||
return m_hParent;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// KeyDown events
|
||||
// -------------
|
||||
void OnKeyDown(WPARAM wParam)
|
||||
{
|
||||
switch (LOWORD( wParam ))
|
||||
{
|
||||
case '3': // OSD keys
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
if (g_Config.bOSDHotKey)
|
||||
OSDMenu(wParam);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
switch( iMsg )
|
||||
{
|
||||
case WM_PAINT:
|
||||
{
|
||||
HDC hdc;
|
||||
PAINTSTRUCT ps;
|
||||
hdc = BeginPaint(hWnd, &ps);
|
||||
EndPaint(hWnd, &ps);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_ENTERSIZEMOVE:
|
||||
s_sizing = true;
|
||||
break;
|
||||
|
||||
case WM_EXITSIZEMOVE:
|
||||
s_sizing = false;
|
||||
break;
|
||||
|
||||
/* Post thes mouse events to the main window, it's nessesary because in difference to the
|
||||
keyboard inputs these events only appear here, not in the parent window or any other WndProc()*/
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
PostMessage(GetParentWnd(), iMsg, wParam, lParam);
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
// When the user closes the window, we post an event to the main window to call Stop()
|
||||
// Which then handles all the necessary steps to Shutdown the core + the plugins
|
||||
if (m_hParent == NULL)
|
||||
PostMessage(m_hParent, WM_USER, WM_USER_STOP, 0);
|
||||
break;
|
||||
|
||||
case WM_USER:
|
||||
if (wParam == WM_USER_KEYDOWN)
|
||||
OnKeyDown(lParam);
|
||||
else if (wParam == WIIMOTE_DISCONNECT)
|
||||
PostMessage(m_hParent, WM_USER, wParam, lParam);
|
||||
break;
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
switch (wParam)
|
||||
{
|
||||
case SC_SCREENSAVE:
|
||||
case SC_MONITORPOWER:
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SETCURSOR:
|
||||
PostMessage(m_hParent, WM_USER, WM_USER_SETCURSOR, 0);
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// OSD Menu
|
||||
// -------------
|
||||
// Let's begin with 3 since 1 and 2 are default Wii keys
|
||||
// -------------
|
||||
void OSDMenu(WPARAM wParam)
|
||||
{
|
||||
switch( LOWORD( wParam ))
|
||||
{
|
||||
//case '3':
|
||||
// OSDChoice = 1;
|
||||
// // Toggle native resolution
|
||||
// OSDInternalW = D3D::GetBackBufferWidth();
|
||||
// OSDInternalH = D3D::GetBackBufferHeight();
|
||||
// break;
|
||||
case '4':
|
||||
OSDChoice = 2;
|
||||
// Toggle aspect ratio
|
||||
g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3;
|
||||
break;
|
||||
case '5':
|
||||
OSDChoice = 3;
|
||||
PanicAlert("Toggling EFB copy not implemented!\n");
|
||||
break;
|
||||
case '6':
|
||||
OSDChoice = 4;
|
||||
g_Config.bDisableFog = !g_Config.bDisableFog;
|
||||
break;
|
||||
case '7':
|
||||
OSDChoice = 5;
|
||||
g_Config.bDisableLighting = !g_Config.bDisableLighting;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title)
|
||||
{
|
||||
wndClass.cbSize = sizeof( wndClass );
|
||||
wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
|
||||
wndClass.lpfnWndProc = WndProc;
|
||||
wndClass.cbClsExtra = 0;
|
||||
wndClass.cbWndExtra = 0;
|
||||
wndClass.hInstance = hInstance;
|
||||
wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
|
||||
wndClass.hCursor = NULL;
|
||||
wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
|
||||
wndClass.lpszMenuName = NULL;
|
||||
wndClass.lpszClassName = m_szClassName;
|
||||
wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
|
||||
|
||||
m_hInstance = hInstance;
|
||||
RegisterClassEx( &wndClass );
|
||||
|
||||
m_hParent = parent;
|
||||
|
||||
m_hWnd = CreateWindow(m_szClassName, title, WS_CHILD,
|
||||
0, 0, width, height, m_hParent, NULL, hInstance, NULL);
|
||||
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
void Show()
|
||||
{
|
||||
ShowWindow(m_hWnd, SW_SHOW);
|
||||
BringWindowToTop(m_hWnd);
|
||||
UpdateWindow(m_hWnd);
|
||||
SetFocus(m_hParent);
|
||||
}
|
||||
|
||||
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title)
|
||||
{
|
||||
// TODO:
|
||||
// 1. Remove redundant window manipulation,
|
||||
// 2. Make DX11 in fullscreen can be overlapped by other dialogs
|
||||
// 3. Request window sizes which actually make the client area map to a common resolution
|
||||
HWND Ret;
|
||||
int x=0, y=0, width=640, height=480;
|
||||
g_VideoInitialize.pRequestWindowSize(x, y, width, height);
|
||||
|
||||
Ret = OpenWindow(hParent, hInstance, width, height, title);
|
||||
|
||||
if (Ret)
|
||||
{
|
||||
Show();
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
if (m_hParent == NULL)
|
||||
DestroyWindow(m_hWnd);
|
||||
UnregisterClass(m_szClassName, m_hInstance);
|
||||
}
|
||||
|
||||
void SetSize(int width, int height)
|
||||
{
|
||||
RECT rc = {0, 0, width, height};
|
||||
DWORD style = GetWindowLong(m_hWnd, GWL_STYLE);
|
||||
AdjustWindowRect(&rc, style, false);
|
||||
|
||||
int w = rc.right - rc.left;
|
||||
int h = rc.bottom - rc.top;
|
||||
|
||||
rc.left = (1280 - w)/2;
|
||||
rc.right = rc.left + w;
|
||||
rc.top = (1024 - h)/2;
|
||||
rc.bottom = rc.top + h;
|
||||
MoveWindow(m_hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
#include "Fifo.h"
|
||||
|
||||
#include "EmuWindow.h"
|
||||
|
||||
int OSDChoice = 0 , OSDTime = 0, OSDInternalW = 0, OSDInternalH = 0;
|
||||
|
||||
namespace EmuWindow
|
||||
{
|
||||
|
||||
HWND m_hWnd = NULL;
|
||||
HWND m_hParent = NULL;
|
||||
HINSTANCE m_hInstance = NULL;
|
||||
WNDCLASSEX wndClass;
|
||||
const TCHAR m_szClassName[] = _T("DolphinEmuWnd");
|
||||
int g_winstyle;
|
||||
static volatile bool s_sizing;
|
||||
|
||||
bool IsSizing()
|
||||
{
|
||||
return s_sizing;
|
||||
}
|
||||
|
||||
HWND GetWnd()
|
||||
{
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
HWND GetParentWnd()
|
||||
{
|
||||
return m_hParent;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// KeyDown events
|
||||
// -------------
|
||||
void OnKeyDown(WPARAM wParam)
|
||||
{
|
||||
switch (LOWORD( wParam ))
|
||||
{
|
||||
case '3': // OSD keys
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
if (g_Config.bOSDHotKey)
|
||||
OSDMenu(wParam);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
switch( iMsg )
|
||||
{
|
||||
case WM_PAINT:
|
||||
{
|
||||
HDC hdc;
|
||||
PAINTSTRUCT ps;
|
||||
hdc = BeginPaint(hWnd, &ps);
|
||||
EndPaint(hWnd, &ps);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_ENTERSIZEMOVE:
|
||||
s_sizing = true;
|
||||
break;
|
||||
|
||||
case WM_EXITSIZEMOVE:
|
||||
s_sizing = false;
|
||||
break;
|
||||
|
||||
/* Post thes mouse events to the main window, it's nessesary because in difference to the
|
||||
keyboard inputs these events only appear here, not in the parent window or any other WndProc()*/
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
PostMessage(GetParentWnd(), iMsg, wParam, lParam);
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
// When the user closes the window, we post an event to the main window to call Stop()
|
||||
// Which then handles all the necessary steps to Shutdown the core + the plugins
|
||||
if (m_hParent == NULL)
|
||||
PostMessage(m_hParent, WM_USER, WM_USER_STOP, 0);
|
||||
break;
|
||||
|
||||
case WM_USER:
|
||||
if (wParam == WM_USER_KEYDOWN)
|
||||
OnKeyDown(lParam);
|
||||
else if (wParam == WIIMOTE_DISCONNECT)
|
||||
PostMessage(m_hParent, WM_USER, wParam, lParam);
|
||||
break;
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
switch (wParam)
|
||||
{
|
||||
case SC_SCREENSAVE:
|
||||
case SC_MONITORPOWER:
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SETCURSOR:
|
||||
PostMessage(m_hParent, WM_USER, WM_USER_SETCURSOR, 0);
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// OSD Menu
|
||||
// -------------
|
||||
// Let's begin with 3 since 1 and 2 are default Wii keys
|
||||
// -------------
|
||||
void OSDMenu(WPARAM wParam)
|
||||
{
|
||||
switch( LOWORD( wParam ))
|
||||
{
|
||||
//case '3':
|
||||
// OSDChoice = 1;
|
||||
// // Toggle native resolution
|
||||
// OSDInternalW = D3D::GetBackBufferWidth();
|
||||
// OSDInternalH = D3D::GetBackBufferHeight();
|
||||
// break;
|
||||
case '4':
|
||||
OSDChoice = 2;
|
||||
// Toggle aspect ratio
|
||||
g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3;
|
||||
break;
|
||||
case '5':
|
||||
OSDChoice = 3;
|
||||
PanicAlert("Toggling EFB copy not implemented!\n");
|
||||
break;
|
||||
case '6':
|
||||
OSDChoice = 4;
|
||||
g_Config.bDisableFog = !g_Config.bDisableFog;
|
||||
break;
|
||||
case '7':
|
||||
OSDChoice = 5;
|
||||
g_Config.bDisableLighting = !g_Config.bDisableLighting;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title)
|
||||
{
|
||||
wndClass.cbSize = sizeof( wndClass );
|
||||
wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
|
||||
wndClass.lpfnWndProc = WndProc;
|
||||
wndClass.cbClsExtra = 0;
|
||||
wndClass.cbWndExtra = 0;
|
||||
wndClass.hInstance = hInstance;
|
||||
wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
|
||||
wndClass.hCursor = NULL;
|
||||
wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
|
||||
wndClass.lpszMenuName = NULL;
|
||||
wndClass.lpszClassName = m_szClassName;
|
||||
wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
|
||||
|
||||
m_hInstance = hInstance;
|
||||
RegisterClassEx( &wndClass );
|
||||
|
||||
m_hParent = parent;
|
||||
|
||||
m_hWnd = CreateWindow(m_szClassName, title, WS_CHILD,
|
||||
0, 0, width, height, m_hParent, NULL, hInstance, NULL);
|
||||
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
void Show()
|
||||
{
|
||||
ShowWindow(m_hWnd, SW_SHOW);
|
||||
BringWindowToTop(m_hWnd);
|
||||
UpdateWindow(m_hWnd);
|
||||
SetFocus(m_hParent);
|
||||
}
|
||||
|
||||
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title)
|
||||
{
|
||||
// TODO:
|
||||
// 1. Remove redundant window manipulation,
|
||||
// 2. Make DX11 in fullscreen can be overlapped by other dialogs
|
||||
// 3. Request window sizes which actually make the client area map to a common resolution
|
||||
HWND Ret;
|
||||
int x=0, y=0, width=640, height=480;
|
||||
g_VideoInitialize.pRequestWindowSize(x, y, width, height);
|
||||
|
||||
Ret = OpenWindow(hParent, hInstance, width, height, title);
|
||||
|
||||
if (Ret)
|
||||
{
|
||||
Show();
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
if (m_hParent == NULL)
|
||||
DestroyWindow(m_hWnd);
|
||||
UnregisterClass(m_szClassName, m_hInstance);
|
||||
}
|
||||
|
||||
void SetSize(int width, int height)
|
||||
{
|
||||
RECT rc = {0, 0, width, height};
|
||||
DWORD style = GetWindowLong(m_hWnd, GWL_STYLE);
|
||||
AdjustWindowRect(&rc, style, false);
|
||||
|
||||
int w = rc.right - rc.left;
|
||||
int h = rc.bottom - rc.top;
|
||||
|
||||
rc.left = (1280 - w)/2;
|
||||
rc.right = rc.left + w;
|
||||
rc.top = (1024 - h)/2;
|
||||
rc.bottom = rc.top + h;
|
||||
MoveWindow(m_hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
|
||||
#ifndef _EMUWINDOW_H_
|
||||
#define _EMUWINDOW_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace EmuWindow
|
||||
{
|
||||
|
||||
HWND GetWnd();
|
||||
HWND GetParentWnd();
|
||||
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR* title);
|
||||
void Show();
|
||||
void Close();
|
||||
void SetSize(int displayWidth, int displayHeight);
|
||||
bool IsSizing();
|
||||
void OSDMenu(WPARAM wParam);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _EMUWINDOW_H_
|
||||
#define _EMUWINDOW_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace EmuWindow
|
||||
{
|
||||
|
||||
HWND GetWnd();
|
||||
HWND GetParentWnd();
|
||||
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR* title);
|
||||
void Show();
|
||||
void Close();
|
||||
void SetSize(int displayWidth, int displayHeight);
|
||||
bool IsSizing();
|
||||
void OSDMenu(WPARAM wParam);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,216 +1,216 @@
|
|||
|
||||
#include "FramebufferManager.h"
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "Renderer.h"
|
||||
|
||||
#include "Main.h"
|
||||
|
||||
FramebufferManagerBase::VirtualXFBListType FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode
|
||||
|
||||
const XFBSourceBase* FramebufferManagerBase::m_overlappingXFBArray[];
|
||||
|
||||
FramebufferManagerBase::~FramebufferManagerBase()
|
||||
{
|
||||
VirtualXFBListType::iterator
|
||||
it = m_virtualXFBList.begin(),
|
||||
vlend = m_virtualXFBList.end();
|
||||
for (; it != vlend; ++it)
|
||||
delete it->xfbSource;
|
||||
}
|
||||
|
||||
const XFBSourceBase** FramebufferManagerBase::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||
{
|
||||
//if (g_ActiveConfig.bUseRealXFB)
|
||||
// return getRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||
//else
|
||||
return getVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||
}
|
||||
|
||||
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
||||
{
|
||||
return !((aLower >= bUpper) || (bLower >= aUpper));
|
||||
}
|
||||
|
||||
void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
//if (g_ActiveConfig.bUseRealXFB)
|
||||
// copyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||
//else
|
||||
copyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||
}
|
||||
|
||||
void FramebufferManagerBase::replaceVirtualXFB()
|
||||
{
|
||||
VirtualXFBListType::iterator
|
||||
it = m_virtualXFBList.begin(),
|
||||
vlend = m_virtualXFBList.end();
|
||||
|
||||
VirtualXFB *vxfb = &*it;
|
||||
|
||||
const s32 srcLower = vxfb->xfbAddr;
|
||||
const s32 srcUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
|
||||
const s32 lineSize = 2 * vxfb->xfbWidth;
|
||||
|
||||
while (++it != vlend)
|
||||
{
|
||||
vxfb = &*it;
|
||||
|
||||
const s32 dstLower = vxfb->xfbAddr;
|
||||
const s32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
|
||||
|
||||
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
||||
{
|
||||
// invalidate the data
|
||||
vxfb->xfbAddr = 0;
|
||||
vxfb->xfbHeight = 0;
|
||||
vxfb->xfbWidth = 0;
|
||||
}
|
||||
else if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
||||
{
|
||||
const s32 upperOverlap = (srcUpper - dstLower) / lineSize;
|
||||
const s32 lowerOverlap = (dstUpper - srcLower) / lineSize;
|
||||
|
||||
if (upperOverlap > 0 && lowerOverlap < 0)
|
||||
{
|
||||
vxfb->xfbAddr += lineSize * upperOverlap;
|
||||
vxfb->xfbHeight -= upperOverlap;
|
||||
}
|
||||
else if (lowerOverlap > 0)
|
||||
{
|
||||
vxfb->xfbHeight -= lowerOverlap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FramebufferManagerBase::VirtualXFBListType::iterator
|
||||
FramebufferManagerBase::findVirtualXFB(u32 xfbAddr, u32 width, u32 height)
|
||||
{
|
||||
const u32 srcLower = xfbAddr;
|
||||
const u32 srcUpper = xfbAddr + 2 * width * height;
|
||||
|
||||
VirtualXFBListType::iterator
|
||||
it = m_virtualXFBList.begin(),
|
||||
vlend = m_virtualXFBList.end();
|
||||
for (; it != vlend; ++it)
|
||||
{
|
||||
const VirtualXFB &vxfb = *it;
|
||||
|
||||
const u32 dstLower = vxfb.xfbAddr;
|
||||
const u32 dstUpper = vxfb.xfbAddr + 2 * vxfb.xfbWidth * vxfb.xfbHeight;
|
||||
|
||||
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
||||
return it;
|
||||
}
|
||||
|
||||
// That address is not in the Virtual XFB list.
|
||||
return m_virtualXFBList.end();
|
||||
}
|
||||
|
||||
void FramebufferManagerBase::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
const VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, fbWidth, fbHeight);
|
||||
|
||||
VirtualXFB *vxfb = NULL;
|
||||
|
||||
if (m_virtualXFBList.end() == it)
|
||||
{
|
||||
if (m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
|
||||
{
|
||||
PanicAlert("Requested creating a new virtual XFB although the maximum number has already been reached! Report this to the devs");
|
||||
return;
|
||||
// TODO, possible alternative to failing: just delete the oldest virtual XFB:
|
||||
// delete m_virtualXFBList.back().xfbSource;
|
||||
// m_virtualXFBList.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
// create a new Virtual XFB and place it at the front of the list
|
||||
VirtualXFB v;
|
||||
m_virtualXFBList.push_front(v);
|
||||
vxfb = &m_virtualXFBList.front();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vxfb = &*it;
|
||||
delete vxfb->xfbSource;
|
||||
}
|
||||
|
||||
vxfb->xfbAddr = xfbAddr;
|
||||
vxfb->xfbWidth = fbWidth;
|
||||
vxfb->xfbHeight = fbHeight;
|
||||
|
||||
const float scaleX = RendererBase::GetXFBScaleX();
|
||||
const float scaleY = RendererBase::GetXFBScaleY();
|
||||
|
||||
TargetRectangle targetSource;
|
||||
targetSource.top = (int)(sourceRc.top * scaleY);
|
||||
targetSource.bottom = (int)(sourceRc.bottom * scaleY);
|
||||
targetSource.left = (int)(sourceRc.left * scaleX);
|
||||
targetSource.right = (int)(sourceRc.right * scaleX);
|
||||
|
||||
const unsigned int target_width = targetSource.right - targetSource.left;
|
||||
const unsigned int target_height = targetSource.bottom - targetSource.top;
|
||||
|
||||
vxfb->xfbSource = g_framebuffer_manager->CreateXFBSource(target_width, target_height);
|
||||
if (NULL == vxfb->xfbSource)
|
||||
{
|
||||
PanicAlert("Failed to create virtual XFB");
|
||||
return;
|
||||
}
|
||||
|
||||
// why do both of these have a height/width/addr ?
|
||||
vxfb->xfbSource->srcAddr = xfbAddr;
|
||||
vxfb->xfbSource->srcWidth = fbWidth;
|
||||
vxfb->xfbSource->srcHeight = fbHeight;
|
||||
|
||||
vxfb->xfbSource->texWidth = target_width;
|
||||
vxfb->xfbSource->texHeight = target_height;
|
||||
|
||||
if (m_virtualXFBList.end() != it)
|
||||
{
|
||||
// move this Virtual XFB to the front of the list.
|
||||
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it);
|
||||
|
||||
// keep stale XFB data from being used
|
||||
replaceVirtualXFB();
|
||||
}
|
||||
|
||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||
|
||||
vxfb->xfbSource->CopyEFB(RendererBase::ConvertEFBRectangle(sourceRc));
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
const XFBSourceBase** FramebufferManagerBase::getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||
{
|
||||
xfbCount = 0;
|
||||
|
||||
if (0 == m_virtualXFBList.size()) // no Virtual XFBs available
|
||||
return NULL;
|
||||
|
||||
u32 srcLower = xfbAddr;
|
||||
u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight;
|
||||
|
||||
VirtualXFBListType::reverse_iterator
|
||||
it = m_virtualXFBList.rbegin(),
|
||||
vlend = m_virtualXFBList.rend();
|
||||
for (; it != vlend; ++it)
|
||||
{
|
||||
VirtualXFB* vxfb = &*it;
|
||||
|
||||
u32 dstLower = vxfb->xfbAddr;
|
||||
u32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
|
||||
|
||||
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
||||
{
|
||||
m_overlappingXFBArray[xfbCount] = vxfb->xfbSource;
|
||||
xfbCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return &m_overlappingXFBArray[0];
|
||||
}
|
||||
|
||||
#include "FramebufferManager.h"
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "Renderer.h"
|
||||
|
||||
#include "Main.h"
|
||||
|
||||
FramebufferManagerBase::VirtualXFBListType FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode
|
||||
|
||||
const XFBSourceBase* FramebufferManagerBase::m_overlappingXFBArray[];
|
||||
|
||||
FramebufferManagerBase::~FramebufferManagerBase()
|
||||
{
|
||||
VirtualXFBListType::iterator
|
||||
it = m_virtualXFBList.begin(),
|
||||
vlend = m_virtualXFBList.end();
|
||||
for (; it != vlend; ++it)
|
||||
delete it->xfbSource;
|
||||
}
|
||||
|
||||
const XFBSourceBase** FramebufferManagerBase::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||
{
|
||||
//if (g_ActiveConfig.bUseRealXFB)
|
||||
// return getRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||
//else
|
||||
return getVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||
}
|
||||
|
||||
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
||||
{
|
||||
return !((aLower >= bUpper) || (bLower >= aUpper));
|
||||
}
|
||||
|
||||
void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
//if (g_ActiveConfig.bUseRealXFB)
|
||||
// copyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||
//else
|
||||
copyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||
}
|
||||
|
||||
void FramebufferManagerBase::replaceVirtualXFB()
|
||||
{
|
||||
VirtualXFBListType::iterator
|
||||
it = m_virtualXFBList.begin(),
|
||||
vlend = m_virtualXFBList.end();
|
||||
|
||||
VirtualXFB *vxfb = &*it;
|
||||
|
||||
const s32 srcLower = vxfb->xfbAddr;
|
||||
const s32 srcUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
|
||||
const s32 lineSize = 2 * vxfb->xfbWidth;
|
||||
|
||||
while (++it != vlend)
|
||||
{
|
||||
vxfb = &*it;
|
||||
|
||||
const s32 dstLower = vxfb->xfbAddr;
|
||||
const s32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
|
||||
|
||||
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
||||
{
|
||||
// invalidate the data
|
||||
vxfb->xfbAddr = 0;
|
||||
vxfb->xfbHeight = 0;
|
||||
vxfb->xfbWidth = 0;
|
||||
}
|
||||
else if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
||||
{
|
||||
const s32 upperOverlap = (srcUpper - dstLower) / lineSize;
|
||||
const s32 lowerOverlap = (dstUpper - srcLower) / lineSize;
|
||||
|
||||
if (upperOverlap > 0 && lowerOverlap < 0)
|
||||
{
|
||||
vxfb->xfbAddr += lineSize * upperOverlap;
|
||||
vxfb->xfbHeight -= upperOverlap;
|
||||
}
|
||||
else if (lowerOverlap > 0)
|
||||
{
|
||||
vxfb->xfbHeight -= lowerOverlap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FramebufferManagerBase::VirtualXFBListType::iterator
|
||||
FramebufferManagerBase::findVirtualXFB(u32 xfbAddr, u32 width, u32 height)
|
||||
{
|
||||
const u32 srcLower = xfbAddr;
|
||||
const u32 srcUpper = xfbAddr + 2 * width * height;
|
||||
|
||||
VirtualXFBListType::iterator
|
||||
it = m_virtualXFBList.begin(),
|
||||
vlend = m_virtualXFBList.end();
|
||||
for (; it != vlend; ++it)
|
||||
{
|
||||
const VirtualXFB &vxfb = *it;
|
||||
|
||||
const u32 dstLower = vxfb.xfbAddr;
|
||||
const u32 dstUpper = vxfb.xfbAddr + 2 * vxfb.xfbWidth * vxfb.xfbHeight;
|
||||
|
||||
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
||||
return it;
|
||||
}
|
||||
|
||||
// That address is not in the Virtual XFB list.
|
||||
return m_virtualXFBList.end();
|
||||
}
|
||||
|
||||
void FramebufferManagerBase::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
const VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, fbWidth, fbHeight);
|
||||
|
||||
VirtualXFB *vxfb = NULL;
|
||||
|
||||
if (m_virtualXFBList.end() == it)
|
||||
{
|
||||
if (m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
|
||||
{
|
||||
PanicAlert("Requested creating a new virtual XFB although the maximum number has already been reached! Report this to the devs");
|
||||
return;
|
||||
// TODO, possible alternative to failing: just delete the oldest virtual XFB:
|
||||
// delete m_virtualXFBList.back().xfbSource;
|
||||
// m_virtualXFBList.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
// create a new Virtual XFB and place it at the front of the list
|
||||
VirtualXFB v;
|
||||
m_virtualXFBList.push_front(v);
|
||||
vxfb = &m_virtualXFBList.front();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vxfb = &*it;
|
||||
delete vxfb->xfbSource;
|
||||
}
|
||||
|
||||
vxfb->xfbAddr = xfbAddr;
|
||||
vxfb->xfbWidth = fbWidth;
|
||||
vxfb->xfbHeight = fbHeight;
|
||||
|
||||
const float scaleX = RendererBase::GetXFBScaleX();
|
||||
const float scaleY = RendererBase::GetXFBScaleY();
|
||||
|
||||
TargetRectangle targetSource;
|
||||
targetSource.top = (int)(sourceRc.top * scaleY);
|
||||
targetSource.bottom = (int)(sourceRc.bottom * scaleY);
|
||||
targetSource.left = (int)(sourceRc.left * scaleX);
|
||||
targetSource.right = (int)(sourceRc.right * scaleX);
|
||||
|
||||
const unsigned int target_width = targetSource.right - targetSource.left;
|
||||
const unsigned int target_height = targetSource.bottom - targetSource.top;
|
||||
|
||||
vxfb->xfbSource = g_framebuffer_manager->CreateXFBSource(target_width, target_height);
|
||||
if (NULL == vxfb->xfbSource)
|
||||
{
|
||||
PanicAlert("Failed to create virtual XFB");
|
||||
return;
|
||||
}
|
||||
|
||||
// why do both of these have a height/width/addr ?
|
||||
vxfb->xfbSource->srcAddr = xfbAddr;
|
||||
vxfb->xfbSource->srcWidth = fbWidth;
|
||||
vxfb->xfbSource->srcHeight = fbHeight;
|
||||
|
||||
vxfb->xfbSource->texWidth = target_width;
|
||||
vxfb->xfbSource->texHeight = target_height;
|
||||
|
||||
if (m_virtualXFBList.end() != it)
|
||||
{
|
||||
// move this Virtual XFB to the front of the list.
|
||||
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it);
|
||||
|
||||
// keep stale XFB data from being used
|
||||
replaceVirtualXFB();
|
||||
}
|
||||
|
||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||
|
||||
vxfb->xfbSource->CopyEFB(RendererBase::ConvertEFBRectangle(sourceRc));
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
const XFBSourceBase** FramebufferManagerBase::getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||
{
|
||||
xfbCount = 0;
|
||||
|
||||
if (0 == m_virtualXFBList.size()) // no Virtual XFBs available
|
||||
return NULL;
|
||||
|
||||
u32 srcLower = xfbAddr;
|
||||
u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight;
|
||||
|
||||
VirtualXFBListType::reverse_iterator
|
||||
it = m_virtualXFBList.rbegin(),
|
||||
vlend = m_virtualXFBList.rend();
|
||||
for (; it != vlend; ++it)
|
||||
{
|
||||
VirtualXFB* vxfb = &*it;
|
||||
|
||||
u32 dstLower = vxfb->xfbAddr;
|
||||
u32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
|
||||
|
||||
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
||||
{
|
||||
m_overlappingXFBArray[xfbCount] = vxfb->xfbSource;
|
||||
xfbCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return &m_overlappingXFBArray[0];
|
||||
}
|
||||
|
|
|
@ -1,71 +1,71 @@
|
|||
|
||||
#ifndef _FRAMEBUFFERMANAGER_H_
|
||||
#define _FRAMEBUFFERMANAGER_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "CommonTypes.h"
|
||||
#include "VideoCommon.h"
|
||||
|
||||
struct XFBSourceBase
|
||||
{
|
||||
u32 srcAddr;
|
||||
u32 srcWidth;
|
||||
u32 srcHeight;
|
||||
|
||||
unsigned int texWidth;
|
||||
unsigned int texHeight;
|
||||
|
||||
virtual void CopyEFB(const TargetRectangle& efbSource) = 0;
|
||||
|
||||
virtual ~XFBSourceBase() {}
|
||||
|
||||
protected:
|
||||
XFBSourceBase() : srcAddr(0), srcWidth(0), srcHeight(0), texWidth(0), texHeight(0) {}
|
||||
};
|
||||
|
||||
class FramebufferManagerBase
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_VIRTUAL_XFB = 8,
|
||||
};
|
||||
|
||||
virtual ~FramebufferManagerBase();
|
||||
|
||||
//virtual void Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples) = 0;
|
||||
//virtual void Shutdown() = 0;
|
||||
|
||||
static void replaceVirtualXFB();
|
||||
|
||||
static void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
|
||||
static const XFBSourceBase** GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||
static const XFBSourceBase** getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||
|
||||
//protected:
|
||||
struct VirtualXFB
|
||||
{
|
||||
// Address and size in GameCube RAM
|
||||
u32 xfbAddr;
|
||||
u32 xfbWidth;
|
||||
u32 xfbHeight;
|
||||
|
||||
XFBSourceBase *xfbSource;
|
||||
};
|
||||
|
||||
virtual XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height) = 0;
|
||||
|
||||
typedef std::list<VirtualXFB> VirtualXFBListType;
|
||||
static VirtualXFBListType m_virtualXFBList; // used in virtual XFB mode
|
||||
|
||||
static VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height);
|
||||
|
||||
static void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
|
||||
static const XFBSourceBase* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _FRAMEBUFFERMANAGER_H_
|
||||
#define _FRAMEBUFFERMANAGER_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "CommonTypes.h"
|
||||
#include "VideoCommon.h"
|
||||
|
||||
struct XFBSourceBase
|
||||
{
|
||||
u32 srcAddr;
|
||||
u32 srcWidth;
|
||||
u32 srcHeight;
|
||||
|
||||
unsigned int texWidth;
|
||||
unsigned int texHeight;
|
||||
|
||||
virtual void CopyEFB(const TargetRectangle& efbSource) = 0;
|
||||
|
||||
virtual ~XFBSourceBase() {}
|
||||
|
||||
protected:
|
||||
XFBSourceBase() : srcAddr(0), srcWidth(0), srcHeight(0), texWidth(0), texHeight(0) {}
|
||||
};
|
||||
|
||||
class FramebufferManagerBase
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_VIRTUAL_XFB = 8,
|
||||
};
|
||||
|
||||
virtual ~FramebufferManagerBase();
|
||||
|
||||
//virtual void Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples) = 0;
|
||||
//virtual void Shutdown() = 0;
|
||||
|
||||
static void replaceVirtualXFB();
|
||||
|
||||
static void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
|
||||
static const XFBSourceBase** GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||
static const XFBSourceBase** getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||
|
||||
//protected:
|
||||
struct VirtualXFB
|
||||
{
|
||||
// Address and size in GameCube RAM
|
||||
u32 xfbAddr;
|
||||
u32 xfbWidth;
|
||||
u32 xfbHeight;
|
||||
|
||||
XFBSourceBase *xfbSource;
|
||||
};
|
||||
|
||||
virtual XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height) = 0;
|
||||
|
||||
typedef std::list<VirtualXFB> VirtualXFBListType;
|
||||
static VirtualXFBListType m_virtualXFBList; // used in virtual XFB mode
|
||||
|
||||
static VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height);
|
||||
|
||||
static void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
|
||||
static const XFBSourceBase* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,57 +1,57 @@
|
|||
// 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 _MAIN_H_
|
||||
#define _MAIN_H_
|
||||
|
||||
#include "PluginSpecs_Video.h"
|
||||
|
||||
#include "Renderer.h"
|
||||
#include "TextureCache.h"
|
||||
#include "VertexManager.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "VertexShaderCache.h"
|
||||
#include "FramebufferManager.h"
|
||||
|
||||
extern SVideoInitialize g_VideoInitialize;
|
||||
extern volatile u32 s_swapRequested;
|
||||
extern PLUGIN_GLOBALS *g_globals;
|
||||
|
||||
extern RendererBase *g_renderer;
|
||||
extern TextureCacheBase *g_texture_cache;
|
||||
extern VertexManagerBase *g_vertex_manager;
|
||||
extern VertexShaderCacheBase* g_vertex_shader_cache;
|
||||
extern PixelShaderCacheBase* g_pixel_shader_cache;
|
||||
extern FramebufferManagerBase* g_framebuffer_manager;
|
||||
|
||||
extern int frameCount;
|
||||
|
||||
void VideoFifo_CheckEFBAccess();
|
||||
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
|
||||
|
||||
enum
|
||||
{
|
||||
GFXAPI_SOFTWARE,
|
||||
GFXAPI_OPENGL,
|
||||
GFXAPI_D3D9,
|
||||
GFXAPI_D3D11,
|
||||
};
|
||||
|
||||
extern const char* const g_gfxapi_names[];
|
||||
extern int g_gfxapi;
|
||||
|
||||
#endif
|
||||
// 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 _MAIN_H_
|
||||
#define _MAIN_H_
|
||||
|
||||
#include "PluginSpecs_Video.h"
|
||||
|
||||
#include "Renderer.h"
|
||||
#include "TextureCache.h"
|
||||
#include "VertexManager.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "VertexShaderCache.h"
|
||||
#include "FramebufferManager.h"
|
||||
|
||||
extern SVideoInitialize g_VideoInitialize;
|
||||
extern volatile u32 s_swapRequested;
|
||||
extern PLUGIN_GLOBALS *g_globals;
|
||||
|
||||
extern RendererBase *g_renderer;
|
||||
extern TextureCacheBase *g_texture_cache;
|
||||
extern VertexManagerBase *g_vertex_manager;
|
||||
extern VertexShaderCacheBase* g_vertex_shader_cache;
|
||||
extern PixelShaderCacheBase* g_pixel_shader_cache;
|
||||
extern FramebufferManagerBase* g_framebuffer_manager;
|
||||
|
||||
extern int frameCount;
|
||||
|
||||
void VideoFifo_CheckEFBAccess();
|
||||
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
|
||||
|
||||
enum
|
||||
{
|
||||
GFXAPI_SOFTWARE,
|
||||
GFXAPI_OPENGL,
|
||||
GFXAPI_D3D9,
|
||||
GFXAPI_D3D11,
|
||||
};
|
||||
|
||||
extern const char* const g_gfxapi_names[];
|
||||
extern int g_gfxapi;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,385 +1,385 @@
|
|||
// 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/
|
||||
|
||||
// OGL
|
||||
#include "OGL_Render.h"
|
||||
#include "OGL_XFB.h"
|
||||
#include "OGL_FramebufferManager.h"
|
||||
#include "OGL_TextureConverter.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
extern bool s_bHaveFramebufferBlit; // comes from Render.cpp
|
||||
|
||||
int FramebufferManager::m_targetWidth;
|
||||
int FramebufferManager::m_targetHeight;
|
||||
int FramebufferManager::m_msaaSamples;
|
||||
int FramebufferManager::m_msaaCoverageSamples;
|
||||
|
||||
GLuint FramebufferManager::m_efbFramebuffer;
|
||||
GLuint FramebufferManager::m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
|
||||
GLuint FramebufferManager::m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
|
||||
|
||||
// Only used in MSAA mode.
|
||||
GLuint FramebufferManager::m_resolvedFramebuffer;
|
||||
GLuint FramebufferManager::m_resolvedColorTexture;
|
||||
GLuint FramebufferManager::m_resolvedDepthTexture;
|
||||
|
||||
GLuint FramebufferManager::m_xfbFramebuffer; // Only used in MSAA mode
|
||||
XFBSource FramebufferManager::m_realXFBSource; // Only used in Real XFB mode
|
||||
|
||||
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
|
||||
{
|
||||
// m_efbFramebuffer(0),
|
||||
// m_efbColor(0),
|
||||
// m_efbDepth(0),
|
||||
// m_resolvedFramebuffer(0),
|
||||
// m_resolvedColorTexture(0),
|
||||
// m_resolvedDepthTexture(0),
|
||||
// m_xfbFramebuffer(0)
|
||||
|
||||
m_targetWidth = targetWidth;
|
||||
m_targetHeight = targetHeight;
|
||||
m_msaaSamples = msaaSamples;
|
||||
m_msaaCoverageSamples = msaaCoverageSamples;
|
||||
|
||||
// The EFB can be set to different pixel formats by the game through the
|
||||
// BPMEM_ZCOMPARE register (which should probably have a different name).
|
||||
// They are:
|
||||
// - 24-bit RGB (8-bit components) with 24-bit Z
|
||||
// - 24-bit RGBA (6-bit components) with 24-bit Z
|
||||
// - Multisampled 16-bit RGB (5-6-5 format) with 16-bit Z
|
||||
// We only use one EFB format here: 32-bit ARGB with 24-bit Z.
|
||||
// Multisampling depends on user settings.
|
||||
// The distinction becomes important for certain operations, i.e. the
|
||||
// alpha channel should be ignored if the EFB does not have one.
|
||||
|
||||
// Create EFB target.
|
||||
|
||||
glGenFramebuffersEXT(1, &m_efbFramebuffer);
|
||||
|
||||
if (m_msaaSamples <= 1)
|
||||
{
|
||||
// EFB targets will be textures in non-MSAA mode.
|
||||
|
||||
GLuint glObj[2];
|
||||
glGenTextures(2, glObj);
|
||||
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_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_ARB, 0);
|
||||
|
||||
// Bind target textures to the EFB framebuffer.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbColor, 0);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0);
|
||||
|
||||
GL_REPORT_FBO_ERROR();
|
||||
}
|
||||
else
|
||||
{
|
||||
// EFB targets will be renderbuffers in MSAA mode (required by OpenGL).
|
||||
// Resolve targets will be created to transfer EFB to RAM textures.
|
||||
// XFB framebuffer will be created to transfer EFB to XFB texture.
|
||||
|
||||
// Create EFB target renderbuffers.
|
||||
|
||||
GLuint glObj[2];
|
||||
glGenRenderbuffersEXT(2, glObj);
|
||||
m_efbColor = glObj[0];
|
||||
m_efbDepth = glObj[1];
|
||||
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor);
|
||||
if (m_msaaCoverageSamples)
|
||||
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
|
||||
else
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
|
||||
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth);
|
||||
if (m_msaaCoverageSamples)
|
||||
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, 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);
|
||||
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||
|
||||
// Bind target renderbuffers to EFB framebuffer.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 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);
|
||||
|
||||
GL_REPORT_FBO_ERROR();
|
||||
|
||||
// Create resolved targets for transferring multisampled EFB to texture.
|
||||
|
||||
glGenFramebuffersEXT(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_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_ARB, 0);
|
||||
|
||||
// Bind resolved textures to resolved framebuffer.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
|
||||
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture, 0);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0);
|
||||
|
||||
GL_REPORT_FBO_ERROR();
|
||||
|
||||
// Return to EFB framebuffer.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||
}
|
||||
|
||||
// Create XFB framebuffer; targets will be created elsewhere.
|
||||
|
||||
glGenFramebuffersEXT(1, &m_xfbFramebuffer);
|
||||
|
||||
// EFB framebuffer is currently bound.
|
||||
}
|
||||
|
||||
FramebufferManager::~FramebufferManager()
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
|
||||
GLuint glObj[3];
|
||||
|
||||
// Note: OpenGL deletion functions silently ignore parameters of "0".
|
||||
|
||||
glObj[0] = m_efbFramebuffer;
|
||||
glObj[1] = m_resolvedFramebuffer;
|
||||
glObj[2] = m_xfbFramebuffer;
|
||||
glDeleteFramebuffersEXT(3, glObj);
|
||||
m_efbFramebuffer = 0;
|
||||
m_xfbFramebuffer = 0;
|
||||
|
||||
glObj[0] = m_resolvedColorTexture;
|
||||
glObj[1] = m_resolvedDepthTexture;
|
||||
glObj[2] = m_realXFBSource.texture;
|
||||
glDeleteTextures(3, glObj);
|
||||
m_resolvedColorTexture = 0;
|
||||
m_resolvedDepthTexture = 0;
|
||||
m_realXFBSource.texture = 0;
|
||||
|
||||
glObj[0] = m_efbColor;
|
||||
glObj[1] = m_efbDepth;
|
||||
if (m_msaaSamples <= 1)
|
||||
glDeleteTextures(2, glObj);
|
||||
else
|
||||
glDeleteRenderbuffersEXT(2, glObj);
|
||||
m_efbColor = 0;
|
||||
m_efbDepth = 0;
|
||||
}
|
||||
|
||||
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
|
||||
{
|
||||
XFBSource* const xfbs = new XFBSource;
|
||||
|
||||
glGenTextures(1, &xfbs->texture);
|
||||
|
||||
return xfbs;
|
||||
}
|
||||
|
||||
void XFBSource::CopyEFB(const TargetRectangle& efbSource)
|
||||
{
|
||||
// Copy EFB to XFB texture
|
||||
|
||||
#if 0
|
||||
if (m_msaaSamples <= 1)
|
||||
#else
|
||||
if (!s_bHaveFramebufferBlit)
|
||||
#endif
|
||||
{
|
||||
// Just copy the EFB directly.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::m_efbFramebuffer);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, texWidth, texHeight, 0);
|
||||
|
||||
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::m_efbFramebuffer);
|
||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, FramebufferManager::m_xfbFramebuffer);
|
||||
|
||||
// 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);
|
||||
|
||||
// Unbind texture.
|
||||
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
|
||||
|
||||
// Return to EFB.
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::m_efbFramebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
|
||||
{
|
||||
if (m_msaaSamples <= 1)
|
||||
{
|
||||
return m_efbColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
|
||||
// required.
|
||||
|
||||
TargetRectangle targetRc = RendererBase::ConvertEFBRectangle(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(
|
||||
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);
|
||||
|
||||
return m_resolvedColorTexture;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc)
|
||||
{
|
||||
if (m_msaaSamples <= 1)
|
||||
{
|
||||
return m_efbDepth;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
|
||||
// required.
|
||||
|
||||
TargetRectangle targetRc = RendererBase::ConvertEFBRectangle(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(
|
||||
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);
|
||||
|
||||
return m_resolvedDepthTexture;
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
u8* pXFB = Memory_GetPtr(xfbAddr);
|
||||
if (!pXFB)
|
||||
{
|
||||
WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
|
||||
return;
|
||||
}
|
||||
|
||||
XFB_Write(pXFB, sourceRc, fbWidth, fbHeight);
|
||||
}
|
||||
|
||||
const XFBSourceBase** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||
{
|
||||
xfbCount = 1;
|
||||
|
||||
m_realXFBSource.texWidth = MAX_XFB_WIDTH;
|
||||
m_realXFBSource.texHeight = MAX_XFB_HEIGHT;
|
||||
|
||||
m_realXFBSource.srcAddr = xfbAddr;
|
||||
m_realXFBSource.srcWidth = fbWidth;
|
||||
m_realXFBSource.srcHeight = fbHeight;
|
||||
|
||||
// OpenGL texture coordinates originate at the lower left, which is why
|
||||
// sourceRc.top = fbHeight and sourceRc.bottom = 0.
|
||||
m_realXFBSource.sourceRc.left = 0;
|
||||
m_realXFBSource.sourceRc.top = fbHeight;
|
||||
m_realXFBSource.sourceRc.right = fbWidth;
|
||||
m_realXFBSource.sourceRc.bottom = 0;
|
||||
|
||||
if (!m_realXFBSource.texture)
|
||||
{
|
||||
glGenTextures(1, &m_realXFBSource.texture);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_realXFBSource.texture);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, MAX_XFB_WIDTH, MAX_XFB_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
}
|
||||
|
||||
// Decode YUYV data from GameCube RAM
|
||||
TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture);
|
||||
|
||||
m_overlappingXFBArray[0] = &m_realXFBSource;
|
||||
|
||||
return &m_overlappingXFBArray[0];
|
||||
}
|
||||
|
||||
void FramebufferManager::SetFramebuffer(GLuint fb)
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb != 0 ? fb : GetEFBFramebuffer());
|
||||
}
|
||||
|
||||
// Apply AA if enabled
|
||||
GLuint FramebufferManager::ResolveAndGetRenderTarget(const EFBRectangle &source_rect)
|
||||
{
|
||||
return GetEFBColorTexture(source_rect);
|
||||
}
|
||||
|
||||
GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_rect)
|
||||
{
|
||||
return GetEFBDepthTexture(source_rect);
|
||||
}
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
// OGL
|
||||
#include "OGL_Render.h"
|
||||
#include "OGL_XFB.h"
|
||||
#include "OGL_FramebufferManager.h"
|
||||
#include "OGL_TextureConverter.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
extern bool s_bHaveFramebufferBlit; // comes from Render.cpp
|
||||
|
||||
int FramebufferManager::m_targetWidth;
|
||||
int FramebufferManager::m_targetHeight;
|
||||
int FramebufferManager::m_msaaSamples;
|
||||
int FramebufferManager::m_msaaCoverageSamples;
|
||||
|
||||
GLuint FramebufferManager::m_efbFramebuffer;
|
||||
GLuint FramebufferManager::m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
|
||||
GLuint FramebufferManager::m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
|
||||
|
||||
// Only used in MSAA mode.
|
||||
GLuint FramebufferManager::m_resolvedFramebuffer;
|
||||
GLuint FramebufferManager::m_resolvedColorTexture;
|
||||
GLuint FramebufferManager::m_resolvedDepthTexture;
|
||||
|
||||
GLuint FramebufferManager::m_xfbFramebuffer; // Only used in MSAA mode
|
||||
XFBSource FramebufferManager::m_realXFBSource; // Only used in Real XFB mode
|
||||
|
||||
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
|
||||
{
|
||||
// m_efbFramebuffer(0),
|
||||
// m_efbColor(0),
|
||||
// m_efbDepth(0),
|
||||
// m_resolvedFramebuffer(0),
|
||||
// m_resolvedColorTexture(0),
|
||||
// m_resolvedDepthTexture(0),
|
||||
// m_xfbFramebuffer(0)
|
||||
|
||||
m_targetWidth = targetWidth;
|
||||
m_targetHeight = targetHeight;
|
||||
m_msaaSamples = msaaSamples;
|
||||
m_msaaCoverageSamples = msaaCoverageSamples;
|
||||
|
||||
// The EFB can be set to different pixel formats by the game through the
|
||||
// BPMEM_ZCOMPARE register (which should probably have a different name).
|
||||
// They are:
|
||||
// - 24-bit RGB (8-bit components) with 24-bit Z
|
||||
// - 24-bit RGBA (6-bit components) with 24-bit Z
|
||||
// - Multisampled 16-bit RGB (5-6-5 format) with 16-bit Z
|
||||
// We only use one EFB format here: 32-bit ARGB with 24-bit Z.
|
||||
// Multisampling depends on user settings.
|
||||
// The distinction becomes important for certain operations, i.e. the
|
||||
// alpha channel should be ignored if the EFB does not have one.
|
||||
|
||||
// Create EFB target.
|
||||
|
||||
glGenFramebuffersEXT(1, &m_efbFramebuffer);
|
||||
|
||||
if (m_msaaSamples <= 1)
|
||||
{
|
||||
// EFB targets will be textures in non-MSAA mode.
|
||||
|
||||
GLuint glObj[2];
|
||||
glGenTextures(2, glObj);
|
||||
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_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_ARB, 0);
|
||||
|
||||
// Bind target textures to the EFB framebuffer.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbColor, 0);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0);
|
||||
|
||||
GL_REPORT_FBO_ERROR();
|
||||
}
|
||||
else
|
||||
{
|
||||
// EFB targets will be renderbuffers in MSAA mode (required by OpenGL).
|
||||
// Resolve targets will be created to transfer EFB to RAM textures.
|
||||
// XFB framebuffer will be created to transfer EFB to XFB texture.
|
||||
|
||||
// Create EFB target renderbuffers.
|
||||
|
||||
GLuint glObj[2];
|
||||
glGenRenderbuffersEXT(2, glObj);
|
||||
m_efbColor = glObj[0];
|
||||
m_efbDepth = glObj[1];
|
||||
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor);
|
||||
if (m_msaaCoverageSamples)
|
||||
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
|
||||
else
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
|
||||
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth);
|
||||
if (m_msaaCoverageSamples)
|
||||
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, 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);
|
||||
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||
|
||||
// Bind target renderbuffers to EFB framebuffer.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 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);
|
||||
|
||||
GL_REPORT_FBO_ERROR();
|
||||
|
||||
// Create resolved targets for transferring multisampled EFB to texture.
|
||||
|
||||
glGenFramebuffersEXT(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_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_ARB, 0);
|
||||
|
||||
// Bind resolved textures to resolved framebuffer.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
|
||||
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture, 0);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0);
|
||||
|
||||
GL_REPORT_FBO_ERROR();
|
||||
|
||||
// Return to EFB framebuffer.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||
}
|
||||
|
||||
// Create XFB framebuffer; targets will be created elsewhere.
|
||||
|
||||
glGenFramebuffersEXT(1, &m_xfbFramebuffer);
|
||||
|
||||
// EFB framebuffer is currently bound.
|
||||
}
|
||||
|
||||
FramebufferManager::~FramebufferManager()
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
|
||||
GLuint glObj[3];
|
||||
|
||||
// Note: OpenGL deletion functions silently ignore parameters of "0".
|
||||
|
||||
glObj[0] = m_efbFramebuffer;
|
||||
glObj[1] = m_resolvedFramebuffer;
|
||||
glObj[2] = m_xfbFramebuffer;
|
||||
glDeleteFramebuffersEXT(3, glObj);
|
||||
m_efbFramebuffer = 0;
|
||||
m_xfbFramebuffer = 0;
|
||||
|
||||
glObj[0] = m_resolvedColorTexture;
|
||||
glObj[1] = m_resolvedDepthTexture;
|
||||
glObj[2] = m_realXFBSource.texture;
|
||||
glDeleteTextures(3, glObj);
|
||||
m_resolvedColorTexture = 0;
|
||||
m_resolvedDepthTexture = 0;
|
||||
m_realXFBSource.texture = 0;
|
||||
|
||||
glObj[0] = m_efbColor;
|
||||
glObj[1] = m_efbDepth;
|
||||
if (m_msaaSamples <= 1)
|
||||
glDeleteTextures(2, glObj);
|
||||
else
|
||||
glDeleteRenderbuffersEXT(2, glObj);
|
||||
m_efbColor = 0;
|
||||
m_efbDepth = 0;
|
||||
}
|
||||
|
||||
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
|
||||
{
|
||||
XFBSource* const xfbs = new XFBSource;
|
||||
|
||||
glGenTextures(1, &xfbs->texture);
|
||||
|
||||
return xfbs;
|
||||
}
|
||||
|
||||
void XFBSource::CopyEFB(const TargetRectangle& efbSource)
|
||||
{
|
||||
// Copy EFB to XFB texture
|
||||
|
||||
#if 0
|
||||
if (m_msaaSamples <= 1)
|
||||
#else
|
||||
if (!s_bHaveFramebufferBlit)
|
||||
#endif
|
||||
{
|
||||
// Just copy the EFB directly.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::m_efbFramebuffer);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, texWidth, texHeight, 0);
|
||||
|
||||
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::m_efbFramebuffer);
|
||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, FramebufferManager::m_xfbFramebuffer);
|
||||
|
||||
// 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);
|
||||
|
||||
// Unbind texture.
|
||||
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
|
||||
|
||||
// Return to EFB.
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::m_efbFramebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
|
||||
{
|
||||
if (m_msaaSamples <= 1)
|
||||
{
|
||||
return m_efbColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
|
||||
// required.
|
||||
|
||||
TargetRectangle targetRc = RendererBase::ConvertEFBRectangle(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(
|
||||
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);
|
||||
|
||||
return m_resolvedColorTexture;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc)
|
||||
{
|
||||
if (m_msaaSamples <= 1)
|
||||
{
|
||||
return m_efbDepth;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
|
||||
// required.
|
||||
|
||||
TargetRectangle targetRc = RendererBase::ConvertEFBRectangle(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(
|
||||
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);
|
||||
|
||||
return m_resolvedDepthTexture;
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
u8* pXFB = Memory_GetPtr(xfbAddr);
|
||||
if (!pXFB)
|
||||
{
|
||||
WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
|
||||
return;
|
||||
}
|
||||
|
||||
XFB_Write(pXFB, sourceRc, fbWidth, fbHeight);
|
||||
}
|
||||
|
||||
const XFBSourceBase** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||
{
|
||||
xfbCount = 1;
|
||||
|
||||
m_realXFBSource.texWidth = MAX_XFB_WIDTH;
|
||||
m_realXFBSource.texHeight = MAX_XFB_HEIGHT;
|
||||
|
||||
m_realXFBSource.srcAddr = xfbAddr;
|
||||
m_realXFBSource.srcWidth = fbWidth;
|
||||
m_realXFBSource.srcHeight = fbHeight;
|
||||
|
||||
// OpenGL texture coordinates originate at the lower left, which is why
|
||||
// sourceRc.top = fbHeight and sourceRc.bottom = 0.
|
||||
m_realXFBSource.sourceRc.left = 0;
|
||||
m_realXFBSource.sourceRc.top = fbHeight;
|
||||
m_realXFBSource.sourceRc.right = fbWidth;
|
||||
m_realXFBSource.sourceRc.bottom = 0;
|
||||
|
||||
if (!m_realXFBSource.texture)
|
||||
{
|
||||
glGenTextures(1, &m_realXFBSource.texture);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_realXFBSource.texture);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, MAX_XFB_WIDTH, MAX_XFB_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
}
|
||||
|
||||
// Decode YUYV data from GameCube RAM
|
||||
TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture);
|
||||
|
||||
m_overlappingXFBArray[0] = &m_realXFBSource;
|
||||
|
||||
return &m_overlappingXFBArray[0];
|
||||
}
|
||||
|
||||
void FramebufferManager::SetFramebuffer(GLuint fb)
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb != 0 ? fb : GetEFBFramebuffer());
|
||||
}
|
||||
|
||||
// Apply AA if enabled
|
||||
GLuint FramebufferManager::ResolveAndGetRenderTarget(const EFBRectangle &source_rect)
|
||||
{
|
||||
return GetEFBColorTexture(source_rect);
|
||||
}
|
||||
|
||||
GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_rect)
|
||||
{
|
||||
return GetEFBDepthTexture(source_rect);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,135 +1,135 @@
|
|||
// 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 _OGL_FRAMEBUFFERMANAGER_H_
|
||||
#define _OGL_FRAMEBUFFERMANAGER_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "OGL_GLUtil.h"
|
||||
|
||||
#include "../FramebufferManager.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
// On the GameCube, the game sends a request for the graphics processor to
|
||||
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
||||
// called the XFB (External Framebuffer). The size and location of the XFB is
|
||||
// decided at the time of the copy, and the format is always YUYV. The video
|
||||
// interface is given a pointer to the XFB, which will be decoded and
|
||||
// displayed on the TV.
|
||||
//
|
||||
// There are two ways for Dolphin to emulate this:
|
||||
//
|
||||
// Real XFB mode:
|
||||
//
|
||||
// Dolphin will behave like the GameCube and encode the EFB to
|
||||
// a portion of GameCube RAM. The emulated video interface will decode the data
|
||||
// for output to the screen.
|
||||
//
|
||||
// Advantages: Behaves exactly like the GameCube.
|
||||
// Disadvantages: Resolution will be limited.
|
||||
//
|
||||
// Virtual XFB mode:
|
||||
//
|
||||
// When a request is made to copy the EFB to an XFB, Dolphin
|
||||
// will remember the RAM location and size of the XFB in a Virtual XFB list.
|
||||
// The video interface will look up the XFB in the list and use the enhanced
|
||||
// data stored there, if available.
|
||||
//
|
||||
// Advantages: Enables high resolution graphics, better than real hardware.
|
||||
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
|
||||
// possible but uncommon), the Virtual XFB will not capture this information.
|
||||
|
||||
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
||||
// virtualize.
|
||||
|
||||
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
||||
{
|
||||
return !((aLower >= bUpper) || (bLower >= aUpper));
|
||||
}
|
||||
|
||||
struct XFBSource : XFBSourceBase
|
||||
{
|
||||
XFBSource() : texture(0) {}
|
||||
|
||||
void CopyEFB(const TargetRectangle& efbSource);
|
||||
|
||||
GLuint texture;
|
||||
TargetRectangle sourceRc;
|
||||
};
|
||||
|
||||
class FramebufferManager : public ::FramebufferManagerBase
|
||||
{
|
||||
friend struct XFBSource;
|
||||
|
||||
public:
|
||||
FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples);
|
||||
~FramebufferManager();
|
||||
|
||||
// To get the EFB in texture form, these functions may have to transfer
|
||||
// the EFB to a resolved texture first.
|
||||
static GLuint GetEFBColorTexture(const EFBRectangle& sourceRc);
|
||||
static GLuint GetEFBDepthTexture(const EFBRectangle& sourceRc);
|
||||
|
||||
static GLuint GetEFBFramebuffer() { return m_efbFramebuffer; }
|
||||
|
||||
// Resolved framebuffer is only used in MSAA mode.
|
||||
static GLuint GetResolvedFramebuffer() { return m_resolvedFramebuffer; }
|
||||
|
||||
static void SetFramebuffer(GLuint fb);
|
||||
|
||||
// If in MSAA mode, this will perform a resolve of the specified rectangle, and return the resolve target as a texture ID.
|
||||
// Thus, this call may be expensive. Don't repeat it unnecessarily.
|
||||
// If not in MSAA mode, will just return the render target texture ID.
|
||||
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
|
||||
static GLuint ResolveAndGetRenderTarget(const EFBRectangle &rect);
|
||||
|
||||
// Same as above but for the depth Target.
|
||||
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
|
||||
static GLuint ResolveAndGetDepthTarget(const EFBRectangle &rect);
|
||||
|
||||
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
|
||||
|
||||
protected:
|
||||
static GLuint m_efbFramebuffer;
|
||||
static GLuint m_xfbFramebuffer; // Only used in MSAA mode
|
||||
|
||||
private:
|
||||
static void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
static const XFBSourceBase** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||
|
||||
static int m_targetWidth;
|
||||
static int m_targetHeight;
|
||||
static int m_msaaSamples;
|
||||
static int m_msaaCoverageSamples;
|
||||
|
||||
static GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
|
||||
static GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
|
||||
|
||||
// Only used in MSAA mode.
|
||||
static GLuint m_resolvedFramebuffer;
|
||||
static GLuint m_resolvedColorTexture;
|
||||
static GLuint m_resolvedDepthTexture;
|
||||
|
||||
static XFBSource m_realXFBSource; // Only used in Real XFB mode
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
// 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 _OGL_FRAMEBUFFERMANAGER_H_
|
||||
#define _OGL_FRAMEBUFFERMANAGER_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "OGL_GLUtil.h"
|
||||
|
||||
#include "../FramebufferManager.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
// On the GameCube, the game sends a request for the graphics processor to
|
||||
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
||||
// called the XFB (External Framebuffer). The size and location of the XFB is
|
||||
// decided at the time of the copy, and the format is always YUYV. The video
|
||||
// interface is given a pointer to the XFB, which will be decoded and
|
||||
// displayed on the TV.
|
||||
//
|
||||
// There are two ways for Dolphin to emulate this:
|
||||
//
|
||||
// Real XFB mode:
|
||||
//
|
||||
// Dolphin will behave like the GameCube and encode the EFB to
|
||||
// a portion of GameCube RAM. The emulated video interface will decode the data
|
||||
// for output to the screen.
|
||||
//
|
||||
// Advantages: Behaves exactly like the GameCube.
|
||||
// Disadvantages: Resolution will be limited.
|
||||
//
|
||||
// Virtual XFB mode:
|
||||
//
|
||||
// When a request is made to copy the EFB to an XFB, Dolphin
|
||||
// will remember the RAM location and size of the XFB in a Virtual XFB list.
|
||||
// The video interface will look up the XFB in the list and use the enhanced
|
||||
// data stored there, if available.
|
||||
//
|
||||
// Advantages: Enables high resolution graphics, better than real hardware.
|
||||
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
|
||||
// possible but uncommon), the Virtual XFB will not capture this information.
|
||||
|
||||
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
||||
// virtualize.
|
||||
|
||||
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
||||
{
|
||||
return !((aLower >= bUpper) || (bLower >= aUpper));
|
||||
}
|
||||
|
||||
struct XFBSource : XFBSourceBase
|
||||
{
|
||||
XFBSource() : texture(0) {}
|
||||
|
||||
void CopyEFB(const TargetRectangle& efbSource);
|
||||
|
||||
GLuint texture;
|
||||
TargetRectangle sourceRc;
|
||||
};
|
||||
|
||||
class FramebufferManager : public ::FramebufferManagerBase
|
||||
{
|
||||
friend struct XFBSource;
|
||||
|
||||
public:
|
||||
FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples);
|
||||
~FramebufferManager();
|
||||
|
||||
// To get the EFB in texture form, these functions may have to transfer
|
||||
// the EFB to a resolved texture first.
|
||||
static GLuint GetEFBColorTexture(const EFBRectangle& sourceRc);
|
||||
static GLuint GetEFBDepthTexture(const EFBRectangle& sourceRc);
|
||||
|
||||
static GLuint GetEFBFramebuffer() { return m_efbFramebuffer; }
|
||||
|
||||
// Resolved framebuffer is only used in MSAA mode.
|
||||
static GLuint GetResolvedFramebuffer() { return m_resolvedFramebuffer; }
|
||||
|
||||
static void SetFramebuffer(GLuint fb);
|
||||
|
||||
// If in MSAA mode, this will perform a resolve of the specified rectangle, and return the resolve target as a texture ID.
|
||||
// Thus, this call may be expensive. Don't repeat it unnecessarily.
|
||||
// If not in MSAA mode, will just return the render target texture ID.
|
||||
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
|
||||
static GLuint ResolveAndGetRenderTarget(const EFBRectangle &rect);
|
||||
|
||||
// Same as above but for the depth Target.
|
||||
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
|
||||
static GLuint ResolveAndGetDepthTarget(const EFBRectangle &rect);
|
||||
|
||||
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
|
||||
|
||||
protected:
|
||||
static GLuint m_efbFramebuffer;
|
||||
static GLuint m_xfbFramebuffer; // Only used in MSAA mode
|
||||
|
||||
private:
|
||||
static void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
static const XFBSourceBase** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||
|
||||
static int m_targetWidth;
|
||||
static int m_targetHeight;
|
||||
static int m_msaaSamples;
|
||||
static int m_msaaCoverageSamples;
|
||||
|
||||
static GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
|
||||
static GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
|
||||
|
||||
// Only used in MSAA mode.
|
||||
static GLuint m_resolvedFramebuffer;
|
||||
static GLuint m_resolvedColorTexture;
|
||||
static GLuint m_resolvedDepthTexture;
|
||||
|
||||
static XFBSource m_realXFBSource; // Only used in Real XFB mode
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,145 +1,145 @@
|
|||
// 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 _GLINIT_H_
|
||||
#define _GLINIT_H_
|
||||
|
||||
// Common
|
||||
#include "MathUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define GLEW_STATIC
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/wglew.h>
|
||||
|
||||
#else // linux and apple basic definitions
|
||||
|
||||
#if defined(USE_WX) && USE_WX
|
||||
#include <GL/glew.h>
|
||||
#include "wx/wx.h"
|
||||
#include "wx/glcanvas.h"
|
||||
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
#include <GL/glxew.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/keysym.h>
|
||||
#include "Thread.h"
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
#include <GL/glew.h>
|
||||
#include "cocoaGL.h"
|
||||
#endif // end USE_WX
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
#endif // linux basic definitions
|
||||
|
||||
#ifndef GL_DEPTH24_STENCIL8_EXT // allows FBOs to support stencils
|
||||
#define GL_DEPTH_STENCIL_EXT 0x84F9
|
||||
#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
|
||||
#define GL_DEPTH24_STENCIL8_EXT 0x88F0
|
||||
#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct {
|
||||
#if defined(USE_WX) && USE_WX
|
||||
wxGLCanvas *glCanvas;
|
||||
wxPanel *panel;
|
||||
wxGLContext *glCtxt;
|
||||
#elif defined(__APPLE__)
|
||||
NSWindow *cocoaWin;
|
||||
NSOpenGLContext *cocoaCtx;
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
int screen;
|
||||
Window win;
|
||||
Window parent;
|
||||
Display *dpy;
|
||||
XVisualInfo *vi;
|
||||
GLXContext ctx;
|
||||
XSetWindowAttributes attr;
|
||||
Common::Thread *xEventThread;
|
||||
int x, y;
|
||||
#endif
|
||||
unsigned int width, height;
|
||||
} GLWindow;
|
||||
|
||||
extern GLWindow GLWin;
|
||||
|
||||
#endif
|
||||
|
||||
// Public OpenGL util
|
||||
|
||||
//#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;
|
||||
//#endif
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
// Initialization / upkeep
|
||||
bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _width, int _height);
|
||||
void OpenGL_Shutdown();
|
||||
void OpenGL_Update();
|
||||
bool OpenGL_MakeCurrent();
|
||||
void OpenGL_SwapBuffers();
|
||||
|
||||
// Get status
|
||||
u32 OpenGL_GetBackbufferWidth();
|
||||
u32 OpenGL_GetBackbufferHeight();
|
||||
|
||||
// Set things
|
||||
void OpenGL_SetWindowText(const char *text);
|
||||
|
||||
// Error reporting - use the convenient macros.
|
||||
void OpenGL_ReportARBProgramError();
|
||||
GLuint OpenGL_ReportGLError(const char *function, const char *file, int line);
|
||||
bool OpenGL_ReportFBOError(const char *function, const char *file, int line);
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
#define GL_REPORT_ERROR() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__)
|
||||
#define GL_REPORT_ERRORD() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__)
|
||||
#define GL_REPORT_FBO_ERROR() OpenGL_ReportFBOError(__FUNCTION__, __FILE__, __LINE__)
|
||||
#define GL_REPORT_PROGRAM_ERROR() OpenGL_ReportARBProgramError()
|
||||
#else
|
||||
#define GL_REPORT_ERROR() 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
|
||||
|
||||
}
|
||||
|
||||
#endif // _GLINIT_H_
|
||||
// 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 _GLINIT_H_
|
||||
#define _GLINIT_H_
|
||||
|
||||
// Common
|
||||
#include "MathUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define GLEW_STATIC
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/wglew.h>
|
||||
|
||||
#else // linux and apple basic definitions
|
||||
|
||||
#if defined(USE_WX) && USE_WX
|
||||
#include <GL/glew.h>
|
||||
#include "wx/wx.h"
|
||||
#include "wx/glcanvas.h"
|
||||
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
#include <GL/glxew.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/keysym.h>
|
||||
#include "Thread.h"
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
#include <GL/glew.h>
|
||||
#include "cocoaGL.h"
|
||||
#endif // end USE_WX
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
#endif // linux basic definitions
|
||||
|
||||
#ifndef GL_DEPTH24_STENCIL8_EXT // allows FBOs to support stencils
|
||||
#define GL_DEPTH_STENCIL_EXT 0x84F9
|
||||
#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
|
||||
#define GL_DEPTH24_STENCIL8_EXT 0x88F0
|
||||
#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct {
|
||||
#if defined(USE_WX) && USE_WX
|
||||
wxGLCanvas *glCanvas;
|
||||
wxPanel *panel;
|
||||
wxGLContext *glCtxt;
|
||||
#elif defined(__APPLE__)
|
||||
NSWindow *cocoaWin;
|
||||
NSOpenGLContext *cocoaCtx;
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
int screen;
|
||||
Window win;
|
||||
Window parent;
|
||||
Display *dpy;
|
||||
XVisualInfo *vi;
|
||||
GLXContext ctx;
|
||||
XSetWindowAttributes attr;
|
||||
Common::Thread *xEventThread;
|
||||
int x, y;
|
||||
#endif
|
||||
unsigned int width, height;
|
||||
} GLWindow;
|
||||
|
||||
extern GLWindow GLWin;
|
||||
|
||||
#endif
|
||||
|
||||
// Public OpenGL util
|
||||
|
||||
//#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;
|
||||
//#endif
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
// Initialization / upkeep
|
||||
bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _width, int _height);
|
||||
void OpenGL_Shutdown();
|
||||
void OpenGL_Update();
|
||||
bool OpenGL_MakeCurrent();
|
||||
void OpenGL_SwapBuffers();
|
||||
|
||||
// Get status
|
||||
u32 OpenGL_GetBackbufferWidth();
|
||||
u32 OpenGL_GetBackbufferHeight();
|
||||
|
||||
// Set things
|
||||
void OpenGL_SetWindowText(const char *text);
|
||||
|
||||
// Error reporting - use the convenient macros.
|
||||
void OpenGL_ReportARBProgramError();
|
||||
GLuint OpenGL_ReportGLError(const char *function, const char *file, int line);
|
||||
bool OpenGL_ReportFBOError(const char *function, const char *file, int line);
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
#define GL_REPORT_ERROR() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__)
|
||||
#define GL_REPORT_ERRORD() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__)
|
||||
#define GL_REPORT_FBO_ERROR() OpenGL_ReportFBOError(__FUNCTION__, __FILE__, __LINE__)
|
||||
#define GL_REPORT_PROGRAM_ERROR() OpenGL_ReportARBProgramError()
|
||||
#else
|
||||
#define GL_REPORT_ERROR() 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
|
||||
|
||||
}
|
||||
|
||||
#endif // _GLINIT_H_
|
||||
|
|
|
@ -1,178 +1,178 @@
|
|||
// 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 _OGL_GLWINDOW_H_
|
||||
#define _OGL_GLWINDOW_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "OGL_Globals.h"
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define GLEW_STATIC
|
||||
|
||||
#include <GLew/glew.h>
|
||||
#include <GLew/wglew.h>
|
||||
#include <GLew/gl.h>
|
||||
#include <GLew/glext.h>
|
||||
#else
|
||||
#include <GL/glew.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
enum OGL_Props
|
||||
{
|
||||
OGL_FULLSCREEN,
|
||||
OGL_KEEPRATIO,
|
||||
OGL_HIDECURSOR,
|
||||
OGL_PROP_COUNT
|
||||
};
|
||||
|
||||
struct res
|
||||
{
|
||||
u32 x;
|
||||
u32 y;
|
||||
};
|
||||
|
||||
class GLWindow
|
||||
{
|
||||
private:
|
||||
|
||||
// TODO: what is xmax and ymax? do we need [xy]render?
|
||||
u32 xWin, yWin; // Windows' size
|
||||
int xOffset, yOffset; // Offset in window
|
||||
float xMax, yMax; // ???
|
||||
u32 xRender, yRender; // Render area
|
||||
|
||||
bool properties[OGL_PROP_COUNT];
|
||||
|
||||
protected:
|
||||
|
||||
EventHandler* eventHandler;
|
||||
res origRes, currFullRes, currWinRes;
|
||||
static std::vector<res> fullResolutions;
|
||||
virtual void SetRender(u32 x, u32 y)
|
||||
{
|
||||
xRender = x;
|
||||
yRender = y;
|
||||
}
|
||||
|
||||
static const std::vector<res>& getFsResolutions()
|
||||
{
|
||||
return fullResolutions;
|
||||
}
|
||||
|
||||
static void addFSResolution(res fsr)
|
||||
{
|
||||
fullResolutions.push_back(fsr);
|
||||
}
|
||||
public:
|
||||
|
||||
virtual void SwapBuffers() {};
|
||||
virtual void SetWindowText(const char *text) {};
|
||||
virtual bool PeekMessages() {return false;};
|
||||
virtual void Update() {};
|
||||
virtual bool MakeCurrent() {return false;};
|
||||
|
||||
virtual void updateDim()
|
||||
{
|
||||
if (GetProperty(OGL_FULLSCREEN))
|
||||
SetWinSize(currFullRes.x, currFullRes.y);
|
||||
else
|
||||
// Set the windowed resolution
|
||||
SetWinSize(currWinRes.x, currWinRes.y);
|
||||
|
||||
float FactorX = 640.0f / (float)GetXwin();
|
||||
float FactorY = 480.0f / (float)GetYwin();
|
||||
//float Max = (FactorX < FactorY) ? FactorX : FactorY;
|
||||
|
||||
SetMax(1.0f / FactorX, 1.0f / FactorY);
|
||||
SetOffset(0,0);
|
||||
}
|
||||
|
||||
void SetEventHandler(EventHandler *eh) { eventHandler = eh;}
|
||||
bool GetProperty(OGL_Props prop) {return properties[prop];}
|
||||
virtual bool SetProperty(OGL_Props prop, bool value)
|
||||
{return properties[prop] = value;}
|
||||
|
||||
u32 GetXrender() {return xRender;}
|
||||
u32 GetYrender() {return yRender;}
|
||||
|
||||
u32 GetXwin() {return xWin;}
|
||||
u32 GetYwin() {return yWin;}
|
||||
void SetWinSize(u32 x, u32 y)
|
||||
{
|
||||
xWin = x;
|
||||
yWin = y;
|
||||
}
|
||||
|
||||
int GetYoff() {return yOffset;}
|
||||
int GetXoff() {return xOffset;}
|
||||
void SetOffset(int x, int y)
|
||||
{
|
||||
yOffset = y;
|
||||
xOffset = x;
|
||||
}
|
||||
|
||||
void SetMax(float x, float y)
|
||||
{
|
||||
yMax = y;
|
||||
xMax = x;
|
||||
}
|
||||
|
||||
float GetXmax() {return xMax;}
|
||||
float GetYmax() {return yMax;}
|
||||
|
||||
static bool valid() { return false;}
|
||||
|
||||
GLWindow()
|
||||
{
|
||||
// Load defaults
|
||||
sscanf(g_Config.iFSResolution, "%dx%d",
|
||||
&currFullRes.x, &currFullRes.y);
|
||||
|
||||
sscanf(g_Config.iInternalRes, "%dx%d",
|
||||
&currWinRes.x, &currWinRes.y);
|
||||
|
||||
SetProperty(OGL_FULLSCREEN, g_Config.bFullscreen);
|
||||
// What does this do?
|
||||
SetProperty(OGL_KEEPRATIO, g_Config.bKeepAR43);
|
||||
SetProperty(OGL_HIDECURSOR, g_Config.bHideCursor);
|
||||
|
||||
updateDim();
|
||||
}
|
||||
|
||||
|
||||
// setResolution
|
||||
// resolution iter
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _GLWINDOW_H_
|
||||
// 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 _OGL_GLWINDOW_H_
|
||||
#define _OGL_GLWINDOW_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "OGL_Globals.h"
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define GLEW_STATIC
|
||||
|
||||
#include <GLew/glew.h>
|
||||
#include <GLew/wglew.h>
|
||||
#include <GLew/gl.h>
|
||||
#include <GLew/glext.h>
|
||||
#else
|
||||
#include <GL/glew.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
enum OGL_Props
|
||||
{
|
||||
OGL_FULLSCREEN,
|
||||
OGL_KEEPRATIO,
|
||||
OGL_HIDECURSOR,
|
||||
OGL_PROP_COUNT
|
||||
};
|
||||
|
||||
struct res
|
||||
{
|
||||
u32 x;
|
||||
u32 y;
|
||||
};
|
||||
|
||||
class GLWindow
|
||||
{
|
||||
private:
|
||||
|
||||
// TODO: what is xmax and ymax? do we need [xy]render?
|
||||
u32 xWin, yWin; // Windows' size
|
||||
int xOffset, yOffset; // Offset in window
|
||||
float xMax, yMax; // ???
|
||||
u32 xRender, yRender; // Render area
|
||||
|
||||
bool properties[OGL_PROP_COUNT];
|
||||
|
||||
protected:
|
||||
|
||||
EventHandler* eventHandler;
|
||||
res origRes, currFullRes, currWinRes;
|
||||
static std::vector<res> fullResolutions;
|
||||
virtual void SetRender(u32 x, u32 y)
|
||||
{
|
||||
xRender = x;
|
||||
yRender = y;
|
||||
}
|
||||
|
||||
static const std::vector<res>& getFsResolutions()
|
||||
{
|
||||
return fullResolutions;
|
||||
}
|
||||
|
||||
static void addFSResolution(res fsr)
|
||||
{
|
||||
fullResolutions.push_back(fsr);
|
||||
}
|
||||
public:
|
||||
|
||||
virtual void SwapBuffers() {};
|
||||
virtual void SetWindowText(const char *text) {};
|
||||
virtual bool PeekMessages() {return false;};
|
||||
virtual void Update() {};
|
||||
virtual bool MakeCurrent() {return false;};
|
||||
|
||||
virtual void updateDim()
|
||||
{
|
||||
if (GetProperty(OGL_FULLSCREEN))
|
||||
SetWinSize(currFullRes.x, currFullRes.y);
|
||||
else
|
||||
// Set the windowed resolution
|
||||
SetWinSize(currWinRes.x, currWinRes.y);
|
||||
|
||||
float FactorX = 640.0f / (float)GetXwin();
|
||||
float FactorY = 480.0f / (float)GetYwin();
|
||||
//float Max = (FactorX < FactorY) ? FactorX : FactorY;
|
||||
|
||||
SetMax(1.0f / FactorX, 1.0f / FactorY);
|
||||
SetOffset(0,0);
|
||||
}
|
||||
|
||||
void SetEventHandler(EventHandler *eh) { eventHandler = eh;}
|
||||
bool GetProperty(OGL_Props prop) {return properties[prop];}
|
||||
virtual bool SetProperty(OGL_Props prop, bool value)
|
||||
{return properties[prop] = value;}
|
||||
|
||||
u32 GetXrender() {return xRender;}
|
||||
u32 GetYrender() {return yRender;}
|
||||
|
||||
u32 GetXwin() {return xWin;}
|
||||
u32 GetYwin() {return yWin;}
|
||||
void SetWinSize(u32 x, u32 y)
|
||||
{
|
||||
xWin = x;
|
||||
yWin = y;
|
||||
}
|
||||
|
||||
int GetYoff() {return yOffset;}
|
||||
int GetXoff() {return xOffset;}
|
||||
void SetOffset(int x, int y)
|
||||
{
|
||||
yOffset = y;
|
||||
xOffset = x;
|
||||
}
|
||||
|
||||
void SetMax(float x, float y)
|
||||
{
|
||||
yMax = y;
|
||||
xMax = x;
|
||||
}
|
||||
|
||||
float GetXmax() {return xMax;}
|
||||
float GetYmax() {return yMax;}
|
||||
|
||||
static bool valid() { return false;}
|
||||
|
||||
GLWindow()
|
||||
{
|
||||
// Load defaults
|
||||
sscanf(g_Config.iFSResolution, "%dx%d",
|
||||
&currFullRes.x, &currFullRes.y);
|
||||
|
||||
sscanf(g_Config.iInternalRes, "%dx%d",
|
||||
&currWinRes.x, &currWinRes.y);
|
||||
|
||||
SetProperty(OGL_FULLSCREEN, g_Config.bFullscreen);
|
||||
// What does this do?
|
||||
SetProperty(OGL_KEEPRATIO, g_Config.bKeepAR43);
|
||||
SetProperty(OGL_HIDECURSOR, g_Config.bHideCursor);
|
||||
|
||||
updateDim();
|
||||
}
|
||||
|
||||
|
||||
// setResolution
|
||||
// resolution iter
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _GLWINDOW_H_
|
||||
|
|
|
@ -1,310 +1,310 @@
|
|||
// 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/
|
||||
|
||||
// Common
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
#include "MemoryUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "Profiler.h"
|
||||
#include "VertexShaderGen.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "NativeVertexWriter.h"
|
||||
#include "CPMemory.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_GLUtil.h"
|
||||
#include "OGL_VertexManager.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
#define COMPILED_CODE_SIZE 4096
|
||||
|
||||
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() const;
|
||||
virtual void EnableComponents(u32 components);
|
||||
};
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
inline GLuint VarToGL(VarType t)
|
||||
{
|
||||
static const GLuint lookup[5] = {
|
||||
GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT
|
||||
};
|
||||
return lookup[t];
|
||||
}
|
||||
|
||||
void GLVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
|
||||
{
|
||||
vertex_stride = _vtx_decl.stride;
|
||||
using namespace Gen;
|
||||
|
||||
// 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void GLVertexFormat::SetupVertexPointers() const {
|
||||
// Cast a pointer to compiled code to a pointer to a function taking no parameters, through a (void *) cast first to
|
||||
// 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]));
|
||||
}
|
||||
}
|
||||
|
||||
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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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]));
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLVertexFormat::EnableComponents(u32 components)
|
||||
{
|
||||
if (s_prevcomponents != components)
|
||||
{
|
||||
g_vertex_manager->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);
|
||||
}
|
||||
}
|
||||
|
||||
// tex
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (!g_ActiveConfig.bDisableTexturing)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE0 + i);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable Lighting
|
||||
// TODO - Is this a good spot for this code?
|
||||
if (g_ActiveConfig.bDisableLighting)
|
||||
{
|
||||
for (int i = 0; i < xfregs.nNumChans; i++)
|
||||
{
|
||||
xfregs.colChans[i].alpha.enablelighting = false;
|
||||
xfregs.colChans[i].color.enablelighting = false;
|
||||
}
|
||||
}
|
||||
|
||||
s_prevcomponents = components;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
// Common
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
#include "MemoryUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "Profiler.h"
|
||||
#include "VertexShaderGen.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "NativeVertexWriter.h"
|
||||
#include "CPMemory.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_GLUtil.h"
|
||||
#include "OGL_VertexManager.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
#define COMPILED_CODE_SIZE 4096
|
||||
|
||||
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() const;
|
||||
virtual void EnableComponents(u32 components);
|
||||
};
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
inline GLuint VarToGL(VarType t)
|
||||
{
|
||||
static const GLuint lookup[5] = {
|
||||
GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT
|
||||
};
|
||||
return lookup[t];
|
||||
}
|
||||
|
||||
void GLVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
|
||||
{
|
||||
vertex_stride = _vtx_decl.stride;
|
||||
using namespace Gen;
|
||||
|
||||
// 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void GLVertexFormat::SetupVertexPointers() const {
|
||||
// Cast a pointer to compiled code to a pointer to a function taking no parameters, through a (void *) cast first to
|
||||
// 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]));
|
||||
}
|
||||
}
|
||||
|
||||
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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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]));
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLVertexFormat::EnableComponents(u32 components)
|
||||
{
|
||||
if (s_prevcomponents != components)
|
||||
{
|
||||
g_vertex_manager->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);
|
||||
}
|
||||
}
|
||||
|
||||
// tex
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (!g_ActiveConfig.bDisableTexturing)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE0 + i);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable Lighting
|
||||
// TODO - Is this a good spot for this code?
|
||||
if (g_ActiveConfig.bDisableLighting)
|
||||
{
|
||||
for (int i = 0; i < xfregs.nNumChans; i++)
|
||||
{
|
||||
xfregs.colChans[i].alpha.enablelighting = false;
|
||||
xfregs.colChans[i].color.enablelighting = false;
|
||||
}
|
||||
}
|
||||
|
||||
s_prevcomponents = components;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,340 +1,340 @@
|
|||
// 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 <cmath>
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "Profiler.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "ImageWrite.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_Render.h"
|
||||
#include "OGL_GLUtil.h"
|
||||
#include "OGL_PixelShaderCache.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
static int s_nMaxPixelInstructions;
|
||||
static GLuint s_ColorMatrixProgram = 0;
|
||||
static GLuint s_DepthMatrixProgram = 0;
|
||||
PixelShaderCache::PSCache PixelShaderCache::pshaders;
|
||||
PIXELSHADERUID PixelShaderCache::s_curuid;
|
||||
bool PixelShaderCache::s_displayCompileAlert;
|
||||
GLuint PixelShaderCache::CurrentShader;
|
||||
bool PixelShaderCache::ShaderEnabled;
|
||||
|
||||
static FRAGMENTSHADER* pShaderLast = NULL;
|
||||
|
||||
|
||||
void PixelShaderCache::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);
|
||||
//SetPSConstant4fv(const_number, f);
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; ++i, f+=4, ++const_number)
|
||||
glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
|
||||
//SetPSConstant4fv(const_number, f);
|
||||
}
|
||||
|
||||
PixelShaderCache::PixelShaderCache()
|
||||
{
|
||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
ShaderEnabled = true;
|
||||
CurrentShader = 0;
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
|
||||
|
||||
s_displayCompileAlert = true;
|
||||
|
||||
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions);
|
||||
#if CG_VERSION_NUM == 2100
|
||||
if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
|
||||
{
|
||||
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[1024];
|
||||
sprintf(pmatrixprog, "!!ARBfp1.0"
|
||||
"TEMP R0;\n"
|
||||
"TEMP R1;\n"
|
||||
"TEX R0, fragment.texcoord[0], texture[0], RECT;\n"
|
||||
"DP4 R1.w, R0, program.env[%d];\n"
|
||||
"DP4 R1.z, R0, program.env[%d];\n"
|
||||
"DP4 R1.x, R0, program.env[%d];\n"
|
||||
"DP4 R1.y, R0, program.env[%d];\n"
|
||||
"ADD result.color, R1, program.env[%d];\n"
|
||||
"END\n", C_COLORMATRIX+3, C_COLORMATRIX+2, C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+4);
|
||||
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"
|
||||
"TEMP R0;\n"
|
||||
"TEMP R1;\n"
|
||||
"TEMP R2;\n"
|
||||
"PARAM K0 = { 65535.0, 255.0,1.0,16777215.0};\n"
|
||||
"PARAM K1 = { 0.999999940395355224609375, 1.0000000596046483281045155587504,0.0,0.0};\n"
|
||||
"TEX R2, fragment.texcoord[0], texture[0], RECT;\n"
|
||||
"MUL R0, R2.x, K1.x;\n"
|
||||
"MUL R0, R0.x, K0;\n"
|
||||
"FRC R0, R0;\n"
|
||||
"MUL R0, R0, K1.y;\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, 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PixelShaderCache::~PixelShaderCache()
|
||||
{
|
||||
glDeleteProgramsARB(1, &s_ColorMatrixProgram);
|
||||
s_ColorMatrixProgram = 0;
|
||||
glDeleteProgramsARB(1, &s_DepthMatrixProgram);
|
||||
s_DepthMatrixProgram = 0;
|
||||
PSCache::iterator iter = pshaders.begin();
|
||||
for (; iter != pshaders.end(); iter++)
|
||||
iter->second.Destroy();
|
||||
pshaders.clear();
|
||||
}
|
||||
|
||||
GLuint PixelShaderCache::GetColorMatrixProgram()
|
||||
{
|
||||
return s_ColorMatrixProgram;
|
||||
}
|
||||
|
||||
GLuint PixelShaderCache::GetDepthMatrixProgram()
|
||||
{
|
||||
return s_DepthMatrixProgram;
|
||||
}
|
||||
|
||||
bool PixelShaderCache::SetShader(bool dstAlphaEnable)
|
||||
{
|
||||
const FRAGMENTSHADER* const ps = GetShader(dstAlphaEnable);
|
||||
if (ps)
|
||||
{
|
||||
SetCurrentShader(ps->glprogid);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
PIXELSHADERUID uid;
|
||||
GetPixelShaderId(&uid, dstAlphaEnable ? 1 : 0);
|
||||
if (uid == last_pixel_shader_uid && pshaders[uid].frameCount == frameCount)
|
||||
{
|
||||
return pShaderLast;
|
||||
}
|
||||
|
||||
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
|
||||
|
||||
PSCache::iterator iter = pshaders.find(uid);
|
||||
|
||||
if (iter != pshaders.end()) {
|
||||
iter->second.frameCount = frameCount;
|
||||
PSCacheEntry &entry = iter->second;
|
||||
if (&entry.shader != pShaderLast)
|
||||
{
|
||||
pShaderLast = &entry.shader;
|
||||
}
|
||||
|
||||
return pShaderLast;
|
||||
}
|
||||
|
||||
//Make an entry in the table
|
||||
PSCacheEntry& newentry = pshaders[uid];
|
||||
newentry.frameCount = frameCount;
|
||||
pShaderLast = &newentry.shader;
|
||||
const char *code = GeneratePixelShaderCode(dstAlphaEnable,API_OPENGL);
|
||||
|
||||
#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), counter++);
|
||||
|
||||
SaveData(szTemp, code);
|
||||
}
|
||||
#endif
|
||||
|
||||
// printf("Compiling pixel shader. size = %i\n", strlen(code));
|
||||
if (!code || !CompilePixelShader(newentry.shader, code)) {
|
||||
ERROR_LOG(VIDEO, "failed to create pixel shader");
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
|
||||
SaveData(szTemp, code);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, pshaders.size());
|
||||
return pShaderLast;
|
||||
}
|
||||
|
||||
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
|
||||
{
|
||||
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=32,NumInstructionSlots=%d", s_nMaxPixelInstructions);
|
||||
const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
|
||||
CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts);
|
||||
|
||||
// handle errors
|
||||
if (!cgIsProgram(tempprog)) {
|
||||
cgDestroyProgram(tempprog);
|
||||
ERROR_LOG(VIDEO, "Failed to compile ps %s:", cgGetLastListing(g_cgcontext));
|
||||
ERROR_LOG(VIDEO, pstrprogram);
|
||||
return false;
|
||||
}
|
||||
|
||||
// handle warnings
|
||||
if (cgGetError() != CG_NO_ERROR)
|
||||
{
|
||||
WARN_LOG(VIDEO, "Warnings on compile ps %s:", cgGetLastListing(g_cgcontext));
|
||||
WARN_LOG(VIDEO, 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, &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)
|
||||
{
|
||||
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
|
||||
}
|
||||
ERROR_LOG(VIDEO, pstrprogram);
|
||||
ERROR_LOG(VIDEO, pcompiledprog);
|
||||
}
|
||||
|
||||
cgDestroyProgram(tempprog);
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
ps.strprog = pstrprogram;
|
||||
#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)
|
||||
{
|
||||
if(!ShaderEnabled)
|
||||
{
|
||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
ShaderEnabled = true;
|
||||
}
|
||||
if(CurrentShader != Shader)
|
||||
{
|
||||
if(Shader != 0)
|
||||
CurrentShader = Shader;
|
||||
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, CurrentShader);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// 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 <cmath>
|
||||
|
||||
// Common
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "Profiler.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "ImageWrite.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_Render.h"
|
||||
#include "OGL_GLUtil.h"
|
||||
#include "OGL_PixelShaderCache.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
static int s_nMaxPixelInstructions;
|
||||
static GLuint s_ColorMatrixProgram = 0;
|
||||
static GLuint s_DepthMatrixProgram = 0;
|
||||
PixelShaderCache::PSCache PixelShaderCache::pshaders;
|
||||
PIXELSHADERUID PixelShaderCache::s_curuid;
|
||||
bool PixelShaderCache::s_displayCompileAlert;
|
||||
GLuint PixelShaderCache::CurrentShader;
|
||||
bool PixelShaderCache::ShaderEnabled;
|
||||
|
||||
static FRAGMENTSHADER* pShaderLast = NULL;
|
||||
|
||||
|
||||
void PixelShaderCache::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);
|
||||
//SetPSConstant4fv(const_number, f);
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
|
||||
}
|
||||
|
||||
void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; ++i, f+=4, ++const_number)
|
||||
glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
|
||||
//SetPSConstant4fv(const_number, f);
|
||||
}
|
||||
|
||||
PixelShaderCache::PixelShaderCache()
|
||||
{
|
||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
ShaderEnabled = true;
|
||||
CurrentShader = 0;
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
|
||||
|
||||
s_displayCompileAlert = true;
|
||||
|
||||
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions);
|
||||
#if CG_VERSION_NUM == 2100
|
||||
if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
|
||||
{
|
||||
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[1024];
|
||||
sprintf(pmatrixprog, "!!ARBfp1.0"
|
||||
"TEMP R0;\n"
|
||||
"TEMP R1;\n"
|
||||
"TEX R0, fragment.texcoord[0], texture[0], RECT;\n"
|
||||
"DP4 R1.w, R0, program.env[%d];\n"
|
||||
"DP4 R1.z, R0, program.env[%d];\n"
|
||||
"DP4 R1.x, R0, program.env[%d];\n"
|
||||
"DP4 R1.y, R0, program.env[%d];\n"
|
||||
"ADD result.color, R1, program.env[%d];\n"
|
||||
"END\n", C_COLORMATRIX+3, C_COLORMATRIX+2, C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+4);
|
||||
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"
|
||||
"TEMP R0;\n"
|
||||
"TEMP R1;\n"
|
||||
"TEMP R2;\n"
|
||||
"PARAM K0 = { 65535.0, 255.0,1.0,16777215.0};\n"
|
||||
"PARAM K1 = { 0.999999940395355224609375, 1.0000000596046483281045155587504,0.0,0.0};\n"
|
||||
"TEX R2, fragment.texcoord[0], texture[0], RECT;\n"
|
||||
"MUL R0, R2.x, K1.x;\n"
|
||||
"MUL R0, R0.x, K0;\n"
|
||||
"FRC R0, R0;\n"
|
||||
"MUL R0, R0, K1.y;\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, 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PixelShaderCache::~PixelShaderCache()
|
||||
{
|
||||
glDeleteProgramsARB(1, &s_ColorMatrixProgram);
|
||||
s_ColorMatrixProgram = 0;
|
||||
glDeleteProgramsARB(1, &s_DepthMatrixProgram);
|
||||
s_DepthMatrixProgram = 0;
|
||||
PSCache::iterator iter = pshaders.begin();
|
||||
for (; iter != pshaders.end(); iter++)
|
||||
iter->second.Destroy();
|
||||
pshaders.clear();
|
||||
}
|
||||
|
||||
GLuint PixelShaderCache::GetColorMatrixProgram()
|
||||
{
|
||||
return s_ColorMatrixProgram;
|
||||
}
|
||||
|
||||
GLuint PixelShaderCache::GetDepthMatrixProgram()
|
||||
{
|
||||
return s_DepthMatrixProgram;
|
||||
}
|
||||
|
||||
bool PixelShaderCache::SetShader(bool dstAlphaEnable)
|
||||
{
|
||||
const FRAGMENTSHADER* const ps = GetShader(dstAlphaEnable);
|
||||
if (ps)
|
||||
{
|
||||
SetCurrentShader(ps->glprogid);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
PIXELSHADERUID uid;
|
||||
GetPixelShaderId(&uid, dstAlphaEnable ? 1 : 0);
|
||||
if (uid == last_pixel_shader_uid && pshaders[uid].frameCount == frameCount)
|
||||
{
|
||||
return pShaderLast;
|
||||
}
|
||||
|
||||
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
|
||||
|
||||
PSCache::iterator iter = pshaders.find(uid);
|
||||
|
||||
if (iter != pshaders.end()) {
|
||||
iter->second.frameCount = frameCount;
|
||||
PSCacheEntry &entry = iter->second;
|
||||
if (&entry.shader != pShaderLast)
|
||||
{
|
||||
pShaderLast = &entry.shader;
|
||||
}
|
||||
|
||||
return pShaderLast;
|
||||
}
|
||||
|
||||
//Make an entry in the table
|
||||
PSCacheEntry& newentry = pshaders[uid];
|
||||
newentry.frameCount = frameCount;
|
||||
pShaderLast = &newentry.shader;
|
||||
const char *code = GeneratePixelShaderCode(dstAlphaEnable,API_OPENGL);
|
||||
|
||||
#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), counter++);
|
||||
|
||||
SaveData(szTemp, code);
|
||||
}
|
||||
#endif
|
||||
|
||||
// printf("Compiling pixel shader. size = %i\n", strlen(code));
|
||||
if (!code || !CompilePixelShader(newentry.shader, code)) {
|
||||
ERROR_LOG(VIDEO, "failed to create pixel shader");
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
|
||||
SaveData(szTemp, code);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, pshaders.size());
|
||||
return pShaderLast;
|
||||
}
|
||||
|
||||
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
|
||||
{
|
||||
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=32,NumInstructionSlots=%d", s_nMaxPixelInstructions);
|
||||
const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
|
||||
CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts);
|
||||
|
||||
// handle errors
|
||||
if (!cgIsProgram(tempprog)) {
|
||||
cgDestroyProgram(tempprog);
|
||||
ERROR_LOG(VIDEO, "Failed to compile ps %s:", cgGetLastListing(g_cgcontext));
|
||||
ERROR_LOG(VIDEO, pstrprogram);
|
||||
return false;
|
||||
}
|
||||
|
||||
// handle warnings
|
||||
if (cgGetError() != CG_NO_ERROR)
|
||||
{
|
||||
WARN_LOG(VIDEO, "Warnings on compile ps %s:", cgGetLastListing(g_cgcontext));
|
||||
WARN_LOG(VIDEO, 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, &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)
|
||||
{
|
||||
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
|
||||
}
|
||||
ERROR_LOG(VIDEO, pstrprogram);
|
||||
ERROR_LOG(VIDEO, pcompiledprog);
|
||||
}
|
||||
|
||||
cgDestroyProgram(tempprog);
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
ps.strprog = pstrprogram;
|
||||
#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)
|
||||
{
|
||||
if(!ShaderEnabled)
|
||||
{
|
||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
ShaderEnabled = true;
|
||||
}
|
||||
if(CurrentShader != Shader)
|
||||
{
|
||||
if(Shader != 0)
|
||||
CurrentShader = Shader;
|
||||
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, CurrentShader);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,96 +1,96 @@
|
|||
// 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 _OGL_PIXELSHADERCACHE_H_
|
||||
#define _OGL_PIXELSHADERCACHE_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
// VideoCommon
|
||||
#include "BPMemory.h"
|
||||
#include "PixelShaderGen.h"
|
||||
|
||||
#include "../PixelShaderCache.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
struct FRAGMENTSHADER
|
||||
{
|
||||
FRAGMENTSHADER() : glprogid(0) { }
|
||||
void Destroy()
|
||||
{
|
||||
if (glprogid)
|
||||
{
|
||||
glDeleteProgramsARB(1, &glprogid);
|
||||
glprogid = 0;
|
||||
}
|
||||
}
|
||||
GLuint glprogid; // opengl program id
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string strprog;
|
||||
#endif
|
||||
};
|
||||
|
||||
class PixelShaderCache : public ::PixelShaderCacheBase
|
||||
{
|
||||
struct PSCacheEntry
|
||||
{
|
||||
FRAGMENTSHADER shader;
|
||||
int frameCount;
|
||||
|
||||
PSCacheEntry() : frameCount(0) {}
|
||||
void Destroy()
|
||||
{
|
||||
shader.Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
|
||||
|
||||
static PSCache pshaders;
|
||||
static PIXELSHADERUID s_curuid; // the current pixel shader uid (progressively changed as memory is written)
|
||||
static bool s_displayCompileAlert;
|
||||
static GLuint CurrentShader;
|
||||
static bool ShaderEnabled;
|
||||
|
||||
public:
|
||||
PixelShaderCache();
|
||||
~PixelShaderCache();
|
||||
|
||||
static FRAGMENTSHADER* GetShader(bool dstAlphaEnable);
|
||||
static bool CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram);
|
||||
|
||||
static GLuint GetColorMatrixProgram();
|
||||
static GLuint GetDepthMatrixProgram();
|
||||
|
||||
bool SetShader(bool dstAlphaEnable);
|
||||
|
||||
static void SetCurrentShader(GLuint Shader);
|
||||
static void DisableShader();
|
||||
|
||||
void Clear() {}
|
||||
|
||||
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetPSConstant4fv(unsigned int const_number, const float *f);
|
||||
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _PIXELSHADERCACHE_H_
|
||||
// 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 _OGL_PIXELSHADERCACHE_H_
|
||||
#define _OGL_PIXELSHADERCACHE_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
// VideoCommon
|
||||
#include "BPMemory.h"
|
||||
#include "PixelShaderGen.h"
|
||||
|
||||
#include "../PixelShaderCache.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
struct FRAGMENTSHADER
|
||||
{
|
||||
FRAGMENTSHADER() : glprogid(0) { }
|
||||
void Destroy()
|
||||
{
|
||||
if (glprogid)
|
||||
{
|
||||
glDeleteProgramsARB(1, &glprogid);
|
||||
glprogid = 0;
|
||||
}
|
||||
}
|
||||
GLuint glprogid; // opengl program id
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string strprog;
|
||||
#endif
|
||||
};
|
||||
|
||||
class PixelShaderCache : public ::PixelShaderCacheBase
|
||||
{
|
||||
struct PSCacheEntry
|
||||
{
|
||||
FRAGMENTSHADER shader;
|
||||
int frameCount;
|
||||
|
||||
PSCacheEntry() : frameCount(0) {}
|
||||
void Destroy()
|
||||
{
|
||||
shader.Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
|
||||
|
||||
static PSCache pshaders;
|
||||
static PIXELSHADERUID s_curuid; // the current pixel shader uid (progressively changed as memory is written)
|
||||
static bool s_displayCompileAlert;
|
||||
static GLuint CurrentShader;
|
||||
static bool ShaderEnabled;
|
||||
|
||||
public:
|
||||
PixelShaderCache();
|
||||
~PixelShaderCache();
|
||||
|
||||
static FRAGMENTSHADER* GetShader(bool dstAlphaEnable);
|
||||
static bool CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram);
|
||||
|
||||
static GLuint GetColorMatrixProgram();
|
||||
static GLuint GetDepthMatrixProgram();
|
||||
|
||||
bool SetShader(bool dstAlphaEnable);
|
||||
|
||||
static void SetCurrentShader(GLuint Shader);
|
||||
static void DisableShader();
|
||||
|
||||
void Clear() {}
|
||||
|
||||
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetPSConstant4fv(unsigned int const_number, const float *f);
|
||||
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _PIXELSHADERCACHE_H_
|
||||
|
|
|
@ -1,97 +1,97 @@
|
|||
// 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/
|
||||
|
||||
// Common
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoCommon.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_GLUtil.h"
|
||||
#include "OGL_PostProcessing.h"
|
||||
#include "OGL_PixelShaderCache.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
namespace PostProcessing
|
||||
{
|
||||
|
||||
static std::string s_currentShader;
|
||||
static FRAGMENTSHADER s_shader;
|
||||
|
||||
void Init()
|
||||
{
|
||||
s_currentShader = "";
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
s_shader.Destroy();
|
||||
}
|
||||
|
||||
void ReloadShader()
|
||||
{
|
||||
s_currentShader = "";
|
||||
}
|
||||
|
||||
bool ApplyShader()
|
||||
{
|
||||
if (s_currentShader != std::string(File::GetUserPath(D_SHADERS_IDX)) + g_ActiveConfig.sPostProcessingShader + ".txt")
|
||||
{
|
||||
// Set immediately to prevent endless recompiles on failure.
|
||||
if (!g_ActiveConfig.sPostProcessingShader.empty())
|
||||
s_currentShader = std::string(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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s_shader.glprogid != 0)
|
||||
{
|
||||
PixelShaderCache::SetCurrentShader(s_shader.glprogid);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
PixelShaderCache::DisableShader();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
// Common
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoCommon.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_GLUtil.h"
|
||||
#include "OGL_PostProcessing.h"
|
||||
#include "OGL_PixelShaderCache.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
namespace PostProcessing
|
||||
{
|
||||
|
||||
static std::string s_currentShader;
|
||||
static FRAGMENTSHADER s_shader;
|
||||
|
||||
void Init()
|
||||
{
|
||||
s_currentShader = "";
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
s_shader.Destroy();
|
||||
}
|
||||
|
||||
void ReloadShader()
|
||||
{
|
||||
s_currentShader = "";
|
||||
}
|
||||
|
||||
bool ApplyShader()
|
||||
{
|
||||
if (s_currentShader != std::string(File::GetUserPath(D_SHADERS_IDX)) + g_ActiveConfig.sPostProcessingShader + ".txt")
|
||||
{
|
||||
// Set immediately to prevent endless recompiles on failure.
|
||||
if (!g_ActiveConfig.sPostProcessingShader.empty())
|
||||
s_currentShader = std::string(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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s_shader.glprogid != 0)
|
||||
{
|
||||
PixelShaderCache::SetCurrentShader(s_shader.glprogid);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
PixelShaderCache::DisableShader();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
|
|
|
@ -1,42 +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 _OGL_POSTPROCESSING_H_
|
||||
#define _OGL_POSTPROCESSING_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
|
||||
#include "OGL_GLUtil.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
namespace PostProcessing
|
||||
{
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
void ReloadShader();
|
||||
// Returns false if no shader was applied.
|
||||
bool ApplyShader();
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
|
||||
#endif // _POSTPROCESSING_H_
|
||||
// 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 _OGL_POSTPROCESSING_H_
|
||||
#define _OGL_POSTPROCESSING_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
|
||||
#include "OGL_GLUtil.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
namespace PostProcessing
|
||||
{
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
void ReloadShader();
|
||||
// Returns false if no shader was applied.
|
||||
bool ApplyShader();
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
|
||||
#endif // _POSTPROCESSING_H_
|
||||
|
|
|
@ -1,226 +1,226 @@
|
|||
// 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 <string.h>
|
||||
|
||||
#include "OGL_GLUtil.h"
|
||||
#include "OGL_RasterFont.h"
|
||||
// globals
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// 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 <string.h>
|
||||
|
||||
#include "OGL_GLUtil.h"
|
||||
#include "OGL_RasterFont.h"
|
||||
// globals
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,51 +1,51 @@
|
|||
// 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 _OGL_RASTERFONT_H_
|
||||
#define _OGL_RASTERFONT_H_
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
class RasterFont {
|
||||
public:
|
||||
RasterFont();
|
||||
~RasterFont(void);
|
||||
static int debug;
|
||||
|
||||
// some useful constants
|
||||
enum
|
||||
{
|
||||
char_width = 10,
|
||||
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_
|
||||
// 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 _OGL_RASTERFONT_H_
|
||||
#define _OGL_RASTERFONT_H_
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
class RasterFont {
|
||||
public:
|
||||
RasterFont();
|
||||
~RasterFont(void);
|
||||
static int debug;
|
||||
|
||||
// some useful constants
|
||||
enum
|
||||
{
|
||||
char_width = 10,
|
||||
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_
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,61 +1,61 @@
|
|||
|
||||
#ifndef _OGL_RENDER_H_
|
||||
#define _OGL_RENDER_H_
|
||||
|
||||
#include "MathUtil.h"
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "Renderer.h"
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
extern int OSDChoice;
|
||||
|
||||
class Renderer : public ::RendererBase
|
||||
{
|
||||
public:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
||||
// What's the real difference between these? Too similar names.
|
||||
void ResetAPIState();
|
||||
void RestoreAPIState();
|
||||
|
||||
void SetColorMask();
|
||||
void SetBlendMode(bool forceUpdate);
|
||||
bool SetScissorRect();
|
||||
void SetGenerationMode();
|
||||
void SetDepthMode();
|
||||
void SetLogicOpMode();
|
||||
void SetDitherMode();
|
||||
void SetLineWidth();
|
||||
|
||||
// Live resolution change
|
||||
bool Allow2x();
|
||||
bool AllowCustom();
|
||||
|
||||
u32 AccessEFB(EFBAccessType type, int x, int y);
|
||||
|
||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
|
||||
void UpdateViewport();
|
||||
|
||||
// virtual funcs used by RendererBase::Swap
|
||||
void PrepareXFBCopy(const TargetRectangle &dst_rect);
|
||||
void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
|
||||
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc);
|
||||
void EndFrame();
|
||||
void Present();
|
||||
bool CheckForResize();
|
||||
void GetBackBufferSize(int* w, int* h);
|
||||
void RecreateFramebufferManger();
|
||||
void BeginFrame();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _OGL_RENDER_H_
|
||||
#define _OGL_RENDER_H_
|
||||
|
||||
#include "MathUtil.h"
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "Renderer.h"
|
||||
#include "pluginspecs_video.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
extern int OSDChoice;
|
||||
|
||||
class Renderer : public ::RendererBase
|
||||
{
|
||||
public:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
||||
// What's the real difference between these? Too similar names.
|
||||
void ResetAPIState();
|
||||
void RestoreAPIState();
|
||||
|
||||
void SetColorMask();
|
||||
void SetBlendMode(bool forceUpdate);
|
||||
bool SetScissorRect();
|
||||
void SetGenerationMode();
|
||||
void SetDepthMode();
|
||||
void SetLogicOpMode();
|
||||
void SetDitherMode();
|
||||
void SetLineWidth();
|
||||
|
||||
// Live resolution change
|
||||
bool Allow2x();
|
||||
bool AllowCustom();
|
||||
|
||||
u32 AccessEFB(EFBAccessType type, int x, int y);
|
||||
|
||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
|
||||
void UpdateViewport();
|
||||
|
||||
// virtual funcs used by RendererBase::Swap
|
||||
void PrepareXFBCopy(const TargetRectangle &dst_rect);
|
||||
void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
|
||||
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc);
|
||||
void EndFrame();
|
||||
void Present();
|
||||
bool CheckForResize();
|
||||
void GetBackBufferSize(int* w, int* h);
|
||||
void RecreateFramebufferManger();
|
||||
void BeginFrame();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,339 +1,339 @@
|
|||
// 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 <vector>
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _interlockedbittestandset workaround_ms_header_bug_platform_sdk6_set
|
||||
#define _interlockedbittestandreset workaround_ms_header_bug_platform_sdk6_reset
|
||||
#define _interlockedbittestandset64 workaround_ms_header_bug_platform_sdk6_set64
|
||||
#define _interlockedbittestandreset64 workaround_ms_header_bug_platform_sdk6_reset64
|
||||
#include <intrin.h>
|
||||
#undef _interlockedbittestandset
|
||||
#undef _interlockedbittestandreset
|
||||
#undef _interlockedbittestandset64
|
||||
#undef _interlockedbittestandreset64
|
||||
#endif
|
||||
|
||||
// Common
|
||||
#include "CommonPaths.h"
|
||||
#include "StringUtil.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
#include "Hash.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "ImageWrite.h"
|
||||
#include "BPStructs.h"
|
||||
#include "TextureDecoder.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "HiresTextures.h"
|
||||
#include "VertexShaderManager.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_TextureCache.h"
|
||||
#include "OGL_PixelShaderCache.h"
|
||||
#include "OGL_TextureConverter.h"
|
||||
#include "OGL_FramebufferManager.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
static u32 s_TempFramebuffer = 0;
|
||||
|
||||
static 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,
|
||||
};
|
||||
|
||||
static const GLint c_WrapSettings[4] = {
|
||||
GL_CLAMP_TO_EDGE,
|
||||
GL_REPEAT,
|
||||
GL_MIRRORED_REPEAT,
|
||||
GL_REPEAT,
|
||||
};
|
||||
|
||||
TextureCache::TCacheEntry::~TCacheEntry()
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
glDeleteTextures(1, &texture);
|
||||
texture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntry::TCacheEntry()
|
||||
{
|
||||
glGenTextures(1, &texture);
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
if (bHaveMipMaps)
|
||||
{
|
||||
if (pcfmt != PC_TEX_FMT_DXT1)
|
||||
{
|
||||
if (expanded_width != (int)width)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, TextureCache::temp);
|
||||
|
||||
if (expanded_width != (int)width)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO:
|
||||
//glCompressedTexImage2D(target, level, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, width, height, 0, expanded_width*expanded_height/2, temp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, width, height, 0, gl_format, gl_type, TextureCache::temp);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
// Make sure to resolve anything we need to read from.
|
||||
const GLuint read_texture = bFromZBuffer ? FramebufferManager::ResolveAndGetDepthTarget(source_rect) : FramebufferManager::ResolveAndGetRenderTarget(source_rect);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
if (s_TempFramebuffer == 0)
|
||||
glGenFramebuffersEXT(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);
|
||||
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);
|
||||
|
||||
glViewport(0, 0, Scaledw, Scaledh);
|
||||
|
||||
PixelShaderCache::SetCurrentShader(bFromZBuffer ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram());
|
||||
const float* const fConstAdd = colmat + 16; // fConstAdd is the last 4 floats of colmat
|
||||
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(source_rect);
|
||||
|
||||
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();
|
||||
|
||||
// Unbind texture from temporary framebuffer
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
|
||||
|
||||
// TODO: these good here?
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
DisableStage(0);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
// TODO: do this?
|
||||
//glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Bind(unsigned int stage)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
||||
unsigned int height, unsigned int expanded_width,
|
||||
unsigned int tex_levels, PC_TexFormat pcfmt)
|
||||
{
|
||||
TCacheEntry &entry = *new TCacheEntry;
|
||||
|
||||
int gl_format = 0;
|
||||
int gl_iformat = 0;
|
||||
int gl_type = 0;
|
||||
|
||||
if (pcfmt != PC_TEX_FMT_DXT1)
|
||||
{
|
||||
switch (pcfmt)
|
||||
{
|
||||
default:
|
||||
case PC_TEX_FMT_NONE:
|
||||
PanicAlert("Invalid PC texture format %i", pcfmt);
|
||||
case PC_TEX_FMT_BGRA32:
|
||||
gl_format = GL_BGRA;
|
||||
gl_iformat = 4;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_RGBA32:
|
||||
gl_format = GL_RGBA;
|
||||
gl_iformat = 4;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_I4_AS_I8:
|
||||
gl_format = GL_LUMINANCE;
|
||||
gl_iformat = GL_INTENSITY4;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_IA4_AS_IA8:
|
||||
gl_format = GL_LUMINANCE_ALPHA;
|
||||
gl_iformat = GL_LUMINANCE4_ALPHA4;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_I8:
|
||||
gl_format = GL_LUMINANCE;
|
||||
gl_iformat = GL_INTENSITY8;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_IA8:
|
||||
gl_format = GL_LUMINANCE_ALPHA;
|
||||
gl_iformat = GL_LUMINANCE8_ALPHA8;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_RGB565:
|
||||
gl_format = GL_RGB;
|
||||
gl_iformat = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_SHORT_5_6_5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
entry.gl_format = gl_format;
|
||||
entry.gl_iformat = gl_iformat;
|
||||
entry.gl_type = gl_type;
|
||||
|
||||
// ok?
|
||||
//Load(width, height, expanded_width, level);
|
||||
|
||||
return &entry;
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h)
|
||||
{
|
||||
TCacheEntry &entry = *new TCacheEntry;
|
||||
|
||||
entry.isDynamic = false;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, entry.texture);
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
const GLenum gl_format = GL_RGBA,
|
||||
gl_iformat = 4,
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, scaled_tex_w, scaled_tex_w, 0, gl_format, gl_type, NULL);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::SetTextureParameters(TexMode0 &newmode, TexMode1 &newmode1)
|
||||
{
|
||||
mode = newmode;
|
||||
//mode1 = newmode1;
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
(newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
if (bHaveMipMaps)
|
||||
{
|
||||
if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
|
||||
mode.min_filter += 4; // take equivalent forced linear
|
||||
|
||||
int filt = newmode.min_filter;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod >> 4);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod >> 4);
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (newmode.lod_bias/32.0f));
|
||||
|
||||
}
|
||||
else
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
(g_ActiveConfig.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]);
|
||||
|
||||
if (g_Config.iMaxAnisotropy >= 1)
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_ActiveConfig.iMaxAnisotropy));
|
||||
|
||||
}
|
||||
|
||||
TextureCache::~TextureCache()
|
||||
{
|
||||
if (s_TempFramebuffer)
|
||||
{
|
||||
glDeleteFramebuffersEXT(1, (GLuint *)&s_TempFramebuffer);
|
||||
s_TempFramebuffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::DisableStage(int stage)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + stage);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
}
|
||||
|
||||
}
|
||||
// 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 <vector>
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _interlockedbittestandset workaround_ms_header_bug_platform_sdk6_set
|
||||
#define _interlockedbittestandreset workaround_ms_header_bug_platform_sdk6_reset
|
||||
#define _interlockedbittestandset64 workaround_ms_header_bug_platform_sdk6_set64
|
||||
#define _interlockedbittestandreset64 workaround_ms_header_bug_platform_sdk6_reset64
|
||||
#include <intrin.h>
|
||||
#undef _interlockedbittestandset
|
||||
#undef _interlockedbittestandreset
|
||||
#undef _interlockedbittestandset64
|
||||
#undef _interlockedbittestandreset64
|
||||
#endif
|
||||
|
||||
// Common
|
||||
#include "CommonPaths.h"
|
||||
#include "StringUtil.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "VideoConfig.h"
|
||||
#include "Hash.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "ImageWrite.h"
|
||||
#include "BPStructs.h"
|
||||
#include "TextureDecoder.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "HiresTextures.h"
|
||||
#include "VertexShaderManager.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_TextureCache.h"
|
||||
#include "OGL_PixelShaderCache.h"
|
||||
#include "OGL_TextureConverter.h"
|
||||
#include "OGL_FramebufferManager.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
static u32 s_TempFramebuffer = 0;
|
||||
|
||||
static 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,
|
||||
};
|
||||
|
||||
static const GLint c_WrapSettings[4] = {
|
||||
GL_CLAMP_TO_EDGE,
|
||||
GL_REPEAT,
|
||||
GL_MIRRORED_REPEAT,
|
||||
GL_REPEAT,
|
||||
};
|
||||
|
||||
TextureCache::TCacheEntry::~TCacheEntry()
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
glDeleteTextures(1, &texture);
|
||||
texture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntry::TCacheEntry()
|
||||
{
|
||||
glGenTextures(1, &texture);
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
if (bHaveMipMaps)
|
||||
{
|
||||
if (pcfmt != PC_TEX_FMT_DXT1)
|
||||
{
|
||||
if (expanded_width != (int)width)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, TextureCache::temp);
|
||||
|
||||
if (expanded_width != (int)width)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO:
|
||||
//glCompressedTexImage2D(target, level, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, width, height, 0, expanded_width*expanded_height/2, temp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, width, height, 0, gl_format, gl_type, TextureCache::temp);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
// Make sure to resolve anything we need to read from.
|
||||
const GLuint read_texture = bFromZBuffer ? FramebufferManager::ResolveAndGetDepthTarget(source_rect) : FramebufferManager::ResolveAndGetRenderTarget(source_rect);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
if (s_TempFramebuffer == 0)
|
||||
glGenFramebuffersEXT(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);
|
||||
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);
|
||||
|
||||
glViewport(0, 0, Scaledw, Scaledh);
|
||||
|
||||
PixelShaderCache::SetCurrentShader(bFromZBuffer ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram());
|
||||
const float* const fConstAdd = colmat + 16; // fConstAdd is the last 4 floats of colmat
|
||||
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(source_rect);
|
||||
|
||||
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();
|
||||
|
||||
// Unbind texture from temporary framebuffer
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
|
||||
|
||||
// TODO: these good here?
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
DisableStage(0);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
// TODO: do this?
|
||||
//glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Bind(unsigned int stage)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
||||
unsigned int height, unsigned int expanded_width,
|
||||
unsigned int tex_levels, PC_TexFormat pcfmt)
|
||||
{
|
||||
TCacheEntry &entry = *new TCacheEntry;
|
||||
|
||||
int gl_format = 0;
|
||||
int gl_iformat = 0;
|
||||
int gl_type = 0;
|
||||
|
||||
if (pcfmt != PC_TEX_FMT_DXT1)
|
||||
{
|
||||
switch (pcfmt)
|
||||
{
|
||||
default:
|
||||
case PC_TEX_FMT_NONE:
|
||||
PanicAlert("Invalid PC texture format %i", pcfmt);
|
||||
case PC_TEX_FMT_BGRA32:
|
||||
gl_format = GL_BGRA;
|
||||
gl_iformat = 4;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_RGBA32:
|
||||
gl_format = GL_RGBA;
|
||||
gl_iformat = 4;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_I4_AS_I8:
|
||||
gl_format = GL_LUMINANCE;
|
||||
gl_iformat = GL_INTENSITY4;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_IA4_AS_IA8:
|
||||
gl_format = GL_LUMINANCE_ALPHA;
|
||||
gl_iformat = GL_LUMINANCE4_ALPHA4;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_I8:
|
||||
gl_format = GL_LUMINANCE;
|
||||
gl_iformat = GL_INTENSITY8;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_IA8:
|
||||
gl_format = GL_LUMINANCE_ALPHA;
|
||||
gl_iformat = GL_LUMINANCE8_ALPHA8;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_RGB565:
|
||||
gl_format = GL_RGB;
|
||||
gl_iformat = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_SHORT_5_6_5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
entry.gl_format = gl_format;
|
||||
entry.gl_iformat = gl_iformat;
|
||||
entry.gl_type = gl_type;
|
||||
|
||||
// ok?
|
||||
//Load(width, height, expanded_width, level);
|
||||
|
||||
return &entry;
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h)
|
||||
{
|
||||
TCacheEntry &entry = *new TCacheEntry;
|
||||
|
||||
entry.isDynamic = false;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, entry.texture);
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
const GLenum gl_format = GL_RGBA,
|
||||
gl_iformat = 4,
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, scaled_tex_w, scaled_tex_w, 0, gl_format, gl_type, NULL);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::SetTextureParameters(TexMode0 &newmode, TexMode1 &newmode1)
|
||||
{
|
||||
mode = newmode;
|
||||
//mode1 = newmode1;
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
(newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
if (bHaveMipMaps)
|
||||
{
|
||||
if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
|
||||
mode.min_filter += 4; // take equivalent forced linear
|
||||
|
||||
int filt = newmode.min_filter;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod >> 4);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod >> 4);
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (newmode.lod_bias/32.0f));
|
||||
|
||||
}
|
||||
else
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
(g_ActiveConfig.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]);
|
||||
|
||||
if (g_Config.iMaxAnisotropy >= 1)
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_ActiveConfig.iMaxAnisotropy));
|
||||
|
||||
}
|
||||
|
||||
TextureCache::~TextureCache()
|
||||
{
|
||||
if (s_TempFramebuffer)
|
||||
{
|
||||
glDeleteFramebuffersEXT(1, (GLuint *)&s_TempFramebuffer);
|
||||
s_TempFramebuffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::DisableStage(int stage)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + stage);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,80 +1,80 @@
|
|||
// 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 _OGL_TEXTURECACHE_H_
|
||||
#define _OGL_TEXTURECACHE_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "BPMemory.h"
|
||||
|
||||
#include "OGL_GLUtil.h"
|
||||
|
||||
#include "../TextureCache.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
class TextureCache : public ::TextureCacheBase
|
||||
{
|
||||
public:
|
||||
struct TCacheEntry : TCacheEntryBase
|
||||
{
|
||||
GLuint texture;
|
||||
|
||||
bool isDynamic;
|
||||
bool bHaveMipMaps;
|
||||
|
||||
PC_TexFormat pcfmt;
|
||||
|
||||
int gl_format;
|
||||
int gl_iformat;
|
||||
int gl_type;
|
||||
|
||||
TexMode0 mode; // current filter and clamp modes that texture is set to
|
||||
TexMode1 mode1; // current filter and clamp modes that texture is set to
|
||||
|
||||
void SetTextureParameters(TexMode0 &newmode, TexMode1 &newmode1);
|
||||
|
||||
TCacheEntry();
|
||||
~TCacheEntry();
|
||||
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level);
|
||||
|
||||
void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect);
|
||||
|
||||
void Bind(unsigned int stage);
|
||||
};
|
||||
|
||||
~TextureCache();
|
||||
|
||||
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt);
|
||||
|
||||
TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h);
|
||||
|
||||
void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, unsigned int bScaleByHalf, const EFBRectangle &source);
|
||||
|
||||
static void DisableStage(int stage); // sets active texture
|
||||
};
|
||||
|
||||
//bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height);
|
||||
|
||||
}
|
||||
|
||||
#endif // _TEXTUREMNGR_H_
|
||||
// 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 _OGL_TEXTURECACHE_H_
|
||||
#define _OGL_TEXTURECACHE_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "BPMemory.h"
|
||||
|
||||
#include "OGL_GLUtil.h"
|
||||
|
||||
#include "../TextureCache.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
class TextureCache : public ::TextureCacheBase
|
||||
{
|
||||
public:
|
||||
struct TCacheEntry : TCacheEntryBase
|
||||
{
|
||||
GLuint texture;
|
||||
|
||||
bool isDynamic;
|
||||
bool bHaveMipMaps;
|
||||
|
||||
PC_TexFormat pcfmt;
|
||||
|
||||
int gl_format;
|
||||
int gl_iformat;
|
||||
int gl_type;
|
||||
|
||||
TexMode0 mode; // current filter and clamp modes that texture is set to
|
||||
TexMode1 mode1; // current filter and clamp modes that texture is set to
|
||||
|
||||
void SetTextureParameters(TexMode0 &newmode, TexMode1 &newmode1);
|
||||
|
||||
TCacheEntry();
|
||||
~TCacheEntry();
|
||||
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level);
|
||||
|
||||
void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect);
|
||||
|
||||
void Bind(unsigned int stage);
|
||||
};
|
||||
|
||||
~TextureCache();
|
||||
|
||||
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt);
|
||||
|
||||
TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h);
|
||||
|
||||
void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, unsigned int bScaleByHalf, const EFBRectangle &source);
|
||||
|
||||
static void DisableStage(int stage); // sets active texture
|
||||
};
|
||||
|
||||
//bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height);
|
||||
|
||||
}
|
||||
|
||||
#endif // _TEXTUREMNGR_H_
|
||||
|
|
|
@ -1,486 +1,486 @@
|
|||
// 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/
|
||||
|
||||
// Fast image conversion using OpenGL shaders.
|
||||
// This kind of stuff would be a LOT nicer with OpenCL.
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// Common
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "TextureConversionShader.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "ImageWrite.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_Render.h"
|
||||
#include "OGL_TextureConverter.h"
|
||||
#include "OGL_TextureCache.h"
|
||||
#include "OGL_PixelShaderCache.h"
|
||||
#include "OGL_FramebufferManager.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
namespace TextureConverter
|
||||
{
|
||||
|
||||
static GLuint s_texConvFrameBuffer = 0;
|
||||
static GLuint s_srcTexture = 0; // for decoding from RAM
|
||||
static GLuint s_srcTextureWidth = 0;
|
||||
static GLuint s_srcTextureHeight = 0;
|
||||
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;
|
||||
|
||||
// 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"
|
||||
"{\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"
|
||||
"}\n";
|
||||
|
||||
if (!PixelShaderCache::CompilePixelShader(s_rgbToYuyvProgram, FProgram)) {
|
||||
ERROR_LOG(VIDEO, "Failed to create RGB to YUYV fragment program");
|
||||
}
|
||||
}
|
||||
|
||||
void CreateYuyvToRgbProgram()
|
||||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format)
|
||||
{
|
||||
if (format > NUM_ENCODING_PROGRAMS)
|
||||
{
|
||||
PanicAlert("Unknown texture copy format: 0x%x\n", format);
|
||||
return s_encodingPrograms[0];
|
||||
}
|
||||
|
||||
if (s_encodingPrograms[format].glprogid == 0)
|
||||
{
|
||||
const char* shader = TextureConversionShader::GenerateEncodingShader(format,API_OPENGL);
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader) {
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%senc_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
|
||||
|
||||
SaveData(szTemp, shader);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!PixelShaderCache::CompilePixelShader(s_encodingPrograms[format], shader)) {
|
||||
ERROR_LOG(VIDEO, "Failed to create encoding fragment program");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
glGenTextures(1, &s_srcTexture);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
CreateRgbToYuyvProgram();
|
||||
CreateYuyvToRgbProgram();
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
glDeleteTextures(1, &s_srcTexture);
|
||||
glDeleteRenderbuffersEXT(1, &s_dstRenderBuffer);
|
||||
glDeleteFramebuffersEXT(1, &s_texConvFrameBuffer);
|
||||
|
||||
s_rgbToYuyvProgram.Destroy();
|
||||
s_yuyvToRgbProgram.Destroy();
|
||||
|
||||
for (unsigned int i = 0; i < NUM_ENCODING_PROGRAMS; i++)
|
||||
s_encodingPrograms[i].Destroy();
|
||||
|
||||
s_srcTexture = 0;
|
||||
s_dstRenderBuffer = 0;
|
||||
s_texConvFrameBuffer = 0;
|
||||
}
|
||||
|
||||
void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight, int readStride, bool toTexture, bool linearFilter)
|
||||
{
|
||||
|
||||
|
||||
// switch to texture converter frame buffer
|
||||
// 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);
|
||||
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);
|
||||
|
||||
if (linearFilter)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, 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);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
// .. and then readback the results.
|
||||
// TODO: make this less slow.
|
||||
|
||||
int writeStride = bpmem.copyMipMapStrideChannels * 32;
|
||||
|
||||
if (writeStride != readStride && toTexture)
|
||||
{
|
||||
// writing to a texture of a different size
|
||||
|
||||
int readHeight = readStride / dstWidth;
|
||||
readHeight /= 4; // 4 bytes per pixel
|
||||
|
||||
int readStart = 0;
|
||||
int readLoops = dstHeight / readHeight;
|
||||
for (int i = 0; i < readLoops; i++)
|
||||
{
|
||||
glReadPixels(0, readStart, (GLsizei)dstWidth, (GLsizei)readHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr);
|
||||
|
||||
readStart += readHeight;
|
||||
destAddr += writeStride;
|
||||
}
|
||||
}
|
||||
else
|
||||
glReadPixels(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
}
|
||||
|
||||
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
|
||||
{
|
||||
u32 format = copyfmt;
|
||||
|
||||
if (bFromZBuffer)
|
||||
{
|
||||
format |= _GX_TF_ZTF;
|
||||
if (copyfmt == 11)
|
||||
format = GX_TF_Z16;
|
||||
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
|
||||
format |= _GX_TF_CTF;
|
||||
}
|
||||
else
|
||||
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;
|
||||
|
||||
u8 *dest_ptr = Memory_GetPtr(address);
|
||||
|
||||
GLuint source_texture = bFromZBuffer ? FramebufferManager::ResolveAndGetDepthTarget(source) : FramebufferManager::ResolveAndGetRenderTarget(source);
|
||||
|
||||
int width = (source.right - source.left) >> bScaleByHalf;
|
||||
int height = (source.bottom - source.top) >> bScaleByHalf;
|
||||
|
||||
int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format);
|
||||
|
||||
// Invalidate any existing texture covering this memory range.
|
||||
// TODO - don't delete the texture if it already exists, just replace the contents.
|
||||
TextureCache::InvalidateRange(address, size_in_bytes);
|
||||
|
||||
u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1;
|
||||
u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1;
|
||||
u16 samples = TextureConversionShader::GetEncodedSampleCount(format);
|
||||
|
||||
// only copy on cache line boundaries
|
||||
// extra pixels are copied but not displayed in the resulting texture
|
||||
s32 expandedWidth = (width + blkW) & (~blkW);
|
||||
s32 expandedHeight = (height + blkH) & (~blkH);
|
||||
|
||||
float MValueX = Renderer::GetTargetScaleX();
|
||||
float MValueY = Renderer::GetTargetScaleY();
|
||||
|
||||
float top = (EFB_HEIGHT - source.top - expandedHeight) * MValueY ;
|
||||
|
||||
float sampleStride = bScaleByHalf?2.0f:1.0f;
|
||||
|
||||
TextureConversionShader::SetShaderParameters((float)expandedWidth,
|
||||
expandedHeight * MValueY,
|
||||
source.left * MValueX,
|
||||
top,
|
||||
sampleStride * MValueX,
|
||||
sampleStride * MValueY);
|
||||
|
||||
TargetRectangle scaledSource;
|
||||
scaledSource.top = 0;
|
||||
scaledSource.bottom = expandedHeight;
|
||||
scaledSource.left = 0;
|
||||
scaledSource.right = expandedWidth / samples;
|
||||
|
||||
|
||||
int cacheBytes = 32;
|
||||
if ((format & 0x0f) == 6)
|
||||
cacheBytes = 64;
|
||||
|
||||
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
|
||||
g_renderer->ResetAPIState();
|
||||
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0);
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
TextureCache::DisableStage(0);
|
||||
g_renderer->RestoreAPIState();
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
|
||||
u64 EncodeToRamFromTexture(u32 address,GLuint source_texture,float MValueX,float MValueY,bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
|
||||
{
|
||||
u32 format = copyfmt;
|
||||
|
||||
if (bFromZBuffer)
|
||||
{
|
||||
format |= _GX_TF_ZTF;
|
||||
if (copyfmt == 11)
|
||||
format = GX_TF_Z16;
|
||||
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
|
||||
format |= _GX_TF_CTF;
|
||||
}
|
||||
else
|
||||
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;
|
||||
|
||||
u8 *dest_ptr = Memory_GetPtr(address);
|
||||
|
||||
int width = (source.right - source.left) >> bScaleByHalf;
|
||||
int height = (source.bottom - source.top) >> bScaleByHalf;
|
||||
|
||||
int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format);
|
||||
|
||||
u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1;
|
||||
u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1;
|
||||
u16 samples = TextureConversionShader::GetEncodedSampleCount(format);
|
||||
|
||||
// only copy on cache line boundaries
|
||||
// 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.0f:1.0f;
|
||||
float top = (EFB_HEIGHT - source.top - expandedHeight) * MValueY ;
|
||||
TextureConversionShader::SetShaderParameters((float)expandedWidth,
|
||||
expandedHeight * MValueY,
|
||||
source.left * MValueX,
|
||||
top,
|
||||
sampleStride * MValueX,
|
||||
sampleStride * MValueY);
|
||||
|
||||
TargetRectangle scaledSource;
|
||||
scaledSource.top = 0;
|
||||
scaledSource.bottom = expandedHeight;
|
||||
scaledSource.left = 0;
|
||||
scaledSource.right = expandedWidth / samples;
|
||||
|
||||
|
||||
int cacheBytes = 32;
|
||||
if ((format & 0x0f) == 6)
|
||||
cacheBytes = 64;
|
||||
|
||||
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
|
||||
|
||||
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0 && !bFromZBuffer);
|
||||
g_texture_cache->MakeRangeDynamic(address,size_in_bytes);
|
||||
return GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples);
|
||||
}
|
||||
|
||||
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);
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
TextureCache::DisableStage(0);
|
||||
g_renderer->RestoreAPIState();
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
|
||||
// Should be scale free.
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture)
|
||||
{
|
||||
u8* srcAddr = Memory_GetPtr(xfbAddr);
|
||||
if (!srcAddr)
|
||||
{
|
||||
WARN_LOG(VIDEO, "Tried to decode from invalid memory address");
|
||||
return;
|
||||
}
|
||||
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
int srcFmtWidth = srcWidth / 2;
|
||||
|
||||
// swich 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);
|
||||
|
||||
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);
|
||||
|
||||
// TODO: make this less slow. (How?)
|
||||
if((GLsizei)s_srcTextureWidth == (GLsizei)srcFmtWidth && (GLsizei)s_srcTextureHeight == (GLsizei)srcHeight)
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,0,0,s_srcTextureWidth, s_srcTextureHeight, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 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);
|
||||
|
||||
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();
|
||||
|
||||
// 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();
|
||||
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
// Fast image conversion using OpenGL shaders.
|
||||
// This kind of stuff would be a LOT nicer with OpenCL.
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// Common
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "TextureConversionShader.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "ImageWrite.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_Render.h"
|
||||
#include "OGL_TextureConverter.h"
|
||||
#include "OGL_TextureCache.h"
|
||||
#include "OGL_PixelShaderCache.h"
|
||||
#include "OGL_FramebufferManager.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
namespace TextureConverter
|
||||
{
|
||||
|
||||
static GLuint s_texConvFrameBuffer = 0;
|
||||
static GLuint s_srcTexture = 0; // for decoding from RAM
|
||||
static GLuint s_srcTextureWidth = 0;
|
||||
static GLuint s_srcTextureHeight = 0;
|
||||
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;
|
||||
|
||||
// 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"
|
||||
"{\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"
|
||||
"}\n";
|
||||
|
||||
if (!PixelShaderCache::CompilePixelShader(s_rgbToYuyvProgram, FProgram)) {
|
||||
ERROR_LOG(VIDEO, "Failed to create RGB to YUYV fragment program");
|
||||
}
|
||||
}
|
||||
|
||||
void CreateYuyvToRgbProgram()
|
||||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format)
|
||||
{
|
||||
if (format > NUM_ENCODING_PROGRAMS)
|
||||
{
|
||||
PanicAlert("Unknown texture copy format: 0x%x\n", format);
|
||||
return s_encodingPrograms[0];
|
||||
}
|
||||
|
||||
if (s_encodingPrograms[format].glprogid == 0)
|
||||
{
|
||||
const char* shader = TextureConversionShader::GenerateEncodingShader(format,API_OPENGL);
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader) {
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%senc_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
|
||||
|
||||
SaveData(szTemp, shader);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!PixelShaderCache::CompilePixelShader(s_encodingPrograms[format], shader)) {
|
||||
ERROR_LOG(VIDEO, "Failed to create encoding fragment program");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
glGenTextures(1, &s_srcTexture);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
CreateRgbToYuyvProgram();
|
||||
CreateYuyvToRgbProgram();
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
glDeleteTextures(1, &s_srcTexture);
|
||||
glDeleteRenderbuffersEXT(1, &s_dstRenderBuffer);
|
||||
glDeleteFramebuffersEXT(1, &s_texConvFrameBuffer);
|
||||
|
||||
s_rgbToYuyvProgram.Destroy();
|
||||
s_yuyvToRgbProgram.Destroy();
|
||||
|
||||
for (unsigned int i = 0; i < NUM_ENCODING_PROGRAMS; i++)
|
||||
s_encodingPrograms[i].Destroy();
|
||||
|
||||
s_srcTexture = 0;
|
||||
s_dstRenderBuffer = 0;
|
||||
s_texConvFrameBuffer = 0;
|
||||
}
|
||||
|
||||
void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight, int readStride, bool toTexture, bool linearFilter)
|
||||
{
|
||||
|
||||
|
||||
// switch to texture converter frame buffer
|
||||
// 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);
|
||||
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);
|
||||
|
||||
if (linearFilter)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, 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);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
// .. and then readback the results.
|
||||
// TODO: make this less slow.
|
||||
|
||||
int writeStride = bpmem.copyMipMapStrideChannels * 32;
|
||||
|
||||
if (writeStride != readStride && toTexture)
|
||||
{
|
||||
// writing to a texture of a different size
|
||||
|
||||
int readHeight = readStride / dstWidth;
|
||||
readHeight /= 4; // 4 bytes per pixel
|
||||
|
||||
int readStart = 0;
|
||||
int readLoops = dstHeight / readHeight;
|
||||
for (int i = 0; i < readLoops; i++)
|
||||
{
|
||||
glReadPixels(0, readStart, (GLsizei)dstWidth, (GLsizei)readHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr);
|
||||
|
||||
readStart += readHeight;
|
||||
destAddr += writeStride;
|
||||
}
|
||||
}
|
||||
else
|
||||
glReadPixels(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
}
|
||||
|
||||
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
|
||||
{
|
||||
u32 format = copyfmt;
|
||||
|
||||
if (bFromZBuffer)
|
||||
{
|
||||
format |= _GX_TF_ZTF;
|
||||
if (copyfmt == 11)
|
||||
format = GX_TF_Z16;
|
||||
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
|
||||
format |= _GX_TF_CTF;
|
||||
}
|
||||
else
|
||||
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;
|
||||
|
||||
u8 *dest_ptr = Memory_GetPtr(address);
|
||||
|
||||
GLuint source_texture = bFromZBuffer ? FramebufferManager::ResolveAndGetDepthTarget(source) : FramebufferManager::ResolveAndGetRenderTarget(source);
|
||||
|
||||
int width = (source.right - source.left) >> bScaleByHalf;
|
||||
int height = (source.bottom - source.top) >> bScaleByHalf;
|
||||
|
||||
int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format);
|
||||
|
||||
// Invalidate any existing texture covering this memory range.
|
||||
// TODO - don't delete the texture if it already exists, just replace the contents.
|
||||
TextureCache::InvalidateRange(address, size_in_bytes);
|
||||
|
||||
u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1;
|
||||
u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1;
|
||||
u16 samples = TextureConversionShader::GetEncodedSampleCount(format);
|
||||
|
||||
// only copy on cache line boundaries
|
||||
// extra pixels are copied but not displayed in the resulting texture
|
||||
s32 expandedWidth = (width + blkW) & (~blkW);
|
||||
s32 expandedHeight = (height + blkH) & (~blkH);
|
||||
|
||||
float MValueX = Renderer::GetTargetScaleX();
|
||||
float MValueY = Renderer::GetTargetScaleY();
|
||||
|
||||
float top = (EFB_HEIGHT - source.top - expandedHeight) * MValueY ;
|
||||
|
||||
float sampleStride = bScaleByHalf?2.0f:1.0f;
|
||||
|
||||
TextureConversionShader::SetShaderParameters((float)expandedWidth,
|
||||
expandedHeight * MValueY,
|
||||
source.left * MValueX,
|
||||
top,
|
||||
sampleStride * MValueX,
|
||||
sampleStride * MValueY);
|
||||
|
||||
TargetRectangle scaledSource;
|
||||
scaledSource.top = 0;
|
||||
scaledSource.bottom = expandedHeight;
|
||||
scaledSource.left = 0;
|
||||
scaledSource.right = expandedWidth / samples;
|
||||
|
||||
|
||||
int cacheBytes = 32;
|
||||
if ((format & 0x0f) == 6)
|
||||
cacheBytes = 64;
|
||||
|
||||
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
|
||||
g_renderer->ResetAPIState();
|
||||
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0);
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
TextureCache::DisableStage(0);
|
||||
g_renderer->RestoreAPIState();
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
|
||||
u64 EncodeToRamFromTexture(u32 address,GLuint source_texture,float MValueX,float MValueY,bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
|
||||
{
|
||||
u32 format = copyfmt;
|
||||
|
||||
if (bFromZBuffer)
|
||||
{
|
||||
format |= _GX_TF_ZTF;
|
||||
if (copyfmt == 11)
|
||||
format = GX_TF_Z16;
|
||||
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
|
||||
format |= _GX_TF_CTF;
|
||||
}
|
||||
else
|
||||
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;
|
||||
|
||||
u8 *dest_ptr = Memory_GetPtr(address);
|
||||
|
||||
int width = (source.right - source.left) >> bScaleByHalf;
|
||||
int height = (source.bottom - source.top) >> bScaleByHalf;
|
||||
|
||||
int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format);
|
||||
|
||||
u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1;
|
||||
u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1;
|
||||
u16 samples = TextureConversionShader::GetEncodedSampleCount(format);
|
||||
|
||||
// only copy on cache line boundaries
|
||||
// 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.0f:1.0f;
|
||||
float top = (EFB_HEIGHT - source.top - expandedHeight) * MValueY ;
|
||||
TextureConversionShader::SetShaderParameters((float)expandedWidth,
|
||||
expandedHeight * MValueY,
|
||||
source.left * MValueX,
|
||||
top,
|
||||
sampleStride * MValueX,
|
||||
sampleStride * MValueY);
|
||||
|
||||
TargetRectangle scaledSource;
|
||||
scaledSource.top = 0;
|
||||
scaledSource.bottom = expandedHeight;
|
||||
scaledSource.left = 0;
|
||||
scaledSource.right = expandedWidth / samples;
|
||||
|
||||
|
||||
int cacheBytes = 32;
|
||||
if ((format & 0x0f) == 6)
|
||||
cacheBytes = 64;
|
||||
|
||||
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
|
||||
|
||||
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0 && !bFromZBuffer);
|
||||
g_texture_cache->MakeRangeDynamic(address,size_in_bytes);
|
||||
return GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples);
|
||||
}
|
||||
|
||||
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);
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
TextureCache::DisableStage(0);
|
||||
g_renderer->RestoreAPIState();
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
|
||||
// Should be scale free.
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture)
|
||||
{
|
||||
u8* srcAddr = Memory_GetPtr(xfbAddr);
|
||||
if (!srcAddr)
|
||||
{
|
||||
WARN_LOG(VIDEO, "Tried to decode from invalid memory address");
|
||||
return;
|
||||
}
|
||||
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
int srcFmtWidth = srcWidth / 2;
|
||||
|
||||
// swich 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);
|
||||
|
||||
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);
|
||||
|
||||
// TODO: make this less slow. (How?)
|
||||
if((GLsizei)s_srcTextureWidth == (GLsizei)srcFmtWidth && (GLsizei)s_srcTextureHeight == (GLsizei)srcHeight)
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,0,0,s_srcTextureWidth, s_srcTextureHeight, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 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);
|
||||
|
||||
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();
|
||||
|
||||
// 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();
|
||||
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
}
|
||||
|
|
|
@ -1,50 +1,50 @@
|
|||
// 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 _OGL_TEXTURECONVERTER_H_
|
||||
#define _OGL_TEXTURECONVERTER_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
|
||||
#include "OGL_GLUtil.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
// Converts textures between formats
|
||||
// TODO: support multiple texture formats
|
||||
namespace TextureConverter
|
||||
{
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
|
||||
u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
|
||||
|
||||
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight);
|
||||
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);
|
||||
|
||||
u64 EncodeToRamFromTexture(u32 address,GLuint source_texture,float MValueX,float MValueY, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // _TEXTURECONVERTER_H_
|
||||
// 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 _OGL_TEXTURECONVERTER_H_
|
||||
#define _OGL_TEXTURECONVERTER_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
|
||||
#include "OGL_GLUtil.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
// Converts textures between formats
|
||||
// TODO: support multiple texture formats
|
||||
namespace TextureConverter
|
||||
{
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
|
||||
u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
|
||||
|
||||
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight);
|
||||
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);
|
||||
|
||||
u64 EncodeToRamFromTexture(u32 address,GLuint source_texture,float MValueX,float MValueY, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // _TEXTURECONVERTER_H_
|
||||
|
|
|
@ -1,113 +1,113 @@
|
|||
// 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 <fstream>
|
||||
#include <vector>
|
||||
|
||||
// Common
|
||||
#include "MemoryUtil.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "Fifo.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "ImageWrite.h"
|
||||
#include "BPMemory.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VertexShaderGen.h"
|
||||
#include "VertexLoader.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_Render.h"
|
||||
#include "OGL_TextureCache.h"
|
||||
#include "OGL_PixelShaderCache.h"
|
||||
#include "OGL_VertexShaderCache.h"
|
||||
#include "OGL_VertexManager.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
MAXVBUFFERSIZE = 0x1FFFF,
|
||||
MAXIBUFFERSIZE = 0xFFFF,
|
||||
MAXVBOBUFFERCOUNT = 0x8,
|
||||
};
|
||||
|
||||
//static GLuint s_vboBuffers[MAXVBOBUFFERCOUNT] = {0};
|
||||
//static int s_nCurVBOIndex = 0; // current free buffer
|
||||
|
||||
VertexManager::VertexManager()
|
||||
{
|
||||
lastPrimitive = GX_DRAW_NONE;
|
||||
|
||||
//s_nCurVBOIndex = 0;
|
||||
//glGenBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
g_nativeVertexFmt = NULL;
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
VertexManager::~VertexManager()
|
||||
{
|
||||
//glDeleteBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers);
|
||||
//s_nCurVBOIndex = 0;
|
||||
}
|
||||
|
||||
void VertexManager::Draw(u32 /*stride*/, bool alphapass)
|
||||
{
|
||||
if (alphapass)
|
||||
{
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (IndexGenerator::GetNumTriangles() > 0)
|
||||
{
|
||||
glDrawElements(GL_TRIANGLES, IndexGenerator::GetTriangleindexLen(), GL_UNSIGNED_SHORT, TIBuffer);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumLines() > 0)
|
||||
{
|
||||
glDrawElements(GL_LINES, IndexGenerator::GetLineindexLen(), GL_UNSIGNED_SHORT, LIBuffer);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumPoints() > 0)
|
||||
{
|
||||
glDrawElements(GL_POINTS, IndexGenerator::GetPointindexLen(), GL_UNSIGNED_SHORT, PIBuffer);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
|
||||
if (alphapass)
|
||||
{
|
||||
// restore color mask
|
||||
g_renderer->SetColorMask();
|
||||
|
||||
if (bpmem.blendmode.blendenable || bpmem.blendmode.subtract)
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// 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 <fstream>
|
||||
#include <vector>
|
||||
|
||||
// Common
|
||||
#include "MemoryUtil.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "Fifo.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "ImageWrite.h"
|
||||
#include "BPMemory.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VertexShaderGen.h"
|
||||
#include "VertexLoader.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_Render.h"
|
||||
#include "OGL_TextureCache.h"
|
||||
#include "OGL_PixelShaderCache.h"
|
||||
#include "OGL_VertexShaderCache.h"
|
||||
#include "OGL_VertexManager.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
MAXVBUFFERSIZE = 0x1FFFF,
|
||||
MAXIBUFFERSIZE = 0xFFFF,
|
||||
MAXVBOBUFFERCOUNT = 0x8,
|
||||
};
|
||||
|
||||
//static GLuint s_vboBuffers[MAXVBOBUFFERCOUNT] = {0};
|
||||
//static int s_nCurVBOIndex = 0; // current free buffer
|
||||
|
||||
VertexManager::VertexManager()
|
||||
{
|
||||
lastPrimitive = GX_DRAW_NONE;
|
||||
|
||||
//s_nCurVBOIndex = 0;
|
||||
//glGenBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
g_nativeVertexFmt = NULL;
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
VertexManager::~VertexManager()
|
||||
{
|
||||
//glDeleteBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers);
|
||||
//s_nCurVBOIndex = 0;
|
||||
}
|
||||
|
||||
void VertexManager::Draw(u32 /*stride*/, bool alphapass)
|
||||
{
|
||||
if (alphapass)
|
||||
{
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (IndexGenerator::GetNumTriangles() > 0)
|
||||
{
|
||||
glDrawElements(GL_TRIANGLES, IndexGenerator::GetTriangleindexLen(), GL_UNSIGNED_SHORT, TIBuffer);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumLines() > 0)
|
||||
{
|
||||
glDrawElements(GL_LINES, IndexGenerator::GetLineindexLen(), GL_UNSIGNED_SHORT, LIBuffer);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumPoints() > 0)
|
||||
{
|
||||
glDrawElements(GL_POINTS, IndexGenerator::GetPointindexLen(), GL_UNSIGNED_SHORT, PIBuffer);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
|
||||
if (alphapass)
|
||||
{
|
||||
// restore color mask
|
||||
g_renderer->SetColorMask();
|
||||
|
||||
if (bpmem.blendmode.blendenable || bpmem.blendmode.subtract)
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,44 +1,44 @@
|
|||
// 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 _OGL_VERTEXMANAGER_H_
|
||||
#define _OGL_VERTEXMANAGER_H_
|
||||
|
||||
#include "CPMemory.h"
|
||||
#include "NativeVertexWriter.h"
|
||||
|
||||
#include "../VertexManager.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
// Handles the OpenGL details of drawing lots of vertices quickly.
|
||||
// Other functionality is moving out.
|
||||
class VertexManager : public ::VertexManagerBase
|
||||
{
|
||||
public:
|
||||
VertexManager();
|
||||
~VertexManager();
|
||||
|
||||
void Draw(u32 stride, bool alphapass);
|
||||
|
||||
NativeVertexFormat* CreateNativeVertexFormat();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _VERTEXMANAGER_H_
|
||||
// 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 _OGL_VERTEXMANAGER_H_
|
||||
#define _OGL_VERTEXMANAGER_H_
|
||||
|
||||
#include "CPMemory.h"
|
||||
#include "NativeVertexWriter.h"
|
||||
|
||||
#include "../VertexManager.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
// Handles the OpenGL details of drawing lots of vertices quickly.
|
||||
// Other functionality is moving out.
|
||||
class VertexManager : public ::VertexManagerBase
|
||||
{
|
||||
public:
|
||||
VertexManager();
|
||||
~VertexManager();
|
||||
|
||||
void Draw(u32 stride, bool alphapass);
|
||||
|
||||
NativeVertexFormat* CreateNativeVertexFormat();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _VERTEXMANAGER_H_
|
||||
|
|
|
@ -1,255 +1,255 @@
|
|||
// 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 <math.h>
|
||||
|
||||
// Common
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "Profiler.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "Statistics.h"
|
||||
#include "VertexShaderGen.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "XFMemory.h"
|
||||
#include "ImageWrite.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_Render.h"
|
||||
#include "OGL_VertexShaderCache.h"
|
||||
#include "OGL_GLUtil.h"
|
||||
#include "OGL_VertexManager.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
VertexShaderCache::VSCache VertexShaderCache::vshaders;
|
||||
bool VertexShaderCache::s_displayCompileAlert;
|
||||
GLuint VertexShaderCache::CurrentShader;
|
||||
bool VertexShaderCache::ShaderEnabled;
|
||||
|
||||
static VERTEXSHADER *pShaderLast = NULL;
|
||||
static int s_nMaxVertexInstructions;
|
||||
|
||||
void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
float f[4] = { f1, f2, f3, f4 };
|
||||
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f);
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f);
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++,f+=4)
|
||||
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, f);
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VertexShaderCache::VertexShaderCache()
|
||||
{
|
||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||
ShaderEnabled = true;
|
||||
CurrentShader = 0;
|
||||
memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid));
|
||||
|
||||
s_displayCompileAlert = true;
|
||||
|
||||
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions);
|
||||
#if CG_VERSION_NUM == 2100
|
||||
if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
|
||||
{
|
||||
s_nMaxVertexInstructions = 4096;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
VertexShaderCache::~VertexShaderCache()
|
||||
{
|
||||
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); iter++)
|
||||
iter->second.Destroy();
|
||||
vshaders.clear();
|
||||
}
|
||||
|
||||
bool VertexShaderCache::SetShader(u32 components)
|
||||
{
|
||||
const VERTEXSHADER* const vs = GetShader(components);
|
||||
if (vs)
|
||||
{
|
||||
SetCurrentShader(vs->glprogid);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
VERTEXSHADERUID uid;
|
||||
GetVertexShaderId(&uid, components);
|
||||
|
||||
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
|
||||
{
|
||||
return pShaderLast;
|
||||
}
|
||||
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
|
||||
|
||||
VSCache::iterator iter = vshaders.find(uid);
|
||||
|
||||
if (iter != vshaders.end()) {
|
||||
iter->second.frameCount = frameCount;
|
||||
VSCacheEntry &entry = iter->second;
|
||||
if (&entry.shader != pShaderLast) {
|
||||
pShaderLast = &entry.shader;
|
||||
}
|
||||
|
||||
return pShaderLast;
|
||||
}
|
||||
|
||||
//Make an entry in the table
|
||||
VSCacheEntry& entry = vshaders[uid];
|
||||
entry.frameCount = frameCount;
|
||||
pShaderLast = &entry.shader;
|
||||
const char *code = GenerateVertexShaderCode(components, API_OPENGL);
|
||||
|
||||
#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), counter++);
|
||||
|
||||
SaveData(szTemp, code);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!code || !VertexShaderCache::CompileVertexShader(entry.shader, code)) {
|
||||
ERROR_LOG(VIDEO, "failed to create vertex shader");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INCSTAT(stats.numVertexShadersCreated);
|
||||
SETSTAT(stats.numVertexShadersAlive, vshaders.size());
|
||||
return pShaderLast;
|
||||
}
|
||||
|
||||
bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
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)) {
|
||||
if (s_displayCompileAlert) {
|
||||
PanicAlert("Failed to create vertex shader");
|
||||
s_displayCompileAlert = false;
|
||||
}
|
||||
cgDestroyProgram(tempprog);
|
||||
ERROR_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
|
||||
ERROR_LOG(VIDEO, pstrprogram);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cgGetError() != CG_NO_ERROR)
|
||||
{
|
||||
WARN_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
|
||||
WARN_LOG(VIDEO, 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, pstrprogram);
|
||||
ERROR_LOG(VIDEO, pcompiledprog);
|
||||
}
|
||||
|
||||
cgDestroyProgram(tempprog);
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
vs.strprog = pstrprogram;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VertexShaderCache::DisableShader()
|
||||
{
|
||||
if (ShaderEnabled)
|
||||
{
|
||||
glDisable(GL_VERTEX_PROGRAM_ARB);
|
||||
ShaderEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VertexShaderCache::SetCurrentShader(GLuint Shader)
|
||||
{
|
||||
if (!ShaderEnabled)
|
||||
{
|
||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||
ShaderEnabled= true;
|
||||
}
|
||||
if (CurrentShader != Shader)
|
||||
{
|
||||
if(Shader != 0)
|
||||
CurrentShader = Shader;
|
||||
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// 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 <math.h>
|
||||
|
||||
// Common
|
||||
#include "FileUtil.h"
|
||||
|
||||
// VideoCommon
|
||||
#include "Profiler.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "Statistics.h"
|
||||
#include "VertexShaderGen.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "XFMemory.h"
|
||||
#include "ImageWrite.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_Render.h"
|
||||
#include "OGL_VertexShaderCache.h"
|
||||
#include "OGL_GLUtil.h"
|
||||
#include "OGL_VertexManager.h"
|
||||
|
||||
#include "../Main.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
VertexShaderCache::VSCache VertexShaderCache::vshaders;
|
||||
bool VertexShaderCache::s_displayCompileAlert;
|
||||
GLuint VertexShaderCache::CurrentShader;
|
||||
bool VertexShaderCache::ShaderEnabled;
|
||||
|
||||
static VERTEXSHADER *pShaderLast = NULL;
|
||||
static int s_nMaxVertexInstructions;
|
||||
|
||||
void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
float f[4] = { f1, f2, f3, f4 };
|
||||
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f);
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f);
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++,f+=4)
|
||||
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, f);
|
||||
}
|
||||
|
||||
void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VertexShaderCache::VertexShaderCache()
|
||||
{
|
||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||
ShaderEnabled = true;
|
||||
CurrentShader = 0;
|
||||
memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid));
|
||||
|
||||
s_displayCompileAlert = true;
|
||||
|
||||
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions);
|
||||
#if CG_VERSION_NUM == 2100
|
||||
if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
|
||||
{
|
||||
s_nMaxVertexInstructions = 4096;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
VertexShaderCache::~VertexShaderCache()
|
||||
{
|
||||
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); iter++)
|
||||
iter->second.Destroy();
|
||||
vshaders.clear();
|
||||
}
|
||||
|
||||
bool VertexShaderCache::SetShader(u32 components)
|
||||
{
|
||||
const VERTEXSHADER* const vs = GetShader(components);
|
||||
if (vs)
|
||||
{
|
||||
SetCurrentShader(vs->glprogid);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
VERTEXSHADERUID uid;
|
||||
GetVertexShaderId(&uid, components);
|
||||
|
||||
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
|
||||
{
|
||||
return pShaderLast;
|
||||
}
|
||||
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
|
||||
|
||||
VSCache::iterator iter = vshaders.find(uid);
|
||||
|
||||
if (iter != vshaders.end()) {
|
||||
iter->second.frameCount = frameCount;
|
||||
VSCacheEntry &entry = iter->second;
|
||||
if (&entry.shader != pShaderLast) {
|
||||
pShaderLast = &entry.shader;
|
||||
}
|
||||
|
||||
return pShaderLast;
|
||||
}
|
||||
|
||||
//Make an entry in the table
|
||||
VSCacheEntry& entry = vshaders[uid];
|
||||
entry.frameCount = frameCount;
|
||||
pShaderLast = &entry.shader;
|
||||
const char *code = GenerateVertexShaderCode(components, API_OPENGL);
|
||||
|
||||
#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), counter++);
|
||||
|
||||
SaveData(szTemp, code);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!code || !VertexShaderCache::CompileVertexShader(entry.shader, code)) {
|
||||
ERROR_LOG(VIDEO, "failed to create vertex shader");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INCSTAT(stats.numVertexShadersCreated);
|
||||
SETSTAT(stats.numVertexShadersAlive, vshaders.size());
|
||||
return pShaderLast;
|
||||
}
|
||||
|
||||
bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
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)) {
|
||||
if (s_displayCompileAlert) {
|
||||
PanicAlert("Failed to create vertex shader");
|
||||
s_displayCompileAlert = false;
|
||||
}
|
||||
cgDestroyProgram(tempprog);
|
||||
ERROR_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
|
||||
ERROR_LOG(VIDEO, pstrprogram);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cgGetError() != CG_NO_ERROR)
|
||||
{
|
||||
WARN_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
|
||||
WARN_LOG(VIDEO, 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, pstrprogram);
|
||||
ERROR_LOG(VIDEO, pcompiledprog);
|
||||
}
|
||||
|
||||
cgDestroyProgram(tempprog);
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
vs.strprog = pstrprogram;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VertexShaderCache::DisableShader()
|
||||
{
|
||||
if (ShaderEnabled)
|
||||
{
|
||||
glDisable(GL_VERTEX_PROGRAM_ARB);
|
||||
ShaderEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VertexShaderCache::SetCurrentShader(GLuint Shader)
|
||||
{
|
||||
if (!ShaderEnabled)
|
||||
{
|
||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||
ShaderEnabled= true;
|
||||
}
|
||||
if (CurrentShader != Shader)
|
||||
{
|
||||
if(Shader != 0)
|
||||
CurrentShader = Shader;
|
||||
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,89 +1,89 @@
|
|||
// 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 _OGL_VERTEXSHADERCACHE_H_
|
||||
#define _OGL_VERTEXSHADERCACHE_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
// VideoCommon
|
||||
#include "BPMemory.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_GLUtil.h"
|
||||
|
||||
#include "../VertexShaderCache.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
struct VERTEXSHADER
|
||||
{
|
||||
VERTEXSHADER() : glprogid(0) {}
|
||||
GLuint glprogid; // opengl program id
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string strprog;
|
||||
#endif
|
||||
};
|
||||
|
||||
class VertexShaderCache : public ::VertexShaderCacheBase
|
||||
{
|
||||
struct VSCacheEntry
|
||||
{
|
||||
VERTEXSHADER shader;
|
||||
int frameCount;
|
||||
VSCacheEntry() : frameCount(0) {}
|
||||
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 bool s_displayCompileAlert;
|
||||
|
||||
static GLuint CurrentShader;
|
||||
static bool ShaderEnabled;
|
||||
|
||||
public:
|
||||
VertexShaderCache();
|
||||
~VertexShaderCache();
|
||||
|
||||
bool SetShader(u32 components);
|
||||
|
||||
static VERTEXSHADER* GetShader(u32 components);
|
||||
static bool CompileVertexShader(VERTEXSHADER& ps, const char* pstrprogram);
|
||||
|
||||
static void SetCurrentShader(GLuint Shader);
|
||||
static void DisableShader();
|
||||
|
||||
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetVSConstant4fv(unsigned int const_number, const float* f);
|
||||
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f);
|
||||
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _VERTEXSHADERCACHE_H_
|
||||
// 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 _OGL_VERTEXSHADERCACHE_H_
|
||||
#define _OGL_VERTEXSHADERCACHE_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
// VideoCommon
|
||||
#include "BPMemory.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
// OGL
|
||||
#include "OGL_GLUtil.h"
|
||||
|
||||
#include "../VertexShaderCache.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
struct VERTEXSHADER
|
||||
{
|
||||
VERTEXSHADER() : glprogid(0) {}
|
||||
GLuint glprogid; // opengl program id
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string strprog;
|
||||
#endif
|
||||
};
|
||||
|
||||
class VertexShaderCache : public ::VertexShaderCacheBase
|
||||
{
|
||||
struct VSCacheEntry
|
||||
{
|
||||
VERTEXSHADER shader;
|
||||
int frameCount;
|
||||
VSCacheEntry() : frameCount(0) {}
|
||||
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 bool s_displayCompileAlert;
|
||||
|
||||
static GLuint CurrentShader;
|
||||
static bool ShaderEnabled;
|
||||
|
||||
public:
|
||||
VertexShaderCache();
|
||||
~VertexShaderCache();
|
||||
|
||||
bool SetShader(u32 components);
|
||||
|
||||
static VERTEXSHADER* GetShader(u32 components);
|
||||
static bool CompileVertexShader(VERTEXSHADER& ps, const char* pstrprogram);
|
||||
|
||||
static void SetCurrentShader(GLuint Shader);
|
||||
static void DisableShader();
|
||||
|
||||
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetVSConstant4fv(unsigned int const_number, const float* f);
|
||||
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f);
|
||||
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _VERTEXSHADERCACHE_H_
|
||||
|
|
|
@ -1,42 +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/
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
// This file handles the External Frame Buffer (XFB). The XFB is a storage point when the picture is resized
|
||||
// by the system to the correct display format for output to the TV. In most cases its function can be
|
||||
// supplemented by the equivalent adjustments in glScissor and glViewport (or their DirectX equivalents). But
|
||||
// for some homebrew games these functions are necessary because the homebrew game communicate directly with
|
||||
// them.
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
|
||||
// OGL
|
||||
#include "OGL_Render.h"
|
||||
#include "OGL_TextureConverter.h"
|
||||
#include "OGL_FramebufferManager.h"
|
||||
#include "OGL_XFB.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
void XFB_Write(u8 *xfb_in_ram, const EFBRectangle& sourceRc, u32 dstWd, u32 dstHt)
|
||||
{
|
||||
TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc);
|
||||
TextureConverter::EncodeToRamYUYV(FramebufferManager::ResolveAndGetRenderTarget(sourceRc), targetRc, xfb_in_ram, dstWd, dstHt);
|
||||
}
|
||||
|
||||
}
|
||||
// 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/
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
// This file handles the External Frame Buffer (XFB). The XFB is a storage point when the picture is resized
|
||||
// by the system to the correct display format for output to the TV. In most cases its function can be
|
||||
// supplemented by the equivalent adjustments in glScissor and glViewport (or their DirectX equivalents). But
|
||||
// for some homebrew games these functions are necessary because the homebrew game communicate directly with
|
||||
// them.
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
|
||||
// OGL
|
||||
#include "OGL_Render.h"
|
||||
#include "OGL_TextureConverter.h"
|
||||
#include "OGL_FramebufferManager.h"
|
||||
#include "OGL_XFB.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
void XFB_Write(u8 *xfb_in_ram, const EFBRectangle& sourceRc, u32 dstWd, u32 dstHt)
|
||||
{
|
||||
TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc);
|
||||
TextureConverter::EncodeToRamYUYV(FramebufferManager::ResolveAndGetRenderTarget(sourceRc), targetRc, xfb_in_ram, dstWd, dstHt);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
// 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 _OGL_XFB_H_
|
||||
#define _OGL_XFB_H_
|
||||
|
||||
#include "OGL_GLUtil.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
// write the EFB to the XFB
|
||||
void XFB_Write(u8 *xfb_in_ram, const EFBRectangle& sourceRc, u32 dstWd, u32 dstHt);
|
||||
|
||||
}
|
||||
|
||||
#endif // _XFB_H_
|
||||
// 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 _OGL_XFB_H_
|
||||
#define _OGL_XFB_H_
|
||||
|
||||
#include "OGL_GLUtil.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
// write the EFB to the XFB
|
||||
void XFB_Write(u8 *xfb_in_ram, const EFBRectangle& sourceRc, u32 dstWd, u32 dstHt);
|
||||
|
||||
}
|
||||
|
||||
#endif // _XFB_H_
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
|
||||
#include "PixelShaderManager.h"
|
||||
|
||||
#include "Main.h"
|
||||
#include "PixelShaderCache.h"
|
||||
|
||||
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
g_pixel_shader_cache->SetPSConstant4f(const_number, f1, f2, f3, f4);
|
||||
}
|
||||
|
||||
void SetPSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
g_pixel_shader_cache->SetPSConstant4fv(const_number, f);
|
||||
}
|
||||
|
||||
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
g_pixel_shader_cache->SetMultiPSConstant4fv(const_number, count, f);
|
||||
}
|
||||
|
||||
#include "PixelShaderManager.h"
|
||||
|
||||
#include "Main.h"
|
||||
#include "PixelShaderCache.h"
|
||||
|
||||
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
g_pixel_shader_cache->SetPSConstant4f(const_number, f1, f2, f3, f4);
|
||||
}
|
||||
|
||||
void SetPSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
g_pixel_shader_cache->SetPSConstant4fv(const_number, f);
|
||||
}
|
||||
|
||||
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
g_pixel_shader_cache->SetMultiPSConstant4fv(const_number, count, f);
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
|
||||
#ifndef _PIXELSHADERCACHE_H_
|
||||
#define _PIXELSHADERCACHE_H_
|
||||
|
||||
class PixelShaderCacheBase
|
||||
{
|
||||
public:
|
||||
virtual ~PixelShaderCacheBase() {}
|
||||
|
||||
virtual bool SetShader(bool dstAlphaEnable) = 0;
|
||||
|
||||
virtual void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) = 0;
|
||||
virtual void SetPSConstant4fv(unsigned int const_number, const float *f) = 0;
|
||||
virtual void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _PIXELSHADERCACHE_H_
|
||||
#define _PIXELSHADERCACHE_H_
|
||||
|
||||
class PixelShaderCacheBase
|
||||
{
|
||||
public:
|
||||
virtual ~PixelShaderCacheBase() {}
|
||||
|
||||
virtual bool SetShader(bool dstAlphaEnable) = 0;
|
||||
|
||||
virtual void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) = 0;
|
||||
virtual void SetPSConstant4fv(unsigned int const_number, const float *f) = 0;
|
||||
virtual void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,390 +1,390 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include "Render.h"
|
||||
#include "BPMemory.h"
|
||||
#include "Atomic.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "FramebufferManager.h"
|
||||
|
||||
#include "Fifo.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "DLCache.h"
|
||||
#include "OnScreenDisplay.h"
|
||||
#include "Statistics.h"
|
||||
|
||||
#include "Renderer.h"
|
||||
|
||||
#include "Main.h"
|
||||
|
||||
int RendererBase::s_target_width;
|
||||
int RendererBase::s_target_height;
|
||||
|
||||
int RendererBase::s_Fulltarget_width;
|
||||
int RendererBase::s_Fulltarget_height;
|
||||
|
||||
int RendererBase::s_backbuffer_width;
|
||||
int RendererBase::s_backbuffer_height;
|
||||
|
||||
int RendererBase::s_XFB_width;
|
||||
int RendererBase::s_XFB_height;
|
||||
|
||||
float RendererBase::xScale;
|
||||
float RendererBase::yScale;
|
||||
|
||||
int RendererBase::s_fps;
|
||||
|
||||
u32 RendererBase::s_blendMode;
|
||||
bool RendererBase::XFBWrited;
|
||||
|
||||
float RendererBase::EFBxScale;
|
||||
float RendererBase::EFByScale;
|
||||
|
||||
volatile u32 RendererBase::s_swapRequested;
|
||||
|
||||
//void VideoConfig::UpdateProjectionHack()
|
||||
//{
|
||||
// return;
|
||||
// //::UpdateProjectionHack(g_Config.iPhackvalue);
|
||||
//}
|
||||
|
||||
RendererBase::RendererBase()
|
||||
{
|
||||
UpdateActiveConfig();
|
||||
s_blendMode = 0;
|
||||
|
||||
s_XFB_width = MAX_XFB_WIDTH;
|
||||
s_XFB_height = MAX_XFB_HEIGHT;
|
||||
}
|
||||
|
||||
// can maybe reuse this func in Renderer::Swap to eliminate redundant code
|
||||
void RendererBase::FramebufferSize(int w, int h)
|
||||
{
|
||||
TargetRectangle dst_rect;
|
||||
ComputeDrawRectangle(w, h, false, &dst_rect);
|
||||
|
||||
xScale = (float)(dst_rect.right - dst_rect.left) / (float)s_XFB_width;
|
||||
yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height;
|
||||
|
||||
// TODO: why these, prolly can remove them
|
||||
const int s_LastAA = g_ActiveConfig.iMultisampleMode;
|
||||
const int s_LastEFBScale = g_ActiveConfig.iEFBScale;
|
||||
|
||||
switch (s_LastEFBScale)
|
||||
{
|
||||
case 0:
|
||||
EFBxScale = xScale;
|
||||
EFByScale = yScale;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
EFBxScale = ceilf(xScale);
|
||||
EFByScale = ceilf(yScale);
|
||||
break;
|
||||
|
||||
default:
|
||||
EFByScale = EFBxScale = (g_ActiveConfig.iEFBScale - 1);
|
||||
break;
|
||||
};
|
||||
|
||||
const float SupersampleCoeficient = s_LastAA + 1;
|
||||
EFBxScale *= SupersampleCoeficient;
|
||||
EFByScale *= SupersampleCoeficient;
|
||||
|
||||
s_target_width = (int)(EFB_WIDTH * EFBxScale);
|
||||
s_target_height = (int)(EFB_HEIGHT * EFByScale);
|
||||
|
||||
// TODO: set anything else?
|
||||
s_Fulltarget_width = s_target_width;
|
||||
s_Fulltarget_height = s_target_height;
|
||||
}
|
||||
|
||||
void UpdateViewport()
|
||||
{
|
||||
g_renderer->UpdateViewport();
|
||||
}
|
||||
|
||||
void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
RendererBase::RenderToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||
}
|
||||
|
||||
// whats this for?
|
||||
bool IsD3D()
|
||||
{
|
||||
//PanicAlert("IsD3D!");
|
||||
// TODO: temporary
|
||||
return true;
|
||||
}
|
||||
|
||||
void Renderer::RenderText(const char *pstr, int left, int top, u32 color)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RendererBase::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
if (!fbWidth || !fbHeight)
|
||||
return;
|
||||
|
||||
VideoFifo_CheckEFBAccess();
|
||||
VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight);
|
||||
XFBWrited = true;
|
||||
|
||||
// XXX: Without the VI, how would we know what kind of field this is? So
|
||||
// just use progressive.
|
||||
|
||||
if (g_ActiveConfig.bUseXFB)
|
||||
{
|
||||
g_framebuffer_manager->CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_renderer->Swap(xfbAddr, FIELD_PROGRESSIVE, fbWidth, fbHeight, sourceRc);
|
||||
Common::AtomicStoreRelease(s_swapRequested, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
TargetRectangle RendererBase::ConvertEFBRectangle(const EFBRectangle& rc)
|
||||
{
|
||||
int Xstride = (s_Fulltarget_width - s_target_width) / 2;
|
||||
int Ystride = (s_Fulltarget_height - s_target_height) / 2;
|
||||
TargetRectangle result;
|
||||
result.left = (int)(rc.left * EFBxScale) + Xstride;
|
||||
result.top = (int)(rc.top * EFByScale) + Ystride;
|
||||
result.right = (int)(rc.right * EFBxScale) + Xstride;
|
||||
result.bottom = (int)(rc.bottom * EFByScale) + Ystride;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool RendererBase::SetScissorRect(EFBRectangle &rc)
|
||||
{
|
||||
int xoff = bpmem.scissorOffset.x * 2 - 342;
|
||||
int yoff = bpmem.scissorOffset.y * 2 - 342;
|
||||
|
||||
rc.left = bpmem.scissorTL.x - xoff - 342;
|
||||
rc.top = bpmem.scissorTL.y - yoff - 342;
|
||||
rc.right = bpmem.scissorBR.x - xoff - 341;
|
||||
rc.bottom = bpmem.scissorBR.y - yoff - 341;
|
||||
|
||||
int Xstride = (s_Fulltarget_width - s_target_width) / 2;
|
||||
int Ystride = (s_Fulltarget_height - s_target_height) / 2;
|
||||
|
||||
rc.left = (int)(rc.left * EFBxScale);
|
||||
rc.top = (int)(rc.top * EFByScale);
|
||||
rc.right = (int)(rc.right * EFBxScale);
|
||||
rc.bottom = (int)(rc.bottom * EFByScale);
|
||||
|
||||
if (rc.left < 0) rc.left = 0;
|
||||
if (rc.right < 0) rc.right = 0;
|
||||
if (rc.left > s_target_width) rc.left = s_target_width;
|
||||
if (rc.right > s_target_width) rc.right = s_target_width;
|
||||
if (rc.top < 0) rc.top = 0;
|
||||
if (rc.bottom < 0) rc.bottom = 0;
|
||||
if (rc.top > s_target_height) rc.top = s_target_height;
|
||||
if (rc.bottom > s_target_height) rc.bottom = s_target_height;
|
||||
|
||||
rc.left += Xstride;
|
||||
rc.top += Ystride;
|
||||
rc.right += Xstride;
|
||||
rc.bottom += Ystride;
|
||||
|
||||
if (rc.left > rc.right)
|
||||
{
|
||||
int temp = rc.right;
|
||||
rc.right = rc.left;
|
||||
rc.left = temp;
|
||||
}
|
||||
if (rc.top > rc.bottom)
|
||||
{
|
||||
int temp = rc.bottom;
|
||||
rc.bottom = rc.top;
|
||||
rc.top = temp;
|
||||
}
|
||||
|
||||
return (rc.right >= rc.left && rc.bottom >= rc.top);
|
||||
}
|
||||
|
||||
void RendererBase::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight, const EFBRectangle& rc)
|
||||
{
|
||||
if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.bUseRealXFB) || !fbWidth || !fbHeight)
|
||||
{
|
||||
g_VideoInitialize.pCopiedToXFB(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// this function is called after the XFB field is changed, not after
|
||||
// EFB is copied to XFB. In this way, flickering is reduced in games
|
||||
// and seems to also give more FPS in ZTP
|
||||
|
||||
if (field == FIELD_LOWER)
|
||||
xfbAddr -= fbWidth * 2;
|
||||
u32 xfbCount = 0;
|
||||
const XFBSourceBase** xfbSourceList = g_framebuffer_manager->GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||
|
||||
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
|
||||
{
|
||||
g_VideoInitialize.pCopiedToXFB(false);
|
||||
return;
|
||||
}
|
||||
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
// prepare copying the XFBs to our backbuffer
|
||||
TargetRectangle dst_rect;
|
||||
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
|
||||
|
||||
g_renderer->PrepareXFBCopy(dst_rect);
|
||||
|
||||
if (g_ActiveConfig.bUseXFB)
|
||||
{
|
||||
const XFBSourceBase* xfbSource;
|
||||
|
||||
// draw each xfb source
|
||||
for (u32 i = 0; i < xfbCount; ++i)
|
||||
{
|
||||
xfbSource = xfbSourceList[i];
|
||||
TargetRectangle sourceRc;
|
||||
|
||||
//if (g_ActiveConfig.bAutoScale)
|
||||
//{
|
||||
// sourceRc = xfbSource->sourceRc;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
sourceRc.left = 0;
|
||||
sourceRc.top = 0;
|
||||
sourceRc.right = xfbSource->texWidth;
|
||||
sourceRc.bottom = xfbSource->texHeight;
|
||||
//}
|
||||
|
||||
MathUtil::Rectangle<float> drawRc;
|
||||
|
||||
if (g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
|
||||
{
|
||||
// use virtual xfb with offset
|
||||
int xfbHeight = xfbSource->srcHeight;
|
||||
int xfbWidth = xfbSource->srcWidth;
|
||||
int hOffset = ((s32)xfbSource->srcAddr - (s32)xfbAddr) / ((s32)fbWidth * 2);
|
||||
|
||||
drawRc.bottom = 1.0f - 2.0f * ((hOffset) / (float)fbHeight);
|
||||
drawRc.top = 1.0f - 2.0f * ((hOffset + xfbHeight) / (float)fbHeight);
|
||||
drawRc.left = -(xfbWidth / (float)fbWidth);
|
||||
drawRc.right = (xfbWidth / (float)fbWidth);
|
||||
|
||||
if (!g_ActiveConfig.bAutoScale)
|
||||
{
|
||||
// scale draw area for a 1 to 1 pixel mapping with the draw target
|
||||
float vScale = (float)fbHeight / (float)s_backbuffer_height;
|
||||
float hScale = (float)fbWidth / (float)s_backbuffer_width;
|
||||
|
||||
drawRc.top *= vScale;
|
||||
drawRc.bottom *= vScale;
|
||||
drawRc.left *= hScale;
|
||||
drawRc.right *= hScale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
drawRc.top = -1;
|
||||
drawRc.bottom = 1;
|
||||
drawRc.left = -1;
|
||||
drawRc.right = 1;
|
||||
}
|
||||
|
||||
g_renderer->Draw(xfbSource, sourceRc, drawRc, rc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: organize drawRc stuff
|
||||
MathUtil::Rectangle<float> drawRc;
|
||||
drawRc.top = -1;
|
||||
drawRc.bottom = 1;
|
||||
drawRc.left = -1;
|
||||
drawRc.right = 1;
|
||||
|
||||
const TargetRectangle targetRc = ConvertEFBRectangle(rc);
|
||||
g_renderer->Draw(NULL, targetRc, drawRc, rc);
|
||||
}
|
||||
|
||||
// done with drawing the game stuff, good moment to save a screenshot
|
||||
// TODO: screenshot code
|
||||
//
|
||||
|
||||
// finally present some information
|
||||
// TODO: debug text, fps, etc...
|
||||
//
|
||||
|
||||
OSD::DrawMessages();
|
||||
|
||||
g_renderer->EndFrame();
|
||||
|
||||
++frameCount;
|
||||
|
||||
DLCache::ProgressiveCleanup();
|
||||
g_texture_cache->Cleanup();
|
||||
|
||||
// check for configuration changes
|
||||
const int last_efbscale = g_ActiveConfig.iEFBScale;
|
||||
//const int last_aa = g_ActiveConfig.iMultisampleMode;
|
||||
|
||||
UpdateActiveConfig();
|
||||
|
||||
|
||||
bool window_resized = g_renderer->CheckForResize();
|
||||
|
||||
bool xfbchanged = false;
|
||||
if (s_XFB_width != fbWidth || s_XFB_height != fbHeight)
|
||||
{
|
||||
xfbchanged = true;
|
||||
s_XFB_width = fbWidth;
|
||||
s_XFB_height = fbHeight;
|
||||
if (s_XFB_width < 1) s_XFB_width = MAX_XFB_WIDTH;
|
||||
if (s_XFB_width > MAX_XFB_WIDTH) s_XFB_width = MAX_XFB_WIDTH;
|
||||
if (s_XFB_height < 1) s_XFB_height = MAX_XFB_HEIGHT;
|
||||
if (s_XFB_height > MAX_XFB_HEIGHT) s_XFB_height = MAX_XFB_HEIGHT;
|
||||
}
|
||||
|
||||
// update FPS counter
|
||||
// TODO: make this better
|
||||
static int fpscount = 0;
|
||||
static unsigned long lasttime = 0;
|
||||
if (Common::Timer::GetTimeMs() - lasttime >= 1000)
|
||||
{
|
||||
lasttime = Common::Timer::GetTimeMs();
|
||||
s_fps = fpscount;
|
||||
fpscount = 0;
|
||||
}
|
||||
if (XFBWrited)
|
||||
++fpscount;
|
||||
|
||||
// set default viewport and scissor, for the clear to work correctly
|
||||
stats.ResetFrame();
|
||||
|
||||
// done. Show our work ;)
|
||||
g_renderer->Present();
|
||||
|
||||
// resize the back buffers NOW to avoid flickering when resizing windows
|
||||
if (xfbchanged || window_resized || last_efbscale != g_ActiveConfig.iEFBScale)
|
||||
{
|
||||
g_renderer->GetBackBufferSize(&s_backbuffer_width, &s_backbuffer_height);
|
||||
|
||||
FramebufferSize(s_backbuffer_width, s_backbuffer_height);
|
||||
|
||||
g_renderer->RecreateFramebufferManger();
|
||||
}
|
||||
|
||||
// begin next frame
|
||||
g_renderer->RestoreAPIState();
|
||||
|
||||
g_renderer->BeginFrame();
|
||||
|
||||
g_renderer->UpdateViewport();
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
g_VideoInitialize.pCopiedToXFB(XFBWrited || g_ActiveConfig.bUseRealXFB);
|
||||
XFBWrited = false;
|
||||
}
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include "Render.h"
|
||||
#include "BPMemory.h"
|
||||
#include "Atomic.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "FramebufferManager.h"
|
||||
|
||||
#include "Fifo.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "DLCache.h"
|
||||
#include "OnScreenDisplay.h"
|
||||
#include "Statistics.h"
|
||||
|
||||
#include "Renderer.h"
|
||||
|
||||
#include "Main.h"
|
||||
|
||||
int RendererBase::s_target_width;
|
||||
int RendererBase::s_target_height;
|
||||
|
||||
int RendererBase::s_Fulltarget_width;
|
||||
int RendererBase::s_Fulltarget_height;
|
||||
|
||||
int RendererBase::s_backbuffer_width;
|
||||
int RendererBase::s_backbuffer_height;
|
||||
|
||||
int RendererBase::s_XFB_width;
|
||||
int RendererBase::s_XFB_height;
|
||||
|
||||
float RendererBase::xScale;
|
||||
float RendererBase::yScale;
|
||||
|
||||
int RendererBase::s_fps;
|
||||
|
||||
u32 RendererBase::s_blendMode;
|
||||
bool RendererBase::XFBWrited;
|
||||
|
||||
float RendererBase::EFBxScale;
|
||||
float RendererBase::EFByScale;
|
||||
|
||||
volatile u32 RendererBase::s_swapRequested;
|
||||
|
||||
//void VideoConfig::UpdateProjectionHack()
|
||||
//{
|
||||
// return;
|
||||
// //::UpdateProjectionHack(g_Config.iPhackvalue);
|
||||
//}
|
||||
|
||||
RendererBase::RendererBase()
|
||||
{
|
||||
UpdateActiveConfig();
|
||||
s_blendMode = 0;
|
||||
|
||||
s_XFB_width = MAX_XFB_WIDTH;
|
||||
s_XFB_height = MAX_XFB_HEIGHT;
|
||||
}
|
||||
|
||||
// can maybe reuse this func in Renderer::Swap to eliminate redundant code
|
||||
void RendererBase::FramebufferSize(int w, int h)
|
||||
{
|
||||
TargetRectangle dst_rect;
|
||||
ComputeDrawRectangle(w, h, false, &dst_rect);
|
||||
|
||||
xScale = (float)(dst_rect.right - dst_rect.left) / (float)s_XFB_width;
|
||||
yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height;
|
||||
|
||||
// TODO: why these, prolly can remove them
|
||||
const int s_LastAA = g_ActiveConfig.iMultisampleMode;
|
||||
const int s_LastEFBScale = g_ActiveConfig.iEFBScale;
|
||||
|
||||
switch (s_LastEFBScale)
|
||||
{
|
||||
case 0:
|
||||
EFBxScale = xScale;
|
||||
EFByScale = yScale;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
EFBxScale = ceilf(xScale);
|
||||
EFByScale = ceilf(yScale);
|
||||
break;
|
||||
|
||||
default:
|
||||
EFByScale = EFBxScale = (g_ActiveConfig.iEFBScale - 1);
|
||||
break;
|
||||
};
|
||||
|
||||
const float SupersampleCoeficient = s_LastAA + 1;
|
||||
EFBxScale *= SupersampleCoeficient;
|
||||
EFByScale *= SupersampleCoeficient;
|
||||
|
||||
s_target_width = (int)(EFB_WIDTH * EFBxScale);
|
||||
s_target_height = (int)(EFB_HEIGHT * EFByScale);
|
||||
|
||||
// TODO: set anything else?
|
||||
s_Fulltarget_width = s_target_width;
|
||||
s_Fulltarget_height = s_target_height;
|
||||
}
|
||||
|
||||
void UpdateViewport()
|
||||
{
|
||||
g_renderer->UpdateViewport();
|
||||
}
|
||||
|
||||
void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
RendererBase::RenderToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||
}
|
||||
|
||||
// whats this for?
|
||||
bool IsD3D()
|
||||
{
|
||||
//PanicAlert("IsD3D!");
|
||||
// TODO: temporary
|
||||
return true;
|
||||
}
|
||||
|
||||
void Renderer::RenderText(const char *pstr, int left, int top, u32 color)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RendererBase::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
if (!fbWidth || !fbHeight)
|
||||
return;
|
||||
|
||||
VideoFifo_CheckEFBAccess();
|
||||
VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight);
|
||||
XFBWrited = true;
|
||||
|
||||
// XXX: Without the VI, how would we know what kind of field this is? So
|
||||
// just use progressive.
|
||||
|
||||
if (g_ActiveConfig.bUseXFB)
|
||||
{
|
||||
g_framebuffer_manager->CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_renderer->Swap(xfbAddr, FIELD_PROGRESSIVE, fbWidth, fbHeight, sourceRc);
|
||||
Common::AtomicStoreRelease(s_swapRequested, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
TargetRectangle RendererBase::ConvertEFBRectangle(const EFBRectangle& rc)
|
||||
{
|
||||
int Xstride = (s_Fulltarget_width - s_target_width) / 2;
|
||||
int Ystride = (s_Fulltarget_height - s_target_height) / 2;
|
||||
TargetRectangle result;
|
||||
result.left = (int)(rc.left * EFBxScale) + Xstride;
|
||||
result.top = (int)(rc.top * EFByScale) + Ystride;
|
||||
result.right = (int)(rc.right * EFBxScale) + Xstride;
|
||||
result.bottom = (int)(rc.bottom * EFByScale) + Ystride;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool RendererBase::SetScissorRect(EFBRectangle &rc)
|
||||
{
|
||||
int xoff = bpmem.scissorOffset.x * 2 - 342;
|
||||
int yoff = bpmem.scissorOffset.y * 2 - 342;
|
||||
|
||||
rc.left = bpmem.scissorTL.x - xoff - 342;
|
||||
rc.top = bpmem.scissorTL.y - yoff - 342;
|
||||
rc.right = bpmem.scissorBR.x - xoff - 341;
|
||||
rc.bottom = bpmem.scissorBR.y - yoff - 341;
|
||||
|
||||
int Xstride = (s_Fulltarget_width - s_target_width) / 2;
|
||||
int Ystride = (s_Fulltarget_height - s_target_height) / 2;
|
||||
|
||||
rc.left = (int)(rc.left * EFBxScale);
|
||||
rc.top = (int)(rc.top * EFByScale);
|
||||
rc.right = (int)(rc.right * EFBxScale);
|
||||
rc.bottom = (int)(rc.bottom * EFByScale);
|
||||
|
||||
if (rc.left < 0) rc.left = 0;
|
||||
if (rc.right < 0) rc.right = 0;
|
||||
if (rc.left > s_target_width) rc.left = s_target_width;
|
||||
if (rc.right > s_target_width) rc.right = s_target_width;
|
||||
if (rc.top < 0) rc.top = 0;
|
||||
if (rc.bottom < 0) rc.bottom = 0;
|
||||
if (rc.top > s_target_height) rc.top = s_target_height;
|
||||
if (rc.bottom > s_target_height) rc.bottom = s_target_height;
|
||||
|
||||
rc.left += Xstride;
|
||||
rc.top += Ystride;
|
||||
rc.right += Xstride;
|
||||
rc.bottom += Ystride;
|
||||
|
||||
if (rc.left > rc.right)
|
||||
{
|
||||
int temp = rc.right;
|
||||
rc.right = rc.left;
|
||||
rc.left = temp;
|
||||
}
|
||||
if (rc.top > rc.bottom)
|
||||
{
|
||||
int temp = rc.bottom;
|
||||
rc.bottom = rc.top;
|
||||
rc.top = temp;
|
||||
}
|
||||
|
||||
return (rc.right >= rc.left && rc.bottom >= rc.top);
|
||||
}
|
||||
|
||||
void RendererBase::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight, const EFBRectangle& rc)
|
||||
{
|
||||
if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.bUseRealXFB) || !fbWidth || !fbHeight)
|
||||
{
|
||||
g_VideoInitialize.pCopiedToXFB(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// this function is called after the XFB field is changed, not after
|
||||
// EFB is copied to XFB. In this way, flickering is reduced in games
|
||||
// and seems to also give more FPS in ZTP
|
||||
|
||||
if (field == FIELD_LOWER)
|
||||
xfbAddr -= fbWidth * 2;
|
||||
u32 xfbCount = 0;
|
||||
const XFBSourceBase** xfbSourceList = g_framebuffer_manager->GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||
|
||||
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
|
||||
{
|
||||
g_VideoInitialize.pCopiedToXFB(false);
|
||||
return;
|
||||
}
|
||||
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
// prepare copying the XFBs to our backbuffer
|
||||
TargetRectangle dst_rect;
|
||||
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
|
||||
|
||||
g_renderer->PrepareXFBCopy(dst_rect);
|
||||
|
||||
if (g_ActiveConfig.bUseXFB)
|
||||
{
|
||||
const XFBSourceBase* xfbSource;
|
||||
|
||||
// draw each xfb source
|
||||
for (u32 i = 0; i < xfbCount; ++i)
|
||||
{
|
||||
xfbSource = xfbSourceList[i];
|
||||
TargetRectangle sourceRc;
|
||||
|
||||
//if (g_ActiveConfig.bAutoScale)
|
||||
//{
|
||||
// sourceRc = xfbSource->sourceRc;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
sourceRc.left = 0;
|
||||
sourceRc.top = 0;
|
||||
sourceRc.right = xfbSource->texWidth;
|
||||
sourceRc.bottom = xfbSource->texHeight;
|
||||
//}
|
||||
|
||||
MathUtil::Rectangle<float> drawRc;
|
||||
|
||||
if (g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
|
||||
{
|
||||
// use virtual xfb with offset
|
||||
int xfbHeight = xfbSource->srcHeight;
|
||||
int xfbWidth = xfbSource->srcWidth;
|
||||
int hOffset = ((s32)xfbSource->srcAddr - (s32)xfbAddr) / ((s32)fbWidth * 2);
|
||||
|
||||
drawRc.bottom = 1.0f - 2.0f * ((hOffset) / (float)fbHeight);
|
||||
drawRc.top = 1.0f - 2.0f * ((hOffset + xfbHeight) / (float)fbHeight);
|
||||
drawRc.left = -(xfbWidth / (float)fbWidth);
|
||||
drawRc.right = (xfbWidth / (float)fbWidth);
|
||||
|
||||
if (!g_ActiveConfig.bAutoScale)
|
||||
{
|
||||
// scale draw area for a 1 to 1 pixel mapping with the draw target
|
||||
float vScale = (float)fbHeight / (float)s_backbuffer_height;
|
||||
float hScale = (float)fbWidth / (float)s_backbuffer_width;
|
||||
|
||||
drawRc.top *= vScale;
|
||||
drawRc.bottom *= vScale;
|
||||
drawRc.left *= hScale;
|
||||
drawRc.right *= hScale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
drawRc.top = -1;
|
||||
drawRc.bottom = 1;
|
||||
drawRc.left = -1;
|
||||
drawRc.right = 1;
|
||||
}
|
||||
|
||||
g_renderer->Draw(xfbSource, sourceRc, drawRc, rc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: organize drawRc stuff
|
||||
MathUtil::Rectangle<float> drawRc;
|
||||
drawRc.top = -1;
|
||||
drawRc.bottom = 1;
|
||||
drawRc.left = -1;
|
||||
drawRc.right = 1;
|
||||
|
||||
const TargetRectangle targetRc = ConvertEFBRectangle(rc);
|
||||
g_renderer->Draw(NULL, targetRc, drawRc, rc);
|
||||
}
|
||||
|
||||
// done with drawing the game stuff, good moment to save a screenshot
|
||||
// TODO: screenshot code
|
||||
//
|
||||
|
||||
// finally present some information
|
||||
// TODO: debug text, fps, etc...
|
||||
//
|
||||
|
||||
OSD::DrawMessages();
|
||||
|
||||
g_renderer->EndFrame();
|
||||
|
||||
++frameCount;
|
||||
|
||||
DLCache::ProgressiveCleanup();
|
||||
g_texture_cache->Cleanup();
|
||||
|
||||
// check for configuration changes
|
||||
const int last_efbscale = g_ActiveConfig.iEFBScale;
|
||||
//const int last_aa = g_ActiveConfig.iMultisampleMode;
|
||||
|
||||
UpdateActiveConfig();
|
||||
|
||||
|
||||
bool window_resized = g_renderer->CheckForResize();
|
||||
|
||||
bool xfbchanged = false;
|
||||
if (s_XFB_width != fbWidth || s_XFB_height != fbHeight)
|
||||
{
|
||||
xfbchanged = true;
|
||||
s_XFB_width = fbWidth;
|
||||
s_XFB_height = fbHeight;
|
||||
if (s_XFB_width < 1) s_XFB_width = MAX_XFB_WIDTH;
|
||||
if (s_XFB_width > MAX_XFB_WIDTH) s_XFB_width = MAX_XFB_WIDTH;
|
||||
if (s_XFB_height < 1) s_XFB_height = MAX_XFB_HEIGHT;
|
||||
if (s_XFB_height > MAX_XFB_HEIGHT) s_XFB_height = MAX_XFB_HEIGHT;
|
||||
}
|
||||
|
||||
// update FPS counter
|
||||
// TODO: make this better
|
||||
static int fpscount = 0;
|
||||
static unsigned long lasttime = 0;
|
||||
if (Common::Timer::GetTimeMs() - lasttime >= 1000)
|
||||
{
|
||||
lasttime = Common::Timer::GetTimeMs();
|
||||
s_fps = fpscount;
|
||||
fpscount = 0;
|
||||
}
|
||||
if (XFBWrited)
|
||||
++fpscount;
|
||||
|
||||
// set default viewport and scissor, for the clear to work correctly
|
||||
stats.ResetFrame();
|
||||
|
||||
// done. Show our work ;)
|
||||
g_renderer->Present();
|
||||
|
||||
// resize the back buffers NOW to avoid flickering when resizing windows
|
||||
if (xfbchanged || window_resized || last_efbscale != g_ActiveConfig.iEFBScale)
|
||||
{
|
||||
g_renderer->GetBackBufferSize(&s_backbuffer_width, &s_backbuffer_height);
|
||||
|
||||
FramebufferSize(s_backbuffer_width, s_backbuffer_height);
|
||||
|
||||
g_renderer->RecreateFramebufferManger();
|
||||
}
|
||||
|
||||
// begin next frame
|
||||
g_renderer->RestoreAPIState();
|
||||
|
||||
g_renderer->BeginFrame();
|
||||
|
||||
g_renderer->UpdateViewport();
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
g_VideoInitialize.pCopiedToXFB(XFBWrited || g_ActiveConfig.bUseRealXFB);
|
||||
XFBWrited = false;
|
||||
}
|
||||
|
|
|
@ -1,99 +1,99 @@
|
|||
|
||||
#ifndef _RENDER_H_
|
||||
#define _RENDER_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "CommonTypes.h"
|
||||
#include "FramebufferManager.h"
|
||||
|
||||
class RendererBase
|
||||
{
|
||||
public:
|
||||
RendererBase();
|
||||
virtual ~RendererBase() {}
|
||||
|
||||
static void FramebufferSize(int w, int h);
|
||||
|
||||
static void RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
|
||||
virtual u32 AccessEFB(EFBAccessType type, int x, int y) = 0;
|
||||
|
||||
static void Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc);
|
||||
|
||||
// virtual funcs used in Swap()
|
||||
virtual void PrepareXFBCopy(const TargetRectangle &dst_rect) = 0;
|
||||
virtual void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
|
||||
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc) = 0;
|
||||
virtual void EndFrame() = 0;
|
||||
virtual void Present() = 0;
|
||||
virtual bool CheckForResize() = 0;
|
||||
virtual void GetBackBufferSize(int* w, int* h) = 0;
|
||||
virtual void RecreateFramebufferManger() = 0;
|
||||
virtual void BeginFrame() = 0;
|
||||
|
||||
// hmm
|
||||
virtual bool SetScissorRect() = 0;
|
||||
static bool SetScissorRect(EFBRectangle &rc);
|
||||
|
||||
static TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc);
|
||||
|
||||
virtual void UpdateViewport() = 0;
|
||||
virtual void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) = 0;
|
||||
|
||||
virtual void ResetAPIState() = 0;
|
||||
virtual void RestoreAPIState() = 0;
|
||||
|
||||
static int GetTargetWidth() { return s_target_width; }
|
||||
static int GetTargetHeight() { return s_target_height; }
|
||||
static int GetFullTargetWidth() { return s_Fulltarget_width; }
|
||||
static int GetFullTargetHeight() { return s_Fulltarget_height; }
|
||||
static float GetTargetScaleX() { return EFBxScale; }
|
||||
static float GetTargetScaleY() { return EFByScale; }
|
||||
static int GetFrameBufferWidth() { return s_backbuffer_width; }
|
||||
static int GetFrameBufferHeight() { return s_backbuffer_height; }
|
||||
static float GetXFBScaleX() { return xScale; }
|
||||
static float GetXFBScaleY() { return yScale; }
|
||||
|
||||
virtual void SetColorMask() {}
|
||||
virtual void SetBlendMode(bool forceUpdate) {}
|
||||
virtual void SetSamplerState(int stage, int texindex) {}
|
||||
virtual void SetDitherMode() {}
|
||||
virtual void SetLineWidth() {}
|
||||
virtual void SetInterlacingMode() {}
|
||||
virtual void SetGenerationMode() = 0;
|
||||
virtual void SetDepthMode() = 0;
|
||||
virtual void SetLogicOpMode() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
// TODO: are all of these needed?
|
||||
static int s_target_width;
|
||||
static int s_target_height;
|
||||
|
||||
static int s_Fulltarget_width;
|
||||
static int s_Fulltarget_height;
|
||||
|
||||
static int s_backbuffer_width;
|
||||
static int s_backbuffer_height;
|
||||
//
|
||||
|
||||
static int s_fps;
|
||||
|
||||
static u32 s_blendMode;
|
||||
static bool XFBWrited;
|
||||
|
||||
// these go with the settings in the GUI 1x,2x,3x,etc
|
||||
static float EFBxScale;
|
||||
static float EFByScale;
|
||||
// these seem be the fractional value
|
||||
// TODO: are these ones needed?
|
||||
static float xScale;
|
||||
static float yScale;
|
||||
|
||||
static int s_XFB_width;
|
||||
static int s_XFB_height;
|
||||
|
||||
static volatile u32 s_swapRequested;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _RENDER_H_
|
||||
#define _RENDER_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "CommonTypes.h"
|
||||
#include "FramebufferManager.h"
|
||||
|
||||
class RendererBase
|
||||
{
|
||||
public:
|
||||
RendererBase();
|
||||
virtual ~RendererBase() {}
|
||||
|
||||
static void FramebufferSize(int w, int h);
|
||||
|
||||
static void RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||
|
||||
virtual u32 AccessEFB(EFBAccessType type, int x, int y) = 0;
|
||||
|
||||
static void Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc);
|
||||
|
||||
// virtual funcs used in Swap()
|
||||
virtual void PrepareXFBCopy(const TargetRectangle &dst_rect) = 0;
|
||||
virtual void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
|
||||
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc) = 0;
|
||||
virtual void EndFrame() = 0;
|
||||
virtual void Present() = 0;
|
||||
virtual bool CheckForResize() = 0;
|
||||
virtual void GetBackBufferSize(int* w, int* h) = 0;
|
||||
virtual void RecreateFramebufferManger() = 0;
|
||||
virtual void BeginFrame() = 0;
|
||||
|
||||
// hmm
|
||||
virtual bool SetScissorRect() = 0;
|
||||
static bool SetScissorRect(EFBRectangle &rc);
|
||||
|
||||
static TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc);
|
||||
|
||||
virtual void UpdateViewport() = 0;
|
||||
virtual void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) = 0;
|
||||
|
||||
virtual void ResetAPIState() = 0;
|
||||
virtual void RestoreAPIState() = 0;
|
||||
|
||||
static int GetTargetWidth() { return s_target_width; }
|
||||
static int GetTargetHeight() { return s_target_height; }
|
||||
static int GetFullTargetWidth() { return s_Fulltarget_width; }
|
||||
static int GetFullTargetHeight() { return s_Fulltarget_height; }
|
||||
static float GetTargetScaleX() { return EFBxScale; }
|
||||
static float GetTargetScaleY() { return EFByScale; }
|
||||
static int GetFrameBufferWidth() { return s_backbuffer_width; }
|
||||
static int GetFrameBufferHeight() { return s_backbuffer_height; }
|
||||
static float GetXFBScaleX() { return xScale; }
|
||||
static float GetXFBScaleY() { return yScale; }
|
||||
|
||||
virtual void SetColorMask() {}
|
||||
virtual void SetBlendMode(bool forceUpdate) {}
|
||||
virtual void SetSamplerState(int stage, int texindex) {}
|
||||
virtual void SetDitherMode() {}
|
||||
virtual void SetLineWidth() {}
|
||||
virtual void SetInterlacingMode() {}
|
||||
virtual void SetGenerationMode() = 0;
|
||||
virtual void SetDepthMode() = 0;
|
||||
virtual void SetLogicOpMode() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
// TODO: are all of these needed?
|
||||
static int s_target_width;
|
||||
static int s_target_height;
|
||||
|
||||
static int s_Fulltarget_width;
|
||||
static int s_Fulltarget_height;
|
||||
|
||||
static int s_backbuffer_width;
|
||||
static int s_backbuffer_height;
|
||||
//
|
||||
|
||||
static int s_fps;
|
||||
|
||||
static u32 s_blendMode;
|
||||
static bool XFBWrited;
|
||||
|
||||
// these go with the settings in the GUI 1x,2x,3x,etc
|
||||
static float EFBxScale;
|
||||
static float EFByScale;
|
||||
// these seem be the fractional value
|
||||
// TODO: are these ones needed?
|
||||
static float xScale;
|
||||
static float yScale;
|
||||
|
||||
static int s_XFB_width;
|
||||
static int s_XFB_height;
|
||||
|
||||
static volatile u32 s_swapRequested;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,80 +1,80 @@
|
|||
|
||||
#ifndef _TEXTURECACHE_H_
|
||||
#define _TEXTURECACHE_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "CommonTypes.h"
|
||||
#include "VideoCommon.h"
|
||||
#include "TextureDecoder.h"
|
||||
|
||||
unsigned int GetPow2(unsigned int val);
|
||||
|
||||
class TextureCacheBase
|
||||
{
|
||||
public:
|
||||
struct TCacheEntryBase
|
||||
{
|
||||
u32 addr;
|
||||
u32 size_in_bytes;
|
||||
u64 hash;
|
||||
u32 paletteHash;
|
||||
u32 oldpixel;
|
||||
|
||||
int frameCount;
|
||||
unsigned int w, h, fmt, MipLevels;
|
||||
int Scaledw, Scaledh;
|
||||
|
||||
bool isRenderTarget;
|
||||
bool isNonPow2;
|
||||
|
||||
TCacheEntryBase() : addr(0), size_in_bytes(0), hash(0), paletteHash(0), oldpixel(0),
|
||||
frameCount(0), w(0), h(0), fmt(0), MipLevels(0), Scaledw(0), Scaledh(0),
|
||||
isRenderTarget(false), isNonPow2(true) {}
|
||||
|
||||
virtual ~TCacheEntryBase();
|
||||
|
||||
virtual void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int levels) = 0;
|
||||
|
||||
virtual void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect) = 0;
|
||||
|
||||
virtual void Bind(unsigned int stage) = 0;
|
||||
|
||||
bool IntersectsMemoryRange(u32 range_address, u32 range_size) const;
|
||||
};
|
||||
|
||||
friend struct TCacheEntryBase;
|
||||
|
||||
TextureCacheBase();
|
||||
virtual ~TextureCacheBase();
|
||||
|
||||
static void Cleanup();
|
||||
|
||||
static void Invalidate(bool shutdown);
|
||||
static void InvalidateRange(u32 start_address, u32 size);
|
||||
|
||||
// TODO: make these 2 static?
|
||||
TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width,
|
||||
unsigned int height, unsigned int tex_format, unsigned int tlutaddr,
|
||||
unsigned int tlutfmt, bool UseNativeMips, unsigned int maxlevel);
|
||||
|
||||
void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
|
||||
u32 copyfmt, bool bScaleByHalf, const EFBRectangle &source_rect);
|
||||
|
||||
virtual TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt) = 0;
|
||||
|
||||
virtual TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h) = 0;
|
||||
|
||||
static void ClearRenderTargets();
|
||||
static void MakeRangeDynamic(u32 start_address, u32 size);
|
||||
|
||||
protected:
|
||||
typedef std::map<u32, TCacheEntryBase*> TexCache;
|
||||
static TexCache textures;
|
||||
static u8 *temp;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _TEXTURECACHE_H_
|
||||
#define _TEXTURECACHE_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "CommonTypes.h"
|
||||
#include "VideoCommon.h"
|
||||
#include "TextureDecoder.h"
|
||||
|
||||
unsigned int GetPow2(unsigned int val);
|
||||
|
||||
class TextureCacheBase
|
||||
{
|
||||
public:
|
||||
struct TCacheEntryBase
|
||||
{
|
||||
u32 addr;
|
||||
u32 size_in_bytes;
|
||||
u64 hash;
|
||||
u32 paletteHash;
|
||||
u32 oldpixel;
|
||||
|
||||
int frameCount;
|
||||
unsigned int w, h, fmt, MipLevels;
|
||||
int Scaledw, Scaledh;
|
||||
|
||||
bool isRenderTarget;
|
||||
bool isNonPow2;
|
||||
|
||||
TCacheEntryBase() : addr(0), size_in_bytes(0), hash(0), paletteHash(0), oldpixel(0),
|
||||
frameCount(0), w(0), h(0), fmt(0), MipLevels(0), Scaledw(0), Scaledh(0),
|
||||
isRenderTarget(false), isNonPow2(true) {}
|
||||
|
||||
virtual ~TCacheEntryBase();
|
||||
|
||||
virtual void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int levels) = 0;
|
||||
|
||||
virtual void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
|
||||
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect) = 0;
|
||||
|
||||
virtual void Bind(unsigned int stage) = 0;
|
||||
|
||||
bool IntersectsMemoryRange(u32 range_address, u32 range_size) const;
|
||||
};
|
||||
|
||||
friend struct TCacheEntryBase;
|
||||
|
||||
TextureCacheBase();
|
||||
virtual ~TextureCacheBase();
|
||||
|
||||
static void Cleanup();
|
||||
|
||||
static void Invalidate(bool shutdown);
|
||||
static void InvalidateRange(u32 start_address, u32 size);
|
||||
|
||||
// TODO: make these 2 static?
|
||||
TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width,
|
||||
unsigned int height, unsigned int tex_format, unsigned int tlutaddr,
|
||||
unsigned int tlutfmt, bool UseNativeMips, unsigned int maxlevel);
|
||||
|
||||
void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
|
||||
u32 copyfmt, bool bScaleByHalf, const EFBRectangle &source_rect);
|
||||
|
||||
virtual TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt) = 0;
|
||||
|
||||
virtual TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h) = 0;
|
||||
|
||||
static void ClearRenderTargets();
|
||||
static void MakeRangeDynamic(u32 start_address, u32 size);
|
||||
|
||||
protected:
|
||||
typedef std::map<u32, TCacheEntryBase*> TexCache;
|
||||
static TexCache textures;
|
||||
static u8 *temp;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,268 +1,268 @@
|
|||
|
||||
// VideoCommon
|
||||
|
||||
#include "CommonTypes.h"
|
||||
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "Profiler.h"
|
||||
|
||||
//
|
||||
#include "TextureCache.h"
|
||||
#include "VertexManager.h"
|
||||
#include "Main.h"
|
||||
|
||||
u16* VertexManagerBase::TIBuffer;
|
||||
u16* VertexManagerBase::LIBuffer;
|
||||
u16* VertexManagerBase::PIBuffer;
|
||||
bool VertexManagerBase::Flushed;
|
||||
|
||||
int VertexManagerBase::lastPrimitive;
|
||||
u8* VertexManagerBase::LocalVBuffer;
|
||||
|
||||
// TODO: put this in .h perhaps
|
||||
extern NativeVertexFormat* g_nativeVertexFmt;
|
||||
|
||||
NativeVertexFormat* NativeVertexFormat::Create()
|
||||
{
|
||||
return g_vertex_manager->CreateNativeVertexFormat();
|
||||
}
|
||||
|
||||
void VertexManagerBase::ResetBuffer()
|
||||
{
|
||||
s_pCurBufferPointer = LocalVBuffer;
|
||||
}
|
||||
|
||||
VertexManagerBase::VertexManagerBase()
|
||||
{
|
||||
LocalVBuffer = new u8[MAXVBUFFERSIZE];
|
||||
TIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
LIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
PIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
|
||||
s_pCurBufferPointer = LocalVBuffer;
|
||||
s_pBaseBufferPointer = LocalVBuffer;
|
||||
|
||||
Flushed = false;
|
||||
|
||||
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
|
||||
}
|
||||
|
||||
VertexManagerBase::~VertexManagerBase()
|
||||
{
|
||||
delete[] LocalVBuffer;
|
||||
delete[] TIBuffer;
|
||||
delete[] LIBuffer;
|
||||
delete[] PIBuffer;
|
||||
|
||||
// most likely not needed
|
||||
ResetBuffer();
|
||||
}
|
||||
|
||||
void VertexManagerBase::AddIndices(int _primitive, int _numVertices)
|
||||
{
|
||||
switch (_primitive)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
IndexGenerator::AddQuads(_numVertices);
|
||||
break;
|
||||
|
||||
case GX_DRAW_TRIANGLES:
|
||||
IndexGenerator::AddList(_numVertices);
|
||||
break;
|
||||
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
IndexGenerator::AddStrip(_numVertices);
|
||||
break;
|
||||
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
IndexGenerator::AddFan(_numVertices);
|
||||
break;
|
||||
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
IndexGenerator::AddLineStrip(_numVertices);
|
||||
break;
|
||||
|
||||
case GX_DRAW_LINES:
|
||||
IndexGenerator::AddLineList(_numVertices);
|
||||
break;
|
||||
|
||||
case GX_DRAW_POINTS:
|
||||
IndexGenerator::AddPoints(_numVertices);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int VertexManager::GetRemainingSize()
|
||||
{
|
||||
return VertexManagerBase::GetRemainingSize();
|
||||
}
|
||||
|
||||
int VertexManagerBase::GetRemainingSize()
|
||||
{
|
||||
return MAXVBUFFERSIZE - (int)(s_pCurBufferPointer - LocalVBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VertexManagerBase::GetRemainingVertices(int primitive)
|
||||
{
|
||||
switch (primitive)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
case GX_DRAW_TRIANGLES:
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3;
|
||||
break;
|
||||
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
case GX_DRAW_LINES:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2;
|
||||
break;
|
||||
|
||||
case GX_DRAW_POINTS:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen());
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexManager::AddVertices(int _primitive, int _numVertices)
|
||||
{
|
||||
VertexManagerBase::AddVertices(_primitive, _numVertices);
|
||||
}
|
||||
|
||||
void VertexManagerBase::AddVertices(int _primitive, int _numVertices)
|
||||
{
|
||||
if (_numVertices <= 0)
|
||||
return;
|
||||
|
||||
switch (_primitive)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
case GX_DRAW_TRIANGLES:
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen() < 3 * _numVertices)
|
||||
g_vertex_manager->Flush();
|
||||
break;
|
||||
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
case GX_DRAW_LINES:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen() < 2 * _numVertices)
|
||||
g_vertex_manager->Flush();
|
||||
break;
|
||||
|
||||
case GX_DRAW_POINTS:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen() < _numVertices)
|
||||
g_vertex_manager->Flush();
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Flushed)
|
||||
{
|
||||
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
|
||||
Flushed = false;
|
||||
}
|
||||
|
||||
lastPrimitive = _primitive;
|
||||
ADDSTAT(stats.thisFrame.numPrims, _numVertices);
|
||||
INCSTAT(stats.thisFrame.numPrimitiveJoins);
|
||||
AddIndices(_primitive, _numVertices);
|
||||
}
|
||||
|
||||
void VertexManager::Flush()
|
||||
{
|
||||
VertexManagerBase::Flush();
|
||||
}
|
||||
|
||||
void VertexManagerBase::Flush()
|
||||
{
|
||||
if (LocalVBuffer == s_pCurBufferPointer)
|
||||
return;
|
||||
|
||||
if (Flushed)
|
||||
return;
|
||||
|
||||
Flushed = true;
|
||||
|
||||
VideoFifo_CheckEFBAccess();
|
||||
|
||||
DVSTARTPROFILE();
|
||||
|
||||
u32 usedtextures = 0;
|
||||
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i)
|
||||
{
|
||||
if (bpmem.tevorders[i/2].getEnable(i & 1))
|
||||
usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1);
|
||||
}
|
||||
|
||||
if (bpmem.genMode.numindstages > 0)
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numtevstages + 1; ++i)
|
||||
if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages)
|
||||
usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt);
|
||||
|
||||
for (unsigned int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (usedtextures & (1 << i))
|
||||
{
|
||||
g_renderer->SetSamplerState(i & 3, i >> 2);
|
||||
|
||||
FourTexUnits &tex = bpmem.tex[i >> 2];
|
||||
|
||||
TextureCacheBase::TCacheEntryBase* tentry = g_texture_cache->Load(i,
|
||||
(tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5,
|
||||
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
|
||||
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
|
||||
tex.texTlut[i&3].tlut_format,
|
||||
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8) && g_ActiveConfig.bUseNativeMips,
|
||||
(tex.texMode1[i&3].max_lod >> 4));
|
||||
|
||||
if (tentry)
|
||||
PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "error loading texture");
|
||||
}
|
||||
}
|
||||
|
||||
VertexShaderManager::SetConstants();
|
||||
PixelShaderManager::SetConstants();
|
||||
|
||||
if (false == g_pixel_shader_cache->SetShader(false))
|
||||
goto shader_fail;
|
||||
|
||||
if (false == g_vertex_shader_cache->SetShader(g_nativeVertexFmt->m_components))
|
||||
goto shader_fail;
|
||||
|
||||
const unsigned int stride = g_nativeVertexFmt->GetVertexStride();
|
||||
g_nativeVertexFmt->SetupVertexPointers();
|
||||
|
||||
// TODO:
|
||||
g_vertex_manager->Draw(stride, false);
|
||||
|
||||
if (false == g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate)
|
||||
{
|
||||
if (false == g_pixel_shader_cache->SetShader(true))
|
||||
goto shader_fail;
|
||||
|
||||
// update alpha only
|
||||
g_vertex_manager->Draw(stride, true);
|
||||
}
|
||||
|
||||
//IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
|
||||
|
||||
shader_fail:
|
||||
ResetBuffer();
|
||||
}
|
||||
|
||||
// VideoCommon
|
||||
|
||||
#include "CommonTypes.h"
|
||||
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "Profiler.h"
|
||||
|
||||
//
|
||||
#include "TextureCache.h"
|
||||
#include "VertexManager.h"
|
||||
#include "Main.h"
|
||||
|
||||
u16* VertexManagerBase::TIBuffer;
|
||||
u16* VertexManagerBase::LIBuffer;
|
||||
u16* VertexManagerBase::PIBuffer;
|
||||
bool VertexManagerBase::Flushed;
|
||||
|
||||
int VertexManagerBase::lastPrimitive;
|
||||
u8* VertexManagerBase::LocalVBuffer;
|
||||
|
||||
// TODO: put this in .h perhaps
|
||||
extern NativeVertexFormat* g_nativeVertexFmt;
|
||||
|
||||
NativeVertexFormat* NativeVertexFormat::Create()
|
||||
{
|
||||
return g_vertex_manager->CreateNativeVertexFormat();
|
||||
}
|
||||
|
||||
void VertexManagerBase::ResetBuffer()
|
||||
{
|
||||
s_pCurBufferPointer = LocalVBuffer;
|
||||
}
|
||||
|
||||
VertexManagerBase::VertexManagerBase()
|
||||
{
|
||||
LocalVBuffer = new u8[MAXVBUFFERSIZE];
|
||||
TIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
LIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
PIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
|
||||
s_pCurBufferPointer = LocalVBuffer;
|
||||
s_pBaseBufferPointer = LocalVBuffer;
|
||||
|
||||
Flushed = false;
|
||||
|
||||
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
|
||||
}
|
||||
|
||||
VertexManagerBase::~VertexManagerBase()
|
||||
{
|
||||
delete[] LocalVBuffer;
|
||||
delete[] TIBuffer;
|
||||
delete[] LIBuffer;
|
||||
delete[] PIBuffer;
|
||||
|
||||
// most likely not needed
|
||||
ResetBuffer();
|
||||
}
|
||||
|
||||
void VertexManagerBase::AddIndices(int _primitive, int _numVertices)
|
||||
{
|
||||
switch (_primitive)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
IndexGenerator::AddQuads(_numVertices);
|
||||
break;
|
||||
|
||||
case GX_DRAW_TRIANGLES:
|
||||
IndexGenerator::AddList(_numVertices);
|
||||
break;
|
||||
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
IndexGenerator::AddStrip(_numVertices);
|
||||
break;
|
||||
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
IndexGenerator::AddFan(_numVertices);
|
||||
break;
|
||||
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
IndexGenerator::AddLineStrip(_numVertices);
|
||||
break;
|
||||
|
||||
case GX_DRAW_LINES:
|
||||
IndexGenerator::AddLineList(_numVertices);
|
||||
break;
|
||||
|
||||
case GX_DRAW_POINTS:
|
||||
IndexGenerator::AddPoints(_numVertices);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int VertexManager::GetRemainingSize()
|
||||
{
|
||||
return VertexManagerBase::GetRemainingSize();
|
||||
}
|
||||
|
||||
int VertexManagerBase::GetRemainingSize()
|
||||
{
|
||||
return MAXVBUFFERSIZE - (int)(s_pCurBufferPointer - LocalVBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VertexManagerBase::GetRemainingVertices(int primitive)
|
||||
{
|
||||
switch (primitive)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
case GX_DRAW_TRIANGLES:
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3;
|
||||
break;
|
||||
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
case GX_DRAW_LINES:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2;
|
||||
break;
|
||||
|
||||
case GX_DRAW_POINTS:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen());
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexManager::AddVertices(int _primitive, int _numVertices)
|
||||
{
|
||||
VertexManagerBase::AddVertices(_primitive, _numVertices);
|
||||
}
|
||||
|
||||
void VertexManagerBase::AddVertices(int _primitive, int _numVertices)
|
||||
{
|
||||
if (_numVertices <= 0)
|
||||
return;
|
||||
|
||||
switch (_primitive)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
case GX_DRAW_TRIANGLES:
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen() < 3 * _numVertices)
|
||||
g_vertex_manager->Flush();
|
||||
break;
|
||||
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
case GX_DRAW_LINES:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen() < 2 * _numVertices)
|
||||
g_vertex_manager->Flush();
|
||||
break;
|
||||
|
||||
case GX_DRAW_POINTS:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen() < _numVertices)
|
||||
g_vertex_manager->Flush();
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Flushed)
|
||||
{
|
||||
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
|
||||
Flushed = false;
|
||||
}
|
||||
|
||||
lastPrimitive = _primitive;
|
||||
ADDSTAT(stats.thisFrame.numPrims, _numVertices);
|
||||
INCSTAT(stats.thisFrame.numPrimitiveJoins);
|
||||
AddIndices(_primitive, _numVertices);
|
||||
}
|
||||
|
||||
void VertexManager::Flush()
|
||||
{
|
||||
VertexManagerBase::Flush();
|
||||
}
|
||||
|
||||
void VertexManagerBase::Flush()
|
||||
{
|
||||
if (LocalVBuffer == s_pCurBufferPointer)
|
||||
return;
|
||||
|
||||
if (Flushed)
|
||||
return;
|
||||
|
||||
Flushed = true;
|
||||
|
||||
VideoFifo_CheckEFBAccess();
|
||||
|
||||
DVSTARTPROFILE();
|
||||
|
||||
u32 usedtextures = 0;
|
||||
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i)
|
||||
{
|
||||
if (bpmem.tevorders[i/2].getEnable(i & 1))
|
||||
usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1);
|
||||
}
|
||||
|
||||
if (bpmem.genMode.numindstages > 0)
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numtevstages + 1; ++i)
|
||||
if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages)
|
||||
usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt);
|
||||
|
||||
for (unsigned int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (usedtextures & (1 << i))
|
||||
{
|
||||
g_renderer->SetSamplerState(i & 3, i >> 2);
|
||||
|
||||
FourTexUnits &tex = bpmem.tex[i >> 2];
|
||||
|
||||
TextureCacheBase::TCacheEntryBase* tentry = g_texture_cache->Load(i,
|
||||
(tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5,
|
||||
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
|
||||
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
|
||||
tex.texTlut[i&3].tlut_format,
|
||||
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8) && g_ActiveConfig.bUseNativeMips,
|
||||
(tex.texMode1[i&3].max_lod >> 4));
|
||||
|
||||
if (tentry)
|
||||
PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "error loading texture");
|
||||
}
|
||||
}
|
||||
|
||||
VertexShaderManager::SetConstants();
|
||||
PixelShaderManager::SetConstants();
|
||||
|
||||
if (false == g_pixel_shader_cache->SetShader(false))
|
||||
goto shader_fail;
|
||||
|
||||
if (false == g_vertex_shader_cache->SetShader(g_nativeVertexFmt->m_components))
|
||||
goto shader_fail;
|
||||
|
||||
const unsigned int stride = g_nativeVertexFmt->GetVertexStride();
|
||||
g_nativeVertexFmt->SetupVertexPointers();
|
||||
|
||||
// TODO:
|
||||
g_vertex_manager->Draw(stride, false);
|
||||
|
||||
if (false == g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate)
|
||||
{
|
||||
if (false == g_pixel_shader_cache->SetShader(true))
|
||||
goto shader_fail;
|
||||
|
||||
// update alpha only
|
||||
g_vertex_manager->Draw(stride, true);
|
||||
}
|
||||
|
||||
//IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
|
||||
|
||||
shader_fail:
|
||||
ResetBuffer();
|
||||
}
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
|
||||
#ifndef _VERTExMANAGER_H_
|
||||
#define _VERTExMANAGER_H_
|
||||
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "NativeVertexWriter.h"
|
||||
#include "BPMemory.h"
|
||||
|
||||
enum
|
||||
{
|
||||
MAXVBUFFERSIZE = 0x50000,
|
||||
MAXIBUFFERSIZE = 0x10000,
|
||||
};
|
||||
|
||||
using VertexManager::s_pBaseBufferPointer;
|
||||
using VertexManager::s_pCurBufferPointer;
|
||||
|
||||
extern NativeVertexFormat *g_nativeVertexFmt;
|
||||
|
||||
class VertexManagerBase
|
||||
{
|
||||
public:
|
||||
VertexManagerBase();
|
||||
virtual ~VertexManagerBase();
|
||||
|
||||
static void Flush();
|
||||
virtual void Draw(u32 stride, bool alphapass) = 0;
|
||||
|
||||
virtual NativeVertexFormat* CreateNativeVertexFormat() = 0;
|
||||
|
||||
static void AddIndices(int _primitive, int _numVertices);
|
||||
static int GetRemainingSize();
|
||||
static int GetRemainingVertices(int primitive);
|
||||
static void AddVertices(int _primitive, int _numVertices);
|
||||
static void ResetBuffer();
|
||||
|
||||
protected:
|
||||
static u16* TIBuffer;
|
||||
static u16* LIBuffer;
|
||||
static u16* PIBuffer;
|
||||
static bool Flushed;
|
||||
|
||||
static int lastPrimitive;
|
||||
static u8* LocalVBuffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _VERTExMANAGER_H_
|
||||
#define _VERTExMANAGER_H_
|
||||
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "NativeVertexWriter.h"
|
||||
#include "BPMemory.h"
|
||||
|
||||
enum
|
||||
{
|
||||
MAXVBUFFERSIZE = 0x50000,
|
||||
MAXIBUFFERSIZE = 0x10000,
|
||||
};
|
||||
|
||||
using VertexManager::s_pBaseBufferPointer;
|
||||
using VertexManager::s_pCurBufferPointer;
|
||||
|
||||
extern NativeVertexFormat *g_nativeVertexFmt;
|
||||
|
||||
class VertexManagerBase
|
||||
{
|
||||
public:
|
||||
VertexManagerBase();
|
||||
virtual ~VertexManagerBase();
|
||||
|
||||
static void Flush();
|
||||
virtual void Draw(u32 stride, bool alphapass) = 0;
|
||||
|
||||
virtual NativeVertexFormat* CreateNativeVertexFormat() = 0;
|
||||
|
||||
static void AddIndices(int _primitive, int _numVertices);
|
||||
static int GetRemainingSize();
|
||||
static int GetRemainingVertices(int primitive);
|
||||
static void AddVertices(int _primitive, int _numVertices);
|
||||
static void ResetBuffer();
|
||||
|
||||
protected:
|
||||
static u16* TIBuffer;
|
||||
static u16* LIBuffer;
|
||||
static u16* PIBuffer;
|
||||
static bool Flushed;
|
||||
|
||||
static int lastPrimitive;
|
||||
static u8* LocalVBuffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
|
||||
#include "VertexShaderManager.h"
|
||||
|
||||
#include "Main.h"
|
||||
#include "VertexShaderCache.h"
|
||||
|
||||
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
g_vertex_shader_cache->SetVSConstant4f(const_number, f1, f2, f3, f4);
|
||||
}
|
||||
|
||||
void SetVSConstant4fv(unsigned int const_number, const float* f)
|
||||
{
|
||||
g_vertex_shader_cache->SetVSConstant4fv(const_number, f);
|
||||
}
|
||||
|
||||
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f)
|
||||
{
|
||||
g_vertex_shader_cache->SetMultiVSConstant3fv(const_number, count, f);
|
||||
}
|
||||
|
||||
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f)
|
||||
{
|
||||
g_vertex_shader_cache->SetMultiVSConstant4fv(const_number, count, f);
|
||||
}
|
||||
|
||||
#include "VertexShaderManager.h"
|
||||
|
||||
#include "Main.h"
|
||||
#include "VertexShaderCache.h"
|
||||
|
||||
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
g_vertex_shader_cache->SetVSConstant4f(const_number, f1, f2, f3, f4);
|
||||
}
|
||||
|
||||
void SetVSConstant4fv(unsigned int const_number, const float* f)
|
||||
{
|
||||
g_vertex_shader_cache->SetVSConstant4fv(const_number, f);
|
||||
}
|
||||
|
||||
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f)
|
||||
{
|
||||
g_vertex_shader_cache->SetMultiVSConstant3fv(const_number, count, f);
|
||||
}
|
||||
|
||||
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f)
|
||||
{
|
||||
g_vertex_shader_cache->SetMultiVSConstant4fv(const_number, count, f);
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
|
||||
#ifndef _VERTEXSHADERCACHE_H_
|
||||
#define _VERTEXSHADERCACHE_H_
|
||||
|
||||
class VertexShaderCacheBase
|
||||
{
|
||||
public:
|
||||
virtual ~VertexShaderCacheBase() {}
|
||||
|
||||
virtual bool SetShader(u32 components) = 0;
|
||||
|
||||
virtual void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) = 0;
|
||||
virtual void SetVSConstant4fv(unsigned int const_number, const float* f) = 0;
|
||||
virtual void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f) = 0;
|
||||
virtual void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _VERTEXSHADERCACHE_H_
|
||||
#define _VERTEXSHADERCACHE_H_
|
||||
|
||||
class VertexShaderCacheBase
|
||||
{
|
||||
public:
|
||||
virtual ~VertexShaderCacheBase() {}
|
||||
|
||||
virtual bool SetShader(u32 components) = 0;
|
||||
|
||||
virtual void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) = 0;
|
||||
virtual void SetVSConstant4fv(unsigned int const_number, const float* f) = 0;
|
||||
virtual void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f) = 0;
|
||||
virtual void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,245 +1,245 @@
|
|||
|
||||
#include "VideoConfigDiag.h"
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "Main.h"
|
||||
|
||||
#define _connect_macro_(b, f, c, s) (b)->Connect(wxID_ANY, (c), wxCommandEventHandler( f ), (wxObject*)0, (wxEvtHandler*)s)
|
||||
|
||||
// template instantiation
|
||||
template class BoolSetting<wxCheckBox>;
|
||||
template class BoolSetting<wxRadioButton>;
|
||||
|
||||
typedef BoolSetting<wxCheckBox> SettingCheckBox;
|
||||
typedef BoolSetting<wxRadioButton> SettingRadioButton;
|
||||
|
||||
SettingCheckBox::BoolSetting(wxWindow* parent, const wxString& label, bool &setting, bool reverse, long style)
|
||||
: wxCheckBox(parent, -1, label, wxDefaultPosition, wxDefaultSize, style)
|
||||
, m_setting(setting)
|
||||
, m_reverse(reverse)
|
||||
{
|
||||
SetValue(m_setting ^ m_reverse);
|
||||
_connect_macro_(this, BoolSetting<W>::UpdateValue, wxEVT_COMMAND_CHECKBOX_CLICKED, this);
|
||||
}
|
||||
|
||||
SettingRadioButton::BoolSetting(wxWindow* parent, const wxString& label, bool &setting, bool reverse, long style)
|
||||
: wxRadioButton(parent, -1, label, wxDefaultPosition, wxDefaultSize, style)
|
||||
, m_setting(setting)
|
||||
, m_reverse(reverse)
|
||||
{
|
||||
SetValue(m_setting ^ m_reverse);
|
||||
_connect_macro_(this, BoolSetting<W>::UpdateValue, wxEVT_COMMAND_RADIOBUTTON_SELECTED, this);
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
void BoolSetting<W>::UpdateValue(wxCommandEvent& ev)
|
||||
{
|
||||
m_setting = (ev.GetInt() != 0) ^ m_reverse;
|
||||
}
|
||||
|
||||
SettingChoice::SettingChoice(wxWindow* parent, int &setting, int num, const wxString choices[])
|
||||
: wxChoice(parent, -1, wxDefaultPosition, wxDefaultSize, num, choices)
|
||||
, m_setting(setting)
|
||||
{
|
||||
Select(m_setting);
|
||||
_connect_macro_(this, SettingChoice::UpdateValue, wxEVT_COMMAND_CHOICE_SELECTED, this);
|
||||
}
|
||||
|
||||
void SettingChoice::UpdateValue(wxCommandEvent& ev)
|
||||
{
|
||||
m_setting = ev.GetInt();
|
||||
}
|
||||
|
||||
void VideoConfigDiag::CloseDiag(wxCommandEvent&)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
VideoConfigDiag::VideoConfigDiag(wxWindow* parent)
|
||||
: wxDialog(parent, -1, wxT("Dolphin Graphics Configuration"), wxDefaultPosition, wxDefaultSize)
|
||||
{
|
||||
VideoConfig &vconfig = g_Config;
|
||||
|
||||
wxNotebook* const notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize);
|
||||
|
||||
// -- GENERAL --
|
||||
{
|
||||
wxPanel* const page_general = new wxPanel(notebook, -1, wxDefaultPosition);
|
||||
notebook->AddPage(page_general, wxT("General"));
|
||||
wxBoxSizer* const szr_general = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
// - basic
|
||||
{
|
||||
wxStaticBoxSizer* const group_basic = new wxStaticBoxSizer(wxVERTICAL, page_general, wxT("Basic"));
|
||||
szr_general->Add(group_basic, 0, wxEXPAND | wxALL, 5);
|
||||
wxFlexGridSizer* const szr_basic = new wxFlexGridSizer(2, 5, 5);
|
||||
group_basic->Add(szr_basic, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
// graphics api
|
||||
{
|
||||
const wxString gfxapi_choices[] = { wxT("Software [not present]"),
|
||||
wxT("OpenGL [broken]"), wxT("Direct3D 9 [broken]"), wxT("Direct3D 11") };
|
||||
|
||||
szr_basic->Add(new wxStaticText(page_general, -1, wxT("Graphics API:")), 1, wxALIGN_CENTER_VERTICAL, 0);
|
||||
wxChoice* const choice_gfxapi = new SettingChoice(page_general,
|
||||
g_gfxapi, sizeof(gfxapi_choices)/sizeof(*gfxapi_choices), gfxapi_choices);
|
||||
szr_basic->Add(choice_gfxapi, 1, 0, 0);
|
||||
}
|
||||
|
||||
// for D3D only
|
||||
// adapter
|
||||
{
|
||||
//szr_basic->Add(new wxStaticText(page_general, -1, wxT("Adapter:")), 1, wxALIGN_CENTER_VERTICAL, 5);
|
||||
//wxChoice* const choice_adapter = new SettingChoice(page_general, vconfig.iAdapter);
|
||||
//szr_basic->Add(choice_adapter, 1, 0, 0);
|
||||
}
|
||||
|
||||
// aspect-ratio
|
||||
{
|
||||
const wxString ar_choices[] = { wxT("Auto [recommended]"),
|
||||
wxT("Force 16:9"), wxT("Force 4:3"), wxT("Strech to Window") };
|
||||
|
||||
szr_basic->Add(new wxStaticText(page_general, -1, wxT("Aspect ratio:")), 1, wxALIGN_CENTER_VERTICAL, 0);
|
||||
wxChoice* const choice_aspect = new SettingChoice(page_general,
|
||||
vconfig.iAspectRatio, sizeof(ar_choices)/sizeof(*ar_choices), ar_choices);
|
||||
szr_basic->Add(choice_aspect, 1, 0, 0);
|
||||
}
|
||||
|
||||
// widescreen hack
|
||||
{
|
||||
szr_basic->AddStretchSpacer(1);
|
||||
szr_basic->Add(new SettingCheckBox(page_general, wxT("Widescreen Hack"), vconfig.bWidescreenHack), 1, 0, 0);
|
||||
szr_basic->AddStretchSpacer(1);
|
||||
szr_basic->Add(new SettingCheckBox(page_general, wxT("V-Sync"), vconfig.bVSync), 1, 0, 0);
|
||||
}
|
||||
|
||||
// - EFB
|
||||
{
|
||||
wxStaticBoxSizer* const group_efb = new wxStaticBoxSizer(wxVERTICAL, page_general, wxT("EFB"));
|
||||
szr_general->Add(group_efb, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
group_efb->Add(new SettingCheckBox(page_general, wxT("Enable CPU Access"), vconfig.bEFBAccessEnable), 0, wxBOTTOM | wxLEFT, 5);
|
||||
|
||||
// EFB scale
|
||||
{
|
||||
// TODO: give this a label
|
||||
const wxString efbscale_choices[] = { wxT("Fractional"), wxT("Integral [recommended]"),
|
||||
wxT("1x"), wxT("2x"), wxT("3x")/*, wxT("4x")*/ };
|
||||
|
||||
wxChoice *const choice_efbscale = new SettingChoice(page_general,
|
||||
vconfig.iEFBScale, sizeof(efbscale_choices)/sizeof(*efbscale_choices), efbscale_choices);
|
||||
group_efb->Add(choice_efbscale, 0, wxBOTTOM | wxLEFT, 5);
|
||||
}
|
||||
|
||||
// EFB copy
|
||||
wxStaticBoxSizer* const group_efbcopy = new wxStaticBoxSizer(wxHORIZONTAL, page_general, wxT("Copy"));
|
||||
group_efb->Add(group_efbcopy, 0, wxEXPAND | wxBOTTOM, 5);
|
||||
|
||||
group_efbcopy->Add(new SettingCheckBox(page_general, wxT("Enable"), vconfig.bEFBCopyDisable, true), 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
group_efbcopy->AddStretchSpacer(1);
|
||||
group_efbcopy->Add(new SettingRadioButton(page_general, wxT("Texture"), vconfig.bCopyEFBToTexture, false, wxRB_GROUP), 0, wxRIGHT, 5);
|
||||
group_efbcopy->Add(new SettingRadioButton(page_general, wxT("RAM"), vconfig.bCopyEFBToTexture, true), 0, wxRIGHT, 5);
|
||||
}
|
||||
|
||||
// - safe texture cache
|
||||
{
|
||||
wxStaticBoxSizer* const group_safetex = new wxStaticBoxSizer(wxHORIZONTAL, page_general, wxT("Safe Texture Cache"));
|
||||
szr_general->Add(group_safetex, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
// safe texture cache
|
||||
group_safetex->Add(new SettingCheckBox(page_general, wxT("Enable"), vconfig.bSafeTextureCache), 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
group_safetex->AddStretchSpacer(1);
|
||||
// TODO: make these radio buttons functional
|
||||
//group_safetex->Add(new wxRadioButton(page_general, -1, wxT("Safe"),
|
||||
// wxDefaultPosition, wxDefaultSize, wxRB_GROUP), 0, wxRIGHT, 5);
|
||||
//group_safetex->Add(new wxRadioButton(page_general, -1, wxT("Normal")), 0, wxRIGHT, 5);
|
||||
//group_safetex->Add(new wxRadioButton(page_general, -1, wxT("Fast")), 0, wxRIGHT, 5);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
page_general->SetSizerAndFit(szr_general);
|
||||
}
|
||||
|
||||
// -- ADVANCED --
|
||||
{
|
||||
wxPanel* const page_advanced = new wxPanel(notebook, -1, wxDefaultPosition);
|
||||
notebook->AddPage(page_advanced, wxT("Advanced"));
|
||||
wxBoxSizer* const szr_advanced = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
// - rendering
|
||||
{
|
||||
wxStaticBoxSizer* const group_rendering = new wxStaticBoxSizer(wxVERTICAL, page_advanced, wxT("Rendering"));
|
||||
szr_advanced->Add(group_rendering, 0, wxEXPAND | wxALL, 5);
|
||||
wxGridSizer* const szr_rendering = new wxGridSizer(2, 5, 5);
|
||||
group_rendering->Add(szr_rendering, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Enable Wireframe"), vconfig.bWireFrame));
|
||||
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Lighting"), vconfig.bDisableLighting));
|
||||
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Textures"), vconfig.bDisableTexturing));
|
||||
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Fog"), vconfig.bDisableFog));
|
||||
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Dest. Alpha Pass"), vconfig.bDstAlphaPass));
|
||||
}
|
||||
|
||||
// - info
|
||||
{
|
||||
wxStaticBoxSizer* const group_info = new wxStaticBoxSizer(wxVERTICAL, page_advanced, wxT("Overlay Information"));
|
||||
szr_advanced->Add(group_info, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
wxGridSizer* const szr_info = new wxGridSizer(2, 5, 5);
|
||||
group_info->Add(szr_info, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
szr_info->Add(new SettingCheckBox(page_advanced, wxT("Show FPS"), vconfig.bShowFPS));
|
||||
szr_info->Add(new SettingCheckBox(page_advanced, wxT("Various Statistics"), vconfig.bOverlayStats));
|
||||
szr_info->Add(new SettingCheckBox(page_advanced, wxT("Projection Stats"), vconfig.bOverlayProjStats));
|
||||
szr_info->Add(new SettingCheckBox(page_advanced, wxT("Texture Format"), vconfig.bTexFmtOverlayEnable));
|
||||
szr_info->Add(new SettingCheckBox(page_advanced, wxT("EFB Copy Regions"), vconfig.bShowEFBCopyRegions));
|
||||
}
|
||||
|
||||
// - XFB
|
||||
{
|
||||
wxStaticBoxSizer* const group_xfb = new wxStaticBoxSizer(wxHORIZONTAL, page_advanced, wxT("XFB"));
|
||||
szr_advanced->Add(group_xfb, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
group_xfb->Add(new SettingCheckBox(page_advanced, wxT("Enable"), vconfig.bUseXFB), 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
group_xfb->AddStretchSpacer(1);
|
||||
group_xfb->Add(new SettingRadioButton(page_advanced, wxT("Virtual"), vconfig.bUseRealXFB, true, wxRB_GROUP), 0, wxRIGHT, 5);
|
||||
group_xfb->Add(new SettingRadioButton(page_advanced, wxT("Real"), vconfig.bUseRealXFB), 0, wxRIGHT, 5);
|
||||
}
|
||||
|
||||
// - utility
|
||||
{
|
||||
wxStaticBoxSizer* const group_utility = new wxStaticBoxSizer(wxVERTICAL, page_advanced, wxT("Utility"));
|
||||
szr_advanced->Add(group_utility, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
wxGridSizer* const szr_utility = new wxGridSizer(2, 5, 5);
|
||||
group_utility->Add(szr_utility, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Dump Textures"), vconfig.bDumpTextures));
|
||||
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Load Hi-Res Textures"), vconfig.bHiresTextures));
|
||||
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Dump EFB Target"), vconfig.bDumpEFBTarget));
|
||||
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Dump Frames"), vconfig.bDumpFrames));
|
||||
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Free Look"), vconfig.bFreeLook));
|
||||
}
|
||||
|
||||
// stuff to move/remove
|
||||
{
|
||||
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Load Native Mipmaps"), vconfig.bUseNativeMips), 0, wxBOTTOM | wxLEFT, 5);
|
||||
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("EFB Scaled Copy"), vconfig.bCopyEFBScaled), 0, wxBOTTOM | wxLEFT, 5);
|
||||
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Auto Scale"), vconfig.bAutoScale), 0, wxBOTTOM | wxLEFT, 5);
|
||||
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Crop"), vconfig.bCrop), 0, wxBOTTOM | wxLEFT, 5);
|
||||
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Enable OpenCL"), vconfig.bEnableOpenCL), 0, wxBOTTOM | wxLEFT, 5);
|
||||
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Enable Display List Caching"), vconfig.bDlistCachingEnable), 0, wxBOTTOM | wxLEFT, 5);
|
||||
}
|
||||
|
||||
page_advanced->SetSizerAndFit(szr_advanced);
|
||||
}
|
||||
|
||||
wxButton* const btn_close = new wxButton(this, -1, wxT("Close"), wxDefaultPosition);
|
||||
_connect_macro_(btn_close, VideoConfigDiag::CloseDiag, wxEVT_COMMAND_BUTTON_CLICKED, this);
|
||||
|
||||
wxBoxSizer* const szr_main = new wxBoxSizer(wxVERTICAL);
|
||||
szr_main->Add(notebook, 1, wxEXPAND | wxALL, 5);
|
||||
szr_main->Add(btn_close, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
SetSizerAndFit(szr_main);
|
||||
Center();
|
||||
}
|
||||
|
||||
#include "VideoConfigDiag.h"
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "Main.h"
|
||||
|
||||
#define _connect_macro_(b, f, c, s) (b)->Connect(wxID_ANY, (c), wxCommandEventHandler( f ), (wxObject*)0, (wxEvtHandler*)s)
|
||||
|
||||
// template instantiation
|
||||
template class BoolSetting<wxCheckBox>;
|
||||
template class BoolSetting<wxRadioButton>;
|
||||
|
||||
typedef BoolSetting<wxCheckBox> SettingCheckBox;
|
||||
typedef BoolSetting<wxRadioButton> SettingRadioButton;
|
||||
|
||||
SettingCheckBox::BoolSetting(wxWindow* parent, const wxString& label, bool &setting, bool reverse, long style)
|
||||
: wxCheckBox(parent, -1, label, wxDefaultPosition, wxDefaultSize, style)
|
||||
, m_setting(setting)
|
||||
, m_reverse(reverse)
|
||||
{
|
||||
SetValue(m_setting ^ m_reverse);
|
||||
_connect_macro_(this, BoolSetting<W>::UpdateValue, wxEVT_COMMAND_CHECKBOX_CLICKED, this);
|
||||
}
|
||||
|
||||
SettingRadioButton::BoolSetting(wxWindow* parent, const wxString& label, bool &setting, bool reverse, long style)
|
||||
: wxRadioButton(parent, -1, label, wxDefaultPosition, wxDefaultSize, style)
|
||||
, m_setting(setting)
|
||||
, m_reverse(reverse)
|
||||
{
|
||||
SetValue(m_setting ^ m_reverse);
|
||||
_connect_macro_(this, BoolSetting<W>::UpdateValue, wxEVT_COMMAND_RADIOBUTTON_SELECTED, this);
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
void BoolSetting<W>::UpdateValue(wxCommandEvent& ev)
|
||||
{
|
||||
m_setting = (ev.GetInt() != 0) ^ m_reverse;
|
||||
}
|
||||
|
||||
SettingChoice::SettingChoice(wxWindow* parent, int &setting, int num, const wxString choices[])
|
||||
: wxChoice(parent, -1, wxDefaultPosition, wxDefaultSize, num, choices)
|
||||
, m_setting(setting)
|
||||
{
|
||||
Select(m_setting);
|
||||
_connect_macro_(this, SettingChoice::UpdateValue, wxEVT_COMMAND_CHOICE_SELECTED, this);
|
||||
}
|
||||
|
||||
void SettingChoice::UpdateValue(wxCommandEvent& ev)
|
||||
{
|
||||
m_setting = ev.GetInt();
|
||||
}
|
||||
|
||||
void VideoConfigDiag::CloseDiag(wxCommandEvent&)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
VideoConfigDiag::VideoConfigDiag(wxWindow* parent)
|
||||
: wxDialog(parent, -1, wxT("Dolphin Graphics Configuration"), wxDefaultPosition, wxDefaultSize)
|
||||
{
|
||||
VideoConfig &vconfig = g_Config;
|
||||
|
||||
wxNotebook* const notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize);
|
||||
|
||||
// -- GENERAL --
|
||||
{
|
||||
wxPanel* const page_general = new wxPanel(notebook, -1, wxDefaultPosition);
|
||||
notebook->AddPage(page_general, wxT("General"));
|
||||
wxBoxSizer* const szr_general = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
// - basic
|
||||
{
|
||||
wxStaticBoxSizer* const group_basic = new wxStaticBoxSizer(wxVERTICAL, page_general, wxT("Basic"));
|
||||
szr_general->Add(group_basic, 0, wxEXPAND | wxALL, 5);
|
||||
wxFlexGridSizer* const szr_basic = new wxFlexGridSizer(2, 5, 5);
|
||||
group_basic->Add(szr_basic, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
// graphics api
|
||||
{
|
||||
const wxString gfxapi_choices[] = { wxT("Software [not present]"),
|
||||
wxT("OpenGL [broken]"), wxT("Direct3D 9 [broken]"), wxT("Direct3D 11") };
|
||||
|
||||
szr_basic->Add(new wxStaticText(page_general, -1, wxT("Graphics API:")), 1, wxALIGN_CENTER_VERTICAL, 0);
|
||||
wxChoice* const choice_gfxapi = new SettingChoice(page_general,
|
||||
g_gfxapi, sizeof(gfxapi_choices)/sizeof(*gfxapi_choices), gfxapi_choices);
|
||||
szr_basic->Add(choice_gfxapi, 1, 0, 0);
|
||||
}
|
||||
|
||||
// for D3D only
|
||||
// adapter
|
||||
{
|
||||
//szr_basic->Add(new wxStaticText(page_general, -1, wxT("Adapter:")), 1, wxALIGN_CENTER_VERTICAL, 5);
|
||||
//wxChoice* const choice_adapter = new SettingChoice(page_general, vconfig.iAdapter);
|
||||
//szr_basic->Add(choice_adapter, 1, 0, 0);
|
||||
}
|
||||
|
||||
// aspect-ratio
|
||||
{
|
||||
const wxString ar_choices[] = { wxT("Auto [recommended]"),
|
||||
wxT("Force 16:9"), wxT("Force 4:3"), wxT("Strech to Window") };
|
||||
|
||||
szr_basic->Add(new wxStaticText(page_general, -1, wxT("Aspect ratio:")), 1, wxALIGN_CENTER_VERTICAL, 0);
|
||||
wxChoice* const choice_aspect = new SettingChoice(page_general,
|
||||
vconfig.iAspectRatio, sizeof(ar_choices)/sizeof(*ar_choices), ar_choices);
|
||||
szr_basic->Add(choice_aspect, 1, 0, 0);
|
||||
}
|
||||
|
||||
// widescreen hack
|
||||
{
|
||||
szr_basic->AddStretchSpacer(1);
|
||||
szr_basic->Add(new SettingCheckBox(page_general, wxT("Widescreen Hack"), vconfig.bWidescreenHack), 1, 0, 0);
|
||||
szr_basic->AddStretchSpacer(1);
|
||||
szr_basic->Add(new SettingCheckBox(page_general, wxT("V-Sync"), vconfig.bVSync), 1, 0, 0);
|
||||
}
|
||||
|
||||
// - EFB
|
||||
{
|
||||
wxStaticBoxSizer* const group_efb = new wxStaticBoxSizer(wxVERTICAL, page_general, wxT("EFB"));
|
||||
szr_general->Add(group_efb, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
group_efb->Add(new SettingCheckBox(page_general, wxT("Enable CPU Access"), vconfig.bEFBAccessEnable), 0, wxBOTTOM | wxLEFT, 5);
|
||||
|
||||
// EFB scale
|
||||
{
|
||||
// TODO: give this a label
|
||||
const wxString efbscale_choices[] = { wxT("Fractional"), wxT("Integral [recommended]"),
|
||||
wxT("1x"), wxT("2x"), wxT("3x")/*, wxT("4x")*/ };
|
||||
|
||||
wxChoice *const choice_efbscale = new SettingChoice(page_general,
|
||||
vconfig.iEFBScale, sizeof(efbscale_choices)/sizeof(*efbscale_choices), efbscale_choices);
|
||||
group_efb->Add(choice_efbscale, 0, wxBOTTOM | wxLEFT, 5);
|
||||
}
|
||||
|
||||
// EFB copy
|
||||
wxStaticBoxSizer* const group_efbcopy = new wxStaticBoxSizer(wxHORIZONTAL, page_general, wxT("Copy"));
|
||||
group_efb->Add(group_efbcopy, 0, wxEXPAND | wxBOTTOM, 5);
|
||||
|
||||
group_efbcopy->Add(new SettingCheckBox(page_general, wxT("Enable"), vconfig.bEFBCopyDisable, true), 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
group_efbcopy->AddStretchSpacer(1);
|
||||
group_efbcopy->Add(new SettingRadioButton(page_general, wxT("Texture"), vconfig.bCopyEFBToTexture, false, wxRB_GROUP), 0, wxRIGHT, 5);
|
||||
group_efbcopy->Add(new SettingRadioButton(page_general, wxT("RAM"), vconfig.bCopyEFBToTexture, true), 0, wxRIGHT, 5);
|
||||
}
|
||||
|
||||
// - safe texture cache
|
||||
{
|
||||
wxStaticBoxSizer* const group_safetex = new wxStaticBoxSizer(wxHORIZONTAL, page_general, wxT("Safe Texture Cache"));
|
||||
szr_general->Add(group_safetex, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
// safe texture cache
|
||||
group_safetex->Add(new SettingCheckBox(page_general, wxT("Enable"), vconfig.bSafeTextureCache), 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
group_safetex->AddStretchSpacer(1);
|
||||
// TODO: make these radio buttons functional
|
||||
//group_safetex->Add(new wxRadioButton(page_general, -1, wxT("Safe"),
|
||||
// wxDefaultPosition, wxDefaultSize, wxRB_GROUP), 0, wxRIGHT, 5);
|
||||
//group_safetex->Add(new wxRadioButton(page_general, -1, wxT("Normal")), 0, wxRIGHT, 5);
|
||||
//group_safetex->Add(new wxRadioButton(page_general, -1, wxT("Fast")), 0, wxRIGHT, 5);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
page_general->SetSizerAndFit(szr_general);
|
||||
}
|
||||
|
||||
// -- ADVANCED --
|
||||
{
|
||||
wxPanel* const page_advanced = new wxPanel(notebook, -1, wxDefaultPosition);
|
||||
notebook->AddPage(page_advanced, wxT("Advanced"));
|
||||
wxBoxSizer* const szr_advanced = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
// - rendering
|
||||
{
|
||||
wxStaticBoxSizer* const group_rendering = new wxStaticBoxSizer(wxVERTICAL, page_advanced, wxT("Rendering"));
|
||||
szr_advanced->Add(group_rendering, 0, wxEXPAND | wxALL, 5);
|
||||
wxGridSizer* const szr_rendering = new wxGridSizer(2, 5, 5);
|
||||
group_rendering->Add(szr_rendering, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Enable Wireframe"), vconfig.bWireFrame));
|
||||
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Lighting"), vconfig.bDisableLighting));
|
||||
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Textures"), vconfig.bDisableTexturing));
|
||||
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Fog"), vconfig.bDisableFog));
|
||||
szr_rendering->Add(new SettingCheckBox(page_advanced, wxT("Disable Dest. Alpha Pass"), vconfig.bDstAlphaPass));
|
||||
}
|
||||
|
||||
// - info
|
||||
{
|
||||
wxStaticBoxSizer* const group_info = new wxStaticBoxSizer(wxVERTICAL, page_advanced, wxT("Overlay Information"));
|
||||
szr_advanced->Add(group_info, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
wxGridSizer* const szr_info = new wxGridSizer(2, 5, 5);
|
||||
group_info->Add(szr_info, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
szr_info->Add(new SettingCheckBox(page_advanced, wxT("Show FPS"), vconfig.bShowFPS));
|
||||
szr_info->Add(new SettingCheckBox(page_advanced, wxT("Various Statistics"), vconfig.bOverlayStats));
|
||||
szr_info->Add(new SettingCheckBox(page_advanced, wxT("Projection Stats"), vconfig.bOverlayProjStats));
|
||||
szr_info->Add(new SettingCheckBox(page_advanced, wxT("Texture Format"), vconfig.bTexFmtOverlayEnable));
|
||||
szr_info->Add(new SettingCheckBox(page_advanced, wxT("EFB Copy Regions"), vconfig.bShowEFBCopyRegions));
|
||||
}
|
||||
|
||||
// - XFB
|
||||
{
|
||||
wxStaticBoxSizer* const group_xfb = new wxStaticBoxSizer(wxHORIZONTAL, page_advanced, wxT("XFB"));
|
||||
szr_advanced->Add(group_xfb, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
group_xfb->Add(new SettingCheckBox(page_advanced, wxT("Enable"), vconfig.bUseXFB), 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
group_xfb->AddStretchSpacer(1);
|
||||
group_xfb->Add(new SettingRadioButton(page_advanced, wxT("Virtual"), vconfig.bUseRealXFB, true, wxRB_GROUP), 0, wxRIGHT, 5);
|
||||
group_xfb->Add(new SettingRadioButton(page_advanced, wxT("Real"), vconfig.bUseRealXFB), 0, wxRIGHT, 5);
|
||||
}
|
||||
|
||||
// - utility
|
||||
{
|
||||
wxStaticBoxSizer* const group_utility = new wxStaticBoxSizer(wxVERTICAL, page_advanced, wxT("Utility"));
|
||||
szr_advanced->Add(group_utility, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
wxGridSizer* const szr_utility = new wxGridSizer(2, 5, 5);
|
||||
group_utility->Add(szr_utility, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Dump Textures"), vconfig.bDumpTextures));
|
||||
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Load Hi-Res Textures"), vconfig.bHiresTextures));
|
||||
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Dump EFB Target"), vconfig.bDumpEFBTarget));
|
||||
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Dump Frames"), vconfig.bDumpFrames));
|
||||
szr_utility->Add(new SettingCheckBox(page_advanced, wxT("Free Look"), vconfig.bFreeLook));
|
||||
}
|
||||
|
||||
// stuff to move/remove
|
||||
{
|
||||
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Load Native Mipmaps"), vconfig.bUseNativeMips), 0, wxBOTTOM | wxLEFT, 5);
|
||||
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("EFB Scaled Copy"), vconfig.bCopyEFBScaled), 0, wxBOTTOM | wxLEFT, 5);
|
||||
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Auto Scale"), vconfig.bAutoScale), 0, wxBOTTOM | wxLEFT, 5);
|
||||
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Crop"), vconfig.bCrop), 0, wxBOTTOM | wxLEFT, 5);
|
||||
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Enable OpenCL"), vconfig.bEnableOpenCL), 0, wxBOTTOM | wxLEFT, 5);
|
||||
szr_advanced->Add(new SettingCheckBox(page_advanced, wxT("Enable Display List Caching"), vconfig.bDlistCachingEnable), 0, wxBOTTOM | wxLEFT, 5);
|
||||
}
|
||||
|
||||
page_advanced->SetSizerAndFit(szr_advanced);
|
||||
}
|
||||
|
||||
wxButton* const btn_close = new wxButton(this, -1, wxT("Close"), wxDefaultPosition);
|
||||
_connect_macro_(btn_close, VideoConfigDiag::CloseDiag, wxEVT_COMMAND_BUTTON_CLICKED, this);
|
||||
|
||||
wxBoxSizer* const szr_main = new wxBoxSizer(wxVERTICAL);
|
||||
szr_main->Add(notebook, 1, wxEXPAND | wxALL, 5);
|
||||
szr_main->Add(btn_close, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
SetSizerAndFit(szr_main);
|
||||
Center();
|
||||
}
|
||||
|
|
|
@ -1,44 +1,44 @@
|
|||
|
||||
#ifndef _CONFIG_DIAG_H_
|
||||
#define _CONFIG_DIAG_H_
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/combobox.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/spinctrl.h>
|
||||
|
||||
template <typename W>
|
||||
class BoolSetting : public W
|
||||
{
|
||||
public:
|
||||
BoolSetting(wxWindow* parent, const wxString& label, bool &setting, bool reverse = false, long style = 0);
|
||||
void UpdateValue(wxCommandEvent& ev);
|
||||
private:
|
||||
bool &m_setting;
|
||||
const bool m_reverse;
|
||||
};
|
||||
|
||||
class SettingChoice : public wxChoice
|
||||
{
|
||||
public:
|
||||
SettingChoice(wxWindow* parent, int &setting, int num = 0, const wxString choices[] = NULL);
|
||||
void UpdateValue(wxCommandEvent& ev);
|
||||
private:
|
||||
int &m_setting;
|
||||
};
|
||||
|
||||
class VideoConfigDiag : public wxDialog
|
||||
{
|
||||
public:
|
||||
VideoConfigDiag(wxWindow* parent);
|
||||
|
||||
protected:
|
||||
void CloseDiag(wxCommandEvent&);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _CONFIG_DIAG_H_
|
||||
#define _CONFIG_DIAG_H_
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/combobox.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/spinctrl.h>
|
||||
|
||||
template <typename W>
|
||||
class BoolSetting : public W
|
||||
{
|
||||
public:
|
||||
BoolSetting(wxWindow* parent, const wxString& label, bool &setting, bool reverse = false, long style = 0);
|
||||
void UpdateValue(wxCommandEvent& ev);
|
||||
private:
|
||||
bool &m_setting;
|
||||
const bool m_reverse;
|
||||
};
|
||||
|
||||
class SettingChoice : public wxChoice
|
||||
{
|
||||
public:
|
||||
SettingChoice(wxWindow* parent, int &setting, int num = 0, const wxString choices[] = NULL);
|
||||
void UpdateValue(wxCommandEvent& ev);
|
||||
private:
|
||||
int &m_setting;
|
||||
};
|
||||
|
||||
class VideoConfigDiag : public wxDialog
|
||||
{
|
||||
public:
|
||||
VideoConfigDiag(wxWindow* parent);
|
||||
|
||||
protected:
|
||||
void CloseDiag(wxCommandEvent&);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,6 +13,7 @@ files = [
|
|||
'WiimoteEmu/Attachment/Nunchuk.cpp',
|
||||
'WiimoteEmu/Attachment/Drums.cpp',
|
||||
'WiimoteEmu/Attachment/Guitar.cpp',
|
||||
'WiimoteEmu/Attachment/Turntable.cpp',
|
||||
'WiimoteEmu/EmuSubroutines.cpp',
|
||||
'WiimoteEmu/Encryption.cpp',
|
||||
'WiimoteEmu/Speaker.cpp',
|
||||
|
|
|
@ -1,122 +1,122 @@
|
|||
#include "Turntable.h"
|
||||
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
static const u8 turntable_id[] = {0x03, 0x00, 0xa4, 0x20, 0x01, 0x03};
|
||||
|
||||
static const u16 turntable_button_bitmasks[] =
|
||||
{
|
||||
Turntable::BUTTON_L_GREEN,
|
||||
Turntable::BUTTON_L_RED,
|
||||
Turntable::BUTTON_L_BLUE,
|
||||
Turntable::BUTTON_R_GREEN,
|
||||
Turntable::BUTTON_R_RED,
|
||||
Turntable::BUTTON_R_BLUE,
|
||||
Turntable::BUTTON_MINUS,
|
||||
Turntable::BUTTON_PLUS,
|
||||
Turntable::BUTTON_EUPHORIA,
|
||||
};
|
||||
|
||||
static const char* const turntable_button_names[] =
|
||||
{
|
||||
"Green Left", "Red Left", "Blue Left",
|
||||
"Green Right", "Red Right", "Blue Right",
|
||||
"-", "+", "Euphoria",
|
||||
};
|
||||
|
||||
Turntable::Turntable() : Attachment("Turntable")
|
||||
{
|
||||
// buttons
|
||||
// TODO: separate buttons into Left and Right
|
||||
groups.push_back(m_buttons = new Buttons("Buttons"));
|
||||
for (unsigned int i = 0; i < sizeof(turntable_button_names)/sizeof(*turntable_button_names); ++i)
|
||||
m_buttons->controls.push_back(new ControlGroup::Input( turntable_button_names[i]));
|
||||
|
||||
// stick
|
||||
groups.push_back(m_stick = new AnalogStick("Stick"));
|
||||
|
||||
// TODO:
|
||||
groups.push_back(m_effect_dial = new Triggers("Effect"));
|
||||
m_effect_dial->controls.push_back(new ControlGroup::Input("Dial"));
|
||||
|
||||
//m_left_turntable
|
||||
//m_right_turntable
|
||||
//m_crossfade_slider
|
||||
|
||||
// set up register
|
||||
// id
|
||||
memcpy(®[0xfa], turntable_id, sizeof(turntable_id));
|
||||
}
|
||||
|
||||
void Turntable::GetState(u8* const data, const bool focus)
|
||||
{
|
||||
wm_turntable_extension* const ttdata = (wm_turntable_extension*)data;
|
||||
ttdata->bt = 0;
|
||||
|
||||
// stick
|
||||
{
|
||||
u8 x, y;
|
||||
m_stick->GetState(&x, &y, 0x20, focus ? 0x1F /*0x15*/ : 0);
|
||||
|
||||
ttdata->sx = x;
|
||||
ttdata->sy = y;
|
||||
}
|
||||
|
||||
// left table
|
||||
// TODO:
|
||||
{
|
||||
s8 tt = 0;
|
||||
//m_left_turntable->GetState(&tt .....);
|
||||
|
||||
ttdata->ltable1 = tt;
|
||||
ttdata->ltable2 = tt << 5;
|
||||
}
|
||||
|
||||
// right table
|
||||
// TODO:
|
||||
{
|
||||
s8 tt = 0;
|
||||
//m_right_turntable->GetState(&tt .....);
|
||||
|
||||
ttdata->rtable1 = tt;
|
||||
ttdata->rtable2 = tt << 1;
|
||||
ttdata->rtable3 = tt << 3;
|
||||
ttdata->rtable4 = tt << 5;
|
||||
}
|
||||
|
||||
// effect dial
|
||||
{
|
||||
u8 dial = 0;
|
||||
m_effect_dial->GetState(&dial, focus ? 0xF : 0);
|
||||
|
||||
ttdata->dial1 = dial;
|
||||
ttdata->dial2 = dial << 3;
|
||||
}
|
||||
|
||||
// crossfade slider
|
||||
// TODO:
|
||||
{
|
||||
u8 cfs = 0;
|
||||
//m_crossfade_slider->GetState(&cfs .....);
|
||||
|
||||
ttdata->slider = cfs;
|
||||
}
|
||||
|
||||
if (focus)
|
||||
{
|
||||
// buttons
|
||||
m_buttons->GetState(&ttdata->bt, turntable_button_bitmasks);
|
||||
}
|
||||
|
||||
// flip button bits :/
|
||||
ttdata->bt ^= (
|
||||
BUTTON_L_GREEN | BUTTON_L_RED | BUTTON_L_BLUE |
|
||||
BUTTON_R_GREEN | BUTTON_R_RED | BUTTON_R_BLUE |
|
||||
BUTTON_MINUS | BUTTON_PLUS | BUTTON_EUPHORIA
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#include "Turntable.h"
|
||||
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
static const u8 turntable_id[] = {0x03, 0x00, 0xa4, 0x20, 0x01, 0x03};
|
||||
|
||||
static const u16 turntable_button_bitmasks[] =
|
||||
{
|
||||
Turntable::BUTTON_L_GREEN,
|
||||
Turntable::BUTTON_L_RED,
|
||||
Turntable::BUTTON_L_BLUE,
|
||||
Turntable::BUTTON_R_GREEN,
|
||||
Turntable::BUTTON_R_RED,
|
||||
Turntable::BUTTON_R_BLUE,
|
||||
Turntable::BUTTON_MINUS,
|
||||
Turntable::BUTTON_PLUS,
|
||||
Turntable::BUTTON_EUPHORIA,
|
||||
};
|
||||
|
||||
static const char* const turntable_button_names[] =
|
||||
{
|
||||
"Green Left", "Red Left", "Blue Left",
|
||||
"Green Right", "Red Right", "Blue Right",
|
||||
"-", "+", "Euphoria",
|
||||
};
|
||||
|
||||
Turntable::Turntable() : Attachment("Turntable")
|
||||
{
|
||||
// buttons
|
||||
// TODO: separate buttons into Left and Right
|
||||
groups.push_back(m_buttons = new Buttons("Buttons"));
|
||||
for (unsigned int i = 0; i < sizeof(turntable_button_names)/sizeof(*turntable_button_names); ++i)
|
||||
m_buttons->controls.push_back(new ControlGroup::Input( turntable_button_names[i]));
|
||||
|
||||
// stick
|
||||
groups.push_back(m_stick = new AnalogStick("Stick"));
|
||||
|
||||
// TODO:
|
||||
groups.push_back(m_effect_dial = new Triggers("Effect"));
|
||||
m_effect_dial->controls.push_back(new ControlGroup::Input("Dial"));
|
||||
|
||||
//m_left_turntable
|
||||
//m_right_turntable
|
||||
//m_crossfade_slider
|
||||
|
||||
// set up register
|
||||
// id
|
||||
memcpy(®[0xfa], turntable_id, sizeof(turntable_id));
|
||||
}
|
||||
|
||||
void Turntable::GetState(u8* const data, const bool focus)
|
||||
{
|
||||
wm_turntable_extension* const ttdata = (wm_turntable_extension*)data;
|
||||
ttdata->bt = 0;
|
||||
|
||||
// stick
|
||||
{
|
||||
u8 x, y;
|
||||
m_stick->GetState(&x, &y, 0x20, focus ? 0x1F /*0x15*/ : 0);
|
||||
|
||||
ttdata->sx = x;
|
||||
ttdata->sy = y;
|
||||
}
|
||||
|
||||
// left table
|
||||
// TODO:
|
||||
{
|
||||
s8 tt = 0;
|
||||
//m_left_turntable->GetState(&tt .....);
|
||||
|
||||
ttdata->ltable1 = tt;
|
||||
ttdata->ltable2 = tt << 5;
|
||||
}
|
||||
|
||||
// right table
|
||||
// TODO:
|
||||
{
|
||||
s8 tt = 0;
|
||||
//m_right_turntable->GetState(&tt .....);
|
||||
|
||||
ttdata->rtable1 = tt;
|
||||
ttdata->rtable2 = tt << 1;
|
||||
ttdata->rtable3 = tt << 3;
|
||||
ttdata->rtable4 = tt << 5;
|
||||
}
|
||||
|
||||
// effect dial
|
||||
{
|
||||
u8 dial = 0;
|
||||
m_effect_dial->GetState(&dial, focus ? 0xF : 0);
|
||||
|
||||
ttdata->dial1 = dial;
|
||||
ttdata->dial2 = dial << 3;
|
||||
}
|
||||
|
||||
// crossfade slider
|
||||
// TODO:
|
||||
{
|
||||
u8 cfs = 0;
|
||||
//m_crossfade_slider->GetState(&cfs .....);
|
||||
|
||||
ttdata->slider = cfs;
|
||||
}
|
||||
|
||||
if (focus)
|
||||
{
|
||||
// buttons
|
||||
m_buttons->GetState(&ttdata->bt, turntable_button_bitmasks);
|
||||
}
|
||||
|
||||
// flip button bits :/
|
||||
ttdata->bt ^= (
|
||||
BUTTON_L_GREEN | BUTTON_L_RED | BUTTON_L_BLUE |
|
||||
BUTTON_R_GREEN | BUTTON_R_RED | BUTTON_R_BLUE |
|
||||
BUTTON_MINUS | BUTTON_PLUS | BUTTON_EUPHORIA
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
#include "Attachment.h"
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
class Turntable : public Attachment
|
||||
{
|
||||
public:
|
||||
Turntable();
|
||||
void GetState(u8* const data, const bool focus);
|
||||
|
||||
enum
|
||||
{
|
||||
BUTTON_EUPHORIA = 0x1000,
|
||||
|
||||
BUTTON_L_GREEN = 0x0800,
|
||||
BUTTON_L_RED = 0x20,
|
||||
BUTTON_L_BLUE = 0x8000,
|
||||
|
||||
BUTTON_R_GREEN = 0x2000,
|
||||
BUTTON_R_RED = 0x02,
|
||||
BUTTON_R_BLUE = 0x0400,
|
||||
|
||||
BUTTON_MINUS = 0x10,
|
||||
BUTTON_PLUS = 0x04,
|
||||
};
|
||||
|
||||
private:
|
||||
Buttons* m_buttons;
|
||||
MixedTriggers* m_triggers;
|
||||
AnalogStick* m_stick;
|
||||
|
||||
Triggers *m_effect_dial;
|
||||
|
||||
// TODO:
|
||||
//m_left_turntable
|
||||
//m_right_turntable
|
||||
//m_crossfade_slider
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#include "Attachment.h"
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
class Turntable : public Attachment
|
||||
{
|
||||
public:
|
||||
Turntable();
|
||||
void GetState(u8* const data, const bool focus);
|
||||
|
||||
enum
|
||||
{
|
||||
BUTTON_EUPHORIA = 0x1000,
|
||||
|
||||
BUTTON_L_GREEN = 0x0800,
|
||||
BUTTON_L_RED = 0x20,
|
||||
BUTTON_L_BLUE = 0x8000,
|
||||
|
||||
BUTTON_R_GREEN = 0x2000,
|
||||
BUTTON_R_RED = 0x02,
|
||||
BUTTON_R_BLUE = 0x0400,
|
||||
|
||||
BUTTON_MINUS = 0x10,
|
||||
BUTTON_PLUS = 0x04,
|
||||
};
|
||||
|
||||
private:
|
||||
Buttons* m_buttons;
|
||||
MixedTriggers* m_triggers;
|
||||
AnalogStick* m_stick;
|
||||
|
||||
Triggers *m_effect_dial;
|
||||
|
||||
// TODO:
|
||||
//m_left_turntable
|
||||
//m_right_turntable
|
||||
//m_crossfade_slider
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,95 +1,95 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="ASM"
|
||||
ProjectGUID="{B0723635-279A-44E0-80A6-FC21DBB7A4B4}"
|
||||
RootNamespace="TestSuite"
|
||||
Keyword="MakeFileProj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="build"
|
||||
IntermediateDirectory="build"
|
||||
ConfigurationType="0"
|
||||
BuildLogFile="build\BuildLog.htm"
|
||||
>
|
||||
<Tool
|
||||
Name="VCNMakeTool"
|
||||
BuildCommandLine="make -r 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):/\1(\2):/’"
|
||||
ReBuildCommandLine="make clean && make -r 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):/\1(\2):/’"
|
||||
CleanCommandLine="make clean"
|
||||
Output="dolphintest_asm.dol"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG"
|
||||
IncludeSearchPath="$(ProjectDir)\include;C:\devkitPro\libogc\include"
|
||||
ForcedIncludes=""
|
||||
AssemblySearchPath=""
|
||||
ForcedUsingAssemblies=""
|
||||
CompileAsManaged=""
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath=".\source\asm_float.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\asm_integer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\asm_tables.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\asm_tables.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Defines.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\dolphintest_asm.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Helpers.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Helpers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Init.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Init.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Instructions.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Makefile"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="ASM"
|
||||
ProjectGUID="{B0723635-279A-44E0-80A6-FC21DBB7A4B4}"
|
||||
RootNamespace="TestSuite"
|
||||
Keyword="MakeFileProj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="build"
|
||||
IntermediateDirectory="build"
|
||||
ConfigurationType="0"
|
||||
BuildLogFile="build\BuildLog.htm"
|
||||
>
|
||||
<Tool
|
||||
Name="VCNMakeTool"
|
||||
BuildCommandLine="make -r 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):/\1(\2):/’"
|
||||
ReBuildCommandLine="make clean && make -r 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):/\1(\2):/’"
|
||||
CleanCommandLine="make clean"
|
||||
Output="dolphintest_asm.dol"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG"
|
||||
IncludeSearchPath="$(ProjectDir)\include;C:\devkitPro\libogc\include"
|
||||
ForcedIncludes=""
|
||||
AssemblySearchPath=""
|
||||
ForcedUsingAssemblies=""
|
||||
CompileAsManaged=""
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath=".\source\asm_float.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\asm_integer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\asm_tables.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\asm_tables.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Defines.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\dolphintest_asm.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Helpers.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Helpers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Init.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Init.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Instructions.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Makefile"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
|
|
Loading…
Reference in New Issue