OpenGL: Trying a new function to fix glScissor() and glViewport() when bpmem.copyTexSrcWH is not 640x480. It's only enabled with g_Config.bStretchToFit and without g_Config.bKeepAR to test how it works. Hopefully I have not broken all other modes.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2310 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2009-02-19 06:52:01 +00:00
parent 14ab646978
commit 5746ed490c
8 changed files with 207 additions and 71 deletions

View File

@ -777,8 +777,8 @@ union UPE_Copy
struct BPMemory struct BPMemory
{ {
GenMode genMode; GenMode genMode;
u32 display_copy_filter[4]; //01-04 u32 display_copy_filter[4]; // 01-04
u32 unknown; //05 u32 unknown; // 05
// indirect matrices (set by GXSetIndTexMtx, selected by TevStageIndirect::mid) // indirect matrices (set by GXSetIndTexMtx, selected by TevStageIndirect::mid)
// abc form a 2x3 offset matrix, there's 3 such matrices // abc form a 2x3 offset matrix, there's 3 such matrices
// the 3 offset matrices can either be indirect type, S-type, or T-type // the 3 offset matrices can either be indirect type, S-type, or T-type
@ -804,9 +804,9 @@ struct BPMemory
u32 drawdone; //45, bit1=1 if end of list u32 drawdone; //45, bit1=1 if end of list
u32 unknown5; //46 clock? u32 unknown5; //46 clock?
u32 petoken; //47 u32 petoken; //47
u32 petokenint; //48 u32 petokenint; // 48
X10Y10 copyTexSrcXY; //49 X10Y10 copyTexSrcXY; // 49
X10Y10 copyTexSrcWH; //4a X10Y10 copyTexSrcWH; // 4a
u32 copyTexDest; //4b// 4b == CopyAddress (GXDispCopy and GXTexCopy use it) u32 copyTexDest; //4b// 4b == CopyAddress (GXDispCopy and GXTexCopy use it)
u32 unknown6; //4c u32 unknown6; //4c
u32 copyMipMapStrideChannels; // 4d usually set to 4 when dest is single channel, 8 when dest is 2 channel, 16 when dest is RGBA u32 copyMipMapStrideChannels; // 4d usually set to 4 when dest is single channel, 8 when dest is 2 channel, 16 when dest is RGBA

View File

@ -35,6 +35,7 @@
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "PixelShaderManager.h" #include "PixelShaderManager.h"
#include "XFB.h" #include "XFB.h"
#include "main.h"
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
@ -56,14 +57,23 @@ void BPInit()
bpmem.bpMask = 0xFFFFFF; bpmem.bpMask = 0xFFFFFF;
} }
// Called at the end of every: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg //////////////////////////////////////////////////////////////////////////////////////
// TODO - turn into function table. The (future) DL jit can then call the functions directly, // Write to bpmem
// getting rid of dynamic dispatch. /* ------------------
Called:
At the end of every: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg
TODO:
Turn into function table. The (future) DL jit can then call the functions directly,
getting rid of dynamic dispatch.
// ------------------ */
void BPWritten(int addr, int changes, int newval) void BPWritten(int addr, int changes, int newval)
{ {
//static int count = 0; //static int count = 0;
//ERROR_LOG("(%d) %x: %x\n", count++, addr, newval); //ERROR_LOG("(%d) %x: %x\n", count++, addr, newval);
//Console::Print("BPWritten: 0x%02x %i %i %i\n", addr, changes, newval, (int)bpmem.copyTexSrcWH.y);
//if(addr == 0x49) PanicAlert("0x49");
switch (addr) switch (addr)
{ {
case BPMEM_GENMODE: case BPMEM_GENMODE:
@ -283,10 +293,12 @@ void BPWritten(int addr, int changes, int newval)
case BPMEM_SCISSORTL: case BPMEM_SCISSORTL:
case BPMEM_SCISSORBR: case BPMEM_SCISSORBR:
if (changes) { if (changes)
{
VertexManager::Flush(); VertexManager::Flush();
((u32*)&bpmem)[addr] = newval; ((u32*)&bpmem)[addr] = newval;
if (!Renderer::SetScissorRect()) { if (!Renderer::SetScissorRect())
{
if (addr == BPMEM_SCISSORBR) { if (addr == BPMEM_SCISSORBR) {
ERROR_LOG("bad scissor!\n"); ERROR_LOG("bad scissor!\n");
} }
@ -346,26 +358,29 @@ void BPWritten(int addr, int changes, int newval)
} }
break; break;
case BPMEM_PE_TOKEN_ID: case BPMEM_PE_TOKEN_ID: // 0x47
g_VideoInitialize.pSetPEToken(static_cast<u16>(newval & 0xFFFF), FALSE); g_VideoInitialize.pSetPEToken(static_cast<u16>(newval & 0xFFFF), FALSE);
DebugLog("SetPEToken 0x%04x", (newval & 0xFFFF)); DebugLog("SetPEToken 0x%04x", (newval & 0xFFFF));
break; break;
case BPMEM_PE_TOKEN_INT_ID: case BPMEM_PE_TOKEN_INT_ID: // 0x48
g_VideoInitialize.pSetPEToken(static_cast<u16>(newval & 0xFFFF), TRUE); g_VideoInitialize.pSetPEToken(static_cast<u16>(newval & 0xFFFF), TRUE);
DebugLog("SetPEToken + INT 0x%04x", (newval & 0xFFFF)); DebugLog("SetPEToken + INT 0x%04x", (newval & 0xFFFF));
break; break;
case 0x67: // set gp metric? // Set gp metric?
case 0x67:
break; break;
// This case writes to bpmem.triggerEFBCopy and may apparently prompt us to update glScissor()
case 0x52: case 0x52:
{ {
DVSTARTSUBPROFILE("LoadBPReg:swap"); DVSTARTSUBPROFILE("LoadBPReg:swap");
VertexManager::Flush(); VertexManager::Flush();
((u32*)&bpmem)[addr] = newval; ((u32*)&bpmem)[addr] = newval;
//The bottom right is within the rectangle. // The bottom right is within the rectangle
// The values in bpmem.copyTexSrcXY and bpmem.copyTexSrcWH are updated in case 0x49 and 0x4a in this function
TRectangle rc = { TRectangle rc = {
(int)(bpmem.copyTexSrcXY.x), (int)(bpmem.copyTexSrcXY.x),
(int)(bpmem.copyTexSrcXY.y), (int)(bpmem.copyTexSrcXY.y),
@ -374,8 +389,8 @@ void BPWritten(int addr, int changes, int newval)
}; };
float MValueX = OpenGL_GetXmax(); float MValueX = OpenGL_GetXmax();
float MValueY = OpenGL_GetYmax(); float MValueY = OpenGL_GetYmax();
//Need another rc here to get it to scale. // Need another rc here to get it to scale.
//Here the bottom right is the out of the rectangle. // Here the bottom right is the out of the rectangle.
TRectangle multirc = { TRectangle multirc = {
(int)(bpmem.copyTexSrcXY.x * MValueX), (int)(bpmem.copyTexSrcXY.x * MValueX),
(int)(bpmem.copyTexSrcXY.y * MValueY), (int)(bpmem.copyTexSrcXY.y * MValueY),
@ -386,23 +401,31 @@ void BPWritten(int addr, int changes, int newval)
UPE_Copy PE_copy; UPE_Copy PE_copy;
PE_copy.Hex = bpmem.triggerEFBCopy; PE_copy.Hex = bpmem.triggerEFBCopy;
if (PE_copy.copy_to_xfb == 0) { if (PE_copy.copy_to_xfb == 0)
{
// EFB to texture // 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 // 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)
glViewport(rc.left,rc.bottom,rc.right,rc.top); {
glScissor(rc.left,rc.bottom,rc.right,rc.top); // We already have this in Render.cpp that we call when (PE_copy.clear) is true, why do we need this here to?
//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) { else if (g_Config.bCopyEFBToRAM)
{
TextureConverter::EncodeToRam(bpmem.copyTexDest<<5, bpmem.zcontrol.pixel_format==PIXELFMT_Z24, PE_copy.intensity_fmt>0, 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); (PE_copy.target_pixel_format/2)+((PE_copy.target_pixel_format&1)*8), PE_copy.half_scale>0, rc);
} }
else { else
{
TextureMngr::CopyRenderTargetToTexture(bpmem.copyTexDest<<5, bpmem.zcontrol.pixel_format==PIXELFMT_Z24, PE_copy.intensity_fmt>0, 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); (PE_copy.target_pixel_format/2)+((PE_copy.target_pixel_format&1)*8), PE_copy.half_scale>0, &rc);
} }
} }
else { else
{
// EFB to XFB // EFB to XFB
if (g_Config.bUseXFB) if (g_Config.bUseXFB)
{ {
@ -429,17 +452,23 @@ void BPWritten(int addr, int changes, int newval)
} }
// clearing // clearing
if (PE_copy.clear) { if (PE_copy.clear)
{
// clear color // clear color
Renderer::SetRenderMode(Renderer::RM_Normal); Renderer::SetRenderMode(Renderer::RM_Normal);
u32 nRestoreZBufferTarget = Renderer::GetZBufferTarget(); u32 nRestoreZBufferTarget = Renderer::GetZBufferTarget();
glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight()); // Why do we have this here and in Render.cpp?
//glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight());
// Always set the scissor in case it was set by the game and has not been reset // Always set the scissor in case it was set by the game and has not been reset
glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom), // But we will do that at the end of this section, in SetScissorRect(), why would we do it twice in the same function?
(multirc.right - multirc.left), (multirc.bottom - multirc.top)); //glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom),
// (multirc.right - multirc.left), (multirc.bottom - multirc.top));
// Logging
// GLScissorX = multirc.left; GLScissorY = (Renderer::GetTargetHeight() - multirc.bottom);
// GLScissorW = (multirc.right - multirc.left); GLScissorH = (multirc.bottom - multirc.top);
VertexShaderManager::SetViewportChanged(); VertexShaderManager::SetViewportChanged();
@ -457,7 +486,8 @@ void BPWritten(int addr, int changes, int newval)
((clearColor>>24) & 0xff)*(1/255.0f)); ((clearColor>>24) & 0xff)*(1/255.0f));
bits |= GL_COLOR_BUFFER_BIT; bits |= GL_COLOR_BUFFER_BIT;
} }
if (bpmem.zmode.updateenable) { if (bpmem.zmode.updateenable)
{
glClearDepth((float)(bpmem.clearZValue&0xFFFFFF) / float(0xFFFFFF)); glClearDepth((float)(bpmem.clearZValue&0xFFFFFF) / float(0xFFFFFF));
bits |= GL_DEPTH_BUFFER_BIT; bits |= GL_DEPTH_BUFFER_BIT;
} }
@ -635,6 +665,8 @@ void BPWritten(int addr, int changes, int newval)
case 0x90: case 0x90:
case 0xA0: case 0xA0:
case 0xB0: case 0xB0:
// Just update the bpmem struct, don't do anything else.
default: default:
if (changes) if (changes)
{ {
@ -691,15 +723,16 @@ void BPWritten(int addr, int changes, int newval)
void LoadBPReg(u32 value0) void LoadBPReg(u32 value0)
{ {
DVSTARTPROFILE(); DVSTARTPROFILE();
//handle the mask register // Handle the mask register
int opcode = value0 >> 24; int opcode = value0 >> 24;
int oldval = ((u32*)&bpmem)[opcode]; int oldval = ((u32*)&bpmem)[opcode];
int newval = (oldval & ~bpmem.bpMask) | (value0 & bpmem.bpMask); int newval = (oldval & ~bpmem.bpMask) | (value0 & bpmem.bpMask);
// Check if it's a new value
int changes = (oldval ^ newval) & 0xFFFFFF; int changes = (oldval ^ newval) & 0xFFFFFF;
//reset the mask register //reset the mask register
if (opcode != 0xFE) if (opcode != 0xFE)
bpmem.bpMask = 0xFFFFFF; bpmem.bpMask = 0xFFFFFF;
//notify the video handling so it can update render states // Notify the video handling so it can update render states
BPWritten(opcode, changes, newval); BPWritten(opcode, changes, newval);
} }

View File

@ -117,6 +117,10 @@ void OpenGL_SetWindowText(const char *text)
#endif #endif
} }
// =======================================================================================
// Draw messages on top of the screen
// ------------------
unsigned int Callback_PeekMessages() unsigned int Callback_PeekMessages()
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -134,13 +138,14 @@ unsigned int Callback_PeekMessages()
return FALSE; return FALSE;
#endif #endif
} }
// Show the current FPS
void UpdateFPSDisplay(const char *text) void UpdateFPSDisplay(const char *text)
{ {
char temp[512]; char temp[512];
sprintf(temp, "SVN R%s: GL: %s", SVN_REV_STR, text); sprintf(temp, "SVN R%s: GL: %s", SVN_REV_STR, text);
OpenGL_SetWindowText(temp); OpenGL_SetWindowText(temp);
} }
// =========================
// ======================================================================================= // =======================================================================================
@ -171,7 +176,7 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
{ {
sscanf(g_Config.iWindowedRes, "%dx%d", &_twidth, &_theight); sscanf(g_Config.iWindowedRes, "%dx%d", &_twidth, &_theight);
} }
else // No Window reso set, fall back to default else // No Window resolution set, fall back to default
{ {
_twidth = _iwidth; _twidth = _iwidth;
_theight = _iheight; _theight = _iheight;
@ -262,15 +267,12 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
// Create rendering window in Windows // Create rendering window in Windows
// ---------------------- // ----------------------
// Create the window // Create a separate window
if (!g_Config.renderToMainframe || g_VideoInitialize.pWindowHandle == NULL) if (!g_Config.renderToMainframe || g_VideoInitialize.pWindowHandle == NULL)
{
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create(NULL, g_hInstance, "Please wait..."); g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create(NULL, g_hInstance, "Please wait...");
} // Create a child window
else else
{
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, "Please wait..."); g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, "Please wait...");
}
// Show the window // Show the window
EmuWindow::Show(); EmuWindow::Show();
@ -311,12 +313,13 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
} }
else else
{ {
// change to default resolution // Change to default resolution
ChangeDisplaySettings(NULL, 0); ChangeDisplaySettings(NULL, 0);
} }
if (g_Config.bFullscreen && !g_Config.renderToMainframe) if (g_Config.bFullscreen && !g_Config.renderToMainframe)
{ {
// Hide the cursor
ShowCursor(FALSE); ShowCursor(FALSE);
} }
else else
@ -332,9 +335,10 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2; int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2;
int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2; int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2;
SetWindowPos(EmuWindow::GetWnd(), NULL, X, Y, rc.right-rc.left, rc.bottom-rc.top, SWP_NOREPOSITION|SWP_NOZORDER); // EmuWindow::GetWnd() is either the new child window or the new separate window
SetWindowPos(EmuWindow::GetWnd(), NULL, X, Y, rc.right-rc.left, rc.bottom-rc.top, SWP_NOREPOSITION | SWP_NOZORDER);
PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
{ {
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number 1, // Version Number
@ -361,7 +365,7 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
return false; return false;
} }
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) { if (!(PixelFormat = ChoosePixelFormat(hDC,&pfd))) {
MessageBox(NULL,"(2) Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); MessageBox(NULL,"(2) Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return false; return false;
} }
@ -371,7 +375,7 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
return false; return false;
} }
if (!(hRC=wglCreateContext(hDC))) { if (!(hRC = wglCreateContext(hDC))) {
MessageBox(NULL,"(4) Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); MessageBox(NULL,"(4) Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return false; return false;
} }
@ -605,9 +609,11 @@ void OpenGL_Update()
// TODO fill in // TODO fill in
#elif defined(_WIN32) #elif defined(_WIN32)
RECT rcWindow; RECT rcWindow;
if (!EmuWindow::GetParentWnd()) { // If we are not rendering to a child window
if (!g_Config.bStretchToFit) if (!EmuWindow::GetParentWnd())
return; {
// return if we don't stretch the picture
if (!g_Config.bStretchToFit) return;
GetWindowRect(EmuWindow::GetWnd(), &rcWindow); GetWindowRect(EmuWindow::GetWnd(), &rcWindow);
rcWindow.top += 25; rcWindow.top += 25;
} }
@ -624,6 +630,7 @@ void OpenGL_Update()
int width = rcWindow.right - rcWindow.left; int width = rcWindow.right - rcWindow.left;
int height = rcWindow.bottom - rcWindow.top; int height = rcWindow.bottom - rcWindow.top;
// If we are rendering to a child window
if (EmuWindow::GetParentWnd() != 0) if (EmuWindow::GetParentWnd() != 0)
::MoveWindow(EmuWindow::GetWnd(), 0, 0, width, height, FALSE); ::MoveWindow(EmuWindow::GetWnd(), 0, 0, width, height, FALSE);
@ -702,17 +709,16 @@ void OpenGL_Update()
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
// Get the new window width and height // Get the new window width and height
/* ------------------
nBackbufferWidth and nBackbufferHeight: Now the actual rendering window size
Max: The highest of w and h
nXoff and nYoff: Controls the picture's position inside the rendering window
MValueX and MValueY: Used for the picture resolution-change rescaling
// ------------------ // ------------------
// nBackbufferWidth and nBackbufferHeight = now the actual screen size MValueX and MValueY: Used for the picture resolution-change rescaling. It will be used in
// Max = the highest of w and h TextureMngr and VertexShaderManager: Rescale textures on resolution changes
// MValueX and MValueY = used for the picture resolution-change rescaling BPStructs.cpp: Control glScissor()
// nXoff and nYoff = controls the picture's position inside the Dolphin window // ------------------ */
// ------------------
/* MValueX and MValueY will be used in
TextureMngr and VertexShaderManager: Rescale textures on resolution changes
BPStructs.cpp: Control glScissor()
*/
// ------------------
float FactorW = 640.0f / (float)nBackbufferWidth; float FactorW = 640.0f / (float)nBackbufferWidth;
float FactorH = 480.0f / (float)nBackbufferHeight; float FactorH = 480.0f / (float)nBackbufferHeight;
float Max = (FactorW < FactorH) ? FactorH : FactorW; float Max = (FactorW < FactorH) ? FactorH : FactorW;
@ -733,7 +739,7 @@ void OpenGL_Update()
nYoff = (int)((nBackbufferHeight - (480 * MValueY)) / 2); nYoff = (int)((nBackbufferHeight - (480 * MValueY)) / 2);
} }
// tell the debugger // Tell the debugger
gleft = rcWindow.left; gright = rcWindow.right; gleft = rcWindow.left; gright = rcWindow.right;
gtop = rcWindow.top; gbottom = rcWindow.bottom; gtop = rcWindow.top; gbottom = rcWindow.bottom;
} }

View File

@ -18,13 +18,14 @@
#ifndef _GLOBALS_H #ifndef _GLOBALS_H
#define _GLOBALS_H #define _GLOBALS_H
#include "Common.h" #include "Common.h"
#include "Config.h" #include "Config.h"
#include "VideoCommon.h" #include "VideoCommon.h"
#include "pluginspecs_video.h" #include "pluginspecs_video.h"
#include "ConsoleWindow.h"
// Turns file logging on and off // Turns file logging on and off
extern bool LocalLogFile; extern bool LocalLogFile;

View File

@ -263,7 +263,7 @@ namespace EmuWindow
} }
// This is called from // This is called from Create()
HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title) HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title)
{ {
wndClass.cbSize = sizeof( wndClass ); wndClass.cbSize = sizeof( wndClass );
@ -273,8 +273,9 @@ namespace EmuWindow
wndClass.cbWndExtra = 0; wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance; wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
// To interfer less with SetCursor() later we set this to NULL
//wndClass.hCursor = LoadCursor( NULL, IDC_ARROW ); //wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
wndClass.hCursor = NULL; // To interfer less with SetCursor() later wndClass.hCursor = NULL;
wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
wndClass.lpszMenuName = NULL; wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = m_szClassName; wndClass.lpszClassName = m_szClassName;
@ -357,7 +358,9 @@ namespace EmuWindow
UnregisterClass(m_szClassName, m_hInstance); UnregisterClass(m_szClassName, m_hInstance);
} }
// ------------------------------------------
// Set the size of the child or main window
// ------------------
void SetSize(int width, int height) void SetSize(int width, int height)
{ {
RECT rc = {0, 0, width, height}; RECT rc = {0, 0, width, height};
@ -366,6 +369,7 @@ namespace EmuWindow
int w = rc.right - rc.left; int w = rc.right - rc.left;
int h = rc.bottom - rc.top; int h = rc.bottom - rc.top;
// Move and resize the window
rc.left = (1280 - w)/2; rc.left = (1280 - w)/2;
rc.right = rc.left + w; rc.right = rc.left + w;
rc.top = (1024 - h)/2; rc.top = (1024 - h)/2;

View File

@ -47,6 +47,11 @@
#include "XFB.h" #include "XFB.h"
#include "Timer.h" #include "Timer.h"
#include "main.h" // Local
#ifdef _WIN32
#include "OS/Win32.h"
#endif
#if defined(HAVE_WX) && HAVE_WX #if defined(HAVE_WX) && HAVE_WX
#include "Debugger/Debugger.h" // for the CDebugger class #include "Debugger/Debugger.h" // for the CDebugger class
#endif #endif
@ -391,7 +396,8 @@ bool Renderer::InitializeGL()
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, (int)OpenGL_GetWidth(), (int)OpenGL_GetHeight()); // 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());
glBlendColorEXT(0, 0, 0, 0.5f); glBlendColorEXT(0, 0, 0, 0.5f);
glClearDepth(1.0f); glClearDepth(1.0f);
@ -504,6 +510,10 @@ void Renderer::ReinitView(int nNewWidth, int nNewHeight)
nNewHeight > 16 ? nNewHeight : 16); nNewHeight > 16 ? nNewHeight : 16);
} }
//////////////////////////////////////////////////////////////////////////////////////
// Return the rendering window width and height
// ------------------------
int Renderer::GetTargetWidth() int Renderer::GetTargetWidth()
{ {
return (g_Config.bStretchToFit ? 640 : (int)OpenGL_GetWidth()); return (g_Config.bStretchToFit ? 640 : (int)OpenGL_GetWidth());
@ -513,6 +523,9 @@ int Renderer::GetTargetHeight()
{ {
return (g_Config.bStretchToFit ? 480 : (int)OpenGL_GetHeight()); return (g_Config.bStretchToFit ? 480 : (int)OpenGL_GetHeight());
} }
/////////////////////////////
void Renderer::SetRenderTarget(GLuint targ) void Renderer::SetRenderTarget(GLuint targ)
{ {
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB,
@ -639,6 +652,7 @@ void Renderer::SetBlendMode(bool forceUpdate)
s_blendMode = newval; s_blendMode = newval;
} }
////////////////////////////////////////////////////////////////////////////////////////////
// Call browser: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg() // Call browser: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg()
// case 0x52 > SetScissorRect() // case 0x52 > SetScissorRect()
// --------------- // ---------------
@ -649,6 +663,7 @@ void Renderer::SetBlendMode(bool forceUpdate)
// Renderer::GetTargetHeight() = the fixed ini file setting // Renderer::GetTargetHeight() = the fixed ini file setting
// donkopunchstania - it appears scissorBR is the bottom right pixel inside the scissor box // donkopunchstania - it appears scissorBR is the bottom right pixel inside the scissor box
// therefore the width and height are (scissorBR + 1) - scissorTL // therefore the width and height are (scissorBR + 1) - scissorTL
// ---------------
bool Renderer::SetScissorRect() bool Renderer::SetScissorRect()
{ {
int xoff = bpmem.scissorOffset.x * 2 - 342; int xoff = bpmem.scissorOffset.x * 2 - 342;
@ -677,13 +692,30 @@ bool Renderer::SetScissorRect()
xoff, yoff xoff, yoff
);*/ );*/
// Check that the coordinates are good
if (rc_right >= rc_left && rc_bottom >= rc_top) if (rc_right >= rc_left && rc_bottom >= rc_top)
{ {
/* I don't know how this works with other options so I'm limiting it to this to test it, if you want to add support for other modes
or make this solution more general please do */
if(g_Config.bStretchToFit && !g_Config.bKeepAR)
{
int WidthDifference = 640 - (int)(rc_right - rc_left);
int HeightDifference = 480 - (int)(rc_bottom - rc_top);
GLScissorX = (int)rc_left; GLScissorY = -(Renderer::GetTargetHeight() - (int)(rc_bottom));
GLScissorW = Renderer::GetTargetWidth() + WidthDifference; GLScissorH = Renderer::GetTargetHeight() + HeightDifference;
}
else
{
GLScissorX = (int)rc_left; GLScissorY = Renderer::GetTargetHeight() - (int)(rc_bottom);
GLScissorW = (int)(rc_right - rc_left); GLScissorH = (int)(rc_bottom - rc_top);
}
glScissor( glScissor(
(int)rc_left, // x = 0 GLScissorX, // x = 0
Renderer::GetTargetHeight() - (int)(rc_bottom), // y = 0 GLScissorY, // y = 0
(int)(rc_right-rc_left), // y = 0 GLScissorW, // width = 640 for example
(int)(rc_bottom-rc_top) // y = 0 GLScissorH // height = 480 for example
); );
return true; return true;
} }
@ -1004,7 +1036,7 @@ void Renderer::SwapBuffers()
} }
#endif #endif
// copy the rendered from to the real window // Copy the rendered frame to the real window
OpenGL_SwapBuffers(); OpenGL_SwapBuffers();
glClearColor(0,0,0,0); glClearColor(0,0,0,0);
@ -1012,7 +1044,7 @@ void Renderer::SwapBuffers()
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
//clean out old stuff from caches // Clean out old stuff from caches
PixelShaderCache::Cleanup(); PixelShaderCache::Cleanup();
TextureMngr::Cleanup(); TextureMngr::Cleanup();
@ -1136,8 +1168,9 @@ void HandleCgError(CGcontext ctx, CGerror err, void* appdata)
} }
} }
//////////////////////////////////////////////////////////////////////////////////////
// Called from VertexShaderManager // Called from VertexShaderManager
// ----------------------
void UpdateViewport() void UpdateViewport()
{ {
// reversed gxsetviewport(xorig, yorig, width, height, nearz, farz) // reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
@ -1261,10 +1294,51 @@ void UpdateViewport()
} }
// ------------------------------------- // -------------------------------------
// I'm limiting it to this modes to test it
if(g_Config.bStretchToFit && !g_Config.bKeepAR)
{
GLWidth = GLWidth + (GLScissorW - 640);
GLHeight = GLHeight + (GLScissorH - 480);
GLy = 0;
GLx = 0;
}
glViewport( glViewport(
GLx, GLy, GLx, GLy,
GLWidth, GLHeight GLWidth, GLHeight
); );
glDepthRange((xfregs.rawViewport[5]- xfregs.rawViewport[2])/16777215.0f, xfregs.rawViewport[5]/16777215.0f); // -----------------------------------------------------------------------
// GLDepthRange
// ------------------
double GLNear = (xfregs.rawViewport[5] - xfregs.rawViewport[2]) / 16777215.0f;
double GLFar = xfregs.rawViewport[5] / 16777215.0f;
glDepthRange(GLNear, GLFar);
// -------------------------------------
// Logging
/*
RECT RcTop, RcParent, RcChild;
HWND Child = EmuWindow::GetWnd();
HWND Parent = GetParent(Child);
HWND Top = GetParent(Parent);
GetWindowRect(Top, &RcTop);
GetWindowRect(Parent, &RcParent);
GetWindowRect(Child, &RcChild);
Console::ClearScreen();
Console::Print("----------------------------------------------------------------\n");
Console::Print("Top window: X:%03i Y:%03i Width:%03i Height:%03i\n", RcTop.left, RcTop.top, RcTop.right - RcTop.left, RcTop.bottom - RcTop.top);
Console::Print("Parent window: X:%03i Y:%03i Width:%03i Height:%03i\n", RcParent.left, RcParent.top, RcParent.right - RcParent.left, RcParent.bottom - RcParent.top);
Console::Print("Child window: X:%03i Y:%03i Width:%03i Height:%03i\n", RcChild.left, RcChild.top, RcChild.right - RcChild.left, RcChild.bottom - RcChild.top);
Console::Print("----------------------------------------------------------------\n");
Console::Print("Res. MValue: X:%f Y:%f XOffs:%f YOffs:%f\n", OpenGL_GetXmax(), OpenGL_GetYmax(), OpenGL_GetXoff(), OpenGL_GetYoff());
Console::Print("GLViewPort: X:%03i Y:%03i Width:%03i Height:%03i\n", GLx, GLy, GLWidth, GLHeight);
Console::Print("GLDepthRange: Near:%f Far:%f\n", GLNear, GLFar);
Console::Print("GLScissor: X:%03i Y:%03i Width:%03i Height:%03i\n", GLScissorX, GLScissorY, GLScissorW, GLScissorH);
Console::Print("----------------------------------------------------------------\n");
*/
} }

View File

@ -15,6 +15,9 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
///////////////////////////////////////////////////////////////////////////////////////////////////
// Include
// --------------------------
#include "Globals.h" #include "Globals.h"
#include <cstdarg> #include <cstdarg>
@ -49,10 +52,20 @@
#include "TextureConverter.h" #include "TextureConverter.h"
#include "VideoState.h" #include "VideoState.h"
///////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// Definitions
// --------------------------
SVideoInitialize g_VideoInitialize; SVideoInitialize g_VideoInitialize;
PLUGIN_GLOBALS* globals; PLUGIN_GLOBALS* globals;
// Logging
int GLScissorX, GLScissorY, GLScissorW, GLScissorH;
///////////////////////////////////////////////
/* Create debugging window. There's currently a strange crash that occurs whe a game is loaded /* Create debugging window. There's currently a strange crash that occurs whe a game is loaded
if the OpenGL plugin was loaded before. I'll try to fix that. Currently you may have to if the OpenGL plugin was loaded before. I'll try to fix that. Currently you may have to
clsoe the window if it has auto started, and then restart it after the dll has loaded clsoe the window if it has auto started, and then restart it after the dll has loaded
@ -193,6 +206,8 @@ void DllConfig(HWND _hParent)
void Initialize(void *init) void Initialize(void *init)
{ {
//Console::Open(130, 5000);
// -------------------------------------------------- // --------------------------------------------------
/* Dolphin currently crashes if the dll is loaded when a game is started so we close the /* Dolphin currently crashes if the dll is loaded when a game is started so we close the
debugger and open it again after loading debugger and open it again after loading

View File

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