GL plugin: VSync option, some renaming, a little bit of MSAA preparations (not there yet)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2563 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2009-03-05 23:11:13 +00:00
parent 02a4b49df1
commit 75390c55bd
17 changed files with 268 additions and 289 deletions

View File

@ -84,7 +84,7 @@ void BPWritten(int addr, int changes, int newval)
glEnable(GL_CULL_FACE);
glFrontFace(bpmem.genMode.cullmode == 2 ? GL_CCW : GL_CW);
}
else if (glIsEnabled(GL_CULL_FACE) == GL_TRUE)
else
glDisable(GL_CULL_FACE);
PixelShaderManager::SetGenModeChanged();
}
@ -159,7 +159,7 @@ void BPWritten(int addr, int changes, int newval)
case BPMEM_LINEPTWIDTH:
{
float fratio = xfregs.rawViewport[0] != 0 ? (float)Renderer::GetTargetWidth() / 640.0f : 1.0f;
float fratio = xfregs.rawViewport[0] != 0 ? ((float)Renderer::GetTargetWidth() / EFB_WIDTH) : 1.0f;
if (bpmem.lineptwidth.linesize > 0)
glLineWidth((float)bpmem.lineptwidth.linesize * fratio / 6.0f); // scale by ratio of widths
if (bpmem.lineptwidth.pointsize > 0)
@ -243,13 +243,6 @@ void BPWritten(int addr, int changes, int newval)
break;
case BPMEM_FOGRANGE:
if (changes) {
// TODO(XK): Fog range format
//glFogi(GL_FOG_START, ...
//glFogi(GL_FOG_END, ...
}
break;
case BPMEM_FOGPARAM0:
case BPMEM_FOGBEXPONENT:
case BPMEM_FOGBMAGNITUDE:
@ -363,9 +356,9 @@ void BPWritten(int addr, int changes, int newval)
case BPMEM_SETGPMETRIC: // Set gp metric?
break;
// ===============================================================
// This case writes to bpmem.triggerEFBCopy and may apparently prompt us to update glScissor()
// ------------------------
// EFB copy command. This copies a rectangle from the EFB to either RAM in a texture format or to XFB as YUYV.
// It can also optionally clear the EFB while copying from it. To emulate this, we of course copy first and clear afterwards.
case BPMEM_TRIGGER_EFB_COPY:
{
DVSTARTSUBPROFILE("LoadBPReg:swap");
@ -395,33 +388,30 @@ void BPWritten(int addr, int changes, int newval)
PE_copy.Hex = bpmem.triggerEFBCopy;
// --------------------------------------------------------
// Check if we should copy the picture to XFB or not
// Check to where we should copy the image data from the EFB.
// --------------------------
if (PE_copy.copy_to_xfb == 0)
{
// EFB to texture
// for some reason it sets bpmem.zcontrol.pixel_format to PIXELFMT_Z24 every time a zbuffer format is given as a dest to GXSetTexCopyDst
if (g_Config.bEFBCopyDisable)
if (!g_Config.bEFBCopyDisable)
{
/* We already have this in Render.cpp that we call when (PE_copy.clear) is true. But we need a separate one
here because UpdateViewport() is not run when this option is set? */
glViewport(rc.left, rc.bottom, rc.right,rc.top);
glScissor(rc.left, rc.bottom, rc.right,rc.top);
// Logging
GLScissorX = rc.left;
GLScissorY = rc.bottom;
GLScissorW = rc.right;
GLScissorH = rc.top;
}
else if (g_Config.bCopyEFBToRAM)
{
TextureConverter::EncodeToRam(bpmem.copyTexDest<<5, bpmem.zcontrol.pixel_format==PIXELFMT_Z24, PE_copy.intensity_fmt>0,
(PE_copy.target_pixel_format/2)+((PE_copy.target_pixel_format&1)*8), PE_copy.half_scale>0, rc);
}
else
{
TextureMngr::CopyRenderTargetToTexture(bpmem.copyTexDest<<5, bpmem.zcontrol.pixel_format==PIXELFMT_Z24, PE_copy.intensity_fmt>0,
(PE_copy.target_pixel_format/2)+((PE_copy.target_pixel_format&1)*8), PE_copy.half_scale>0, &rc);
if (g_Config.bCopyEFBToRAM)
{
TextureConverter::EncodeToRam(bpmem.copyTexDest<<5,
bpmem.zcontrol.pixel_format==PIXELFMT_Z24,
PE_copy.intensity_fmt > 0,
(PE_copy.target_pixel_format/2) + ((PE_copy.target_pixel_format&1) * 8), // ??
PE_copy.half_scale>0, rc);
}
else
{
TextureMngr::CopyRenderTargetToTexture(bpmem.copyTexDest<<5,
bpmem.zcontrol.pixel_format==PIXELFMT_Z24,
PE_copy.intensity_fmt > 0,
(PE_copy.target_pixel_format/2) + ((PE_copy.target_pixel_format & 1)*8), // ??
PE_copy.half_scale > 0, rc);
}
}
}
else
@ -446,6 +436,8 @@ void BPWritten(int addr, int changes, int newval)
}
else
{
// Hm, we need to compensate for the fact that the copy may be bigger than what is displayed.
// Seen in Spartan Warrior. Not sure how to deal with it yet.
Renderer::Swap(multirc);
}
g_VideoInitialize.pCopiedToXFB();
@ -459,16 +451,12 @@ void BPWritten(int addr, int changes, int newval)
// Clear color
Renderer::SetRenderMode(Renderer::RM_Normal);
// Clear Z-Buffer target
u32 nRestoreZBufferTarget = Renderer::GetZBufferTarget();
bool bRestoreZBufferTarget = Renderer::GetFakeZTarget() != 0;
// -----------------------------------------------------------------
// Update the view port for clearing the picture
// -----------------------
glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight());
// Always set the scissor in case it was set by the game and has not been reset
/* We will also do this at the end of this section, in SetScissorRect(), but that is for creating the new picture
this is for clearing the picture */
glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom),
(multirc.right - multirc.left), (multirc.bottom - multirc.top));
// ---------------------------
@ -484,23 +472,23 @@ void BPWritten(int addr, int changes, int newval)
{
u32 clearColor = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
glClearColor(((clearColor>>16) & 0xff)*(1/255.0f),
((clearColor>>8 ) & 0xff)*(1/255.0f),
((clearColor>>0 ) & 0xff)*(1/255.0f),
((clearColor>>24) & 0xff)*(1/255.0f));
((clearColor>>8 ) & 0xff)*(1/255.0f),
((clearColor>>0 ) & 0xff)*(1/255.0f),
((clearColor>>24) & 0xff)*(1/255.0f));
bits |= GL_COLOR_BUFFER_BIT;
}
if (bpmem.zmode.updateenable)
{
glClearDepth((float)(bpmem.clearZValue&0xFFFFFF) / float(0xFFFFFF));
glClearDepth((float)(bpmem.clearZValue & 0xFFFFFF) / float(0xFFFFFF));
bits |= GL_DEPTH_BUFFER_BIT;
}
if (nRestoreZBufferTarget )
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); // don't clear ztarget here
if (bRestoreZBufferTarget)
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); // don't clear ztarget here
glClear(bits);
}
// Have to clear the target zbuffer
if (bpmem.zmode.updateenable && nRestoreZBufferTarget)
if (bpmem.zmode.updateenable && bRestoreZBufferTarget)
{
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
GL_REPORT_ERRORD();
@ -515,16 +503,14 @@ void BPWritten(int addr, int changes, int newval)
GL_REPORT_ERRORD();
}
if (nRestoreZBufferTarget)
if (bRestoreZBufferTarget)
{
// restore target
GLenum s_drawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
glDrawBuffers(2, s_drawbuffers);
}
Renderer::SetScissorRect(); // reset the scissor rectangle
}
// ------------------------------
Renderer::RestoreGLState();
}
break;
// ==================================
@ -643,7 +629,7 @@ void BPWritten(int addr, int changes, int newval)
break;
default:
switch(addr&0xF0) {
switch (addr&0xF0) {
case 0x10: // tevindirect 0-15
if (changes) {
VertexManager::Flush();

View File

@ -41,6 +41,7 @@ void Config::Load()
strncpy(iFSResolution, temp.c_str(), 16);
iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware
iniFile.Get("Hardware", "VSync", &bVSync, 0); // Hardware
iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, false);
iniFile.Get("Settings", "StretchToFit", &bNativeResolution, true);
iniFile.Get("Settings", "KeepAR_4_3", &bKeepAR43, false);
@ -93,6 +94,7 @@ void Config::Save()
iniFile.Set("Hardware", "WindowedRes", iWindowedRes);
iniFile.Set("Hardware", "FullscreenRes", iFSResolution);
iniFile.Set("Hardware", "Fullscreen", bFullscreen);
iniFile.Set("Hardware", "VSync", bVSync);
iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe);
iniFile.Set("Settings", "StretchToFit", bNativeResolution);
iniFile.Set("Settings", "KeepAR_4_3", bKeepAR43);

View File

@ -38,6 +38,7 @@ struct Config
bool bFullscreen;
bool bHideCursor;
bool renderToMainframe;
bool bVSync;
// Resolution control
char iFSResolution[16];

View File

@ -27,6 +27,7 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
EVT_BUTTON(ID_CLOSE, ConfigDialog::CloseClick)
EVT_BUTTON(ID_ABOUTOGL, ConfigDialog::AboutClick)
EVT_CHECKBOX(ID_FULLSCREEN, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_VSYNC, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_RENDERTOMAINWINDOW, ConfigDialog::GeneralSettingsChanged)
EVT_COMBOBOX(ID_FULLSCREENCB, ConfigDialog::GeneralSettingsChanged)
EVT_COMBOBOX(ID_WINDOWRESOLUTIONCB, ConfigDialog::GeneralSettingsChanged)
@ -161,6 +162,8 @@ void ConfigDialog::CreateGUIControls()
sbBasic = new wxStaticBoxSizer(wxVERTICAL, m_PageGeneral, wxT("Basic Settings"));
m_Fullscreen = new wxCheckBox(m_PageGeneral, ID_FULLSCREEN, wxT("Fullscreen"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_Fullscreen->SetValue(g_Config.bFullscreen);
m_VSync = new wxCheckBox(m_PageGeneral, ID_VSYNC, wxT("VSync (req. restart)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_VSync->SetValue(g_Config.bVSync);
m_RenderToMainWindow = new wxCheckBox(m_PageGeneral, ID_RENDERTOMAINWINDOW, wxT("Render to main window"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_RenderToMainWindow->SetValue(g_Config.renderToMainframe);
m_NativeResolution = new wxCheckBox(m_PageGeneral, ID_NATIVERESOLUTION, wxT("Native resolution"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
@ -239,16 +242,17 @@ void ConfigDialog::CreateGUIControls()
sGeneral = new wxBoxSizer(wxVERTICAL);
sBasic = new wxGridBagSizer(0, 0);
sBasic->Add(m_Fullscreen, wxGBPosition(0, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_RenderToMainWindow, wxGBPosition(1, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_AutoScale, wxGBPosition(2, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_NativeResolution, wxGBPosition(3, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_UseXFB, wxGBPosition(4, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_KeepAR43, wxGBPosition(5, 0), wxGBSpan(1, 1), wxALL, 5);
sBasic->Add(m_KeepAR169, wxGBPosition(5, 1), wxGBSpan(1, 1), wxALL, 5);
sBasic->Add(m_Crop, wxGBPosition(5, 2), wxGBSpan(1, 1), wxALL, 5);
sBasic->Add(m_VSync, wxGBPosition(1, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_RenderToMainWindow, wxGBPosition(2, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_AutoScale, wxGBPosition(3, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_NativeResolution, wxGBPosition(4, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_UseXFB, wxGBPosition(5, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_KeepAR43, wxGBPosition(6, 0), wxGBSpan(1, 1), wxALL, 5);
sBasic->Add(m_KeepAR169, wxGBPosition(6, 1), wxGBSpan(1, 1), wxALL, 5);
sBasic->Add(m_Crop, wxGBPosition(6, 2), wxGBSpan(1, 1), wxALL, 5);
// Because of the ifdef here we need this variable for the row number
int Row = 6;
int Row = 7;
#ifndef _WIN32
sBasic->Add(m_HideCursor, wxGBPosition(Row++, 0), wxGBSpan(1, 3), wxALL, 5);
#endif
@ -430,7 +434,9 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
case ID_NATIVERESOLUTION:
g_Config.bNativeResolution = m_NativeResolution->IsChecked();
break;
case ID_VSYNC:
g_Config.bVSync = m_VSync->IsChecked();
break;
case ID_USEXFB:
g_Config.bUseXFB = m_UseXFB->IsChecked();
break;

View File

@ -75,6 +75,7 @@ class ConfigDialog : public wxDialog
wxPanel *m_PageGeneral;
wxPanel *m_PageAdvanced;
wxCheckBox *m_Fullscreen;
wxCheckBox *m_VSync;
wxCheckBox *m_RenderToMainWindow;
wxCheckBox *m_NativeResolution;
wxCheckBox *m_KeepAR43, *m_KeepAR169, *m_Crop;
@ -125,6 +126,7 @@ class ConfigDialog : public wxDialog
ID_PAGEADVANCED,
ID_FULLSCREEN,
ID_VSYNC,
ID_RENDERTOMAINWINDOW,
ID_NATIVERESOLUTION,
ID_KEEPAR_4_3, ID_KEEPAR_16_9, ID_CROP,

View File

@ -63,7 +63,7 @@ bool LocalLogFile = true;
#if LOGLEVEL > 0
void __Log(const char *fmt, ...)
{
int len = strlen(fmt);
size_t len = strlen(fmt);
if (!len)
return;
char* Msg = (char*)alloca(len + 512);

View File

@ -109,7 +109,7 @@ FRAGMENTSHADER* PixelShaderCache::GetShader()
{
DVSTARTPROFILE();
PIXELSHADERUID uid;
u32 zbufrender = (Renderer::GetZBufferTarget() && bpmem.zmode.updateenable) ? 1 : 0;
u32 zbufrender = (Renderer::GetFakeZTarget() && bpmem.zmode.updateenable) ? 1 : 0;
u32 zBufRenderToCol0 = Renderer::GetRenderMode() != Renderer::RM_Normal;
GetPixelShaderId(uid, PixelShaderManager::GetTextureMask(), zbufrender, zBufRenderToCol0);
@ -127,7 +127,7 @@ FRAGMENTSHADER* PixelShaderCache::GetShader()
PSCacheEntry& newentry = pshaders[uid];
const char *code = GeneratePixelShader(PixelShaderManager::GetTextureMask(),
Renderer::GetZBufferTarget() != 0,
Renderer::GetFakeZTarget() != 0,
Renderer::GetRenderMode() != Renderer::RM_Normal);
#if defined(_DEBUG) || defined(DEBUGFAST)

View File

@ -15,8 +15,8 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Globals.h"
#include <vector>
#include <cmath>
@ -63,7 +63,6 @@
#else
#endif
CGcontext g_cgcontext;
CGprofile g_cgvProf;
CGprofile g_cgfProf;
@ -72,15 +71,38 @@ RasterFont* s_pfont = NULL;
static bool s_bFullscreen = false;
static int nZBufferRender = 0; // if > 0, then use zbuffer render, and count down.
static int nZBufferRender = 0; // if > 0, then use zbuffer render, and count down.
static bool MSAA = false;
// Normal Mode
// s_RenderTarget is a texture_rect
// s_DepthTarget is a Z renderbuffer
// s_FakeZTarget is a texture_rect
// MSAA mode
// s_uFramebuffer is a FBO
// s_RenderTarget is a MSAA renderbuffer
// s_FakeZBufferTarget is a MSAA renderbuffer
// s_DepthTarget is a real MSAA z/stencilbuffer
//
// s_ResolvedFramebuffer is a FBO
// s_ResolvedColorTarget is a texture
// s_ResolvedFakeZTarget is a texture
// s_ResolvedDepthTarget is a Z renderbuffer
// A framebuffer is a set of render targets: a color and a z buffer. They can be either RenderBuffers or Textures.
static GLuint s_uFramebuffer = 0;
// The size of these should be a (not necessarily even) multiple of the EFB size, 640x528, but isn'.t
// The size of these should be a (not necessarily even) multiple of the EFB size, 640x528, but isn't.
// These are all texture IDs. Bind them as rect arb textures.
static GLuint s_RenderTarget = 0;
static GLuint s_DepthTarget = 0;
static GLuint s_ZBufferTarget = 0;
static GLuint s_FakeZTarget = 0;
static GLuint s_DepthTarget = 0;
static GLuint s_ResolvedRenderTarget = 0;
static GLuint s_ResolvedFakeZTarget = 0;
static GLuint s_ResolvedDepthTarget = 0;
static bool s_bATIDrawBuffers = false;
static bool s_bHaveStencilBuffer = false;
@ -96,13 +118,16 @@ bool g_bBlendSeparate = false;
int frameCount;
static int s_fps = 0;
// These STAY CONSTANT during execution, no matter how much you resize the game window.
// These STAY CONSTANT during execution, no matter how much you resize the game window.\
// TODO: Add functionality to reinit all the render targets when the window is resized.
static int s_targetwidth; // Size of render buffer FBO.
static int s_targetheight;
static u32 s_blendMode;
void HandleCgError(CGcontext ctx, CGerror err, void *appdata);
extern void HandleCgError(CGcontext ctx, CGerror err, void *appdata);
namespace {
static const GLenum glSrcFactors[8] =
{
@ -121,6 +146,24 @@ static const GLenum glDestFactors[8] = {
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA
};
void SetDefaultRectTexParams()
{
// Set some standard texture filter modes.
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (glGetError() != GL_NO_ERROR) {
GLenum err;
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
GL_REPORT_ERROR();
}
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
} // namespace
bool Renderer::Init()
{
bool bSuccess = true;
@ -132,6 +175,7 @@ bool Renderer::Init()
cgGetError();
cgSetErrorHandler(HandleCgError, NULL);
// Look for required extensions.
const char *ptoken = (const char*)glGetString(GL_EXTENSIONS);
if (!ptoken)
@ -143,9 +187,10 @@ bool Renderer::Init()
INFO_LOG(VIDEO, ptoken); // write to the log file
INFO_LOG(VIDEO, "\n");
if (strstr(ptoken, "GL_EXT_blend_func_separate") != NULL && strstr(ptoken,
"GL_EXT_blend_equation_separate") != NULL)
if (strstr(ptoken, "GL_EXT_blend_func_separate") != NULL &&
strstr(ptoken, "GL_EXT_blend_equation_separate") != NULL)
g_bBlendSeparate = true;
// Checks if it ONLY has the ATI_draw_buffers extension, some have both
if (GLEW_ATI_draw_buffers && !GLEW_ARB_draw_buffers)
s_bATIDrawBuffers = true;
@ -176,20 +221,17 @@ bool Renderer::Init()
if (!bSuccess)
return false;
// Handle VSync on/off
#ifdef _WIN32
if (WGLEW_EXT_swap_control)
wglSwapIntervalEXT(0);
wglSwapIntervalEXT(g_Config.bVSync ? 1 : 0);
else
ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)\nDoes your video card support OpenGL 2.x?");
#elif defined(HAVE_X11) && HAVE_X11
if (glXSwapIntervalSGI)
glXSwapIntervalSGI(0);
glXSwapIntervalSGI(g_Config.bVSync ? 1 : 0);
else
ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)\n");
#else
//TODO
#endif
// check the max texture width and height
@ -229,83 +271,60 @@ bool Renderer::Init()
if (s_targetheight < EFB_HEIGHT)
s_targetheight = EFB_HEIGHT;
// Create the framebuffer target texture
glGenTextures(1, (GLuint *)&s_RenderTarget);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_RenderTarget);
if (!MSAA) {
// Create the framebuffer target texture
glGenTextures(1, (GLuint *)&s_RenderTarget);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_RenderTarget);
// Create our main color render target as a texture rectangle of the desired size.
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, s_targetwidth, s_targetheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
SetDefaultRectTexParams();
// Setup the texture params
// initialize to default
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, s_targetwidth, s_targetheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (glGetError() != GL_NO_ERROR) {
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
GL_REPORT_ERROR();
}
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GL_REPORT_ERROR();
GL_REPORT_ERROR();
GLint nMaxMRT = 0;
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &nMaxMRT);
if (nMaxMRT > 1)
{
// There's MRT support. Create a color texture image to use as secondary render target.
// We use MRT to render Z into this one, for various purposes (mostly copy Z to texture).
glGenTextures(1, (GLuint *)&s_FakeZTarget);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_FakeZTarget);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, s_targetwidth, s_targetheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
SetDefaultRectTexParams();
}
GLint nMaxMRT = 0;
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &nMaxMRT);
if (nMaxMRT > 1)
{
// Create zbuffer target.
glGenTextures(1, (GLuint *)&s_ZBufferTarget);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, s_targetwidth, s_targetheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (glGetError() != GL_NO_ERROR) {
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
GL_REPORT_ERROR();
}
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
// Create the real depth/stencil buffer. It's a renderbuffer, not a texture.
glGenRenderbuffersEXT(1, &s_DepthTarget);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_DepthTarget);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, s_targetwidth, s_targetheight);
GL_REPORT_ERROR();
// Our framebuffer object is still bound here. Attach the two render targets, color and Z/stencil, to the framebuffer object.
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, s_RenderTarget, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget);
GL_REPORT_ERROR();
// create the depth buffer
glGenRenderbuffersEXT(1, &s_DepthTarget);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_DepthTarget);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, s_targetwidth, s_targetheight);
if (glGetError() != GL_NO_ERROR)
{
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, s_targetwidth, s_targetheight);
s_bHaveStencilBuffer = false;
}
else
{
s_bHaveStencilBuffer = true;
if (s_FakeZTarget != 0) {
// We do a simple test to make sure that MRT works. I don't really know why - this is probably a workaround for
// some terribly buggy ancient driver.
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, s_FakeZTarget, 0);
bool bFailed = glGetError() != GL_NO_ERROR || glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT;
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
if (bFailed) {
glDeleteTextures(1, (GLuint *)&s_FakeZTarget);
s_FakeZTarget = 0;
}
}
if (s_FakeZTarget == 0)
ERROR_LOG(VIDEO, "Disabling ztarget MRT feature (max MRT = %d)\n", nMaxMRT);
} else {
// TODO MSAA rendertarget init
}
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
GL_REPORT_ERROR();
// Select our render and depth targets as render targets.
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, s_RenderTarget, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget);
GL_REPORT_ERROR();
if (s_ZBufferTarget != 0) {
// test to make sure it works
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget, 0);
bool bFailed = glGetError() != GL_NO_ERROR || glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT;
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
if (bFailed) {
glDeleteTextures(1, (GLuint *)&s_ZBufferTarget);
s_ZBufferTarget = 0;
}
}
if (s_ZBufferTarget == 0)
ERROR_LOG(VIDEO, "Disabling ztarget MRT feature (max MRT = %d)\n", nMaxMRT);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
nZBufferRender = 0;
nZBufferRender = 0; // Initialize the Z render shutoff countdown. We only render Z if it's desired, to save GPU power.
GL_REPORT_ERROR();
if (err != GL_NO_ERROR)
@ -331,9 +350,9 @@ bool Renderer::Init()
INFO_LOG(VIDEO, "Max buffer sizes: %d %d\n", cgGetProgramBufferMaxSize(g_cgvProf), cgGetProgramBufferMaxSize(g_cgfProf));
int nenvvertparams, nenvfragparams, naddrregisters[2];
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvvertparams);
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvfragparams);
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[0]);
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvvertparams);
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvfragparams);
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[0]);
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[1]);
DEBUG_LOG(VIDEO, "Max program env parameters: vert=%d, frag=%d\n", nenvvertparams, nenvfragparams);
DEBUG_LOG(VIDEO, "Max program address register parameters: vert=%d, frag=%d\n", naddrregisters[0], naddrregisters[1]);
@ -344,14 +363,8 @@ bool Renderer::Init()
#ifndef _DEBUG
cgGLSetDebugMode(GL_FALSE);
#endif
if (cgGetError() != CG_NO_ERROR) {
ERROR_LOG(VIDEO, "cg error\n");
return false;
}
s_RenderMode = Renderer::RM_Normal;
if (!InitializeGL())
return false;
@ -406,13 +419,13 @@ bool Renderer::InitializeGL()
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // perspective correct interpolation of colors and tex coords
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glHint(GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE); // Polygon smoothing is ancient junk that doesn't work anymore. MSAA is modern AA.
glDisable(GL_STENCIL_TEST);
glEnable(GL_SCISSOR_TEST);
// Do we really need to set this initial glScissor() value? Wont it be called all the time while the game is running?
//glScissor(0, 0, (int)OpenGL_GetWidth(), (int)OpenGL_GetHeight());
glScissor(0, 0, GetTargetWidth(), GetTargetHeight());
glBlendColorEXT(0, 0, 0, 0.5f);
glClearDepth(1.0f);
@ -438,12 +451,12 @@ bool Renderer::InitializeGL()
// ------------------------
int Renderer::GetTargetWidth()
{
return (g_Config.bNativeResolution ? EFB_WIDTH : s_targetwidth);
return g_Config.bNativeResolution ? EFB_WIDTH : s_targetwidth;
}
int Renderer::GetTargetHeight()
{
return (g_Config.bNativeResolution ? EFB_HEIGHT : s_targetheight);
return g_Config.bNativeResolution ? EFB_HEIGHT : s_targetheight;
}
float Renderer::GetTargetScaleX()
@ -476,13 +489,21 @@ void Renderer::SetFramebuffer(GLuint fb)
fb != 0 ? fb : s_uFramebuffer);
}
GLuint Renderer::GetRenderTarget()
GLuint Renderer::ResolveAndGetRenderTarget(const TRectangle &source_rect)
{
return s_RenderTarget;
}
GLuint Renderer::GetZBufferTarget()
GLuint Renderer::ResolveAndGetFakeZTarget(const TRectangle &source_rect)
{
return nZBufferRender > 0 ? s_ZBufferTarget : 0;
// This logic should be moved elsewhere.
return s_FakeZTarget;
}
GLuint Renderer::GetFakeZTarget()
{
// This logic should be moved elsewhere.
return nZBufferRender > 0 ? s_FakeZTarget : 0;
}
void Renderer::ResetGLState()
@ -503,16 +524,17 @@ void Renderer::ResetGLState()
void Renderer::RestoreGLState()
{
// Gets us back into a more game-like state.
glEnable(GL_SCISSOR_TEST);
if (bpmem.genMode.cullmode > 0) glEnable(GL_CULL_FACE);
if (bpmem.zmode.testenable) glEnable(GL_DEPTH_TEST);
if (bpmem.zmode.updateenable) glDepthMask(GL_TRUE);
if (bpmem.zmode.testenable) glEnable(GL_DEPTH_TEST);
if (bpmem.zmode.updateenable) glDepthMask(GL_TRUE);
glEnable(GL_VERTEX_PROGRAM_ARB);
glEnable(GL_FRAGMENT_PROGRAM_ARB);
glEnable(GL_SCISSOR_TEST);
SetScissorRect();
SetColorMask();
SetBlendMode(true);
glEnable(GL_VERTEX_PROGRAM_ARB);
glEnable(GL_FRAGMENT_PROGRAM_ARB);
}
void Renderer::SetColorMask()
@ -546,7 +568,6 @@ void Renderer::SetBlendMode(bool forceUpdate)
if (bpmem.blendmode.blendenable) {
newval |= 1;
if (bpmem.blendmode.subtract) {
newval |= 0x0048; // src 1 dst 1
} else {
@ -560,7 +581,7 @@ void Renderer::SetBlendMode(bool forceUpdate)
u32 changes = forceUpdate ? 0xFFFFFFFF : newval ^ s_blendMode;
if (changes & 1) {
newval & 1 ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
(newval & 1) ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
}
bool dstAlphaEnable = g_bBlendSeparate && newval & 2;
@ -635,8 +656,8 @@ bool Renderer::SetScissorRect()
glScissor(
(int)rc_left, // x = 0 for example
Renderer::GetTargetHeight() - (int)(rc_bottom), // y = 0 for example
(int)(rc_right-rc_left), // width = 640 for example
(int)(rc_bottom-rc_top) // height = 480 for example
(int)(rc_right - rc_left), // width = 640 for example
(int)(rc_bottom - rc_top) // height = 480 for example
);
return true;
}
@ -656,16 +677,18 @@ bool Renderer::HaveStencilBuffer()
void Renderer::SetZBufferRender()
{
nZBufferRender = 10; // give it 10 frames
nZBufferRender = 10; // The game asked for Z. Give it 10 frames, then turn it off for speed.
GLenum s_drawbuffers[2] = {
GL_COLOR_ATTACHMENT0_EXT,
GL_COLOR_ATTACHMENT1_EXT
};
glDrawBuffers(2, s_drawbuffers);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, s_FakeZTarget, 0);
_assert_(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT);
}
// Does this function even work correctly???
void Renderer::FlushZBufferAlphaToTarget()
{
ResetGLState();
@ -673,12 +696,11 @@ void Renderer::FlushZBufferAlphaToTarget()
SetRenderTarget(0);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glViewport(0, 0, GetTargetWidth(), GetTargetHeight());
// texture map s_RenderTargets[s_curtarget] onto the main buffer
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_FakeZTarget);
TextureMngr::EnableTexRECT(0);
// disable all other stages
for (int i = 1; i < 8; ++i)
@ -691,7 +713,6 @@ void Renderer::FlushZBufferAlphaToTarget()
// TODO: This code should not have to bother with stretchtofit checking -
// all necessary scale initialization should be done elsewhere.
// TODO: Investigate BlitFramebufferEXT.
if (g_Config.bNativeResolution)
{
//TODO: Do Correctly in a bit
@ -748,7 +769,6 @@ void Renderer::SetRenderMode(RenderMode mode)
else if (s_RenderMode == RM_Normal) {
// setup buffers
_assert_(GetZBufferTarget() && bpmem.zmode.updateenable);
if (mode == RM_ZBufferAlpha) {
glEnable(GL_STENCIL_TEST);
glClearStencil(0);
@ -771,7 +791,7 @@ void Renderer::SetRenderMode(RenderMode mode)
FlushZBufferAlphaToTarget();
glDisable(GL_STENCIL_TEST);
SetRenderTarget(s_ZBufferTarget);
SetRenderTarget(s_FakeZTarget);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
GL_REPORT_ERRORD();
}
@ -797,11 +817,6 @@ Renderer::RenderMode Renderer::GetRenderMode()
void ComputeBackbufferRectangle(TRectangle *rc)
{
// -----------------------------------------------------------------------
// GLViewPort variables
// ------------------
// Work with float values for the XFB supplement and aspect ratio functions. These are default
// values that are used if the XFB supplement and the keep aspect ratio function are unused.
float FloatGLWidth = (float)OpenGL_GetBackbufferWidth();
float FloatGLHeight = (float)OpenGL_GetBackbufferHeight();
float FloatXOffset = 0;
@ -833,7 +848,7 @@ void ComputeBackbufferRectangle(TRectangle *rc)
}
// -----------------------------------------------------------------------
/* Crop the picture from 4:3 to 5:4 or from 16:9 to 16:10. */
// Crop the picture from 4:3 to 5:4 or from 16:9 to 16:10.
// Output: FloatGLWidth, FloatGLHeight, FloatXOffset, FloatYOffset
// ------------------
if ((g_Config.bKeepAR43 || g_Config.bKeepAR169) && g_Config.bCrop)
@ -858,7 +873,7 @@ void ComputeBackbufferRectangle(TRectangle *rc)
//Console::Print("Crop Ratio:%1.2f IncreasedHeight:%3.0f YOffset:%3.0f\n", Ratio, IncreasedHeight, FloatYOffset);
}
// Because there is no round() function we use round(float) = floor(float + 0.5) instead
// round(float) = floor(float + 0.5)
int XOffset = floor(FloatXOffset + 0.5);
int YOffset = floor(FloatYOffset + 0.5);
rc->left = XOffset;
@ -885,12 +900,8 @@ void Renderer::Swap(const TRectangle& rc)
// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer);
// render to the real buffer now
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the window backbuffer
// -----------------------------------------------------------------------
// Show the finished picture
// --------------------
// Reset GL state
ResetGLState();
// Texture map s_RenderTargets[s_curtarget] onto the main buffer
@ -901,7 +912,7 @@ void Renderer::Swap(const TRectangle& rc)
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
TextureMngr::EnableTexRECT(0);
// Disable all other stages
// Disable all other stages.
for (int i = 1; i < 8; ++i)
TextureMngr::DisableStage(i);
@ -973,7 +984,7 @@ void Renderer::Swap(const TRectangle& rc)
// For testing zbuffer targets.
// Renderer::SetZBufferRender();
// SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget, GetTargetWidth(), GetTargetHeight());
// SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_ARB, s_FakeZTarget, GetTargetWidth(), GetTargetHeight());
}
////////////////////////////////////////////////

View File

@ -15,54 +15,14 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// How the non-true-XFB mode COULD work:
//
// The game renders to the EFB:
//
// ----------------------+
// | |
// | |
// | |
// | |
// | |
// | | efb_height
// | |
// | |
// | - - - - - - - - - - |
// | |
// +---------------------+
// efb_width
//
// At XFB blit time, the top 640-xxx X XXX part of the above buffer (size dotted below),
// should be stretch blitted into the inner rectangle of the window:
// +-----------------------------------------+
// | | | |
// | | . | |
// | | | |
// | | . | |
// | | | |
// | | . | | OpenGL_Height()
// | | | |
// | | . | |
// | | - - - - - - - - - - | |
// | | \ | |
// +-------+---------------------------------+
// OpenGL_Width()
//
//
// efb_width and efb_height can even be adjusted so that the last blit will result
// in a 1:1 rather than a stretch. That would require creating a bigger efb from the
// start though.
//
// The above is not how it works today.
/*
int win_w = OpenGL_Width();
int win_h = OpenGL_Height();
// GC graphics pipeline
int blit_w_640 = last_xfb_specified_width;
int blit_h_640 = last_xfb_specified_height;
*/
// 3d commands are issued through the fifo. The gpu draws to the 2MB EFB.
// The efb can be copied back into ram in two forms: as textures or as XFB.
// The XFB is the region in RAM that the VI chip scans out to the television.
// So, after all rendering to EFB is done, the image is copied into one of two XFBs in RAM.
// Next frame, that one is scanned out and the other one gets the copy. = double buffering.
#ifndef GCOGL_RENDER
#define GCOGL_RENDER
@ -116,7 +76,7 @@ public:
static int GetTargetWidth();
static int GetTargetHeight();
// Multiply any 0-640 / 0-480 coordinates by these when rendering.
// Multiply any 2D EFB coordinates by these when rendering.
static float GetTargetScaleX();
static float GetTargetScaleY();
@ -125,8 +85,14 @@ public:
static void SetRenderTarget(GLuint targ); // if targ is 0, sets to original render target
static void SetDepthTarget(GLuint targ);
static GLuint GetRenderTarget();
static GLuint GetZBufferTarget();
// 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.
static GLuint ResolveAndGetRenderTarget(const TRectangle &rect);
// Same as above but for the FakeZ Target.
static GLuint ResolveAndGetFakeZTarget(const TRectangle &rect);
static GLuint GetFakeZTarget(); // This is used by some functions to check for Z target existence. Should be changed to a bool.
// Random utilities
static void RenderText(const char* pstr, int left, int top, u32 color);

View File

@ -159,8 +159,8 @@ void Shutdown()
s_texConvFrameBuffer = 0;
}
void EncodeToRam(GLuint srcTexture, const TRectangle& sourceRc,
u8* destAddr, int dstWidth, int dstHeight, bool linearFilter, FRAGMENTSHADER& shader)
void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const TRectangle& sourceRc,
u8* destAddr, int dstWidth, int dstHeight, bool linearFilter)
{
Renderer::SetRenderMode(Renderer::RM_Normal);
@ -241,20 +241,22 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
format |= _GX_TF_CTF;
}
FRAGMENTSHADER& fs = GetOrCreateEncodingShader(format);
if (fs.glprogid == 0)
FRAGMENTSHADER& texconv_shader = GetOrCreateEncodingShader(format);
if (texconv_shader.glprogid == 0)
return;
u8* ptr = Memory_GetPtr(address);
u32 target = bFromZBuffer ? Renderer::GetZBufferTarget() : Renderer::GetRenderTarget();
u32 source_texture = bFromZBuffer ? Renderer::ResolveAndGetFakeZTarget(source) : Renderer::ResolveAndGetRenderTarget(source);
s32 width = source.right - source.left;
s32 height = source.bottom - source.top;
if (bScaleByHalf)
{
// Hm. Shouldn't this only scale destination, not source?
// The bloom in Beyond Good & Evil is a good test case - due to this problem,
// it goes very wrong. Compare by switching back and forth between Copy textures to RAM and GL Texture.
// This also affects the shadows in Burnout 2 badly.
width /= 2;
height /= 2;
}
@ -278,7 +280,7 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
scaledSource.left = 0;
scaledSource.right = expandedWidth / samples;
EncodeToRam(target, scaledSource, ptr, expandedWidth / samples, expandedHeight, bScaleByHalf, fs);
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, ptr, expandedWidth / samples, expandedHeight, bScaleByHalf);
if (bFromZBuffer)
Renderer::SetZBufferRender(); // notify for future settings
@ -287,7 +289,7 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
void EncodeToRamYUYV(GLuint srcTexture, const TRectangle& sourceRc,
u8* destAddr, int dstWidth, int dstHeight)
{
EncodeToRam(srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, false, s_rgbToYuyvProgram);
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, false);
}

View File

@ -239,14 +239,12 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
* The problem here was just the sparse hash on the texture. This texture is partly overwrited (what is needed only)
* so lot's of remaning old text. Thin white chars on black bg too.
*/
// TODO: - clean this up when ready to kill old "unsafe texture cache"
// - fix the key index situation with CopyRenderTargetToTexture.
// Could happen only for GX_TF_C4, GX_TF_C8 and GX_TF_C14X2 fmt.
// Wonder if we can't use tex width&height to know if EFB might be copied to it...
// raw idea: TOCHECK if addresses are aligned we have few bits left...
if (address == 0)
return NULL;
@ -259,19 +257,24 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
u32 texID = address;
if (g_Config.bSafeTextureCache)
{
hash_value = TexDecoder_GetSafeTextureHash(ptr, expandedWidth, height, format, 0); // remove last arg
if ( (format == GX_TF_C4) || (format == GX_TF_C8) || (format == GX_TF_C14X2) )
hash_value = TexDecoder_GetSafeTextureHash(ptr, expandedWidth, height, format, 0); // remove last arg
if ((format == GX_TF_C4) || (format == GX_TF_C8) || (format == GX_TF_C14X2))
{
// WARNING! texID != address now => may break CopyRenderTargetToTexture (cf. TODO up)
// tlut size can be up to 32768B (GX_TF_C14X2) but Safer == Slower.
//texID ^= TexDecoder_GetTlutHash(&texMem[tlutaddr], TexDecoder_GetPaletteSize(format));
// This trick (to change the texID depending on the TLUT addr) is a trick to get around
// an issue with metroid prime's fonts, where it has multiple sets of fonts on top of
// each other stored in a single texture, and uses the palette to make different characters
// visible or invisible. Thus, unless we want to recreate the textures for every drawn character,
// we must make sure that texture with different tluts get different IDs.
texID ^= TexDecoder_GetTlutHash(&texMem[tlutaddr], (format == GX_TF_C4) ? 32 : 128);
//DebugLog("addr: %08x | texID: %08x | texHash: %08x", address, texID, hash_value);
}
}
bool skip_texture_create = false;
TexCache::iterator iter = textures.find(texID);
if (iter != textures.end()) {
@ -280,10 +283,12 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
if (!g_Config.bSafeTextureCache)
hash_value = ((u32 *)ptr)[entry.hashoffset];
if (entry.isRenderTarget || ((address == entry.addr) && (hash_value == entry.hash))) {
if (entry.isRenderTarget || ((address == entry.addr) && (hash_value == entry.hash)))
{
entry.frameCount = frameCount;
//glEnable(entry.isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D);
glBindTexture(entry.isNonPow2 ? GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D, entry.texture);
//glEnable(entry.isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D);
// entry.isNonPow2 ? TextureMngr::EnableTex2D(texstage) : TextureMngr::EnableTexRECT(texstage);
glBindTexture(entry.isNonPow2 ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, entry.texture);
if (entry.mode.hex != tm0.hex)
entry.SetTextureParameters(tm0);
//DebugLog("%cC addr: %08x | fmt: %i | e.hash: %08x | w:%04i h:%04i", g_Config.bSafeTextureCache ? 'S' : 'U'
@ -406,7 +411,8 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
return &entry;
}
void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, bool bScaleByHalf, TRectangle *source)
void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, bool bScaleByHalf, const TRectangle &source_rect)
{
DVSTARTPROFILE();
GL_REPORT_ERRORD();
@ -431,8 +437,8 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
entry.frameCount = frameCount;
int mult = bScaleByHalf?2:1;
int w = (abs(source->right-source->left)/mult);
int h = (abs(source->bottom-source->top)/mult);
int w = (abs(source_rect.GetWidth())/mult);
int h = (abs(source_rect.GetHeight())/mult);
GL_REPORT_ERRORD();
@ -600,7 +606,7 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
Renderer::SetRenderMode(Renderer::RM_Normal); // set back to normal
GL_REPORT_ERRORD();
// have to run a pixel shader
// We have to run a pixel shader, for color conversion.
Renderer::ResetGLState(); // reset any game specific settings
@ -632,7 +638,11 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, bFromZBuffer?Renderer::GetZBufferTarget():Renderer::GetRenderTarget());
if (bFromZBuffer) {
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, Renderer::ResolveAndGetFakeZTarget(source_rect));
} else {
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, Renderer::ResolveAndGetRenderTarget(source_rect));
}
TextureMngr::EnableTexRECT(0);
glViewport(0, 0, w, h);
@ -645,10 +655,10 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
glBegin(GL_QUADS);
float MValueX = Renderer::GetTargetScaleX();
float MValueY = Renderer::GetTargetScaleY();
glTexCoord2f((float)source->left * MValueX, Renderer::GetTargetHeight()-(float)source->bottom * MValueY); glVertex2f(-1, 1);
glTexCoord2f((float)source->left * MValueX, Renderer::GetTargetHeight()-(float)source->top * MValueY); glVertex2f(-1, -1);
glTexCoord2f((float)source->right * MValueX, Renderer::GetTargetHeight()-(float)source->top * MValueY); glVertex2f( 1, -1);
glTexCoord2f((float)source->right * MValueX, Renderer::GetTargetHeight()-(float)source->bottom * MValueY); glVertex2f( 1, 1);
glTexCoord2f((float)source_rect.left * MValueX, Renderer::GetTargetHeight()-(float)source_rect.bottom * MValueY); glVertex2f(-1, 1);
glTexCoord2f((float)source_rect.left * MValueX, Renderer::GetTargetHeight()-(float)source_rect.top * MValueY); glVertex2f(-1, -1);
glTexCoord2f((float)source_rect.right * MValueX, Renderer::GetTargetHeight()-(float)source_rect.top * MValueY); glVertex2f( 1, -1);
glTexCoord2f((float)source_rect.right * MValueX, Renderer::GetTargetHeight()-(float)source_rect.bottom * MValueY); glVertex2f( 1, 1);
glEnd();
GL_REPORT_ERRORD();
@ -669,14 +679,14 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
void TextureMngr::EnableTex2D(int stage)
{
if (!(nTex2DEnabled & (1<<stage))) {
nTex2DEnabled |= (1<<stage);
glEnable(GL_TEXTURE_2D);
}
if (nTexRECTEnabled & (1<<stage)) {
nTexRECTEnabled &= ~(1<<stage);
glDisable(GL_TEXTURE_RECTANGLE_ARB);
}
if (!(nTex2DEnabled & (1<<stage))) {
nTex2DEnabled |= (1<<stage);
glEnable(GL_TEXTURE_2D);
}
}
void TextureMngr::EnableTexRECT(int stage)
@ -710,6 +720,6 @@ void TextureMngr::DisableStage(int stage)
void TextureMngr::ClearRenderTargets()
{
for (TexCache::iterator iter = textures.begin(); iter!=textures.end(); iter++)
for (TexCache::iterator iter = textures.begin(); iter != textures.end(); iter++)
iter->second.isRenderTarget = false;
}

View File

@ -74,7 +74,7 @@ public:
static void Shutdown();
static void Invalidate(bool shutdown);
static TCacheEntry* Load(int texstage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt);
static void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, bool bScaleByHalf, TRectangle *source);
static void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, bool bScaleByHalf, const TRectangle &source);
static void EnableTex2D(int stage);
static void EnableTexRECT(int stage);

View File

@ -242,7 +242,7 @@ void Flush()
VERTEXSHADER* vs = VertexShaderCache::GetShader(g_nativeVertexFmt->m_components);
bool bRestoreBuffers = false;
if (Renderer::GetZBufferTarget()) {
if (Renderer::GetFakeZTarget()) {
if (bpmem.zmode.updateenable) {
if (!bpmem.blendmode.colorupdate) {
Renderer::SetRenderMode(bpmem.blendmode.alphaupdate ? Renderer::RM_ZBufferAlpha : Renderer::RM_ZBufferOnly);

View File

@ -72,7 +72,7 @@ VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
{
DVSTARTPROFILE();
VERTEXSHADERUID uid;
u32 zbufrender = (bpmem.ztex2.op == ZTEXTURE_ADD) || Renderer::GetZBufferTarget() != 0;
u32 zbufrender = (bpmem.ztex2.op == ZTEXTURE_ADD) || Renderer::GetFakeZTarget() != 0;
GetVertexShaderId(uid, components, zbufrender);
VSCache::iterator iter = vshaders.find(uid);
@ -87,7 +87,7 @@ VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
}
VSCacheEntry& entry = vshaders[uid];
const char *code = GenerateVertexShader(components, Renderer::GetZBufferTarget() != 0);
const char *code = GenerateVertexShader(components, Renderer::GetFakeZTarget() != 0);
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_Config.iLog & CONF_SAVESHADERS && code) {

View File

@ -86,7 +86,7 @@ void XFB_Write(u8 *xfb_in_ram, const TRectangle& sourceRc, u32 dstWd, u32 dstHt)
// OpenGL upside down as usual...
renderSrcRc.top = Renderer::GetTargetHeight() - sourceRc.top;
renderSrcRc.bottom = Renderer::GetTargetHeight() - sourceRc.bottom;
TextureConverter::EncodeToRamYUYV(Renderer::GetRenderTarget(), renderSrcRc, xfb_in_ram, dstWd, dstHt);
TextureConverter::EncodeToRamYUYV(Renderer::ResolveAndGetRenderTarget(sourceRc), renderSrcRc, xfb_in_ram, dstWd, dstHt);
}
// Draw the XFB straight to the OpenGL backbuffer.
@ -208,7 +208,7 @@ void XFB_Write(u8 *xfb_in_ram, const TRectangle& sourceRc, u32 dstWd, u32 dstHt)
glEnd();
GL_REPORT_ERRORD();
int width = sourceRc.right - sourceRc.left;
int width = sourceRc.right - sourceRc.left;
int height = sourceRc.bottom - sourceRc.top;
glReadPixels(sourceRc.left, sourceRc.top, width, height, GL_RGBA, GL_UNSIGNED_BYTE, efb_buffer);
GL_REPORT_ERRORD();

View File

@ -189,7 +189,7 @@ void DllConfig(HWND _hParent)
{
for (int i = 0; i < modeNum; i++)
{
if(px != modes[i]->hdisplay && py != modes[i]->vdisplay)
if (px != modes[i]->hdisplay && py != modes[i]->vdisplay)
{
char temp[32];
sprintf(temp,"%dx%d", modes[i]->hdisplay, modes[i]->vdisplay);
@ -219,8 +219,6 @@ void DllConfig(HWND _hParent)
void Initialize(void *init)
{
//Console::Open();
frameCount = 0;
SVideoInitialize *_pVideoInitialize = (SVideoInitialize*)init;
g_VideoInitialize = *(_pVideoInitialize); // Create a shortcut to _pVideoInitialize that can also update it
@ -250,8 +248,6 @@ void DoState(unsigned char **ptr, int mode) {
#endif
// Clear all caches that touch RAM
TextureMngr::Invalidate(false);
// DisplayListManager::Invalidate();
VertexLoaderManager::MarkAllDirty();
PointerWrap p(ptr, mode);

View File

@ -22,7 +22,4 @@
extern SVideoInitialize g_VideoInitialize;
// Logging
extern int GLScissorX, GLScissorY, GLScissorW, GLScissorH;
#endif