From 481bf0647f1ef64128572de14c7a18d839971935 Mon Sep 17 00:00:00 2001 From: OV2 Date: Wed, 2 Mar 2011 23:13:02 +0100 Subject: [PATCH 1/5] Win32: rework hi-res blending Only blend on filters that do not blend themself. --- win32/render.cpp | 90 ++++++++++++++++++++++++++++------------- win32/render.h | 8 +--- win32/win32.cpp | 9 +---- win32/win32_display.cpp | 7 ---- win32/win32_display.h | 1 - win32/wsnes9x.cpp | 2 +- 6 files changed, 66 insertions(+), 51 deletions(-) diff --git a/win32/render.cpp b/win32/render.cpp index e1c8b25c..57ab5530 100644 --- a/win32/render.cpp +++ b/win32/render.cpp @@ -220,15 +220,21 @@ void RenderBlarggNTSCComposite(SSurface Src, SSurface Dst, RECT *); void RenderBlarggNTSCSvideo(SSurface Src, SSurface Dst, RECT *); void RenderBlarggNTSCRgb(SSurface Src, SSurface Dst, RECT *); void RenderBlarggNTSC(SSurface Src, SSurface Dst, RECT *); +void RenderMergeHires(void *src, int srcPitch , void* dst, int dstPitch, unsigned int width, unsigned int height); +void InitLUTsWin32(void); // Contains the pointer to the now active render method -TRenderMethod RenderMethod = RenderPlain; -TRenderMethod RenderMethodHiRes = RenderPlain; +typedef void (*TRenderMethod)( SSurface Src, SSurface Dst, RECT *); +TRenderMethod _RenderMethod = RenderPlain; +TRenderMethod _RenderMethodHiRes = RenderPlain; // Used as change log static uint8 ChangeLog1 [EXT_PITCH * MAX_SNES_HEIGHT]; static uint8 ChangeLog2 [EXT_PITCH * MAX_SNES_HEIGHT]; static uint8 ChangeLog3 [EXT_PITCH * MAX_SNES_HEIGHT]; +BYTE *BlendBuf = NULL; +BYTE *BlendBuffer = NULL; + uint8 *ChangeLog [3] = { ChangeLog1, ChangeLog2, ChangeLog3 }; @@ -237,6 +243,11 @@ START_EXTERN_C uint8 snes9x_clear_change_log = 0; END_EXTERN_C +enum BlarggMode { UNINITIALIZED,BLARGGCOMPOSITE,BLARGGSVIDEO,BLARGGRGB }; + +snes_ntsc_t *ntsc = NULL; +BlarggMode blarggMode = UNINITIALIZED; + TRenderMethod FilterToMethod(RenderFilter filterID) { switch(filterID) @@ -381,15 +392,30 @@ inline static bool GetFilter32BitSupport(RenderFilter filterID) } } +inline static bool GetFilterBlendSupport(RenderFilter filterID) +{ + switch(filterID) + { + case FILTER_SIMPLE1X: + case FILTER_BLARGGCOMP: + case FILTER_BLARGGSVID: + case FILTER_BLARGGRGB: + return true; + + default: + return false; + } +} + void SelectRenderMethod() { - TRenderMethod OldRenderMethod = RenderMethod; - TRenderMethod OldRenderMethodHiRes = RenderMethodHiRes; + TRenderMethod OldRenderMethod = _RenderMethod; + TRenderMethod OldRenderMethodHiRes = _RenderMethodHiRes; - RenderMethod = FilterToMethod(GUI.Scale); - RenderMethodHiRes = FilterToMethod(GUI.ScaleHiRes); + _RenderMethod = FilterToMethod(GUI.Scale); + _RenderMethodHiRes = FilterToMethod(GUI.ScaleHiRes); - if (OldRenderMethod != RenderMethod || OldRenderMethodHiRes != RenderMethodHiRes) + if (OldRenderMethod != _RenderMethod || OldRenderMethodHiRes != _RenderMethodHiRes) snes9x_clear_change_log = GUI.NumFlipFrames; GUI.DepthConverted = !GUI.NeedDepthConvert; @@ -402,6 +428,32 @@ void SelectRenderMethod() } } +void RenderMethod(SSurface Src, SSurface Dst, RECT * rect) +{ + if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) { + if(GUI.BlendHiRes && Src.Width == 512 && !GetFilterBlendSupport(GUI.ScaleHiRes)) { + RenderMergeHires(Src.Surface,Src.Pitch,BlendBuffer,EXT_PITCH,Src.Width,Src.Height); + Src.Surface = BlendBuffer; + } + _RenderMethodHiRes(Src,Dst,rect); + } else { + _RenderMethod(Src,Dst,rect); + } +} + +void InitRenderFilters(void) +{ + InitLUTsWin32(); + if(!ntsc) { + ntsc = new snes_ntsc_t; + } + if(!BlendBuf) { + BlendBuf = new BYTE [EXT_PITCH * EXT_HEIGHT]; + BlendBuffer = BlendBuf + EXT_OFFSET; + memset(BlendBuf, 0, EXT_PITCH * EXT_HEIGHT); + } +} + #define R5G6B5 // windows port uses RGB565 #ifdef R5G6B5 @@ -550,15 +602,12 @@ inline void SetRect(RECT* rect, int width, int height, int scale) } #define AVERAGE_565(el0, el1) (((el0) & (el1)) + ((((el0) ^ (el1)) & 0xF7DE) >> 1)) -void RenderMergeHires(void *src, void* dst, int pitch, unsigned int &width, unsigned int &height) +void RenderMergeHires(void *src, int srcPitch , void* dst, int dstPitch, unsigned int width, unsigned int height) { - if (width <= 256) - return; - for (register int y = 0; y < height; y++) { - register uint16 *input = (uint16 *) ((uint8 *) src + y * pitch); - register uint16 *output = (uint16 *) ((uint8 *) dst + y * pitch); + register uint16 *input = (uint16 *) ((uint8 *) src + y * srcPitch); + register uint16 *output = (uint16 *) ((uint8 *) dst + y * dstPitch); register uint16 l, r; l = 0; @@ -2538,17 +2587,8 @@ void RenderSimple4X( SSurface Src, SSurface Dst, RECT *rect) } } - -enum BlarggMode { UNINITIALIZED,BLARGGCOMPOSITE,BLARGGSVIDEO,BLARGGRGB }; - -snes_ntsc_t *ntsc = NULL; -BlarggMode blarggMode = UNINITIALIZED; - void RenderBlarggNTSCComposite( SSurface Src, SSurface Dst, RECT *rect) { - if(!ntsc) { - ntsc = (snes_ntsc_t *)malloc(sizeof(snes_ntsc_t)); - } if(blarggMode!=BLARGGCOMPOSITE) { snes_ntsc_setup_t setup = snes_ntsc_composite; setup.merge_fields = 1; @@ -2560,9 +2600,6 @@ void RenderBlarggNTSCComposite( SSurface Src, SSurface Dst, RECT *rect) void RenderBlarggNTSCSvideo( SSurface Src, SSurface Dst, RECT *rect) { - if(!ntsc) { - ntsc = (snes_ntsc_t *)malloc(sizeof(snes_ntsc_t)); - } if(blarggMode!=BLARGGSVIDEO) { snes_ntsc_setup_t setup = snes_ntsc_svideo; setup.merge_fields = 1; @@ -2574,9 +2611,6 @@ void RenderBlarggNTSCSvideo( SSurface Src, SSurface Dst, RECT *rect) void RenderBlarggNTSCRgb( SSurface Src, SSurface Dst, RECT *rect) { - if(!ntsc) { - ntsc = (snes_ntsc_t *)malloc(sizeof(snes_ntsc_t)); - } if(blarggMode!=BLARGGRGB) { snes_ntsc_setup_t setup = snes_ntsc_rgb; setup.merge_fields = 1; diff --git a/win32/render.h b/win32/render.h index 6d760443..292562ef 100644 --- a/win32/render.h +++ b/win32/render.h @@ -191,13 +191,9 @@ struct SSurface { unsigned int Width, Height; }; -typedef void (*TRenderMethod)( SSurface Src, SSurface Dst, RECT *); +void RenderMethod(SSurface Src, SSurface Dst, RECT *); void SelectRenderMethod(); -void InitLUTsWin32(); -void RenderMergeHires(void *src, void* dst, int pitch, unsigned int &width, unsigned int &height); - -extern TRenderMethod RenderMethod; -extern TRenderMethod RenderMethodHiRes; +void InitRenderFilters(); #endif diff --git a/win32/win32.cpp b/win32/win32.cpp index cb09edf5..f444c56f 100644 --- a/win32/win32.cpp +++ b/win32/win32.cpp @@ -204,9 +204,7 @@ #include BYTE *ScreenBuf = NULL; -BYTE *ScreenBufBlend = NULL; BYTE *ScreenBuffer = NULL; -BYTE *ScreenBufferBlend = NULL; struct SJoyState Joystick [16]; uint32 joypads [8]; @@ -979,12 +977,8 @@ void InitSnes9X( void) Memory.PostRomInitFunc = S9xPostRomInit; ScreenBuf = new BYTE [EXT_PITCH * EXT_HEIGHT]; - ScreenBufBlend = new BYTE [EXT_PITCH * EXT_HEIGHT]; - ScreenBuffer = ScreenBuf + EXT_OFFSET; - ScreenBufferBlend = ScreenBufBlend + EXT_OFFSET; memset (ScreenBuf, 0, EXT_PITCH * EXT_HEIGHT); - memset (ScreenBufBlend, 0, EXT_PITCH * EXT_HEIGHT); GFX.Pitch = EXT_PITCH; GFX.RealPPL = EXT_PITCH; @@ -1008,8 +1002,7 @@ void DeinitS9x() { if(ScreenBuf) delete [] ScreenBuf; - if(ScreenBufBlend) - delete [] ScreenBufBlend; + DeleteCriticalSection(&GUI.SoundCritSect); CoUninitialize(); if(GUI.GunSight) diff --git a/win32/win32_display.cpp b/win32/win32_display.cpp index 45c55272..bc385c2a 100644 --- a/win32/win32_display.cpp +++ b/win32/win32_display.cpp @@ -222,13 +222,6 @@ void WinRefreshDisplay(void) SelectRenderMethod (); - Src.Surface = (BYTE *)GFX.Screen; - - if(Src.Width > SNES_WIDTH && GUI.BlendHiRes) { - RenderMergeHires(Src.Surface,ScreenBufferBlend,Src.Pitch,Src.Width,Src.Height); - Src.Surface = ScreenBufferBlend; - } - S9xDisplayOutput->Render(Src); GUI.FlipCounter++; } diff --git a/win32/win32_display.h b/win32/win32_display.h index b7f50fda..1ee30fbb 100644 --- a/win32/win32_display.h +++ b/win32/win32_display.h @@ -183,7 +183,6 @@ #include #define IsHiRes(x) ((x.Height > SNES_HEIGHT_EXTENDED || x.Width == 512)) -#define RenderMethod (IsHiRes(Src) ? RenderMethodHiRes : RenderMethod) #define CurrentScale (IsHiRes(Src) ? GUI.ScaleHiRes : GUI.Scale) void WinRefreshDisplay(void); diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 115ddc30..70a380d4 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -3217,7 +3217,7 @@ int WINAPI WinMain( SetMenu (GUI.hWnd, NULL); } - InitLUTsWin32(); // init win hq2x + InitRenderFilters(); GUI.ControlForced = 0xff; From f1b7d31c8e26adabb8392fe9d19964698c93c329 Mon Sep 17 00:00:00 2001 From: OV2 Date: Fri, 4 Mar 2011 00:38:16 +0100 Subject: [PATCH 2/5] Win32: fix osd for all hires filter scales --- win32/win32_display.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/win32/win32_display.cpp b/win32/win32_display.cpp index bc385c2a..8d166e90 100644 --- a/win32/win32_display.cpp +++ b/win32/win32_display.cpp @@ -789,7 +789,7 @@ void WinDisplayStringFromBottom (const char *string, int linesFromBottom, int pi static int font_width = 8, font_height = 9; static void *displayScreen; -int displayPpl, displayWidth, displayHeight, displayScale,fontwidth_scaled,fontheight_scaled; +int displayPpl, displayWidth, displayHeight, displayScale, fontwidth_scaled, fontheight_scaled; void WinSetCustomDisplaySurface(void *screen, int ppl, int width, int height, int scale) { @@ -797,7 +797,7 @@ void WinSetCustomDisplaySurface(void *screen, int ppl, int width, int height, in displayPpl=ppl; displayWidth=width; displayHeight=height; - displayScale=scale; + displayScale=max(1,width/IPPU.RenderedScreenWidth); fontwidth_scaled=font_width*displayScale; fontheight_scaled=font_height*displayScale; } @@ -926,7 +926,7 @@ void WinDisplayStringInBuffer (const char *string, int linesFromBottom, int pixe if (linesFromBottom <= 0) linesFromBottom = 1; - screenPtrType *dst = (screenPtrType *)displayScreen + (displayHeight - fontheight_scaled * linesFromBottom) * displayPpl + (int)(pixelsFromLeft * (2*(float)displayWidth/IPPU.RenderedScreenWidth - displayScale)); + screenPtrType *dst = (screenPtrType *)displayScreen + (displayHeight - fontheight_scaled * linesFromBottom) * displayPpl + (int)(pixelsFromLeft * (float)displayWidth/IPPU.RenderedScreenWidth); int len = strlen(string); int max_chars = displayWidth / (fontwidth_scaled - displayScale); From 42afceb2878469d6cf15bd9f898e2475a0620a2c Mon Sep 17 00:00:00 2001 From: OV2 Date: Fri, 4 Mar 2011 00:46:18 +0100 Subject: [PATCH 3/5] Win32: fix hi-res filter box (again) --- win32/wsnes9x.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 70a380d4..80a7003f 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -7085,12 +7085,15 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) strcpy(temp,GetFilterName((RenderFilter)filter)); SendDlgItemMessageA(hDlg,IDC_FILTERBOX,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)temp); } - for(int filter = 0 ; filter < (int)NUM_FILTERS ; filter++) + for(int filter = 0, hiResPos = 0 ; filter < (int)NUM_FILTERS ; filter++) { if(GetFilterHiResSupport((RenderFilter)filter)) { strcpy(temp,GetFilterName((RenderFilter)filter)); SendDlgItemMessageA(hDlg,IDC_FILTERBOX2,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)temp); + if(GUI.ScaleHiRes==filter) + SendDlgItemMessage(hDlg,IDC_FILTERBOX2,CB_SETCURSEL,(WPARAM)hiResPos,0); + hiResPos++; } } @@ -7101,8 +7104,6 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) // have to start focus on something like this or Escape won't exit the dialog SetFocus(hDlg); - SendDlgItemMessage(hDlg,IDC_FILTERBOX2,CB_SETCURSEL,(WPARAM)GUI.ScaleHiRes,0); - break; case WM_CLOSE: case WM_DESTROY: From 82fe0f7819af27afbc89011dce14558d792e28c5 Mon Sep 17 00:00:00 2001 From: OV2 Date: Fri, 4 Mar 2011 02:11:36 +0100 Subject: [PATCH 4/5] Win32: update cg shader handling, output compile errors --- win32/CDirect3D.cpp | 57 +++++++++++++++++++++++++++++++++------------ win32/CDirect3D.h | 1 + win32/COpenGL.cpp | 47 +++++++++++++++++++++++++++++++------ win32/COpenGL.h | 1 + 4 files changed, 84 insertions(+), 22 deletions(-) diff --git a/win32/CDirect3D.cpp b/win32/CDirect3D.cpp index 6e418df9..d30924b5 100644 --- a/win32/CDirect3D.cpp +++ b/win32/CDirect3D.cpp @@ -341,6 +341,26 @@ bool CDirect3D::SetShader(const TCHAR *file) } } +void CDirect3D::checkForCgError(const char *situation) +{ + char buffer[4096]; + CGerror error = cgGetError(); + const char *string = cgGetErrorString(error); + + if (error != CG_NO_ERROR) { + sprintf(buffer, + "Situation: %s\n" + "Error: %s\n\n" + "Cg compiler output...\n", situation, string); + MessageBoxA(0, buffer, + "Cg error", MB_OK|MB_ICONEXCLAMATION); + if (error == CG_COMPILER_ERROR) { + MessageBoxA(0, cgGetLastListing(cgContext), + "Cg compilation error", MB_OK|MB_ICONEXCLAMATION); + } + } +} + bool CDirect3D::SetShaderCG(const TCHAR *file) { TCHAR errorMsg[MAX_PATH + 50]; @@ -371,14 +391,16 @@ bool CDirect3D::SetShaderCG(const TCHAR *file) cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, vertexProfile, "main_vertex", vertexOptions); + checkForCgError("Compiling vertex program"); + cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, pixelProfile, "main_fragment", pixelOptions); + checkForCgError("Compiling fragment program"); + delete [] fileContents; - if(!cgVertexProgram && !cgFragmentProgram) { - _stprintf(errorMsg,TEXT("No vertex or fragment program in file:\n%s"),file); - MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION); + if(!cgVertexProgram || !cgFragmentProgram) { return false; } @@ -591,12 +613,6 @@ void CDirect3D::SetShaderVars() } } } else if(shader_type == D3D_SHADER_CG) { - CGparameter cgpModelViewProj = cgGetNamedParameter(cgVertexProgram, "modelViewProj"); - - CGparameter cgpVideoSize = cgGetNamedParameter(cgFragmentProgram, "IN.video_size"); - CGparameter cgpTextureSize = cgGetNamedParameter(cgFragmentProgram, "IN.texture_size"); - CGparameter cgpOutputSize = cgGetNamedParameter(cgFragmentProgram, "IN.output_size"); - D3DXMATRIX mvpMat; D3DXVECTOR2 videoSize; D3DXVECTOR2 textureSize; @@ -609,14 +625,25 @@ void CDirect3D::SetShaderVars() D3DXMatrixIdentity(&mvpMat); + CGparameter cgpModelViewProj = cgGetNamedParameter(cgVertexProgram, "modelViewProj"); + if(cgpModelViewProj) cgD3D9SetUniformMatrix(cgpModelViewProj,&mvpMat); - if(cgpVideoSize) - cgD3D9SetUniform(cgpVideoSize,&videoSize); - if(cgpTextureSize) - cgD3D9SetUniform(cgpTextureSize,&textureSize); - if(cgpOutputSize) - cgD3D9SetUniform(cgpOutputSize,&outputSize); + +#define setProgramUniform(program,varname,floats)\ +{\ + CGparameter cgp = cgGetNamedParameter(program, varname);\ + if(cgp)\ + cgD3D9SetUniform(cgp,floats);\ +}\ + + setProgramUniform(cgFragmentProgram,"IN.video_size",&videoSize); + setProgramUniform(cgFragmentProgram,"IN.texture_size",&textureSize); + setProgramUniform(cgFragmentProgram,"IN.output_size",&outputSize); + + setProgramUniform(cgVertexProgram,"IN.video_size",&videoSize); + setProgramUniform(cgVertexProgram,"IN.texture_size",&textureSize); + setProgramUniform(cgVertexProgram,"IN.output_size",&outputSize); } } diff --git a/win32/CDirect3D.h b/win32/CDirect3D.h index 43b94e8b..57439b64 100644 --- a/win32/CDirect3D.h +++ b/win32/CDirect3D.h @@ -239,6 +239,7 @@ private: void SetShaderVars(); bool SetShader(const TCHAR *file); bool SetShaderHLSL(const TCHAR *file); + void checkForCgError(const char *situation); bool SetShaderCG(const TCHAR *file); public: diff --git a/win32/COpenGL.cpp b/win32/COpenGL.cpp index ee2de7da..750d9f40 100644 --- a/win32/COpenGL.cpp +++ b/win32/COpenGL.cpp @@ -282,14 +282,25 @@ void COpenGL::Render(SSurface Src) } else if(shader_type == OGL_SHADER_CG) { CGparameter cgpModelViewProj = cgGetNamedParameter(cgVertexProgram, "modelViewProj"); + cgGLSetStateMatrixParameter(cgpModelViewProj, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); + CGparameter cgpVideoSize = cgGetNamedParameter(cgFragmentProgram, "IN.video_size"); CGparameter cgpTextureSize = cgGetNamedParameter(cgFragmentProgram, "IN.texture_size"); CGparameter cgpOutputSize = cgGetNamedParameter(cgFragmentProgram, "IN.output_size"); - cgGLSetStateMatrixParameter(cgpModelViewProj, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); - cgGLSetParameter2fv(cgpVideoSize, inputSize); - cgGLSetParameter2fv(cgpTextureSize, textureSize); - cgGLSetParameter2fv(cgpOutputSize, outputSize); +#define setProgram2fv(program,varname,floats)\ +{\ + CGparameter cgp = cgGetNamedParameter(program, varname);\ + if(cgp)\ + cgGLSetParameter2fv(cgp,floats);\ +}\ + + setProgram2fv(cgFragmentProgram,"IN.video_size",inputSize); + setProgram2fv(cgFragmentProgram,"IN.texture_size",textureSize); + setProgram2fv(cgFragmentProgram,"IN.output_size",outputSize); + setProgram2fv(cgVertexProgram,"IN.video_size",inputSize); + setProgram2fv(cgVertexProgram,"IN.texture_size",textureSize); + setProgram2fv(cgVertexProgram,"IN.output_size",outputSize); } } @@ -487,6 +498,26 @@ bool COpenGL::SetShaders(const TCHAR *file) } } +void COpenGL::checkForCgError(const char *situation) +{ + char buffer[4096]; + CGerror error = cgGetError(); + const char *string = cgGetErrorString(error); + + if (error != CG_NO_ERROR) { + sprintf(buffer, + "Situation: %s\n" + "Error: %s\n\n" + "Cg compiler output...\n", situation, string); + MessageBoxA(0, buffer, + "Cg error", MB_OK|MB_ICONEXCLAMATION); + if (error == CG_COMPILER_ERROR) { + MessageBoxA(0, cgGetLastListing(cgContext), + "Cg compilation error", MB_OK|MB_ICONEXCLAMATION); + } + } +} + bool COpenGL::SetShadersCG(const TCHAR *file) { TCHAR errorMsg[MAX_PATH + 50]; @@ -520,14 +551,16 @@ bool COpenGL::SetShadersCG(const TCHAR *file) cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, vertexProfile, "main_vertex", NULL); + checkForCgError("Compiling vertex program"); + cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, fragmentProfile, "main_fragment", NULL); + checkForCgError("Compiling fragment program"); + delete [] fileContents; - if(!cgVertexProgram && !cgFragmentProgram) { - _stprintf(errorMsg,TEXT("No vertex or fragment program in file:\n%s"),file); - MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION); + if(!cgVertexProgram || !cgFragmentProgram) { return false; } diff --git a/win32/COpenGL.h b/win32/COpenGL.h index 1ef32a60..8adb1518 100644 --- a/win32/COpenGL.h +++ b/win32/COpenGL.h @@ -246,6 +246,7 @@ private: PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; bool SetShaders(const TCHAR *file); + void checkForCgError(const char *situation); bool SetShadersCG(const TCHAR *file); bool SetShadersGLSL(const TCHAR *glslFileName); bool LoadShaderFunctions(); From 8f63cb0cea8c94b61bc6370f77afff9c02d1fb19 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sun, 6 Mar 2011 00:48:54 +0100 Subject: [PATCH 5/5] Win32: do not use pre-transformed vertices in D3D Using pre-transformed vertices bypasses vertex shaders, which prevented some of the cg shaders to run correctly. --- win32/CDirect3D.cpp | 82 ++++++++++++++++++++++++++++++++------------- win32/CDirect3D.h | 9 ++--- win32/COpenGL.cpp | 1 - 3 files changed, 64 insertions(+), 28 deletions(-) diff --git a/win32/CDirect3D.cpp b/win32/CDirect3D.cpp index d30924b5..204b30c3 100644 --- a/win32/CDirect3D.cpp +++ b/win32/CDirect3D.cpp @@ -284,10 +284,14 @@ bool CDirect3D::Initialize(HWND hWnd) DXTRACE_ERR_MSGBOX(TEXT("Error setting cg device"), hr); } + pDevice->SetRenderState(D3DRS_LIGHTING, FALSE); + pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); init_done = true; + SetViewport(); + ApplyDisplayChanges(); return true; @@ -405,8 +409,25 @@ bool CDirect3D::SetShaderCG(const TCHAR *file) } if(cgVertexProgram) { - hr = cgD3D9LoadProgram(cgVertexProgram,false,0); + hr = cgD3D9LoadProgram(cgVertexProgram,true,0); hr = cgD3D9BindProgram(cgVertexProgram); + + D3DXMATRIX matWorld; + D3DXMATRIX matView; + D3DXMATRIX matProj; + D3DXMATRIX mvp; + + pDevice->GetTransform(D3DTS_WORLD,&matWorld); + pDevice->GetTransform(D3DTS_VIEW,&matView); + pDevice->GetTransform(D3DTS_PROJECTION,&matProj); + + mvp = matWorld * matView * matProj; + D3DXMatrixTranspose(&mvp,&mvp); + + CGparameter cgpModelViewProj = cgGetNamedParameter(cgVertexProgram, "modelViewProj"); + + if(cgpModelViewProj) + cgD3D9SetUniformMatrix(cgpModelViewProj,&mvp); } if(cgFragmentProgram) { hr = cgD3D9LoadProgram(cgFragmentProgram,false,0); @@ -613,7 +634,7 @@ void CDirect3D::SetShaderVars() } } } else if(shader_type == D3D_SHADER_CG) { - D3DXMATRIX mvpMat; + D3DXVECTOR2 videoSize; D3DXVECTOR2 textureSize; D3DXVECTOR2 outputSize; @@ -623,13 +644,6 @@ void CDirect3D::SetShaderVars() outputSize.x = GUI.Stretch?(float)dPresentParams.BackBufferWidth:(float)afterRenderWidth; outputSize.y = GUI.Stretch?(float)dPresentParams.BackBufferHeight:(float)afterRenderHeight; - D3DXMatrixIdentity(&mvpMat); - - CGparameter cgpModelViewProj = cgGetNamedParameter(cgVertexProgram, "modelViewProj"); - - if(cgpModelViewProj) - cgD3D9SetUniformMatrix(cgpModelViewProj,&mvpMat); - #define setProgramUniform(program,varname,floats)\ {\ CGparameter cgp = cgGetNamedParameter(program, varname);\ @@ -703,11 +717,11 @@ void CDirect3D::Render(SSurface Src) drawSurface->UnlockRect(0); } - //if the output size of the render method changes we need new vertices + //if the output size of the render method changes we need to update the viewport if(afterRenderHeight != dstRect.bottom || afterRenderWidth != dstRect.right) { afterRenderHeight = dstRect.bottom; afterRenderWidth = dstRect.right; - SetupVertices(); + SetViewport(); } if(!GUI.Stretch||GUI.AspectRatio) @@ -719,13 +733,13 @@ void CDirect3D::Render(SSurface Src) pDevice->SetFVF(FVF_COORDS_TEX); pDevice->SetStreamSource(0,vertexBuffer,0,sizeof(VERTEX)); + SetShaderVars(); + if(shader_type == D3D_SHADER_CG) { cgD3D9BindProgram(cgFragmentProgram); cgD3D9BindProgram(cgVertexProgram); } - SetShaderVars(); - if (shader_type == D3D_SHADER_HLSL) { UINT passes; @@ -839,26 +853,45 @@ calculates the vertex coordinates */ void CDirect3D::SetupVertices() { - RECT drawRect; void *pLockedVertexBuffer; - drawRect = CalculateDisplayRect(afterRenderWidth,afterRenderHeight,dPresentParams.BackBufferWidth,dPresentParams.BackBufferHeight); - float tX = (float)afterRenderWidth / (float)quadTextureSize; float tY = (float)afterRenderHeight / (float)quadTextureSize; - //we need to substract -0.5 from the x/y coordinates to match texture with pixel space - //see http://msdn.microsoft.com/en-us/library/bb219690(VS.85).aspx - triangleStripVertices[0] = VERTEX((float)drawRect.left - 0.5f,(float)drawRect.bottom - 0.5f,0.0f,1.0f,0.0f,tY); - triangleStripVertices[1] = VERTEX((float)drawRect.left - 0.5f,(float)drawRect.top - 0.5f,0.0f,1.0f,0.0f,0.0f); - triangleStripVertices[2] = VERTEX((float)drawRect.right - 0.5f,(float)drawRect.bottom - 0.5f,0.0f,1.0f,tX,tY); - triangleStripVertices[3] = VERTEX((float)drawRect.right - 0.5f,(float)drawRect.top - 0.5f,0.0f,1.0f,tX,0.0f); + triangleStripVertices[0] = VERTEX(0.0f,0.0f,0.0f,0.0f,tY); + triangleStripVertices[1] = VERTEX(0.0f,1.0f,0.0f,0.0f,0.0f); + triangleStripVertices[2] = VERTEX(1.0f,0.0f,0.0f,tX,tY); + triangleStripVertices[3] = VERTEX(1.0f,1.0f,0.0f,tX,0.0f); HRESULT hr = vertexBuffer->Lock(0,0,&pLockedVertexBuffer,NULL); memcpy(pLockedVertexBuffer,triangleStripVertices,sizeof(triangleStripVertices)); vertexBuffer->Unlock(); } +void CDirect3D::SetViewport() +{ + D3DXMATRIX matIdentity; + D3DXMATRIX matProjection; + + D3DXMatrixOrthoOffCenterLH(&matProjection,0.0f,1.0f,0.0f,1.0f,0.0f,1.0f); + D3DXMatrixIdentity(&matIdentity); + pDevice->SetTransform(D3DTS_WORLD,&matIdentity); + pDevice->SetTransform(D3DTS_VIEW,&matIdentity); + pDevice->SetTransform(D3DTS_PROJECTION,&matProjection); + + RECT drawRect = CalculateDisplayRect(afterRenderWidth,afterRenderHeight,dPresentParams.BackBufferWidth,dPresentParams.BackBufferHeight); + D3DVIEWPORT9 viewport; + viewport.X = drawRect.left; + viewport.Y = drawRect.top; + viewport.Height = drawRect.bottom - drawRect.top; + viewport.Width = drawRect.right - drawRect.left; + viewport.MinZ = 0.0f; + viewport.MaxZ = 1.0f; + HRESULT hr = pDevice->SetViewport(&viewport); + + SetupVertices(); +} + /* CDirect3D::ChangeRenderSize determines if we need to reset the device (if the size changed) called with (0,0) whenever we want new settings to take effect @@ -879,7 +912,8 @@ bool CDirect3D::ChangeRenderSize(unsigned int newWidth, unsigned int newHeight) if(!ResetDevice()) return false; - SetupVertices(); + + SetViewport(); return true; } @@ -938,6 +972,8 @@ bool CDirect3D::ResetDevice() pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); } + pDevice->SetRenderState(D3DRS_LIGHTING, FALSE); + pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); //recreate the surface diff --git a/win32/CDirect3D.h b/win32/CDirect3D.h index 57439b64..813b4078 100644 --- a/win32/CDirect3D.h +++ b/win32/CDirect3D.h @@ -190,15 +190,14 @@ #include "wsnes9x.h" #include "IS9xDisplayOutput.h" -#define FVF_COORDS_TEX D3DFVF_XYZRHW | D3DFVF_TEX1 +#define FVF_COORDS_TEX D3DFVF_XYZ | D3DFVF_TEX1 typedef struct _VERTEX { float x, y, z; - float rhw; float tx, ty; _VERTEX() {} - _VERTEX(float x,float y,float z,float rhw,float tx,float ty) { - this->x=x;this->y=y;this->z=z;this->rhw=rhw;this->tx=tx;this->ty=ty; + _VERTEX(float x,float y,float z,float tx,float ty) { + this->x=x;this->y=y;this->z=z;this->tx=tx;this->ty=ty; } } VERTEX; //our custom vertex with a constuctor for easier assignment @@ -226,6 +225,7 @@ private: CGcontext cgContext; CGprogram cgVertexProgram, cgFragmentProgram; current_d3d_shader_type shader_type; + float shaderTimer; int shaderTimeStart; int shaderTimeElapsed; @@ -234,6 +234,7 @@ private: void CreateDrawSurface(); void DestroyDrawSurface(); bool ChangeDrawSurfaceSize(unsigned int scale); + void SetViewport(); void SetupVertices(); bool ResetDevice(); void SetShaderVars(); diff --git a/win32/COpenGL.cpp b/win32/COpenGL.cpp index 750d9f40..0b14c952 100644 --- a/win32/COpenGL.cpp +++ b/win32/COpenGL.cpp @@ -343,7 +343,6 @@ bool COpenGL::ApplyDisplayChanges(void) RECT windowSize; GetClientRect(hWnd,&windowSize); ChangeRenderSize(windowSize.right,windowSize.bottom); - SetupVertices(); return true; }