diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp index af263235cd..0d7d741a92 100644 --- a/Source/Core/VideoCommon/Src/BPStructs.cpp +++ b/Source/Core/VideoCommon/Src/BPStructs.cpp @@ -456,6 +456,7 @@ void BPWritten(const BPCmd& bp) case BPMEM_ZCOMPARE: // Set the Z-Compare and EFB pixel format g_renderer->SetColorMask(); // alpha writing needs to be disabled if the new pixel format doesn't have an alpha channel + g_renderer->SetBlendMode(true); OnPixelFormatChange(); break; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 44eaaf5dcf..57812aa067 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -54,8 +54,6 @@ static int s_fps = 0; static u32 s_LastAA = 0; -static u32 s_blendMode; - static Television s_television; ID3D11Buffer* access_efb_cbuf = NULL; @@ -76,151 +74,6 @@ struct D3D11_RASTERIZER_DESC rastdc; } gx_state; -// State translation lookup tables -static const D3D11_BLEND d3dSrcFactors[8] = -{ - D3D11_BLEND_ZERO, - D3D11_BLEND_ONE, - D3D11_BLEND_DEST_COLOR, - D3D11_BLEND_INV_DEST_COLOR, - D3D11_BLEND_SRC_ALPHA, - D3D11_BLEND_INV_SRC_ALPHA, // NOTE: Use SRC1_ALPHA if dst alpha is enabled! - D3D11_BLEND_DEST_ALPHA, - D3D11_BLEND_INV_DEST_ALPHA -}; - -static const D3D11_BLEND d3dDestFactors[8] = -{ - D3D11_BLEND_ZERO, - D3D11_BLEND_ONE, - D3D11_BLEND_SRC_COLOR, - D3D11_BLEND_INV_SRC_COLOR, - D3D11_BLEND_SRC_ALPHA, - D3D11_BLEND_INV_SRC_ALPHA, // NOTE: Use SRC1_ALPHA if dst alpha is enabled! - D3D11_BLEND_DEST_ALPHA, - D3D11_BLEND_INV_DEST_ALPHA -}; - -// 0 0x00 -// 1 Source & destination -// 2 Source & ~destination -// 3 Source -// 4 ~Source & destination -// 5 Destination -// 6 Source ^ destination = Source & ~destination | ~Source & destination -// 7 Source | destination - -// 8 ~(Source | destination) -// 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination -// 10 ~Destination -// 11 Source | ~destination -// 12 ~Source -// 13 ~Source | destination -// 14 ~(Source & destination) -// 15 0xff - -static const D3D11_BLEND_OP d3dLogicOps[16] = -{ - D3D11_BLEND_OP_ADD,//0 - D3D11_BLEND_OP_ADD,//1 - D3D11_BLEND_OP_SUBTRACT,//2 - D3D11_BLEND_OP_ADD,//3 - D3D11_BLEND_OP_REV_SUBTRACT,//4 - D3D11_BLEND_OP_ADD,//5 - D3D11_BLEND_OP_MAX,//6 - D3D11_BLEND_OP_ADD,//7 - - D3D11_BLEND_OP_MAX,//8 - D3D11_BLEND_OP_MAX,//9 - D3D11_BLEND_OP_ADD,//10 - D3D11_BLEND_OP_ADD,//11 - D3D11_BLEND_OP_ADD,//12 - D3D11_BLEND_OP_ADD,//13 - D3D11_BLEND_OP_ADD,//14 - D3D11_BLEND_OP_ADD//15 -}; - -static const D3D11_BLEND d3dLogicOpSrcFactors[16] = -{ - D3D11_BLEND_ZERO,//0 - D3D11_BLEND_DEST_COLOR,//1 - D3D11_BLEND_ONE,//2 - D3D11_BLEND_ONE,//3 - D3D11_BLEND_DEST_COLOR,//4 - D3D11_BLEND_ZERO,//5 - D3D11_BLEND_INV_DEST_COLOR,//6 - D3D11_BLEND_INV_DEST_COLOR,//7 - - D3D11_BLEND_INV_SRC_COLOR,//8 - D3D11_BLEND_INV_SRC_COLOR,//9 - D3D11_BLEND_INV_DEST_COLOR,//10 - D3D11_BLEND_ONE,//11 - D3D11_BLEND_INV_SRC_COLOR,//12 - D3D11_BLEND_INV_SRC_COLOR,//13 - D3D11_BLEND_INV_DEST_COLOR,//14 - D3D11_BLEND_ONE//15 -}; - -static const D3D11_BLEND d3dLogicOpDestFactors[16] = -{ - D3D11_BLEND_ZERO,//0 - D3D11_BLEND_ZERO,//1 - D3D11_BLEND_INV_SRC_COLOR,//2 - D3D11_BLEND_ZERO,//3 - D3D11_BLEND_ONE,//4 - D3D11_BLEND_ONE,//5 - D3D11_BLEND_INV_SRC_COLOR,//6 - D3D11_BLEND_ONE,//7 - - D3D11_BLEND_INV_DEST_COLOR,//8 - D3D11_BLEND_SRC_COLOR,//9 - D3D11_BLEND_INV_DEST_COLOR,//10 - D3D11_BLEND_INV_DEST_COLOR,//11 - D3D11_BLEND_INV_SRC_COLOR,//12 - D3D11_BLEND_ONE,//13 - D3D11_BLEND_INV_SRC_COLOR,//14 - D3D11_BLEND_ONE//15 -}; - -static const D3D11_CULL_MODE d3dCullModes[4] = -{ - D3D11_CULL_NONE, - D3D11_CULL_BACK, - D3D11_CULL_FRONT, - D3D11_CULL_BACK -}; - -static const D3D11_COMPARISON_FUNC d3dCmpFuncs[8] = -{ - D3D11_COMPARISON_NEVER, - D3D11_COMPARISON_LESS, - D3D11_COMPARISON_EQUAL, - D3D11_COMPARISON_LESS_EQUAL, - D3D11_COMPARISON_GREATER, - D3D11_COMPARISON_NOT_EQUAL, - D3D11_COMPARISON_GREATER_EQUAL, - D3D11_COMPARISON_ALWAYS -}; - -#define TEXF_NONE 0 -#define TEXF_POINT 1 -#define TEXF_LINEAR 2 -static const unsigned int d3dMipFilters[4] = -{ - TEXF_NONE, - TEXF_POINT, - TEXF_LINEAR, - TEXF_NONE, //reserved -}; - -static const D3D11_TEXTURE_ADDRESS_MODE d3dClamps[4] = -{ - D3D11_TEXTURE_ADDRESS_CLAMP, - D3D11_TEXTURE_ADDRESS_WRAP, - D3D11_TEXTURE_ADDRESS_MIRROR, - D3D11_TEXTURE_ADDRESS_WRAP //reserved -}; - void SetupDeviceObjects() { @@ -338,7 +191,6 @@ void CreateScreenshotTexture() Renderer::Renderer() { int x, y, w_temp, h_temp; - s_blendMode = 0; InitFPSCounter(); @@ -833,6 +685,32 @@ void SetBlendOp(D3D11_BLEND_OP val) void Renderer::SetBlendMode(bool forceUpdate) { + // Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel + // Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1. + bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; + const D3D11_BLEND d3dSrcFactors[8] = + { + D3D11_BLEND_ZERO, + D3D11_BLEND_ONE, + D3D11_BLEND_DEST_COLOR, + D3D11_BLEND_INV_DEST_COLOR, + D3D11_BLEND_SRC_ALPHA, + D3D11_BLEND_INV_SRC_ALPHA, // NOTE: Use SRC1_ALPHA if dst alpha is enabled! + (target_has_alpha) ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_ONE, + (target_has_alpha) ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_ZERO + }; + const D3D11_BLEND d3dDestFactors[8] = + { + D3D11_BLEND_ZERO, + D3D11_BLEND_ONE, + D3D11_BLEND_SRC_COLOR, + D3D11_BLEND_INV_SRC_COLOR, + D3D11_BLEND_SRC_ALPHA, + D3D11_BLEND_INV_SRC_ALPHA, // NOTE: Use SRC1_ALPHA if dst alpha is enabled! + (target_has_alpha) ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_ONE, + (target_has_alpha) ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_ZERO + }; + if (bpmem.blendmode.logicopenable && !forceUpdate) return; @@ -845,8 +723,8 @@ void Renderer::SetBlendMode(bool forceUpdate) } else { - gx_state.blenddc.RenderTarget[0].BlendEnable = bpmem.blendmode.blendenable && (!( bpmem.blendmode.srcfactor == 1 && bpmem.blendmode.dstfactor == 0)); - if (bpmem.blendmode.blendenable && (!( bpmem.blendmode.srcfactor == 1 && bpmem.blendmode.dstfactor == 0))) + gx_state.blenddc.RenderTarget[0].BlendEnable = bpmem.blendmode.blendenable; + if (bpmem.blendmode.blendenable) { SetBlendOp(D3D11_BLEND_OP_ADD); SetSrcBlend(d3dSrcFactors[bpmem.blendmode.srcfactor]); @@ -1331,12 +1209,32 @@ void Renderer::RestoreCull() void Renderer::SetGenerationMode() { + const D3D11_CULL_MODE d3dCullModes[4] = + { + D3D11_CULL_NONE, + D3D11_CULL_BACK, + D3D11_CULL_FRONT, + D3D11_CULL_BACK + }; + // rastdc.FrontCounterClockwise must be false for this to work gx_state.rastdc.CullMode = d3dCullModes[bpmem.genMode.cullmode]; } void Renderer::SetDepthMode() { + const D3D11_COMPARISON_FUNC d3dCmpFuncs[8] = + { + D3D11_COMPARISON_NEVER, + D3D11_COMPARISON_LESS, + D3D11_COMPARISON_EQUAL, + D3D11_COMPARISON_LESS_EQUAL, + D3D11_COMPARISON_GREATER, + D3D11_COMPARISON_NOT_EQUAL, + D3D11_COMPARISON_GREATER_EQUAL, + D3D11_COMPARISON_ALWAYS + }; + if (bpmem.zmode.testenable) { gx_state.depthdc.DepthEnable = TRUE; @@ -1353,9 +1251,85 @@ void Renderer::SetDepthMode() void Renderer::SetLogicOpMode() { - if (bpmem.blendmode.logicopenable && bpmem.blendmode.logicmode != 3) + // D3D11 doesn't support logic blending, so this is a huge hack + // TODO: Make use of D3D11.1's logic blending support + + // 0 0x00 + // 1 Source & destination + // 2 Source & ~destination + // 3 Source + // 4 ~Source & destination + // 5 Destination + // 6 Source ^ destination = Source & ~destination | ~Source & destination + // 7 Source | destination + // 8 ~(Source | destination) + // 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination + // 10 ~Destination + // 11 Source | ~destination + // 12 ~Source + // 13 ~Source | destination + // 14 ~(Source & destination) + // 15 0xff + const D3D11_BLEND_OP d3dLogicOps[16] = + { + D3D11_BLEND_OP_ADD,//0 + D3D11_BLEND_OP_ADD,//1 + D3D11_BLEND_OP_SUBTRACT,//2 + D3D11_BLEND_OP_ADD,//3 + D3D11_BLEND_OP_REV_SUBTRACT,//4 + D3D11_BLEND_OP_ADD,//5 + D3D11_BLEND_OP_MAX,//6 + D3D11_BLEND_OP_ADD,//7 + D3D11_BLEND_OP_MAX,//8 + D3D11_BLEND_OP_MAX,//9 + D3D11_BLEND_OP_ADD,//10 + D3D11_BLEND_OP_ADD,//11 + D3D11_BLEND_OP_ADD,//12 + D3D11_BLEND_OP_ADD,//13 + D3D11_BLEND_OP_ADD,//14 + D3D11_BLEND_OP_ADD//15 + }; + const D3D11_BLEND d3dLogicOpSrcFactors[16] = + { + D3D11_BLEND_ZERO,//0 + D3D11_BLEND_DEST_COLOR,//1 + D3D11_BLEND_ONE,//2 + D3D11_BLEND_ONE,//3 + D3D11_BLEND_DEST_COLOR,//4 + D3D11_BLEND_ZERO,//5 + D3D11_BLEND_INV_DEST_COLOR,//6 + D3D11_BLEND_INV_DEST_COLOR,//7 + D3D11_BLEND_INV_SRC_COLOR,//8 + D3D11_BLEND_INV_SRC_COLOR,//9 + D3D11_BLEND_INV_DEST_COLOR,//10 + D3D11_BLEND_ONE,//11 + D3D11_BLEND_INV_SRC_COLOR,//12 + D3D11_BLEND_INV_SRC_COLOR,//13 + D3D11_BLEND_INV_DEST_COLOR,//14 + D3D11_BLEND_ONE//15 + }; + const D3D11_BLEND d3dLogicOpDestFactors[16] = + { + D3D11_BLEND_ZERO,//0 + D3D11_BLEND_ZERO,//1 + D3D11_BLEND_INV_SRC_COLOR,//2 + D3D11_BLEND_ZERO,//3 + D3D11_BLEND_ONE,//4 + D3D11_BLEND_ONE,//5 + D3D11_BLEND_INV_SRC_COLOR,//6 + D3D11_BLEND_ONE,//7 + D3D11_BLEND_INV_DEST_COLOR,//8 + D3D11_BLEND_SRC_COLOR,//9 + D3D11_BLEND_INV_DEST_COLOR,//10 + D3D11_BLEND_INV_DEST_COLOR,//11 + D3D11_BLEND_INV_SRC_COLOR,//12 + D3D11_BLEND_ONE,//13 + D3D11_BLEND_INV_SRC_COLOR,//14 + D3D11_BLEND_ONE//15 + }; + + if (bpmem.blendmode.logicopenable) { - s_blendMode = 0; gx_state.blenddc.RenderTarget[0].BlendEnable = true; SetBlendOp(d3dLogicOps[bpmem.blendmode.logicmode]); SetSrcBlend(d3dLogicOpSrcFactors[bpmem.blendmode.logicmode]); @@ -1379,18 +1353,32 @@ void Renderer::SetLineWidth() void Renderer::SetSamplerState(int stage, int texindex) { +#define TEXF_NONE 0 +#define TEXF_POINT 1 +#define TEXF_LINEAR 2 + const unsigned int d3dMipFilters[4] = + { + TEXF_NONE, + TEXF_POINT, + TEXF_LINEAR, + TEXF_NONE, //reserved + }; + const D3D11_TEXTURE_ADDRESS_MODE d3dClamps[4] = + { + D3D11_TEXTURE_ADDRESS_CLAMP, + D3D11_TEXTURE_ADDRESS_WRAP, + D3D11_TEXTURE_ADDRESS_MIRROR, + D3D11_TEXTURE_ADDRESS_WRAP //reserved + }; + const FourTexUnits &tex = bpmem.tex[texindex]; const TexMode0 &tm0 = tex.texMode0[stage]; const TexMode1 &tm1 = tex.texMode1[stage]; - unsigned int mip; - mip = (tm0.min_filter == 8) ? TEXF_NONE:d3dMipFilters[tm0.min_filter & 3]; - if ((tm0.min_filter & 3) && (tm0.min_filter != 8) && ((tm1.max_lod >> 4) == 0)) mip = TEXF_NONE; + unsigned int mip = d3dMipFilters[tm0.min_filter & 3]; if (texindex) stage += 4; - // TODO: Clarify whether these values are correct - // NOTE: since there's no "no filter" in DX11 we're using point filters in these cases if (g_ActiveConfig.bForceFiltering) { gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index f750313642..0ff4f4f99a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -73,148 +73,6 @@ static char *st; static LPDIRECT3DSURFACE9 ScreenShootMEMSurface = NULL; -// State translation lookup tables -static const D3DBLEND d3dSrcFactors[8] = -{ - D3DBLEND_ZERO, - D3DBLEND_ONE, - D3DBLEND_DESTCOLOR, - D3DBLEND_INVDESTCOLOR, - D3DBLEND_SRCALPHA, - D3DBLEND_INVSRCALPHA, - D3DBLEND_DESTALPHA, - D3DBLEND_INVDESTALPHA -}; - -static const D3DBLEND d3dDestFactors[8] = -{ - D3DBLEND_ZERO, - D3DBLEND_ONE, - D3DBLEND_SRCCOLOR, - D3DBLEND_INVSRCCOLOR, - D3DBLEND_SRCALPHA, - D3DBLEND_INVSRCALPHA, - D3DBLEND_DESTALPHA, - D3DBLEND_INVDESTALPHA -}; - -// 0 0x00 -// 1 Source & destination -// 2 Source & ~destination -// 3 Source -// 4 ~Source & destination -// 5 Destination -// 6 Source ^ destination = Source & ~destination | ~Source & destination -// 7 Source | destination - -// 8 ~(Source | destination) -// 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination -// 10 ~Destination -// 11 Source | ~destination -// 12 ~Source -// 13 ~Source | destination -// 14 ~(Source & destination) -// 15 0xff - -static const D3DBLENDOP d3dLogicOpop[16] = -{ - D3DBLENDOP_ADD, - D3DBLENDOP_ADD, - D3DBLENDOP_SUBTRACT, - D3DBLENDOP_ADD, - D3DBLENDOP_REVSUBTRACT, - D3DBLENDOP_ADD, - D3DBLENDOP_MAX, - D3DBLENDOP_ADD, - - D3DBLENDOP_MAX, - D3DBLENDOP_MAX, - D3DBLENDOP_ADD, - D3DBLENDOP_ADD, - D3DBLENDOP_ADD, - D3DBLENDOP_ADD, - D3DBLENDOP_ADD, - D3DBLENDOP_ADD -}; - -static const D3DBLEND d3dLogicOpSrcFactors[16] = -{ - D3DBLEND_ZERO, - D3DBLEND_DESTCOLOR, - D3DBLEND_ONE, - D3DBLEND_ONE, - D3DBLEND_DESTCOLOR, - D3DBLEND_ZERO, - D3DBLEND_INVDESTCOLOR, - D3DBLEND_INVDESTCOLOR, - - D3DBLEND_INVSRCCOLOR, - D3DBLEND_INVSRCCOLOR, - D3DBLEND_INVDESTCOLOR, - D3DBLEND_ONE, - D3DBLEND_INVSRCCOLOR, - D3DBLEND_INVSRCCOLOR, - D3DBLEND_INVDESTCOLOR, - D3DBLEND_ONE -}; - -static const D3DBLEND d3dLogicOpDestFactors[16] = -{ - D3DBLEND_ZERO, - D3DBLEND_ZERO, - D3DBLEND_INVSRCCOLOR, - D3DBLEND_ZERO, - D3DBLEND_ONE, - D3DBLEND_ONE, - D3DBLEND_INVSRCCOLOR, - D3DBLEND_ONE, - - D3DBLEND_INVDESTCOLOR, - D3DBLEND_SRCCOLOR, - D3DBLEND_INVDESTCOLOR, - D3DBLEND_INVDESTCOLOR, - D3DBLEND_INVSRCCOLOR, - D3DBLEND_ONE, - D3DBLEND_INVSRCCOLOR, - D3DBLEND_ONE -}; - -static const D3DCULL d3dCullModes[4] = -{ - D3DCULL_NONE, - D3DCULL_CCW, - D3DCULL_CW, - D3DCULL_CCW -}; - -static const D3DCMPFUNC d3dCmpFuncs[8] = -{ - D3DCMP_NEVER, - D3DCMP_LESS, - D3DCMP_EQUAL, - D3DCMP_LESSEQUAL, - D3DCMP_GREATER, - D3DCMP_NOTEQUAL, - D3DCMP_GREATEREQUAL, - D3DCMP_ALWAYS -}; - -static const D3DTEXTUREFILTERTYPE d3dMipFilters[4] = -{ - D3DTEXF_NONE, - D3DTEXF_POINT, - D3DTEXF_LINEAR, - D3DTEXF_NONE, //reserved -}; - -static const D3DTEXTUREADDRESS d3dClamps[4] = -{ - D3DTADDRESS_CLAMP, - D3DTADDRESS_WRAP, - D3DTADDRESS_MIRROR, - D3DTADDRESS_WRAP //reserved -}; - void SetupDeviceObjects() { D3D::font.Init(); @@ -796,6 +654,32 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) void Renderer::SetBlendMode(bool forceUpdate) { + // Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel + // Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1. + bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; + const D3DBLEND d3dSrcFactors[8] = + { + D3DBLEND_ZERO, + D3DBLEND_ONE, + D3DBLEND_DESTCOLOR, + D3DBLEND_INVDESTCOLOR, + D3DBLEND_SRCALPHA, + D3DBLEND_INVSRCALPHA, + (target_has_alpha) ? D3DBLEND_DESTALPHA : D3DBLEND_ONE, + (target_has_alpha) ? D3DBLEND_INVDESTALPHA : D3DBLEND_ZERO + }; + const D3DBLEND d3dDestFactors[8] = + { + D3DBLEND_ZERO, + D3DBLEND_ONE, + D3DBLEND_SRCCOLOR, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_SRCALPHA, + D3DBLEND_INVSRCALPHA, + (target_has_alpha) ? D3DBLEND_DESTALPHA : D3DBLEND_ONE, + (target_has_alpha) ? D3DBLEND_INVDESTALPHA : D3DBLEND_ZERO + }; + if (bpmem.blendmode.logicopenable && !forceUpdate) return; @@ -808,8 +692,8 @@ void Renderer::SetBlendMode(bool forceUpdate) } else { - D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable && (!( bpmem.blendmode.srcfactor == 1 && bpmem.blendmode.dstfactor == 0))); - if (bpmem.blendmode.blendenable && (!( bpmem.blendmode.srcfactor == 1 && bpmem.blendmode.dstfactor == 0))) + D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable); + if (bpmem.blendmode.blendenable) { D3D::SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); D3D::SetRenderState(D3DRS_SRCBLEND, d3dSrcFactors[bpmem.blendmode.srcfactor]); @@ -1261,11 +1145,31 @@ void Renderer::RestoreAPIState() void Renderer::SetGenerationMode() { + const D3DCULL d3dCullModes[4] = + { + D3DCULL_NONE, + D3DCULL_CCW, + D3DCULL_CW, + D3DCULL_CCW + }; + D3D::SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]); } void Renderer::SetDepthMode() { + const D3DCMPFUNC d3dCmpFuncs[8] = + { + D3DCMP_NEVER, + D3DCMP_LESS, + D3DCMP_EQUAL, + D3DCMP_LESSEQUAL, + D3DCMP_GREATER, + D3DCMP_NOTEQUAL, + D3DCMP_GREATEREQUAL, + D3DCMP_ALWAYS + }; + if (bpmem.zmode.testenable) { D3D::SetRenderState(D3DRS_ZENABLE, TRUE); @@ -1282,7 +1186,83 @@ void Renderer::SetDepthMode() void Renderer::SetLogicOpMode() { - if (bpmem.blendmode.logicopenable && bpmem.blendmode.logicmode != 3) + // D3D9 doesn't support logic blending, so this is a huge hack + + // 0 0x00 + // 1 Source & destination + // 2 Source & ~destination + // 3 Source + // 4 ~Source & destination + // 5 Destination + // 6 Source ^ destination = Source & ~destination | ~Source & destination + // 7 Source | destination + // 8 ~(Source | destination) + // 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination + // 10 ~Destination + // 11 Source | ~destination + // 12 ~Source + // 13 ~Source | destination + // 14 ~(Source & destination) + // 15 0xff + const D3DBLENDOP d3dLogicOpop[16] = + { + D3DBLENDOP_ADD, + D3DBLENDOP_ADD, + D3DBLENDOP_SUBTRACT, + D3DBLENDOP_ADD, + D3DBLENDOP_REVSUBTRACT, + D3DBLENDOP_ADD, + D3DBLENDOP_MAX, + D3DBLENDOP_ADD, + D3DBLENDOP_MAX, + D3DBLENDOP_MAX, + D3DBLENDOP_ADD, + D3DBLENDOP_ADD, + D3DBLENDOP_ADD, + D3DBLENDOP_ADD, + D3DBLENDOP_ADD, + D3DBLENDOP_ADD + }; + const D3DBLEND d3dLogicOpSrcFactors[16] = + { + D3DBLEND_ZERO, + D3DBLEND_DESTCOLOR, + D3DBLEND_ONE, + D3DBLEND_ONE, + D3DBLEND_DESTCOLOR, + D3DBLEND_ZERO, + D3DBLEND_INVDESTCOLOR, + D3DBLEND_INVDESTCOLOR, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_INVDESTCOLOR, + D3DBLEND_ONE, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_INVDESTCOLOR, + D3DBLEND_ONE + }; + const D3DBLEND d3dLogicOpDestFactors[16] = + { + D3DBLEND_ZERO, + D3DBLEND_ZERO, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_ZERO, + D3DBLEND_ONE, + D3DBLEND_ONE, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_ONE, + D3DBLEND_INVDESTCOLOR, + D3DBLEND_SRCCOLOR, + D3DBLEND_INVDESTCOLOR, + D3DBLEND_INVDESTCOLOR, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_ONE, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_ONE + }; + + if (bpmem.blendmode.logicopenable) { D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, true); D3D::SetRenderState(D3DRS_BLENDOP, d3dLogicOpop[bpmem.blendmode.logicmode]); @@ -1310,6 +1290,21 @@ void Renderer::SetLineWidth() void Renderer::SetSamplerState(int stage, int texindex) { + const D3DTEXTUREFILTERTYPE d3dMipFilters[4] = + { + D3DTEXF_NONE, + D3DTEXF_POINT, + D3DTEXF_LINEAR, + D3DTEXF_NONE, //reserved + }; + const D3DTEXTUREADDRESS d3dClamps[4] = + { + D3DTADDRESS_CLAMP, + D3DTADDRESS_WRAP, + D3DTADDRESS_MIRROR, + D3DTADDRESS_WRAP //reserved + }; + const FourTexUnits &tex = bpmem.tex[texindex]; const TexMode0 &tm0 = tex.texMode0[stage]; const TexMode1 &tm1 = tex.texMode1[stage]; @@ -1323,13 +1318,11 @@ void Renderer::SetSamplerState(int stage, int texindex) { min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT; mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT; - mip = (tm0.min_filter == 8) ? D3DTEXF_NONE : d3dMipFilters[tm0.min_filter & 3]; - if((tm0.min_filter & 3) && (tm0.min_filter != 8) && ((tm1.max_lod >> 4) == 0)) - mip = D3DTEXF_NONE; + mip = d3dMipFilters[tm0.min_filter & 3]; } if (texindex) stage += 4; - + if (mag == D3DTEXF_LINEAR && min == D3DTEXF_LINEAR && g_ActiveConfig.iMaxAnisotropy) { min = D3DTEXF_ANISOTROPIC; @@ -1340,8 +1333,7 @@ void Renderer::SetSamplerState(int stage, int texindex) D3D::SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]); D3D::SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]); - //float SuperSampleCoeficient = (s_LastAA < 3)? s_LastAA + 1 : s_LastAA - 1;// uncoment this changes to conserve detail when incresing ssaa level - float lodbias = (tm0.lod_bias / 32.0f);// + (s_LastAA)?(log(SuperSampleCoeficient) / log(2.0f)):0; + float lodbias = tm0.lod_bias / 32.0f; D3D::SetSamplerState(stage, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)&lodbias); D3D::SetSamplerState(stage, D3DSAMP_MAXMIPLEVEL, tm1.min_lod >> 4); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index a10aaf7204..3ff8b834ce 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -132,58 +132,6 @@ const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_ static bool s_efbCacheValid[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT]; static std::vector s_efbCache[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT]; // 2 for PEEK_Z and PEEK_COLOR -static const GLenum glSrcFactors[8] = -{ - GL_ZERO, - GL_ONE, - GL_DST_COLOR, - GL_ONE_MINUS_DST_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA -}; - -static const GLenum glDestFactors[8] = { - GL_ZERO, - GL_ONE, - GL_SRC_COLOR, - GL_ONE_MINUS_SRC_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA -}; - -static const GLenum glCmpFuncs[8] = { - GL_NEVER, - GL_LESS, - GL_EQUAL, - GL_LEQUAL, - GL_GREATER, - GL_NOTEQUAL, - GL_GEQUAL, - GL_ALWAYS -}; - -static const GLenum glLogicOpCodes[16] = { - GL_CLEAR, - GL_AND, - GL_AND_REVERSE, - GL_COPY, - GL_AND_INVERTED, - GL_NOOP, - GL_XOR, - GL_OR, - GL_NOR, - GL_EQUIV, - GL_INVERT, - GL_OR_REVERSE, - GL_COPY_INVERTED, - GL_OR_INVERTED, - GL_NAND, - GL_SET -}; #if defined HAVE_CG && HAVE_CG void HandleCgError(CGcontext ctx, CGerror err, void* appdata) @@ -908,6 +856,32 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) void Renderer::SetBlendMode(bool forceUpdate) { + // Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel + // Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1. + bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; + const GLenum glSrcFactors[8] = + { + GL_ZERO, + GL_ONE, + GL_DST_COLOR, + GL_ONE_MINUS_DST_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA + (target_has_alpha) ? GL_DST_ALPHA : (GLenum)GL_ONE, + (target_has_alpha) ? GL_ONE_MINUS_DST_ALPHA : (GLenum)GL_ZERO + }; + const GLenum glDestFactors[8] = + { + GL_ZERO, + GL_ONE, + GL_SRC_COLOR, + GL_ONE_MINUS_SRC_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA + (target_has_alpha) ? GL_DST_ALPHA : (GLenum)GL_ONE, + (target_has_alpha) ? GL_ONE_MINUS_DST_ALPHA : (GLenum)GL_ZERO + }; + // blend mode bit mask // 0 - blend enable // 2 - reverse subtract enable (else add) @@ -951,10 +925,10 @@ void Renderer::SetBlendMode(bool forceUpdate) if (changes & 0x1F8) { -#ifdef USE_DUAL_SOURCE_BLEND GLenum srcFactor = glSrcFactors[(newval >> 3) & 7]; - GLenum srcFactorAlpha = srcFactor; GLenum dstFactor = glDestFactors[(newval >> 6) & 7]; +#ifdef USE_DUAL_SOURCE_BLEND + GLenum srcFactorAlpha = srcFactor; GLenum dstFactorAlpha = dstFactor; if (useDualSource) { @@ -975,7 +949,7 @@ void Renderer::SetBlendMode(bool forceUpdate) // blend RGB change glBlendFuncSeparate(srcFactor, dstFactor, srcFactorAlpha, dstFactorAlpha); #else - glBlendFunc(glSrcFactors[(newval >> 3) & 7], glDestFactors[(newval >> 6) & 7]); + glBlendFunc(srcFactor, dstFactor); #endif } @@ -1438,6 +1412,18 @@ void Renderer::SetGenerationMode() void Renderer::SetDepthMode() { + const GLenum glCmpFuncs[8] = + { + GL_NEVER, + GL_LESS, + GL_EQUAL, + GL_LEQUAL, + GL_GREATER, + GL_NOTEQUAL, + GL_GEQUAL, + GL_ALWAYS + }; + if (bpmem.zmode.testenable) { glEnable(GL_DEPTH_TEST); @@ -1454,7 +1440,27 @@ void Renderer::SetDepthMode() void Renderer::SetLogicOpMode() { - if (bpmem.blendmode.logicopenable && bpmem.blendmode.logicmode != 3) + const GLenum glLogicOpCodes[16] = + { + GL_CLEAR, + GL_AND, + GL_AND_REVERSE, + GL_COPY, + GL_AND_INVERTED, + GL_NOOP, + GL_XOR, + GL_OR, + GL_NOR, + GL_EQUIV, + GL_INVERT, + GL_OR_REVERSE, + GL_COPY_INVERTED, + GL_OR_INVERTED, + GL_NAND, + GL_SET + }; + + if (bpmem.blendmode.logicopenable) { glEnable(GL_COLOR_LOGIC_OP); glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp index 1c43ed1d59..a21333e534 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp @@ -58,24 +58,6 @@ namespace OGL static u32 s_TempFramebuffer = 0; -static const GLint c_MinLinearFilter[8] = { - GL_NEAREST, - GL_NEAREST_MIPMAP_NEAREST, - GL_NEAREST_MIPMAP_LINEAR, - GL_NEAREST, - GL_LINEAR, - GL_LINEAR_MIPMAP_NEAREST, - GL_LINEAR_MIPMAP_LINEAR, - GL_LINEAR, -}; - -static const GLint c_WrapSettings[4] = { - GL_CLAMP_TO_EDGE, - GL_REPEAT, - GL_MIRRORED_REPEAT, - GL_REPEAT, -}; - bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level) { int width = std::max(virtual_width >> level, 1); @@ -357,32 +339,41 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo void TextureCache::TCacheEntry::SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1) { - // TODO: not used anywhere - TexMode0 mode = newmode; - //mode1 = newmode1; + const GLint c_MinLinearFilter[8] = + { + GL_NEAREST, + GL_NEAREST_MIPMAP_NEAREST, + GL_NEAREST_MIPMAP_LINEAR, + GL_NEAREST, + GL_LINEAR, + GL_LINEAR_MIPMAP_NEAREST, + GL_LINEAR_MIPMAP_LINEAR, + GL_LINEAR, + }; + const GLint c_WrapSettings[4] = + { + GL_CLAMP_TO_EDGE, + GL_REPEAT, + GL_MIRRORED_REPEAT, + GL_REPEAT, + }; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); + (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); - if (bHaveMipMaps) - { - // TODO: not used anywhere - if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4) - mode.min_filter += 4; // take equivalent forced linear + int filt = newmode.min_filter; + if (g_ActiveConfig.bForceFiltering && filt < 4) + filt += 4; // take equivalent forced linear - int filt = newmode.min_filter; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod >> 4); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod >> 4); - glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (newmode.lod_bias / 32.0f)); - } - else - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - (g_ActiveConfig.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt]); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod / 16.f); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod / 16.f); + glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, newmode.lod_bias / 32.0f); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]); + // TODO: Reset anisotrop when changed to 1 if (g_Config.iMaxAnisotropy >= 1) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_ActiveConfig.iMaxAnisotropy));