diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 625db5f44e..9fcabb4796 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -63,165 +63,165 @@ static LPDIRECT3DSURFACE9 ScreenShootMEMSurface = NULL; void SetupDeviceObjects() { - D3D::font.Init(); - VertexLoaderManager::Init(); - g_framebuffer_manager = new FramebufferManager; + D3D::font.Init(); + VertexLoaderManager::Init(); + g_framebuffer_manager = new FramebufferManager; - VertexShaderManager::Dirty(); - PixelShaderManager::Dirty(); - TextureConverter::Init(); - - // To avoid shader compilation stutters, read back all shaders from cache. - VertexShaderCache::Init(); - PixelShaderCache::Init(); - g_vertex_manager->CreateDeviceObjects(); - ((PerfQuery*)g_perf_query)->CreateDeviceObjects(); - // Texture cache will recreate themselves over time. + VertexShaderManager::Dirty(); + PixelShaderManager::Dirty(); + TextureConverter::Init(); + + // To avoid shader compilation stutters, read back all shaders from cache. + VertexShaderCache::Init(); + PixelShaderCache::Init(); + g_vertex_manager->CreateDeviceObjects(); + ((PerfQuery*)g_perf_query)->CreateDeviceObjects(); + // Texture cache will recreate themselves over time. } // Kill off all POOL_DEFAULT device objects. void TeardownDeviceObjects() { - if(ScreenShootMEMSurface) - ScreenShootMEMSurface->Release(); - ScreenShootMEMSurface = NULL; - D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); - D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface()); - delete g_framebuffer_manager; - ((PerfQuery*)g_perf_query)->DestroyDeviceObjects(); - D3D::font.Shutdown(); - TextureCache::Invalidate(); - VertexLoaderManager::Shutdown(); - VertexShaderCache::Shutdown(); - PixelShaderCache::Shutdown(); - TextureConverter::Shutdown(); - g_vertex_manager->DestroyDeviceObjects(); + if(ScreenShootMEMSurface) + ScreenShootMEMSurface->Release(); + ScreenShootMEMSurface = NULL; + D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); + D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface()); + delete g_framebuffer_manager; + ((PerfQuery*)g_perf_query)->DestroyDeviceObjects(); + D3D::font.Shutdown(); + TextureCache::Invalidate(); + VertexLoaderManager::Shutdown(); + VertexShaderCache::Shutdown(); + PixelShaderCache::Shutdown(); + TextureConverter::Shutdown(); + g_vertex_manager->DestroyDeviceObjects(); } // Init functions Renderer::Renderer() { - InitFPSCounter(); + InitFPSCounter(); - st = new char[32768]; + st = new char[32768]; - int fullScreenRes, x, y, w_temp, h_temp; - s_blendMode = 0; - // Multisample Anti-aliasing hasn't been implemented yet use supersamling instead - int backbuffer_ms_mode = 0; + int fullScreenRes, x, y, w_temp, h_temp; + s_blendMode = 0; + // Multisample Anti-aliasing hasn't been implemented yet use supersamling instead + int backbuffer_ms_mode = 0; - Host_GetRenderWindowSize(x, y, w_temp, h_temp); + Host_GetRenderWindowSize(x, y, w_temp, h_temp); - for (fullScreenRes = 0; fullScreenRes < (int)D3D::GetAdapter(g_ActiveConfig.iAdapter).resolutions.size(); fullScreenRes++) - { - if ((D3D::GetAdapter(g_ActiveConfig.iAdapter).resolutions[fullScreenRes].xres == w_temp) && - (D3D::GetAdapter(g_ActiveConfig.iAdapter).resolutions[fullScreenRes].yres == h_temp)) - break; - } - if (fullScreenRes == D3D::GetAdapter(g_ActiveConfig.iAdapter).resolutions.size()) - fullScreenRes = 0; + for (fullScreenRes = 0; fullScreenRes < (int)D3D::GetAdapter(g_ActiveConfig.iAdapter).resolutions.size(); fullScreenRes++) + { + if ((D3D::GetAdapter(g_ActiveConfig.iAdapter).resolutions[fullScreenRes].xres == w_temp) && + (D3D::GetAdapter(g_ActiveConfig.iAdapter).resolutions[fullScreenRes].yres == h_temp)) + break; + } + if (fullScreenRes == D3D::GetAdapter(g_ActiveConfig.iAdapter).resolutions.size()) + fullScreenRes = 0; - D3D::Create(g_ActiveConfig.iAdapter, EmuWindow::GetWnd(), - fullScreenRes, backbuffer_ms_mode, false); + D3D::Create(g_ActiveConfig.iAdapter, EmuWindow::GetWnd(), + fullScreenRes, backbuffer_ms_mode, false); - IS_AMD = D3D::IsATIDevice(); + IS_AMD = D3D::IsATIDevice(); - // Decide framebuffer size - s_backbuffer_width = D3D::GetBackBufferWidth(); - s_backbuffer_height = D3D::GetBackBufferHeight(); + // Decide framebuffer size + s_backbuffer_width = D3D::GetBackBufferWidth(); + s_backbuffer_height = D3D::GetBackBufferHeight(); - FramebufferManagerBase::SetLastXfbWidth(MAX_XFB_WIDTH); - FramebufferManagerBase::SetLastXfbHeight(MAX_XFB_HEIGHT); + FramebufferManagerBase::SetLastXfbWidth(MAX_XFB_WIDTH); + FramebufferManagerBase::SetLastXfbHeight(MAX_XFB_HEIGHT); - UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height); + UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height); - s_LastAA = g_ActiveConfig.iMultisampleMode; - int SupersampleCoeficient = (s_LastAA % 3) + 1; + s_LastAA = g_ActiveConfig.iMultisampleMode; + int SupersampleCoeficient = (s_LastAA % 3) + 1; - s_LastEFBScale = g_ActiveConfig.iEFBScale; - CalculateTargetSize(s_backbuffer_width, s_backbuffer_height, SupersampleCoeficient); + s_LastEFBScale = g_ActiveConfig.iEFBScale; + CalculateTargetSize(s_backbuffer_width, s_backbuffer_height, SupersampleCoeficient); - // Make sure to use valid texture sizes - D3D::FixTextureSize(s_target_width, s_target_height); + // Make sure to use valid texture sizes + D3D::FixTextureSize(s_target_width, s_target_height); - // We're not using fixed function. - // Let's just set the matrices to identity to be sure. - D3DXMATRIX mtx; - D3DXMatrixIdentity(&mtx); - D3D::dev->SetTransform(D3DTS_VIEW, &mtx); - D3D::dev->SetTransform(D3DTS_WORLD, &mtx); + // We're not using fixed function. + // Let's just set the matrices to identity to be sure. + D3DXMATRIX mtx; + D3DXMatrixIdentity(&mtx); + D3D::dev->SetTransform(D3DTS_VIEW, &mtx); + D3D::dev->SetTransform(D3DTS_WORLD, &mtx); - SetupDeviceObjects(); + SetupDeviceObjects(); - for (int stage = 0; stage < 8; stage++) - D3D::SetSamplerState(stage, D3DSAMP_MAXANISOTROPY, 1 << g_ActiveConfig.iMaxAnisotropy); + for (int stage = 0; stage < 8; stage++) + D3D::SetSamplerState(stage, D3DSAMP_MAXANISOTROPY, 1 << g_ActiveConfig.iMaxAnisotropy); - D3DVIEWPORT9 vp; - vp.X = 0; - vp.Y = 0; - vp.Width = s_backbuffer_width; - vp.Height = s_backbuffer_height; - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; - D3D::dev->SetViewport(&vp); - D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET, 0x0, 0, 0); - - D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); - D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); - vp.X = 0; - vp.Y = 0; - vp.Width = s_target_width; - vp.Height = s_target_height; - D3D::dev->SetViewport(&vp); - D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); - D3D::BeginFrame(); - D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, true); - D3D::dev->CreateOffscreenPlainSurface(s_backbuffer_width,s_backbuffer_height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL ); - D3D::SetRenderState(D3DRS_POINTSCALEENABLE,false); - m_fMaxPointSize = D3D::GetCaps().MaxPointSize; - // Handle VSync on/off - s_vsync = g_ActiveConfig.IsVSync(); + D3DVIEWPORT9 vp; + vp.X = 0; + vp.Y = 0; + vp.Width = s_backbuffer_width; + vp.Height = s_backbuffer_height; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + D3D::dev->SetViewport(&vp); + D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET, 0x0, 0, 0); + + D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); + D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); + vp.X = 0; + vp.Y = 0; + vp.Width = s_target_width; + vp.Height = s_target_height; + D3D::dev->SetViewport(&vp); + D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); + D3D::BeginFrame(); + D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, true); + D3D::dev->CreateOffscreenPlainSurface(s_backbuffer_width,s_backbuffer_height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL ); + D3D::SetRenderState(D3DRS_POINTSCALEENABLE,false); + m_fMaxPointSize = D3D::GetCaps().MaxPointSize; + // Handle VSync on/off + s_vsync = g_ActiveConfig.IsVSync(); } Renderer::~Renderer() { - TeardownDeviceObjects(); - D3D::EndFrame(); - D3D::Present(); - D3D::Close(); - - delete[] st; + TeardownDeviceObjects(); + D3D::EndFrame(); + D3D::Present(); + D3D::Close(); + + delete[] st; } void Renderer::RenderText(const char *text, int left, int top, u32 color) { - D3D::font.DrawTextScaled((float)left, (float)top, 20, 20, 0.0f, color, text); + D3D::font.DrawTextScaled((float)left, (float)top, 20, 20, 0.0f, color, text); } TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) { - TargetRectangle result; - result.left = EFBToScaledX(rc.left); - result.top = EFBToScaledY(rc.top); - result.right = EFBToScaledX(rc.right); - result.bottom = EFBToScaledY(rc.bottom); - return result; + TargetRectangle result; + result.left = EFBToScaledX(rc.left); + result.top = EFBToScaledY(rc.top); + result.right = EFBToScaledX(rc.right); + result.bottom = EFBToScaledY(rc.bottom); + return result; } } void formatBufferDump(const u8* in, u8* out, int w, int h, int p) { - for (int y = 0; y < h; y++) - { - auto line = in + (h - y - 1) * p; - for (int x = 0; x < w; x++) - { - memcpy(out, line, 3); - out += 3; - line += 4; - } - } + for (int y = 0; y < h; y++) + { + auto line = in + (h - y - 1) * p; + for (int x = 0; x < w; x++) + { + memcpy(out, line, 3); + out += 3; + line += 4; + } + } } namespace DX9 @@ -231,63 +231,63 @@ namespace DX9 // size. bool Renderer::CheckForResize() { - while (EmuWindow::IsSizing()) - Sleep(10); + while (EmuWindow::IsSizing()) + Sleep(10); - if (EmuWindow::GetParentWnd()) - { - // Re-stretch window to parent window size again, if it has a parent window. - RECT rcParentWindow; - GetWindowRect(EmuWindow::GetParentWnd(), &rcParentWindow); - int width = rcParentWindow.right - rcParentWindow.left; - int height = rcParentWindow.bottom - rcParentWindow.top; - if (width != Renderer::GetBackbufferWidth() || height != Renderer::GetBackbufferHeight()) - MoveWindow(EmuWindow::GetWnd(), 0, 0, width, height, FALSE); - } + if (EmuWindow::GetParentWnd()) + { + // Re-stretch window to parent window size again, if it has a parent window. + RECT rcParentWindow; + GetWindowRect(EmuWindow::GetParentWnd(), &rcParentWindow); + int width = rcParentWindow.right - rcParentWindow.left; + int height = rcParentWindow.bottom - rcParentWindow.top; + if (width != Renderer::GetBackbufferWidth() || height != Renderer::GetBackbufferHeight()) + MoveWindow(EmuWindow::GetWnd(), 0, 0, width, height, FALSE); + } - RECT rcWindow; - GetClientRect(EmuWindow::GetWnd(), &rcWindow); - int client_width = rcWindow.right - rcWindow.left; - int client_height = rcWindow.bottom - rcWindow.top; + RECT rcWindow; + GetClientRect(EmuWindow::GetWnd(), &rcWindow); + int client_width = rcWindow.right - rcWindow.left; + int client_height = rcWindow.bottom - rcWindow.top; - // Sanity check - if ((client_width != Renderer::GetBackbufferWidth() || - client_height != Renderer::GetBackbufferHeight()) && - client_width >= 4 && client_height >= 4) - { - TeardownDeviceObjects(); + // Sanity check + if ((client_width != Renderer::GetBackbufferWidth() || + client_height != Renderer::GetBackbufferHeight()) && + client_width >= 4 && client_height >= 4) + { + TeardownDeviceObjects(); - D3D::Reset(); - s_backbuffer_width = D3D::GetBackBufferWidth(); - s_backbuffer_height = D3D::GetBackBufferHeight(); - if(ScreenShootMEMSurface) - ScreenShootMEMSurface->Release(); - D3D::dev->CreateOffscreenPlainSurface(Renderer::GetBackbufferWidth(), Renderer::GetBackbufferHeight(), - D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL ); + D3D::Reset(); + s_backbuffer_width = D3D::GetBackBufferWidth(); + s_backbuffer_height = D3D::GetBackBufferHeight(); + if(ScreenShootMEMSurface) + ScreenShootMEMSurface->Release(); + D3D::dev->CreateOffscreenPlainSurface(Renderer::GetBackbufferWidth(), Renderer::GetBackbufferHeight(), + D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL ); - return true; - } - - return false; + return true; + } + + return false; } void Renderer::SetScissorRect(const TargetRectangle& rc) { - D3D::dev->SetScissorRect(rc.AsRECT()); + D3D::dev->SetScissorRect(rc.AsRECT()); } void Renderer::SetColorMask() { - // Only enable alpha channel if it's supported by the current EFB format - DWORD color_mask = 0; - if (bpmem.alpha_test.TestResult() != AlphaTest::FAIL) - { - if (bpmem.blendmode.alphaupdate && (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24)) - color_mask = D3DCOLORWRITEENABLE_ALPHA; - if (bpmem.blendmode.colorupdate) - color_mask |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; - } - D3D::SetRenderState(D3DRS_COLORWRITEENABLE, color_mask); + // Only enable alpha channel if it's supported by the current EFB format + DWORD color_mask = 0; + if (bpmem.alpha_test.TestResult() != AlphaTest::FAIL) + { + if (bpmem.blendmode.alphaupdate && (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24)) + color_mask = D3DCOLORWRITEENABLE_ALPHA; + if (bpmem.blendmode.colorupdate) + color_mask |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; + } + D3D::SetRenderState(D3DRS_COLORWRITEENABLE, color_mask); } // This function allows the CPU to directly access the EFB. @@ -306,191 +306,191 @@ void Renderer::SetColorMask() // - GX_PokeZMode (TODO) u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) { - if (!g_ActiveConfig.bEFBAccessEnable) - return 0; + if (!g_ActiveConfig.bEFBAccessEnable) + return 0; - if (type == POKE_Z) - { - static bool alert_only_once = true; - if (!alert_only_once) return 0; - PanicAlert("EFB: Poke Z not implemented (tried to poke z value %#x at (%d,%d))", poke_data, x, y); - alert_only_once = false; - return 0; - } + if (type == POKE_Z) + { + static bool alert_only_once = true; + if (!alert_only_once) return 0; + PanicAlert("EFB: Poke Z not implemented (tried to poke z value %#x at (%d,%d))", poke_data, x, y); + alert_only_once = false; + return 0; + } - // if depth textures aren't supported by the hardware, just return - if (type == PEEK_Z) - if (FramebufferManager::GetEFBDepthTexture() == NULL) - return 0; + // if depth textures aren't supported by the hardware, just return + if (type == PEEK_Z) + if (FramebufferManager::GetEFBDepthTexture() == NULL) + return 0; - // We're using three surfaces here: - // - pEFBSurf: EFB Surface. Source surface when peeking, destination surface when poking. - // - pBufferRT: A render target surface. When peeking, we render a textured quad to this surface. - // - pSystemBuf: An offscreen surface. Used to retrieve the pixel data from pBufferRT. - LPDIRECT3DSURFACE9 pEFBSurf, pBufferRT, pSystemBuf; - if(type == PEEK_Z || type == POKE_Z) - { - pEFBSurf = FramebufferManager::GetEFBDepthRTSurface(); - pBufferRT = FramebufferManager::GetEFBDepthReadSurface(); - pSystemBuf = FramebufferManager::GetEFBDepthOffScreenRTSurface(); - } - else //if(type == PEEK_COLOR || type == POKE_COLOR) - { - pEFBSurf = FramebufferManager::GetEFBColorRTSurface(); - pBufferRT = FramebufferManager::GetEFBColorReadSurface(); - pSystemBuf = FramebufferManager::GetEFBColorOffScreenRTSurface(); - } + // We're using three surfaces here: + // - pEFBSurf: EFB Surface. Source surface when peeking, destination surface when poking. + // - pBufferRT: A render target surface. When peeking, we render a textured quad to this surface. + // - pSystemBuf: An offscreen surface. Used to retrieve the pixel data from pBufferRT. + LPDIRECT3DSURFACE9 pEFBSurf, pBufferRT, pSystemBuf; + if(type == PEEK_Z || type == POKE_Z) + { + pEFBSurf = FramebufferManager::GetEFBDepthRTSurface(); + pBufferRT = FramebufferManager::GetEFBDepthReadSurface(); + pSystemBuf = FramebufferManager::GetEFBDepthOffScreenRTSurface(); + } + else //if(type == PEEK_COLOR || type == POKE_COLOR) + { + pEFBSurf = FramebufferManager::GetEFBColorRTSurface(); + pBufferRT = FramebufferManager::GetEFBColorReadSurface(); + pSystemBuf = FramebufferManager::GetEFBColorOffScreenRTSurface(); + } - // Buffer not found alert - if (!pEFBSurf) { - PanicAlert("No %s!", (type == PEEK_Z || type == POKE_Z) ? "Z-Buffer" : "Color EFB"); - return 0; - } + // Buffer not found alert + if (!pEFBSurf) { + PanicAlert("No %s!", (type == PEEK_Z || type == POKE_Z) ? "Z-Buffer" : "Color EFB"); + return 0; + } - // Convert EFB dimensions to the ones of our render target - EFBRectangle efbPixelRc; - efbPixelRc.left = x; - efbPixelRc.top = y; - efbPixelRc.right = x + 1; - efbPixelRc.bottom = y + 1; + // Convert EFB dimensions to the ones of our render target + EFBRectangle efbPixelRc; + efbPixelRc.left = x; + efbPixelRc.top = y; + efbPixelRc.right = x + 1; + efbPixelRc.bottom = y + 1; - TargetRectangle targetPixelRc = ConvertEFBRectangle(efbPixelRc); + TargetRectangle targetPixelRc = ConvertEFBRectangle(efbPixelRc); - HRESULT hr; - RECT RectToLock; - RectToLock.bottom = targetPixelRc.bottom; - RectToLock.left = targetPixelRc.left; - RectToLock.right = targetPixelRc.right; - RectToLock.top = targetPixelRc.top; - if (type == PEEK_Z) - { - // TODO: why is D3DFMT_D24X8 singled out here? why not D3DFMT_D24X4S4/D24S8/D24FS8/D32/D16/D15S1 too, or none of them? - if (FramebufferManager::GetEFBDepthRTSurfaceFormat() == D3DFMT_D24X8) - return 0; + HRESULT hr; + RECT RectToLock; + RectToLock.bottom = targetPixelRc.bottom; + RectToLock.left = targetPixelRc.left; + RectToLock.right = targetPixelRc.right; + RectToLock.top = targetPixelRc.top; + if (type == PEEK_Z) + { + // TODO: why is D3DFMT_D24X8 singled out here? why not D3DFMT_D24X4S4/D24S8/D24FS8/D32/D16/D15S1 too, or none of them? + if (FramebufferManager::GetEFBDepthRTSurfaceFormat() == D3DFMT_D24X8) + return 0; - RECT PixelRect; - PixelRect.bottom = 4; - PixelRect.left = 0; - PixelRect.right = 4; - PixelRect.top = 0; - RectToLock.bottom+=2; - RectToLock.right+=1; - RectToLock.top-=1; - RectToLock.left-=2; - if ((RectToLock.bottom - RectToLock.top) > 4) - RectToLock.bottom--; - if ((RectToLock.right - RectToLock.left) > 4) - RectToLock.left++; + RECT PixelRect; + PixelRect.bottom = 4; + PixelRect.left = 0; + PixelRect.right = 4; + PixelRect.top = 0; + RectToLock.bottom+=2; + RectToLock.right+=1; + RectToLock.top-=1; + RectToLock.left-=2; + if ((RectToLock.bottom - RectToLock.top) > 4) + RectToLock.bottom--; + if ((RectToLock.right - RectToLock.left) > 4) + RectToLock.left++; - ResetAPIState(); // Reset any game specific settings - D3D::dev->SetDepthStencilSurface(NULL); - D3D::dev->SetRenderTarget(0, pBufferRT); + ResetAPIState(); // Reset any game specific settings + D3D::dev->SetDepthStencilSurface(NULL); + D3D::dev->SetRenderTarget(0, pBufferRT); - // Stretch picture with increased internal resolution - D3DVIEWPORT9 vp; - vp.X = 0; - vp.Y = 0; - vp.Width = 4; - vp.Height = 4; - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; - D3D::dev->SetViewport(&vp); + // Stretch picture with increased internal resolution + D3DVIEWPORT9 vp; + vp.X = 0; + vp.Y = 0; + vp.Width = 4; + vp.Height = 4; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + D3D::dev->SetViewport(&vp); - float colmat[28] = {0.0f}; - colmat[0] = colmat[5] = colmat[10] = 1.0f; - PixelShaderManager::SetColorMatrix(colmat); // set transformation - LPDIRECT3DTEXTURE9 read_texture = FramebufferManager::GetEFBDepthTexture(); - - D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + float colmat[28] = {0.0f}; + colmat[0] = colmat[5] = colmat[10] = 1.0f; + PixelShaderManager::SetColorMatrix(colmat); // set transformation + LPDIRECT3DTEXTURE9 read_texture = FramebufferManager::GetEFBDepthTexture(); - D3DFORMAT bformat = FramebufferManager::GetEFBDepthRTSurfaceFormat(); + D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - D3D::drawShadedTexQuad( - read_texture, - &RectToLock, - Renderer::GetTargetWidth(), - Renderer::GetTargetHeight(), - 4, 4, - PixelShaderCache::GetDepthMatrixProgram(0, bformat != FOURCC_RAWZ), - VertexShaderCache::GetSimpleVertexShader(0)); + D3DFORMAT bformat = FramebufferManager::GetEFBDepthRTSurfaceFormat(); - D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); + D3D::drawShadedTexQuad( + read_texture, + &RectToLock, + Renderer::GetTargetWidth(), + Renderer::GetTargetHeight(), + 4, 4, + PixelShaderCache::GetDepthMatrixProgram(0, bformat != FOURCC_RAWZ), + VertexShaderCache::GetSimpleVertexShader(0)); - D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); - D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); - RestoreAPIState(); + D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); - // Retrieve the pixel data to the local memory buffer - RectToLock.bottom = 4; - RectToLock.left = 0; - RectToLock.right = 4; - RectToLock.top = 0; - D3D::dev->GetRenderTargetData(pBufferRT, pSystemBuf); + D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); + D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); + RestoreAPIState(); - // EFB data successfully retrieved, now get the pixel data - D3DLOCKED_RECT drect; - pSystemBuf->LockRect(&drect, &RectToLock, D3DLOCK_READONLY); - u32 z = ((u32*)drect.pBits)[6]; // 24 bit depth value - pSystemBuf->UnlockRect(); + // Retrieve the pixel data to the local memory buffer + RectToLock.bottom = 4; + RectToLock.left = 0; + RectToLock.right = 4; + RectToLock.top = 0; + D3D::dev->GetRenderTargetData(pBufferRT, pSystemBuf); - // if Z is in 16 bit format you must return a 16 bit integer - if(bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16) { - z >>= 8; - } + // EFB data successfully retrieved, now get the pixel data + D3DLOCKED_RECT drect; + pSystemBuf->LockRect(&drect, &RectToLock, D3DLOCK_READONLY); + u32 z = ((u32*)drect.pBits)[6]; // 24 bit depth value + pSystemBuf->UnlockRect(); - return z; - } - else if(type == PEEK_COLOR) - { - // We can't directly StretchRect to System buf because is not supported by all implementations - // this is the only safe path that works in most cases - hr = D3D::dev->StretchRect(pEFBSurf, &RectToLock, pBufferRT, NULL, D3DTEXF_NONE); - D3D::dev->GetRenderTargetData(pBufferRT, pSystemBuf); + // if Z is in 16 bit format you must return a 16 bit integer + if(bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16) { + z >>= 8; + } - // EFB data successfully retrieved, now get the pixel data - RectToLock.bottom = 1; - RectToLock.left = 0; - RectToLock.right = 1; - RectToLock.top = 0; + return z; + } + else if(type == PEEK_COLOR) + { + // We can't directly StretchRect to System buf because is not supported by all implementations + // this is the only safe path that works in most cases + hr = D3D::dev->StretchRect(pEFBSurf, &RectToLock, pBufferRT, NULL, D3DTEXF_NONE); + D3D::dev->GetRenderTargetData(pBufferRT, pSystemBuf); - D3DLOCKED_RECT drect; - pSystemBuf->LockRect(&drect, &RectToLock, D3DLOCK_READONLY); - u32 ret = ((u32*)drect.pBits)[0]; - pSystemBuf->UnlockRect(); + // EFB data successfully retrieved, now get the pixel data + RectToLock.bottom = 1; + RectToLock.left = 0; + RectToLock.right = 1; + RectToLock.top = 0; - // check what to do with the alpha channel (GX_PokeAlphaRead) - PixelEngine::UPEAlphaReadReg alpha_read_mode; - PixelEngine::Read16((u16&)alpha_read_mode, PE_ALPHAREAD); + D3DLOCKED_RECT drect; + pSystemBuf->LockRect(&drect, &RectToLock, D3DLOCK_READONLY); + u32 ret = ((u32*)drect.pBits)[0]; + pSystemBuf->UnlockRect(); - if (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24) - { - ret = RGBA8ToRGBA6ToRGBA8(ret); - } - else if (bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16) - { - ret = RGBA8ToRGB565ToRGBA8(ret); - } - if(bpmem.zcontrol.pixel_format != PIXELFMT_RGBA6_Z24) - { - ret |= 0xFF000000; - } + // check what to do with the alpha channel (GX_PokeAlphaRead) + PixelEngine::UPEAlphaReadReg alpha_read_mode; + PixelEngine::Read16((u16&)alpha_read_mode, PE_ALPHAREAD); - if(alpha_read_mode.ReadMode == 2) return ret; // GX_READ_NONE - else if(alpha_read_mode.ReadMode == 1) return (ret | 0xFF000000); // GX_READ_FF - else return (ret & 0x00FFFFFF); // GX_READ_00 - } - else //if(type == POKE_COLOR) - { - // TODO: Speed this up by batching pokes? - ResetAPIState(); - D3D::drawColorQuad(poke_data, - (float)RectToLock.left * 2.f / (float)Renderer::GetTargetWidth() - 1.f, - - (float)RectToLock.top * 2.f / (float)Renderer::GetTargetHeight() + 1.f, - (float)RectToLock.right * 2.f / (float)Renderer::GetTargetWidth() - 1.f, - - (float)RectToLock.bottom * 2.f / (float)Renderer::GetTargetHeight() + 1.f); - RestoreAPIState(); - return 0; - } + if (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24) + { + ret = RGBA8ToRGBA6ToRGBA8(ret); + } + else if (bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16) + { + ret = RGBA8ToRGB565ToRGBA8(ret); + } + if(bpmem.zcontrol.pixel_format != PIXELFMT_RGBA6_Z24) + { + ret |= 0xFF000000; + } + + if(alpha_read_mode.ReadMode == 2) return ret; // GX_READ_NONE + else if(alpha_read_mode.ReadMode == 1) return (ret | 0xFF000000); // GX_READ_FF + else return (ret & 0x00FFFFFF); // GX_READ_00 + } + else //if(type == POKE_COLOR) + { + // TODO: Speed this up by batching pokes? + ResetAPIState(); + D3D::drawColorQuad(poke_data, + (float)RectToLock.left * 2.f / (float)Renderer::GetTargetWidth() - 1.f, + - (float)RectToLock.top * 2.f / (float)Renderer::GetTargetHeight() + 1.f, + (float)RectToLock.right * 2.f / (float)Renderer::GetTargetWidth() - 1.f, + - (float)RectToLock.bottom * 2.f / (float)Renderer::GetTargetHeight() + 1.f); + RestoreAPIState(); + return 0; + } } // Viewport correction: @@ -503,884 +503,884 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) // [ 0 0 1 0 ] // [ 0 0 0 1 ] static void ViewportCorrectionMatrix(Matrix44& result, - float ix, float iy, float iw, float ih, // Intended viewport (x, y, width, height) - float ax, float ay, float aw, float ah) // Actual viewport (x, y, width, height) + float ix, float iy, float iw, float ih, // Intended viewport (x, y, width, height) + float ax, float ay, float aw, float ah) // Actual viewport (x, y, width, height) { - Matrix44::LoadIdentity(result); - if (aw == 0.f || ah == 0.f) - return; - result.data[4*0+0] = iw / aw; - result.data[4*0+3] = (iw - 2.f * (ax - ix)) / aw - 1.f; - result.data[4*1+1] = ih / ah; - result.data[4*1+3] = (-ih + 2.f * (ay - iy)) / ah + 1.f; + Matrix44::LoadIdentity(result); + if (aw == 0.f || ah == 0.f) + return; + result.data[4*0+0] = iw / aw; + result.data[4*0+3] = (iw - 2.f * (ax - ix)) / aw - 1.f; + result.data[4*1+1] = ih / ah; + result.data[4*1+3] = (-ih + 2.f * (ay - iy)) / ah + 1.f; } // Called from VertexShaderManager void Renderer::UpdateViewport(Matrix44& vpCorrection) { - // reversed gxsetviewport(xorig, yorig, width, height, nearz, farz) - // [0] = width/2 - // [1] = height/2 - // [2] = 16777215 * (farz - nearz) - // [3] = xorig + width/2 + 342 - // [4] = yorig + height/2 + 342 - // [5] = 16777215 * farz + // reversed gxsetviewport(xorig, yorig, width, height, nearz, farz) + // [0] = width/2 + // [1] = height/2 + // [2] = 16777215 * (farz - nearz) + // [3] = xorig + width/2 + 342 + // [4] = yorig + height/2 + 342 + // [5] = 16777215 * farz - int scissorXOff = bpmem.scissorOffset.x * 2; - int scissorYOff = bpmem.scissorOffset.y * 2; + int scissorXOff = bpmem.scissorOffset.x * 2; + int scissorYOff = bpmem.scissorOffset.y * 2; - // TODO: ceil, floor or just cast to int? - int intendedX = EFBToScaledX((int)ceil(xfregs.viewport.xOrig - xfregs.viewport.wd - scissorXOff)); - int intendedY = EFBToScaledY((int)ceil(xfregs.viewport.yOrig + xfregs.viewport.ht - scissorYOff)); - int intendedWd = EFBToScaledX((int)ceil(2.0f * xfregs.viewport.wd)); - int intendedHt = EFBToScaledY((int)ceil(-2.0f * xfregs.viewport.ht)); - if (intendedWd < 0) - { - intendedX += intendedWd; - intendedWd = -intendedWd; - } - if (intendedHt < 0) - { - intendedY += intendedHt; - intendedHt = -intendedHt; - } + // TODO: ceil, floor or just cast to int? + int intendedX = EFBToScaledX((int)ceil(xfregs.viewport.xOrig - xfregs.viewport.wd - scissorXOff)); + int intendedY = EFBToScaledY((int)ceil(xfregs.viewport.yOrig + xfregs.viewport.ht - scissorYOff)); + int intendedWd = EFBToScaledX((int)ceil(2.0f * xfregs.viewport.wd)); + int intendedHt = EFBToScaledY((int)ceil(-2.0f * xfregs.viewport.ht)); + if (intendedWd < 0) + { + intendedX += intendedWd; + intendedWd = -intendedWd; + } + if (intendedHt < 0) + { + intendedY += intendedHt; + intendedHt = -intendedHt; + } - // In D3D, the viewport rectangle must fit within the render target. - int X = intendedX; - if (X < 0) - X = 0; - int Y = intendedY; - if (Y < 0) - Y = 0; - int Wd = intendedWd; - if (X + Wd > GetTargetWidth()) - Wd = GetTargetWidth() - X; - int Ht = intendedHt; - if (Y + Ht > GetTargetHeight()) - Ht = GetTargetHeight() - Y; + // In D3D, the viewport rectangle must fit within the render target. + int X = intendedX; + if (X < 0) + X = 0; + int Y = intendedY; + if (Y < 0) + Y = 0; + int Wd = intendedWd; + if (X + Wd > GetTargetWidth()) + Wd = GetTargetWidth() - X; + int Ht = intendedHt; + if (Y + Ht > GetTargetHeight()) + Ht = GetTargetHeight() - Y; - // If GX viewport is off the render target, we must clamp our viewport - // within the bounds. Use the correction matrix to compensate. - ViewportCorrectionMatrix(vpCorrection, - (float)intendedX, (float)intendedY, (float)intendedWd, (float)intendedHt, - (float)X, (float)Y, (float)Wd, (float)Ht); + // If GX viewport is off the render target, we must clamp our viewport + // within the bounds. Use the correction matrix to compensate. + ViewportCorrectionMatrix(vpCorrection, + (float)intendedX, (float)intendedY, (float)intendedWd, (float)intendedHt, + (float)X, (float)Y, (float)Wd, (float)Ht); - D3DVIEWPORT9 vp; - vp.X = X; - vp.Y = Y; - vp.Width = Wd; - vp.Height = Ht; + D3DVIEWPORT9 vp; + vp.X = X; + vp.Y = Y; + vp.Width = Wd; + vp.Height = Ht; - // Some games set invalids values for z min and z max so fix them to the max an min alowed and let the shaders do this work - vp.MinZ = 0.0f; // (xfregs.viewport.farZ - xfregs.viewport.zRange) / 16777216.0f; - vp.MaxZ = 1.0f; // xfregs.viewport.farZ / 16777216.0f; - D3D::dev->SetViewport(&vp); + // Some games set invalids values for z min and z max so fix them to the max an min alowed and let the shaders do this work + vp.MinZ = 0.0f; // (xfregs.viewport.farZ - xfregs.viewport.zRange) / 16777216.0f; + vp.MaxZ = 1.0f; // xfregs.viewport.farZ / 16777216.0f; + D3D::dev->SetViewport(&vp); } void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) { - // Reset rendering pipeline while keeping color masks and depth buffer settings - ResetAPIState(); + // Reset rendering pipeline while keeping color masks and depth buffer settings + ResetAPIState(); - DWORD color_mask = 0; - if (alphaEnable) - color_mask = D3DCOLORWRITEENABLE_ALPHA; - if (colorEnable) - color_mask |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; - D3D::ChangeRenderState(D3DRS_COLORWRITEENABLE, color_mask); + DWORD color_mask = 0; + if (alphaEnable) + color_mask = D3DCOLORWRITEENABLE_ALPHA; + if (colorEnable) + color_mask |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; + D3D::ChangeRenderState(D3DRS_COLORWRITEENABLE, color_mask); - if (zEnable) - { - D3D::ChangeRenderState(D3DRS_ZENABLE, TRUE); - D3D::ChangeRenderState(D3DRS_ZWRITEENABLE, TRUE); - D3D::ChangeRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); - } - else - { - D3D::ChangeRenderState(D3DRS_ZENABLE, FALSE); - } + if (zEnable) + { + D3D::ChangeRenderState(D3DRS_ZENABLE, TRUE); + D3D::ChangeRenderState(D3DRS_ZWRITEENABLE, TRUE); + D3D::ChangeRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); + } + else + { + D3D::ChangeRenderState(D3DRS_ZENABLE, FALSE); + } - // Update the viewport for clearing the target EFB rect - TargetRectangle targetRc = ConvertEFBRectangle(rc); - D3DVIEWPORT9 vp; - vp.X = targetRc.left; - vp.Y = targetRc.top; - vp.Width = targetRc.GetWidth(); - vp.Height = targetRc.GetHeight(); - vp.MinZ = 0.0; - vp.MaxZ = 1.0; - D3D::dev->SetViewport(&vp); - D3D::drawClearQuad(color, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); - RestoreAPIState(); + // Update the viewport for clearing the target EFB rect + TargetRectangle targetRc = ConvertEFBRectangle(rc); + D3DVIEWPORT9 vp; + vp.X = targetRc.left; + vp.Y = targetRc.top; + vp.Width = targetRc.GetWidth(); + vp.Height = targetRc.GetHeight(); + vp.MinZ = 0.0; + vp.MaxZ = 1.0; + D3D::dev->SetViewport(&vp); + D3D::drawClearQuad(color, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); + RestoreAPIState(); } void Renderer::ReinterpretPixelData(unsigned int convtype) { - RECT source; - SetRect(&source, 0, 0, g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight()); + RECT source; + SetRect(&source, 0, 0, g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight()); - LPDIRECT3DPIXELSHADER9 pixel_shader; - if (convtype == 0) pixel_shader = PixelShaderCache::ReinterpRGB8ToRGBA6(); - else if (convtype == 2) pixel_shader = PixelShaderCache::ReinterpRGBA6ToRGB8(); - else - { - ERROR_LOG(VIDEO, "Trying to reinterpret pixel data with unsupported conversion type %d", convtype); - return; - } + LPDIRECT3DPIXELSHADER9 pixel_shader; + if (convtype == 0) pixel_shader = PixelShaderCache::ReinterpRGB8ToRGBA6(); + else if (convtype == 2) pixel_shader = PixelShaderCache::ReinterpRGBA6ToRGB8(); + else + { + ERROR_LOG(VIDEO, "Trying to reinterpret pixel data with unsupported conversion type %d", convtype); + return; + } - // convert data and set the target texture as our new EFB - g_renderer->ResetAPIState(); - D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorReinterpretSurface()); - D3DVIEWPORT9 vp; - vp.X = 0; - vp.Y = 0; - vp.Width = g_renderer->GetTargetWidth(); - vp.Height = g_renderer->GetTargetHeight(); - vp.MinZ = 0.0; - vp.MaxZ = 1.0; - D3D::dev->SetViewport(&vp); - D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture(), &source, - g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(), - g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(), - pixel_shader, VertexShaderCache::GetSimpleVertexShader(0)); - FramebufferManager::SwapReinterpretTexture(); - D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); - g_renderer->RestoreAPIState(); + // convert data and set the target texture as our new EFB + g_renderer->ResetAPIState(); + D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorReinterpretSurface()); + D3DVIEWPORT9 vp; + vp.X = 0; + vp.Y = 0; + vp.Width = g_renderer->GetTargetWidth(); + vp.Height = g_renderer->GetTargetHeight(); + vp.MinZ = 0.0; + vp.MaxZ = 1.0; + D3D::dev->SetViewport(&vp); + D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture(), &source, + g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(), + g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(), + pixel_shader, VertexShaderCache::GetSimpleVertexShader(0)); + FramebufferManager::SwapReinterpretTexture(); + D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); + g_renderer->RestoreAPIState(); } 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; - //bDstAlphaPass is taken into account because the ability to disable alpha composition is - //really useful for debugging shader and blending errors - bool use_DstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && target_has_alpha; - bool use_DualSource = use_DstAlpha && g_ActiveConfig.backend_info.bSupportsDualSourceBlend; - const D3DBLEND d3dSrcFactors[8] = - { - D3DBLEND_ZERO, - D3DBLEND_ONE, - D3DBLEND_DESTCOLOR, - D3DBLEND_INVDESTCOLOR, - (use_DualSource) ? D3DBLEND_SRCCOLOR2 : D3DBLEND_SRCALPHA, - (use_DualSource) ? D3DBLEND_INVSRCCOLOR2 : 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, - (use_DualSource) ? D3DBLEND_SRCCOLOR2 : D3DBLEND_SRCALPHA, - (use_DualSource) ? D3DBLEND_INVSRCCOLOR2 : D3DBLEND_INVSRCALPHA, - (target_has_alpha) ? D3DBLEND_DESTALPHA : D3DBLEND_ONE, - (target_has_alpha) ? D3DBLEND_INVDESTALPHA : D3DBLEND_ZERO - }; + // 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; + //bDstAlphaPass is taken into account because the ability to disable alpha composition is + //really useful for debugging shader and blending errors + bool use_DstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && target_has_alpha; + bool use_DualSource = use_DstAlpha && g_ActiveConfig.backend_info.bSupportsDualSourceBlend; + const D3DBLEND d3dSrcFactors[8] = + { + D3DBLEND_ZERO, + D3DBLEND_ONE, + D3DBLEND_DESTCOLOR, + D3DBLEND_INVDESTCOLOR, + (use_DualSource) ? D3DBLEND_SRCCOLOR2 : D3DBLEND_SRCALPHA, + (use_DualSource) ? D3DBLEND_INVSRCCOLOR2 : 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, + (use_DualSource) ? D3DBLEND_SRCCOLOR2 : D3DBLEND_SRCALPHA, + (use_DualSource) ? D3DBLEND_INVSRCCOLOR2 : D3DBLEND_INVSRCALPHA, + (target_has_alpha) ? D3DBLEND_DESTALPHA : D3DBLEND_ONE, + (target_has_alpha) ? D3DBLEND_INVDESTALPHA : D3DBLEND_ZERO + }; - if (bpmem.blendmode.logicopenable && !forceUpdate) - { - D3D::SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE , false); - return; - } + if (bpmem.blendmode.logicopenable && !forceUpdate) + { + D3D::SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE , false); + return; + } - bool blend_enable = bpmem.blendmode.subtract || bpmem.blendmode.blendenable; - D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, blend_enable); - D3D::SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, blend_enable && g_ActiveConfig.backend_info.bSupportsSeparateAlphaFunction); - if (blend_enable) - { - D3DBLENDOP op = D3DBLENDOP_ADD; - u32 srcidx = bpmem.blendmode.srcfactor; - u32 dstidx = bpmem.blendmode.dstfactor; - if (bpmem.blendmode.subtract) - { - op = D3DBLENDOP_REVSUBTRACT; - srcidx = GX_BL_ONE; - dstidx = GX_BL_ONE; - } - D3D::SetRenderState(D3DRS_BLENDOP, op); - D3D::SetRenderState(D3DRS_SRCBLEND, d3dSrcFactors[srcidx]); - D3D::SetRenderState(D3DRS_DESTBLEND, d3dDestFactors[dstidx]); - if (g_ActiveConfig.backend_info.bSupportsSeparateAlphaFunction) - { - if (use_DualSource) - { - op = D3DBLENDOP_ADD; - srcidx = GX_BL_ONE; - dstidx = GX_BL_ZERO; - } - else - { - // we can't use D3DBLEND_DESTCOLOR or D3DBLEND_INVDESTCOLOR for source in alpha channel so use their alpha equivalent instead - if (srcidx == GX_BL_DSTCLR) srcidx = GX_BL_DSTALPHA; - if (srcidx == GX_BL_INVDSTCLR) srcidx = GX_BL_INVDSTALPHA; - // we can't use D3DBLEND_SRCCOLOR or D3DBLEND_INVSRCCOLOR for destination in alpha channel so use their alpha equivalent instead - if (dstidx == GX_BL_SRCCLR) dstidx = GX_BL_SRCALPHA; - if (dstidx == GX_BL_INVSRCCLR) dstidx = GX_BL_INVSRCALPHA; - } - D3D::SetRenderState(D3DRS_BLENDOPALPHA, op); - D3D::SetRenderState(D3DRS_SRCBLENDALPHA, d3dSrcFactors[srcidx]); - D3D::SetRenderState(D3DRS_DESTBLENDALPHA, d3dDestFactors[dstidx]); - } - } + bool blend_enable = bpmem.blendmode.subtract || bpmem.blendmode.blendenable; + D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, blend_enable); + D3D::SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, blend_enable && g_ActiveConfig.backend_info.bSupportsSeparateAlphaFunction); + if (blend_enable) + { + D3DBLENDOP op = D3DBLENDOP_ADD; + u32 srcidx = bpmem.blendmode.srcfactor; + u32 dstidx = bpmem.blendmode.dstfactor; + if (bpmem.blendmode.subtract) + { + op = D3DBLENDOP_REVSUBTRACT; + srcidx = GX_BL_ONE; + dstidx = GX_BL_ONE; + } + D3D::SetRenderState(D3DRS_BLENDOP, op); + D3D::SetRenderState(D3DRS_SRCBLEND, d3dSrcFactors[srcidx]); + D3D::SetRenderState(D3DRS_DESTBLEND, d3dDestFactors[dstidx]); + if (g_ActiveConfig.backend_info.bSupportsSeparateAlphaFunction) + { + if (use_DualSource) + { + op = D3DBLENDOP_ADD; + srcidx = GX_BL_ONE; + dstidx = GX_BL_ZERO; + } + else + { + // we can't use D3DBLEND_DESTCOLOR or D3DBLEND_INVDESTCOLOR for source in alpha channel so use their alpha equivalent instead + if (srcidx == GX_BL_DSTCLR) srcidx = GX_BL_DSTALPHA; + if (srcidx == GX_BL_INVDSTCLR) srcidx = GX_BL_INVDSTALPHA; + // we can't use D3DBLEND_SRCCOLOR or D3DBLEND_INVSRCCOLOR for destination in alpha channel so use their alpha equivalent instead + if (dstidx == GX_BL_SRCCLR) dstidx = GX_BL_SRCALPHA; + if (dstidx == GX_BL_INVSRCCLR) dstidx = GX_BL_INVSRCALPHA; + } + D3D::SetRenderState(D3DRS_BLENDOPALPHA, op); + D3D::SetRenderState(D3DRS_SRCBLENDALPHA, d3dSrcFactors[srcidx]); + D3D::SetRenderState(D3DRS_DESTBLENDALPHA, d3dDestFactors[dstidx]); + } + } } bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle &dst_rect) { - HRESULT hr = D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(),ScreenShootMEMSurface); - if(FAILED(hr)) - { - PanicAlert("Error dumping surface data."); - return false; - } - hr = PD3DXSaveSurfaceToFileA(filename.c_str(), D3DXIFF_PNG, ScreenShootMEMSurface, NULL, dst_rect.AsRECT()); - if(FAILED(hr)) - { - PanicAlert("Error saving screen."); - return false; - } + HRESULT hr = D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(),ScreenShootMEMSurface); + if(FAILED(hr)) + { + PanicAlert("Error dumping surface data."); + return false; + } + hr = PD3DXSaveSurfaceToFileA(filename.c_str(), D3DXIFF_PNG, ScreenShootMEMSurface, NULL, dst_rect.AsRECT()); + if(FAILED(hr)) + { + PanicAlert("Error saving screen."); + return false; + } - return true; + return true; } // This function has the final picture. We adjust the aspect ratio here. void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma) { - if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight) - { - if (g_ActiveConfig.bDumpFrames && !frame_data.empty()) - AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); + if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight) + { + if (g_ActiveConfig.bDumpFrames && !frame_data.empty()) + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); - Core::Callback_VideoCopiedToXFB(false); - return; - } + Core::Callback_VideoCopiedToXFB(false); + return; + } - if (field == FIELD_LOWER) xfbAddr -= fbWidth * 2; - u32 xfbCount = 0; - const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); - if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) - { - if (g_ActiveConfig.bDumpFrames && !frame_data.empty()) - AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); + if (field == FIELD_LOWER) xfbAddr -= fbWidth * 2; + u32 xfbCount = 0; + const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); + if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) + { + if (g_ActiveConfig.bDumpFrames && !frame_data.empty()) + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); - Core::Callback_VideoCopiedToXFB(false); - return; - } + Core::Callback_VideoCopiedToXFB(false); + return; + } - ResetAPIState(); + ResetAPIState(); - if(g_ActiveConfig.bAnaglyphStereo) - { - static bool RightFrame = false; - if(RightFrame) - { - D3D::SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN); - VertexShaderManager::ResetView(); - VertexShaderManager::TranslateView(-0.001f * g_ActiveConfig.iAnaglyphStereoSeparation,0.0f); - VertexShaderManager::RotateView(-0.0001f *g_ActiveConfig.iAnaglyphFocalAngle,0.0f); - RightFrame = false; - } - else - { - D3D::SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED); - VertexShaderManager::ResetView(); - VertexShaderManager::TranslateView(0.001f *g_ActiveConfig.iAnaglyphStereoSeparation,0.0f); - VertexShaderManager::RotateView(0.0001f * g_ActiveConfig.iAnaglyphFocalAngle,0.0f); - RightFrame = true; - } - } + if(g_ActiveConfig.bAnaglyphStereo) + { + static bool RightFrame = false; + if(RightFrame) + { + D3D::SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN); + VertexShaderManager::ResetView(); + VertexShaderManager::TranslateView(-0.001f * g_ActiveConfig.iAnaglyphStereoSeparation,0.0f); + VertexShaderManager::RotateView(-0.0001f *g_ActiveConfig.iAnaglyphFocalAngle,0.0f); + RightFrame = false; + } + else + { + D3D::SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED); + VertexShaderManager::ResetView(); + VertexShaderManager::TranslateView(0.001f *g_ActiveConfig.iAnaglyphStereoSeparation,0.0f); + VertexShaderManager::RotateView(0.0001f * g_ActiveConfig.iAnaglyphFocalAngle,0.0f); + RightFrame = true; + } + } - // Prepare to copy the XFBs to our backbuffer - D3D::dev->SetDepthStencilSurface(NULL); - D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); - - UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height); - D3DVIEWPORT9 vp; + // Prepare to copy the XFBs to our backbuffer + D3D::dev->SetDepthStencilSurface(NULL); + D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); - // Clear full target screen (edges, borders etc) - if(g_ActiveConfig.bAnaglyphStereo) { - // use a clear quad to keep old red or blue/green data - vp.X = 0; - vp.Y = 0; - vp.Width = s_backbuffer_width; - vp.Height = s_backbuffer_height; - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; - D3D::dev->SetViewport(&vp); - D3D::drawClearQuad(0, 1.0, PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); - } - else - { - D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); - } + UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height); + D3DVIEWPORT9 vp; - int X = GetTargetRectangle().left; - int Y = GetTargetRectangle().top; - int Width = GetTargetRectangle().right - GetTargetRectangle().left; - int Height = GetTargetRectangle().bottom - GetTargetRectangle().top; + // Clear full target screen (edges, borders etc) + if(g_ActiveConfig.bAnaglyphStereo) { + // use a clear quad to keep old red or blue/green data + vp.X = 0; + vp.Y = 0; + vp.Width = s_backbuffer_width; + vp.Height = s_backbuffer_height; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + D3D::dev->SetViewport(&vp); + D3D::drawClearQuad(0, 1.0, PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); + } + else + { + D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); + } - // Sanity check - if (X < 0) X = 0; - if (Y < 0) Y = 0; - if (X > s_backbuffer_width) X = s_backbuffer_width; - if (Y > s_backbuffer_height) Y = s_backbuffer_height; - if (Width < 0) Width = 0; - if (Height < 0) Height = 0; - if (Width > (s_backbuffer_width - X)) Width = s_backbuffer_width - X; - if (Height > (s_backbuffer_height - Y)) Height = s_backbuffer_height - Y; + int X = GetTargetRectangle().left; + int Y = GetTargetRectangle().top; + int Width = GetTargetRectangle().right - GetTargetRectangle().left; + int Height = GetTargetRectangle().bottom - GetTargetRectangle().top; - vp.X = X; - vp.Y = Y; - vp.Width = Width; - vp.Height = Height; - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; + // Sanity check + if (X < 0) X = 0; + if (Y < 0) Y = 0; + if (X > s_backbuffer_width) X = s_backbuffer_width; + if (Y > s_backbuffer_height) Y = s_backbuffer_height; + if (Width < 0) Width = 0; + if (Height < 0) Height = 0; + if (Width > (s_backbuffer_width - X)) Width = s_backbuffer_width - X; + if (Height > (s_backbuffer_height - Y)) Height = s_backbuffer_height - Y; - D3D::dev->SetViewport(&vp); + vp.X = X; + vp.Y = Y; + vp.Width = Width; + vp.Height = Height; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; - D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + D3D::dev->SetViewport(&vp); - const XFBSourceBase* xfbSource = NULL; + D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - if(g_ActiveConfig.bUseXFB) - { - // draw each xfb source - // Render to the real buffer now. - for (u32 i = 0; i < xfbCount; ++i) - { - xfbSource = xfbSourceList[i]; + const XFBSourceBase* xfbSource = NULL; - MathUtil::Rectangle sourceRc; - - sourceRc.left = 0; - sourceRc.top = 0; - sourceRc.right = (float)xfbSource->texWidth; - sourceRc.bottom = (float)xfbSource->texHeight; + if(g_ActiveConfig.bUseXFB) + { + // draw each xfb source + // Render to the real buffer now. + for (u32 i = 0; i < xfbCount; ++i) + { + xfbSource = xfbSourceList[i]; - MathUtil::Rectangle drawRc; + MathUtil::Rectangle sourceRc; - if (g_ActiveConfig.bUseRealXFB) - { - drawRc.top = -1; - drawRc.bottom = 1; - drawRc.left = -1; - drawRc.right = 1; - } - else - { - // use virtual xfb with offset - int xfbHeight = xfbSource->srcHeight; - int xfbWidth = xfbSource->srcWidth; - int hOffset = ((s32)xfbSource->srcAddr - (s32)xfbAddr) / ((s32)fbWidth * 2); + sourceRc.left = 0; + sourceRc.top = 0; + sourceRc.right = (float)xfbSource->texWidth; + sourceRc.bottom = (float)xfbSource->texHeight; - drawRc.bottom = 1.0f - (2.0f * (hOffset) / (float)fbHeight); - drawRc.top = 1.0f - (2.0f * (hOffset + xfbHeight) / (float)fbHeight); - drawRc.left = -(xfbWidth / (float)fbWidth); - drawRc.right = (xfbWidth / (float)fbWidth); + MathUtil::Rectangle drawRc; - // The following code disables auto stretch. Kept for reference. - // scale draw area for a 1 to 1 pixel mapping with the draw target - //float vScale = (float)fbHeight / (float)GetTargetRectangle().GetHeight(); - //float hScale = (float)fbWidth / (float)GetTargetRectangle().GetWidth(); - //drawRc.top *= vScale; - //drawRc.bottom *= vScale; - //drawRc.left *= hScale; - //drawRc.right *= hScale; - } + if (g_ActiveConfig.bUseRealXFB) + { + drawRc.top = -1; + drawRc.bottom = 1; + drawRc.left = -1; + drawRc.right = 1; + } + else + { + // use virtual xfb with offset + int xfbHeight = xfbSource->srcHeight; + int xfbWidth = xfbSource->srcWidth; + int hOffset = ((s32)xfbSource->srcAddr - (s32)xfbAddr) / ((s32)fbWidth * 2); - xfbSource->Draw(sourceRc, drawRc, Width, Height); - } - } - else - { - TargetRectangle targetRc = ConvertEFBRectangle(rc); - LPDIRECT3DTEXTURE9 read_texture = FramebufferManager::GetEFBColorTexture(); - D3D::drawShadedTexQuad(read_texture,targetRc.AsRECT(), - Renderer::GetTargetWidth(),Renderer::GetTargetHeight(), - Width,Height, - PixelShaderCache::GetColorCopyProgram(g_ActiveConfig.iMultisampleMode), - VertexShaderCache::GetSimpleVertexShader(g_ActiveConfig.iMultisampleMode),Gamma); - - } - D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); - D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER); + drawRc.bottom = 1.0f - (2.0f * (hOffset) / (float)fbHeight); + drawRc.top = 1.0f - (2.0f * (hOffset + xfbHeight) / (float)fbHeight); + drawRc.left = -(xfbWidth / (float)fbWidth); + drawRc.right = (xfbWidth / (float)fbWidth); - if(g_ActiveConfig.bAnaglyphStereo) - { - DWORD color_mask = D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; - D3D::SetRenderState(D3DRS_COLORWRITEENABLE, color_mask); - } + // The following code disables auto stretch. Kept for reference. + // scale draw area for a 1 to 1 pixel mapping with the draw target + //float vScale = (float)fbHeight / (float)GetTargetRectangle().GetHeight(); + //float hScale = (float)fbWidth / (float)GetTargetRectangle().GetWidth(); + //drawRc.top *= vScale; + //drawRc.bottom *= vScale; + //drawRc.left *= hScale; + //drawRc.right *= hScale; + } - vp.X = 0; - vp.Y = 0; - vp.Width = s_backbuffer_width; - vp.Height = s_backbuffer_height; - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; - D3D::dev->SetViewport(&vp); + xfbSource->Draw(sourceRc, drawRc, Width, Height); + } + } + else + { + TargetRectangle targetRc = ConvertEFBRectangle(rc); + LPDIRECT3DTEXTURE9 read_texture = FramebufferManager::GetEFBColorTexture(); + D3D::drawShadedTexQuad(read_texture,targetRc.AsRECT(), + Renderer::GetTargetWidth(),Renderer::GetTargetHeight(), + Width,Height, + PixelShaderCache::GetColorCopyProgram(g_ActiveConfig.iMultisampleMode), + VertexShaderCache::GetSimpleVertexShader(g_ActiveConfig.iMultisampleMode),Gamma); - // Save screenshot - if (s_bScreenshot) - { - std::lock_guard lk(s_criticalScreenshot); - SaveScreenshot(s_sScreenshotName, GetTargetRectangle()); - s_bScreenshot = false; - } + } + D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); + D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER); - // Dump frames - static int w = 0, h = 0; - if (g_ActiveConfig.bDumpFrames) - { - static int s_recordWidth; - static int s_recordHeight; + if(g_ActiveConfig.bAnaglyphStereo) + { + DWORD color_mask = D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; + D3D::SetRenderState(D3DRS_COLORWRITEENABLE, color_mask); + } - HRESULT hr = D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(),ScreenShootMEMSurface); - if (!bLastFrameDumped) - { - s_recordWidth = GetTargetRectangle().GetWidth(); - s_recordHeight = GetTargetRectangle().GetHeight(); - bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight); - if (!bAVIDumping) - { - PanicAlert("Error dumping frames to AVI."); - } - else - { - char msg [255]; - sprintf_s(msg,255, "Dumping Frames to \"%sframedump0.avi\" (%dx%d RGB24)", - File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), s_recordWidth, s_recordHeight); - OSD::AddMessage(msg, 2000); - } - } - if (bAVIDumping) - { - D3DLOCKED_RECT rect; - if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, GetTargetRectangle().AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY))) - { - if (frame_data.empty() || w != s_recordWidth || h != s_recordHeight) - { - frame_data.resize(3 * s_recordWidth * s_recordHeight); - w = s_recordWidth; - h = s_recordHeight; - } - formatBufferDump((const u8*)rect.pBits, &frame_data[0], s_recordWidth, s_recordHeight, rect.Pitch); - AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); - ScreenShootMEMSurface->UnlockRect(); - } - } - bLastFrameDumped = true; - } - else - { - if (bLastFrameDumped && bAVIDumping) - { - std::vector().swap(frame_data); - w = h = 0; - AVIDump::Stop(); - bAVIDumping = false; - OSD::AddMessage("Stop dumping frames to AVI", 2000); - } - bLastFrameDumped = false; - } + vp.X = 0; + vp.Y = 0; + vp.Width = s_backbuffer_width; + vp.Height = s_backbuffer_height; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + D3D::dev->SetViewport(&vp); - // Finish up the current frame, print some stats - if (g_ActiveConfig.bShowFPS) - { - char fps[20]; - StringCchPrintfA(fps, 20, "FPS: %d\n", s_fps); - D3D::font.DrawTextScaled(0, 0, 20, 20, 0.0f, 0xFF00FFFF, fps); - } + // Save screenshot + if (s_bScreenshot) + { + std::lock_guard lk(s_criticalScreenshot); + SaveScreenshot(s_sScreenshotName, GetTargetRectangle()); + s_bScreenshot = false; + } - if (SConfig::GetInstance().m_ShowLag) - { - char lag[10]; - StringCchPrintfA(lag, 10, "Lag: %llu\n", Movie::g_currentLagCount); - D3D::font.DrawTextScaled(0, 18, 20, 20, 0.0f, 0xFF00FFFF, lag); - } + // Dump frames + static int w = 0, h = 0; + if (g_ActiveConfig.bDumpFrames) + { + static int s_recordWidth; + static int s_recordHeight; - if (g_ActiveConfig.bShowInputDisplay) - { - char inputDisplay[1000]; - StringCchPrintfA(inputDisplay, 1000, Movie::GetInputDisplay().c_str()); - D3D::font.DrawTextScaled(0, 36, 20, 20, 0.0f, 0xFF00FFFF, inputDisplay); - } + HRESULT hr = D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(),ScreenShootMEMSurface); + if (!bLastFrameDumped) + { + s_recordWidth = GetTargetRectangle().GetWidth(); + s_recordHeight = GetTargetRectangle().GetHeight(); + bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight); + if (!bAVIDumping) + { + PanicAlert("Error dumping frames to AVI."); + } + else + { + char msg [255]; + sprintf_s(msg,255, "Dumping Frames to \"%sframedump0.avi\" (%dx%d RGB24)", + File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), s_recordWidth, s_recordHeight); + OSD::AddMessage(msg, 2000); + } + } + if (bAVIDumping) + { + D3DLOCKED_RECT rect; + if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, GetTargetRectangle().AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY))) + { + if (frame_data.empty() || w != s_recordWidth || h != s_recordHeight) + { + frame_data.resize(3 * s_recordWidth * s_recordHeight); + w = s_recordWidth; + h = s_recordHeight; + } + formatBufferDump((const u8*)rect.pBits, &frame_data[0], s_recordWidth, s_recordHeight, rect.Pitch); + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); + ScreenShootMEMSurface->UnlockRect(); + } + } + bLastFrameDumped = true; + } + else + { + if (bLastFrameDumped && bAVIDumping) + { + std::vector().swap(frame_data); + w = h = 0; + AVIDump::Stop(); + bAVIDumping = false; + OSD::AddMessage("Stop dumping frames to AVI", 2000); + } + bLastFrameDumped = false; + } - Renderer::DrawDebugText(); + // Finish up the current frame, print some stats + if (g_ActiveConfig.bShowFPS) + { + char fps[20]; + StringCchPrintfA(fps, 20, "FPS: %d\n", s_fps); + D3D::font.DrawTextScaled(0, 0, 20, 20, 0.0f, 0xFF00FFFF, fps); + } - if (g_ActiveConfig.bOverlayStats) - { - Statistics::ToString(st); - D3D::font.DrawTextScaled(0, 36, 20, 20, 0.0f, 0xFF00FFFF, st); - } - else if (g_ActiveConfig.bOverlayProjStats) - { - Statistics::ToStringProj(st); - D3D::font.DrawTextScaled(0, 36, 20, 20, 0.0f, 0xFF00FFFF, st); - } + if (SConfig::GetInstance().m_ShowLag) + { + char lag[10]; + StringCchPrintfA(lag, 10, "Lag: %llu\n", Movie::g_currentLagCount); + D3D::font.DrawTextScaled(0, 18, 20, 20, 0.0f, 0xFF00FFFF, lag); + } - OSD::DrawMessages(); - D3D::EndFrame(); - ++frameCount; + if (g_ActiveConfig.bShowInputDisplay) + { + char inputDisplay[1000]; + StringCchPrintfA(inputDisplay, 1000, Movie::GetInputDisplay().c_str()); + D3D::font.DrawTextScaled(0, 36, 20, 20, 0.0f, 0xFF00FFFF, inputDisplay); + } - GFX_DEBUGGER_PAUSE_AT(NEXT_FRAME, true); + Renderer::DrawDebugText(); - DLCache::ProgressiveCleanup(); - TextureCache::Cleanup(); - // Flip/present backbuffer to frontbuffer here - D3D::Present(); - // Enable configuration changes - UpdateActiveConfig(); - TextureCache::OnConfigChanged(g_ActiveConfig); + if (g_ActiveConfig.bOverlayStats) + { + Statistics::ToString(st); + D3D::font.DrawTextScaled(0, 36, 20, 20, 0.0f, 0xFF00FFFF, st); + } + else if (g_ActiveConfig.bOverlayProjStats) + { + Statistics::ToStringProj(st); + D3D::font.DrawTextScaled(0, 36, 20, 20, 0.0f, 0xFF00FFFF, st); + } - SetWindowSize(fbWidth, fbHeight); + OSD::DrawMessages(); + D3D::EndFrame(); + ++frameCount; - const bool windowResized = CheckForResize(); + GFX_DEBUGGER_PAUSE_AT(NEXT_FRAME, true); - bool xfbchanged = false; + DLCache::ProgressiveCleanup(); + TextureCache::Cleanup(); + // Flip/present backbuffer to frontbuffer here + D3D::Present(); + // Enable configuration changes + UpdateActiveConfig(); + TextureCache::OnConfigChanged(g_ActiveConfig); - if (FramebufferManagerBase::LastXfbWidth() != fbWidth || FramebufferManagerBase::LastXfbHeight() != fbHeight) - { - xfbchanged = true; - unsigned int w = (fbWidth < 1 || fbWidth > MAX_XFB_WIDTH) ? MAX_XFB_WIDTH : fbWidth; - unsigned int h = (fbHeight < 1 || fbHeight > MAX_XFB_HEIGHT) ? MAX_XFB_HEIGHT : fbHeight; - FramebufferManagerBase::SetLastXfbWidth(w); - FramebufferManagerBase::SetLastXfbHeight(h); - } + SetWindowSize(fbWidth, fbHeight); - u32 newAA = g_ActiveConfig.iMultisampleMode; + const bool windowResized = CheckForResize(); - if (xfbchanged || windowResized || s_LastEFBScale != g_ActiveConfig.iEFBScale || s_LastAA != newAA) - { - s_LastAA = newAA; + bool xfbchanged = false; - UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height); - - int SupersampleCoeficient = (s_LastAA % 3) + 1; + if (FramebufferManagerBase::LastXfbWidth() != fbWidth || FramebufferManagerBase::LastXfbHeight() != fbHeight) + { + xfbchanged = true; + unsigned int w = (fbWidth < 1 || fbWidth > MAX_XFB_WIDTH) ? MAX_XFB_WIDTH : fbWidth; + unsigned int h = (fbHeight < 1 || fbHeight > MAX_XFB_HEIGHT) ? MAX_XFB_HEIGHT : fbHeight; + FramebufferManagerBase::SetLastXfbWidth(w); + FramebufferManagerBase::SetLastXfbHeight(h); + } - s_LastEFBScale = g_ActiveConfig.iEFBScale; - CalculateTargetSize(s_backbuffer_width, s_backbuffer_height, SupersampleCoeficient); + u32 newAA = g_ActiveConfig.iMultisampleMode; - D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); - D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface()); - if (windowResized) - { - // device objects lost, so recreate all of them - SetupDeviceObjects(); - } - else - { - // just resize the frame buffer - delete g_framebuffer_manager; - g_framebuffer_manager = new FramebufferManager; - } - D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); - D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); - D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); - } + if (xfbchanged || windowResized || s_LastEFBScale != g_ActiveConfig.iEFBScale || s_LastAA != newAA) + { + s_LastAA = newAA; - if (XFBWrited) - s_fps = UpdateFPSCounter(); + UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height); - // Begin new frame - // Set default viewport and scissor, for the clear to work correctly - // New frame - stats.ResetFrame(); + int SupersampleCoeficient = (s_LastAA % 3) + 1; - // Handle vsync changes during execution - if(s_vsync != g_ActiveConfig.IsVSync()) - { - s_vsync = g_ActiveConfig.IsVSync(); - TeardownDeviceObjects(); - D3D::Reset(); - // device objects lost, so recreate all of them - SetupDeviceObjects(); - } - D3D::BeginFrame(); - RestoreAPIState(); + s_LastEFBScale = g_ActiveConfig.iEFBScale; + CalculateTargetSize(s_backbuffer_width, s_backbuffer_height, SupersampleCoeficient); - D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); - D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); - VertexShaderManager::SetViewportChanged(); + D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); + D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface()); + if (windowResized) + { + // device objects lost, so recreate all of them + SetupDeviceObjects(); + } + else + { + // just resize the frame buffer + delete g_framebuffer_manager; + g_framebuffer_manager = new FramebufferManager; + } + D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); + D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); + D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); + SetLineWidth(); + } - Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)); - XFBWrited = false; + if (XFBWrited) + s_fps = UpdateFPSCounter(); + + // Begin new frame + // Set default viewport and scissor, for the clear to work correctly + // New frame + stats.ResetFrame(); + + // Handle vsync changes during execution + if(s_vsync != g_ActiveConfig.IsVSync()) + { + s_vsync = g_ActiveConfig.IsVSync(); + TeardownDeviceObjects(); + D3D::Reset(); + // device objects lost, so recreate all of them + SetupDeviceObjects(); + } + D3D::BeginFrame(); + RestoreAPIState(); + + D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); + D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); + VertexShaderManager::SetViewportChanged(); + + Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)); + XFBWrited = false; } void Renderer::ApplyState(bool bUseDstAlpha) { - if (bUseDstAlpha) - { - // If we get here we are sure that we are using dst alpha pass. (bpmem.dstalpha.enable) - // Alpha write is enabled. (because bpmem.blendmode.alphaupdate && bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24) - // We must disable blend because we want to write alpha value directly to the alpha channel without modifications. - D3D::ChangeRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA); - D3D::ChangeRenderState(D3DRS_ALPHABLENDENABLE, false); - if(bpmem.zmode.testenable && bpmem.zmode.updateenable) - { - // This is needed to draw to the correct pixels in multi-pass algorithms - // to avoid z-fighting and grants that you write to the same pixels - // affected by the last pass - D3D::ChangeRenderState(D3DRS_ZWRITEENABLE, false); - D3D::ChangeRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL); - } - } + if (bUseDstAlpha) + { + // If we get here we are sure that we are using dst alpha pass. (bpmem.dstalpha.enable) + // Alpha write is enabled. (because bpmem.blendmode.alphaupdate && bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24) + // We must disable blend because we want to write alpha value directly to the alpha channel without modifications. + D3D::ChangeRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA); + D3D::ChangeRenderState(D3DRS_ALPHABLENDENABLE, false); + if(bpmem.zmode.testenable && bpmem.zmode.updateenable) + { + // This is needed to draw to the correct pixels in multi-pass algorithms + // to avoid z-fighting and grants that you write to the same pixels + // affected by the last pass + D3D::ChangeRenderState(D3DRS_ZWRITEENABLE, false); + D3D::ChangeRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL); + } + } } void Renderer::RestoreState() { - D3D::RefreshRenderState(D3DRS_COLORWRITEENABLE); - D3D::RefreshRenderState(D3DRS_ALPHABLENDENABLE); - if(bpmem.zmode.testenable && bpmem.zmode.updateenable) - { - D3D::RefreshRenderState(D3DRS_ZWRITEENABLE); - D3D::RefreshRenderState(D3DRS_ZFUNC); - } - // TODO: Enable this code. Caused glitches for me however (neobrain) -// for (unsigned int i = 0; i < 8; ++i) -// D3D::dev->SetTexture(i, NULL); + D3D::RefreshRenderState(D3DRS_COLORWRITEENABLE); + D3D::RefreshRenderState(D3DRS_ALPHABLENDENABLE); + if(bpmem.zmode.testenable && bpmem.zmode.updateenable) + { + D3D::RefreshRenderState(D3DRS_ZWRITEENABLE); + D3D::RefreshRenderState(D3DRS_ZFUNC); + } + // TODO: Enable this code. Caused glitches for me however (neobrain) + // for (unsigned int i = 0; i < 8; ++i) + // D3D::dev->SetTexture(i, NULL); } // ALWAYS call RestoreAPIState for each ResetAPIState call you're doing void Renderer::ResetAPIState() { - D3D::SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - D3D::SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - D3D::SetRenderState(D3DRS_ZENABLE, FALSE); - D3D::SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - DWORD color_mask = D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; - D3D::SetRenderState(D3DRS_COLORWRITEENABLE, color_mask); + D3D::SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + D3D::SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + D3D::SetRenderState(D3DRS_ZENABLE, FALSE); + D3D::SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + DWORD color_mask = D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; + D3D::SetRenderState(D3DRS_COLORWRITEENABLE, color_mask); } void Renderer::RestoreAPIState() { - // Gets us back into a more game-like state. - D3D::SetRenderState(D3DRS_FILLMODE, g_ActiveConfig.bWireFrame ? D3DFILL_WIREFRAME : D3DFILL_SOLID); - D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); - VertexShaderManager::SetViewportChanged(); - BPFunctions::SetScissor(); - if (bpmem.zmode.testenable) { - D3D::SetRenderState(D3DRS_ZENABLE, TRUE); - if (bpmem.zmode.updateenable) - D3D::SetRenderState(D3DRS_ZWRITEENABLE, TRUE); - } - SetColorMask(); - SetLogicOpMode(); - SetGenerationMode(); + // Gets us back into a more game-like state. + D3D::SetRenderState(D3DRS_FILLMODE, g_ActiveConfig.bWireFrame ? D3DFILL_WIREFRAME : D3DFILL_SOLID); + D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); + VertexShaderManager::SetViewportChanged(); + BPFunctions::SetScissor(); + if (bpmem.zmode.testenable) { + D3D::SetRenderState(D3DRS_ZENABLE, TRUE); + if (bpmem.zmode.updateenable) + D3D::SetRenderState(D3DRS_ZWRITEENABLE, TRUE); + } + SetColorMask(); + SetLogicOpMode(); + SetGenerationMode(); } void Renderer::SetGenerationMode() { - const D3DCULL d3dCullModes[4] = - { - D3DCULL_NONE, - D3DCULL_CCW, - D3DCULL_CW, - D3DCULL_CCW - }; + const D3DCULL d3dCullModes[4] = + { + D3DCULL_NONE, + D3DCULL_CCW, + D3DCULL_CW, + D3DCULL_CCW + }; - D3D::SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]); + 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 - }; + 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); - D3D::SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable); - D3D::SetRenderState(D3DRS_ZFUNC, d3dCmpFuncs[bpmem.zmode.func]); - } - else - { - // if the test is disabled write is disabled too - D3D::SetRenderState(D3DRS_ZENABLE, FALSE); - D3D::SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - } + if (bpmem.zmode.testenable) + { + D3D::SetRenderState(D3DRS_ZENABLE, TRUE); + D3D::SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable); + D3D::SetRenderState(D3DRS_ZFUNC, d3dCmpFuncs[bpmem.zmode.func]); + } + else + { + // if the test is disabled write is disabled too + D3D::SetRenderState(D3DRS_ZENABLE, FALSE); + D3D::SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + } } void Renderer::SetLogicOpMode() { - // D3D9 doesn't support logic blending, so this is a huge hack + // 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 - }; + // 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]); - D3D::SetRenderState(D3DRS_SRCBLEND, d3dLogicOpSrcFactors[bpmem.blendmode.logicmode]); - D3D::SetRenderState(D3DRS_DESTBLEND, d3dLogicOpDestFactors[bpmem.blendmode.logicmode]); - } - else - { - SetBlendMode(true); - } + if (bpmem.blendmode.logicopenable) + { + D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, true); + D3D::SetRenderState(D3DRS_BLENDOP, d3dLogicOpop[bpmem.blendmode.logicmode]); + D3D::SetRenderState(D3DRS_SRCBLEND, d3dLogicOpSrcFactors[bpmem.blendmode.logicmode]); + D3D::SetRenderState(D3DRS_DESTBLEND, d3dLogicOpDestFactors[bpmem.blendmode.logicmode]); + } + else + { + SetBlendMode(true); + } } void Renderer::SetDitherMode() { - D3D::SetRenderState(D3DRS_DITHERENABLE, bpmem.blendmode.dither); + D3D::SetRenderState(D3DRS_DITHERENABLE, bpmem.blendmode.dither); } void Renderer::SetLineWidth() { - // We can't change line width in D3D unless we use ID3DXLine - float fratio = xfregs.viewport.wd != 0 ? Renderer::EFBToScaledXf(1.f) : 1.0f; - float psize = bpmem.lineptwidth.linesize * fratio / 6.0f; - //little hack to compensate scaling problems in dx9 must be taken out when scaling is fixed. - psize *= 2.0f; - if (psize > m_fMaxPointSize) - { - psize = m_fMaxPointSize; - } - D3D::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize)); - D3D::SetRenderState(D3DRS_POINTSIZE_MIN, *((DWORD*)&psize)); - D3D::SetRenderState(D3DRS_POINTSIZE_MAX, *((DWORD*)&psize)); + // We can't change line width in D3D unless we use ID3DXLine + float fratio = xfregs.viewport.wd != 0 ? Renderer::EFBToScaledXf(1.f) : 1.0f; + float psize = bpmem.lineptwidth.pointsize * fratio / 6.0f; + psize = psize > 0 ? psize : 1.0; + if (psize > m_fMaxPointSize) + { + psize = m_fMaxPointSize; + } + D3D::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize)); + D3D::SetRenderState(D3DRS_POINTSIZE_MIN, *((DWORD*)&psize)); + D3D::SetRenderState(D3DRS_POINTSIZE_MAX, *((DWORD*)&psize)); } 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 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]; - - D3DTEXTUREFILTERTYPE min, mag, mip; - if (g_ActiveConfig.bForceFiltering) - { - min = mag = mip = D3DTEXF_LINEAR; - } - else - { - min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT; - mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT; - mip = d3dMipFilters[tm0.min_filter & 3]; - } - if (texindex) - stage += 4; + const FourTexUnits &tex = bpmem.tex[texindex]; + const TexMode0 &tm0 = tex.texMode0[stage]; + const TexMode1 &tm1 = tex.texMode1[stage]; - if (mag == D3DTEXF_LINEAR && min == D3DTEXF_LINEAR && g_ActiveConfig.iMaxAnisotropy) - { - min = D3DTEXF_ANISOTROPIC; - } - D3D::SetSamplerState(stage, D3DSAMP_MINFILTER, min); - D3D::SetSamplerState(stage, D3DSAMP_MAGFILTER, mag); - D3D::SetSamplerState(stage, D3DSAMP_MIPFILTER, mip); - - D3D::SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]); - D3D::SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]); + D3DTEXTUREFILTERTYPE min, mag, mip; + if (g_ActiveConfig.bForceFiltering) + { + min = mag = mip = D3DTEXF_LINEAR; + } + else + { + min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT; + mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT; + mip = d3dMipFilters[tm0.min_filter & 3]; + } + if (texindex) + stage += 4; - float lodbias = (s32)tm0.lod_bias / 32.0f; - D3D::SetSamplerState(stage, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)&lodbias); - D3D::SetSamplerState(stage, D3DSAMP_MAXMIPLEVEL, tm1.min_lod >> 4); + if (mag == D3DTEXF_LINEAR && min == D3DTEXF_LINEAR && g_ActiveConfig.iMaxAnisotropy) + { + min = D3DTEXF_ANISOTROPIC; + } + D3D::SetSamplerState(stage, D3DSAMP_MINFILTER, min); + D3D::SetSamplerState(stage, D3DSAMP_MAGFILTER, mag); + D3D::SetSamplerState(stage, D3DSAMP_MIPFILTER, mip); + + D3D::SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]); + D3D::SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]); + + float lodbias = (s32)tm0.lod_bias / 32.0f; + D3D::SetSamplerState(stage, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)&lodbias); + D3D::SetSamplerState(stage, D3DSAMP_MAXMIPLEVEL, tm1.min_lod >> 4); } void Renderer::SetInterlacingMode() { - // TODO + // TODO } } // namespace DX9 diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index adb4ddf580..12f3b88576 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -36,375 +36,383 @@ const u32 MAX_VBUFFER_COUNT = 2; inline void DumpBadShaders() { #if defined(_DEBUG) || defined(DEBUGFAST) - // TODO: Reimplement! -/* std::string error_shaders; - error_shaders.append(VertexShaderCache::GetCurrentShaderCode()); - error_shaders.append(PixelShaderCache::GetCurrentShaderCode()); - char filename[512] = "bad_shader_combo_0.txt"; - int which = 0; - while (File::Exists(filename)) - { - which++; - sprintf(filename, "bad_shader_combo_%i.txt", which); - } - File::WriteStringToFile(true, error_shaders, filename); - PanicAlert("DrawIndexedPrimitiveUP failed. Shaders written to %s", filename);*/ + // TODO: Reimplement! + /* std::string error_shaders; + error_shaders.append(VertexShaderCache::GetCurrentShaderCode()); + error_shaders.append(PixelShaderCache::GetCurrentShaderCode()); + char filename[512] = "bad_shader_combo_0.txt"; + int which = 0; + while (File::Exists(filename)) + { + which++; + sprintf(filename, "bad_shader_combo_%i.txt", which); + } + File::WriteStringToFile(true, error_shaders, filename); + PanicAlert("DrawIndexedPrimitiveUP failed. Shaders written to %s", filename);*/ #endif } void VertexManager::CreateDeviceObjects() { - m_buffers_count = 0; - m_vertex_buffers = NULL; - m_index_buffers = NULL; - D3DCAPS9 DeviceCaps = D3D::GetCaps(); - u32 devicevMaxBufferSize = DeviceCaps.MaxPrimitiveCount * 3 * DeviceCaps.MaxStreamStride; - //Calculate Device Dependant size - m_vertex_buffer_size = (VBUFFER_SIZE > devicevMaxBufferSize) ? devicevMaxBufferSize : VBUFFER_SIZE; - m_index_buffer_size = (IBUFFER_SIZE > DeviceCaps.MaxVertexIndex) ? DeviceCaps.MaxVertexIndex : IBUFFER_SIZE; - //if device caps are not enough for Vbuffer fall back to vertex arrays - if (m_index_buffer_size < MAXIBUFFERSIZE || m_vertex_buffer_size < MAXVBUFFERSIZE) return; - - m_vertex_buffers = new LPDIRECT3DVERTEXBUFFER9[MAX_VBUFFER_COUNT]; - m_index_buffers = new LPDIRECT3DINDEXBUFFER9[MAX_VBUFFER_COUNT]; + m_buffers_count = 0; + m_vertex_buffers = NULL; + m_index_buffers = NULL; + D3DCAPS9 DeviceCaps = D3D::GetCaps(); + u32 devicevMaxBufferSize = DeviceCaps.MaxPrimitiveCount * 3 * DeviceCaps.MaxStreamStride; + //Calculate Device Dependant size + m_vertex_buffer_size = (VBUFFER_SIZE > devicevMaxBufferSize) ? devicevMaxBufferSize : VBUFFER_SIZE; + m_index_buffer_size = (IBUFFER_SIZE > DeviceCaps.MaxVertexIndex) ? DeviceCaps.MaxVertexIndex : IBUFFER_SIZE; + //if device caps are not enough for Vbuffer fall back to vertex arrays + if (m_index_buffer_size < MAXIBUFFERSIZE || m_vertex_buffer_size < MAXVBUFFERSIZE) return; - bool Fail = false; - for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++) - { - m_vertex_buffers[m_current_vertex_buffer] = NULL; - m_index_buffers[m_current_vertex_buffer] = NULL; - } - for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++) - { - if(FAILED( D3D::dev->CreateVertexBuffer( m_vertex_buffer_size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_vertex_buffers[m_current_vertex_buffer], NULL ) ) ) - { - Fail = true; - break; - } - if( FAILED( D3D::dev->CreateIndexBuffer( m_index_buffer_size * sizeof(u16), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_index_buffers[m_current_vertex_buffer], NULL ) ) ) - { - Fail = true; - return; - } - } - m_buffers_count = m_current_vertex_buffer; - m_current_vertex_buffer = 0; - m_current_index_buffer = 0; - m_index_buffer_cursor = m_index_buffer_size; - m_vertex_buffer_cursor = m_vertex_buffer_size; - m_current_stride = 0; - if (Fail) - { - m_buffers_count--; - if (m_buffers_count < 2) - { - //Error creating Vertex buffers. clean and fall to Vertex arrays - m_buffers_count = MAX_VBUFFER_COUNT; - DestroyDeviceObjects(); - } - } + m_vertex_buffers = new LPDIRECT3DVERTEXBUFFER9[MAX_VBUFFER_COUNT]; + m_index_buffers = new LPDIRECT3DINDEXBUFFER9[MAX_VBUFFER_COUNT]; + + bool Fail = false; + for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++) + { + m_vertex_buffers[m_current_vertex_buffer] = NULL; + m_index_buffers[m_current_vertex_buffer] = NULL; + } + for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++) + { + if(FAILED( D3D::dev->CreateVertexBuffer( m_vertex_buffer_size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_vertex_buffers[m_current_vertex_buffer], NULL ) ) ) + { + Fail = true; + break; + } + if( FAILED( D3D::dev->CreateIndexBuffer( m_index_buffer_size * sizeof(u16), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_index_buffers[m_current_vertex_buffer], NULL ) ) ) + { + Fail = true; + return; + } + } + m_buffers_count = m_current_vertex_buffer; + m_current_vertex_buffer = 0; + m_current_index_buffer = 0; + m_index_buffer_cursor = m_index_buffer_size; + m_vertex_buffer_cursor = m_vertex_buffer_size; + m_current_stride = 0; + if (Fail) + { + m_buffers_count--; + if (m_buffers_count < 2) + { + //Error creating Vertex buffers. clean and fall to Vertex arrays + m_buffers_count = MAX_VBUFFER_COUNT; + DestroyDeviceObjects(); + } + } } void VertexManager::DestroyDeviceObjects() { - D3D::SetStreamSource( 0, NULL, 0, 0); - D3D::SetIndices(NULL); - for (int i = 0; i < MAX_VBUFFER_COUNT; i++) - { - if(m_vertex_buffers) - { - if (m_vertex_buffers[i]) - { - m_vertex_buffers[i]->Release(); - m_vertex_buffers[i] = NULL; - } - } + D3D::SetStreamSource( 0, NULL, 0, 0); + D3D::SetIndices(NULL); + for (int i = 0; i < MAX_VBUFFER_COUNT; i++) + { + if(m_vertex_buffers) + { + if (m_vertex_buffers[i]) + { + m_vertex_buffers[i]->Release(); + m_vertex_buffers[i] = NULL; + } + } - if (m_index_buffers[i]) - { - m_index_buffers[i]->Release(); - m_index_buffers[i] = NULL; - } - } - if(m_vertex_buffers) - delete [] m_vertex_buffers; - if(m_index_buffers) - delete [] m_index_buffers; - m_vertex_buffers = NULL; - m_index_buffers = NULL; + if (m_index_buffers[i]) + { + m_index_buffers[i]->Release(); + m_index_buffers[i] = NULL; + } + } + if(m_vertex_buffers) + delete [] m_vertex_buffers; + if(m_index_buffers) + delete [] m_index_buffers; + m_vertex_buffers = NULL; + m_index_buffers = NULL; } void VertexManager::PrepareDrawBuffers(u32 stride) { - if (!m_buffers_count) - { - return; - } - u8* pVertices; - u16* pIndices; - int datasize = IndexGenerator::GetNumVerts() * stride; - int TdataSize = IndexGenerator::GetTriangleindexLen(); - int LDataSize = IndexGenerator::GetLineindexLen(); - int PDataSize = IndexGenerator::GetPointindexLen(); - int IndexDataSize = TdataSize + LDataSize; - DWORD LockMode = D3DLOCK_NOOVERWRITE; - m_vertex_buffer_cursor--; - m_vertex_buffer_cursor = m_vertex_buffer_cursor - (m_vertex_buffer_cursor % stride) + stride; - if (m_vertex_buffer_cursor > m_vertex_buffer_size - datasize) - { - LockMode = D3DLOCK_DISCARD; - m_vertex_buffer_cursor = 0; - m_current_vertex_buffer = (m_current_vertex_buffer + 1) % m_buffers_count; - } - if(FAILED(m_vertex_buffers[m_current_vertex_buffer]->Lock(m_vertex_buffer_cursor, datasize,(VOID**)(&pVertices), LockMode))) - { - DestroyDeviceObjects(); - return; - } - memcpy(pVertices, s_pBaseBufferPointer, datasize); - m_vertex_buffers[m_current_vertex_buffer]->Unlock(); + if (!m_buffers_count) + { + return; + } + u8* pVertices; + u16* pIndices; + int datasize = IndexGenerator::GetNumVerts() * stride; + int TdataSize = IndexGenerator::GetTriangleindexLen(); + int LDataSize = IndexGenerator::GetLineindexLen(); + int IndexDataSize = TdataSize + LDataSize; + if(IndexDataSize) + { + DWORD LockMode = D3DLOCK_NOOVERWRITE; + m_vertex_buffer_cursor--; + m_vertex_buffer_cursor = m_vertex_buffer_cursor - (m_vertex_buffer_cursor % stride) + stride; + if (m_vertex_buffer_cursor > m_vertex_buffer_size - datasize) + { + LockMode = D3DLOCK_DISCARD; + m_vertex_buffer_cursor = 0; + m_current_vertex_buffer = (m_current_vertex_buffer + 1) % m_buffers_count; + } + if(FAILED(m_vertex_buffers[m_current_vertex_buffer]->Lock(m_vertex_buffer_cursor, datasize,(VOID**)(&pVertices), LockMode))) + { + DestroyDeviceObjects(); + return; + } + memcpy(pVertices, s_pBaseBufferPointer, datasize); + m_vertex_buffers[m_current_vertex_buffer]->Unlock(); - LockMode = D3DLOCK_NOOVERWRITE; - if (m_index_buffer_cursor > m_index_buffer_size - IndexDataSize) - { - LockMode = D3DLOCK_DISCARD; - m_index_buffer_cursor = 0; - m_current_index_buffer = (m_current_index_buffer + 1) % m_buffers_count; - } - - if(FAILED(m_index_buffers[m_current_index_buffer]->Lock(m_index_buffer_cursor * sizeof(u16), IndexDataSize * sizeof(u16), (VOID**)(&pIndices), LockMode ))) - { - DestroyDeviceObjects(); - return; - } - if(TdataSize) - { - memcpy(pIndices, GetTriangleIndexBuffer(), TdataSize * sizeof(u16)); - pIndices += TdataSize; - } - if(LDataSize) - { - memcpy(pIndices, GetLineIndexBuffer(), LDataSize * sizeof(u16)); - pIndices += LDataSize; - } - m_index_buffers[m_current_index_buffer]->Unlock(); - if(m_current_stride != stride || m_vertex_buffer_cursor == 0) - { - m_current_stride = stride; - D3D::SetStreamSource( 0, m_vertex_buffers[m_current_vertex_buffer], 0, stride); - } - if (m_index_buffer_cursor == 0) - { - D3D::SetIndices(m_index_buffers[m_current_index_buffer]); - } - - ADDSTAT(stats.thisFrame.bytesVertexStreamed, datasize); - ADDSTAT(stats.thisFrame.bytesIndexStreamed, IndexDataSize); + LockMode = D3DLOCK_NOOVERWRITE; + if (m_index_buffer_cursor > m_index_buffer_size - IndexDataSize) + { + LockMode = D3DLOCK_DISCARD; + m_index_buffer_cursor = 0; + m_current_index_buffer = (m_current_index_buffer + 1) % m_buffers_count; + } + + if(FAILED(m_index_buffers[m_current_index_buffer]->Lock(m_index_buffer_cursor * sizeof(u16), IndexDataSize * sizeof(u16), (VOID**)(&pIndices), LockMode ))) + { + DestroyDeviceObjects(); + return; + } + if(TdataSize) + { + memcpy(pIndices, GetTriangleIndexBuffer(), TdataSize * sizeof(u16)); + pIndices += TdataSize; + } + if(LDataSize) + { + memcpy(pIndices, GetLineIndexBuffer(), LDataSize * sizeof(u16)); + pIndices += LDataSize; + } + m_index_buffers[m_current_index_buffer]->Unlock(); + } + if(m_current_stride != stride || m_vertex_buffer_cursor == 0) + { + m_current_stride = stride; + D3D::SetStreamSource( 0, m_vertex_buffers[m_current_vertex_buffer], 0, m_current_stride); + } + if (m_index_buffer_cursor == 0) + { + D3D::SetIndices(m_index_buffers[m_current_index_buffer]); + } + + ADDSTAT(stats.thisFrame.bytesVertexStreamed, datasize); + ADDSTAT(stats.thisFrame.bytesIndexStreamed, IndexDataSize); } void VertexManager::DrawVertexBuffer(int stride) { - int triangles = IndexGenerator::GetNumTriangles(); - int lines = IndexGenerator::GetNumLines(); - int points = IndexGenerator::GetNumPoints(); - int numverts = IndexGenerator::GetNumVerts(); - int StartIndex = m_index_buffer_cursor; - int basevertex = m_vertex_buffer_cursor / stride; - if (triangles > 0) - { - if (FAILED(D3D::dev->DrawIndexedPrimitive( - D3DPT_TRIANGLELIST, - basevertex, - 0, - numverts, - StartIndex, - triangles))) - { - DumpBadShaders(); - } - StartIndex += IndexGenerator::GetTriangleindexLen(); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - if (lines > 0) - { - if (FAILED(D3D::dev->DrawIndexedPrimitive( - D3DPT_LINELIST, - basevertex, - 0, - numverts, - StartIndex, - IndexGenerator::GetNumLines()))) - { - DumpBadShaders(); - } - StartIndex += IndexGenerator::GetLineindexLen(); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - if (points > 0) - { - //DrawIndexedPrimitive does not support point list so we have to draw the points one by one - for (int i = 0; i < points; i++) - { - if (FAILED(D3D::dev->DrawPrimitive( - D3DPT_POINTLIST, - basevertex + GetPointIndexBuffer()[i], - 1))) - { - DumpBadShaders(); - } - INCSTAT(stats.thisFrame.numDrawCalls); - } - - - } - + int triangles = IndexGenerator::GetNumTriangles(); + int lines = IndexGenerator::GetNumLines(); + int points = IndexGenerator::GetNumPoints(); + int numverts = IndexGenerator::GetNumVerts(); + int StartIndex = m_index_buffer_cursor; + int basevertex = m_vertex_buffer_cursor / stride; + if (triangles > 0) + { + if (FAILED(D3D::dev->DrawIndexedPrimitive( + D3DPT_TRIANGLELIST, + basevertex, + 0, + numverts, + StartIndex, + triangles))) + { + DumpBadShaders(); + } + StartIndex += IndexGenerator::GetTriangleindexLen(); + INCSTAT(stats.thisFrame.numIndexedDrawCalls); + } + if (lines > 0) + { + if (FAILED(D3D::dev->DrawIndexedPrimitive( + D3DPT_LINELIST, + basevertex, + 0, + numverts, + StartIndex, + IndexGenerator::GetNumLines()))) + { + DumpBadShaders(); + } + StartIndex += IndexGenerator::GetLineindexLen(); + INCSTAT(stats.thisFrame.numIndexedDrawCalls); + } + if (points > 0) + { + //DrawIndexedPrimitive does not support point list so we have to draw them using DrawPrimitive + u16* PointIndexBuffer = GetPointIndexBuffer(); + int i = 0; + do + { + int count = i + 1; + while (count < points && PointIndexBuffer[count - 1] + 1 == PointIndexBuffer[count]) + { + count++; + } + if (FAILED(D3D::dev->DrawPrimitive( + D3DPT_POINTLIST, + basevertex + PointIndexBuffer[i], + count - i))) + { + DumpBadShaders(); + } + INCSTAT(stats.thisFrame.numDrawCalls); + i = count; + } while (i < points); + } + } void VertexManager::DrawVertexArray(int stride) { - int triangles = IndexGenerator::GetNumTriangles(); - int lines = IndexGenerator::GetNumLines(); - int points = IndexGenerator::GetNumPoints(); - int numverts = IndexGenerator::GetNumVerts(); - if (triangles > 0) - { - if (FAILED(D3D::dev->DrawIndexedPrimitiveUP( - D3DPT_TRIANGLELIST, - 0, numverts, triangles, - GetTriangleIndexBuffer(), - D3DFMT_INDEX16, - s_pBaseBufferPointer, - stride))) - { - DumpBadShaders(); - } - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - if (lines > 0) - { - if (FAILED(D3D::dev->DrawIndexedPrimitiveUP( - D3DPT_LINELIST, - 0, numverts, lines, - GetLineIndexBuffer(), - D3DFMT_INDEX16, - s_pBaseBufferPointer, - stride))) - { - DumpBadShaders(); - } - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - if (points > 0) - { - if (FAILED(D3D::dev->DrawIndexedPrimitiveUP( - D3DPT_POINTLIST, - 0, numverts, points, - GetPointIndexBuffer(), - D3DFMT_INDEX16, - s_pBaseBufferPointer, - stride))) - { - DumpBadShaders(); - } - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } + int triangles = IndexGenerator::GetNumTriangles(); + int lines = IndexGenerator::GetNumLines(); + int points = IndexGenerator::GetNumPoints(); + int numverts = IndexGenerator::GetNumVerts(); + if (triangles > 0) + { + if (FAILED(D3D::dev->DrawIndexedPrimitiveUP( + D3DPT_TRIANGLELIST, + 0, numverts, triangles, + GetTriangleIndexBuffer(), + D3DFMT_INDEX16, + s_pBaseBufferPointer, + stride))) + { + DumpBadShaders(); + } + INCSTAT(stats.thisFrame.numIndexedDrawCalls); + } + if (lines > 0) + { + if (FAILED(D3D::dev->DrawIndexedPrimitiveUP( + D3DPT_LINELIST, + 0, numverts, lines, + GetLineIndexBuffer(), + D3DFMT_INDEX16, + s_pBaseBufferPointer, + stride))) + { + DumpBadShaders(); + } + INCSTAT(stats.thisFrame.numIndexedDrawCalls); + } + if (points > 0) + { + if (FAILED(D3D::dev->DrawIndexedPrimitiveUP( + D3DPT_POINTLIST, + 0, numverts, points, + GetPointIndexBuffer(), + D3DFMT_INDEX16, + s_pBaseBufferPointer, + stride))) + { + DumpBadShaders(); + } + INCSTAT(stats.thisFrame.numIndexedDrawCalls); + } } void VertexManager::vFlush() { - u32 usedtextures = 0; - for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) - if (bpmem.tevorders[i / 2].getEnable(i & 1)) - usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1); + u32 usedtextures = 0; + for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) + if (bpmem.tevorders[i / 2].getEnable(i & 1)) + usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1); - if (bpmem.genMode.numindstages > 0) - for (unsigned int i = 0; i < bpmem.genMode.numtevstages + 1; ++i) - if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) - usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt); + if (bpmem.genMode.numindstages > 0) + for (unsigned int i = 0; i < bpmem.genMode.numtevstages + 1; ++i) + if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) + usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt); - for (unsigned int i = 0; i < 8; i++) - { - if (usedtextures & (1 << i)) - { - g_renderer->SetSamplerState(i & 3, i >> 2); - FourTexUnits &tex = bpmem.tex[i >> 2]; - TextureCache::TCacheEntryBase* tentry = TextureCache::Load(i, - (tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5, - tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1, - tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, - tex.texTlut[i&3].tlut_format, - (tex.texMode0[i&3].min_filter & 3), - (tex.texMode1[i&3].max_lod + 0xf) / 0x10, - tex.texImage1[i&3].image_type); + for (unsigned int i = 0; i < 8; i++) + { + if (usedtextures & (1 << i)) + { + g_renderer->SetSamplerState(i & 3, i >> 2); + FourTexUnits &tex = bpmem.tex[i >> 2]; + TextureCache::TCacheEntryBase* tentry = TextureCache::Load(i, + (tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5, + tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1, + tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, + tex.texTlut[i&3].tlut_format, + (tex.texMode0[i&3].min_filter & 3), + (tex.texMode1[i&3].max_lod + 0xf) / 0x10, + tex.texImage1[i&3].image_type); - if (tentry) - { - // 0s are probably for no manual wrapping needed. - PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0); - } - else - ERROR_LOG(VIDEO, "Error loading texture"); - } - } + if (tentry) + { + // 0s are probably for no manual wrapping needed. + PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0); + } + else + ERROR_LOG(VIDEO, "Error loading texture"); + } + } - // set global constants - VertexShaderManager::SetConstants(); - PixelShaderManager::SetConstants(g_nativeVertexFmt->m_components); - u32 stride = g_nativeVertexFmt->GetVertexStride(); - bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && - bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; - bool useDualSource = useDstAlpha && g_ActiveConfig.backend_info.bSupportsDualSourceBlend; - DSTALPHA_MODE AlphaMode = useDualSource ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE; + // set global constants + VertexShaderManager::SetConstants(); + PixelShaderManager::SetConstants(g_nativeVertexFmt->m_components); + u32 stride = g_nativeVertexFmt->GetVertexStride(); + bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && + bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; + bool useDualSource = useDstAlpha && g_ActiveConfig.backend_info.bSupportsDualSourceBlend; + DSTALPHA_MODE AlphaMode = useDualSource ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE; - if (!PixelShaderCache::SetShader(AlphaMode ,g_nativeVertexFmt->m_components)) - { - GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");}); - goto shader_fail; - } - if (!VertexShaderCache::SetShader(g_nativeVertexFmt->m_components)) - { - GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set vertex shader\n");}); - goto shader_fail; + if (!PixelShaderCache::SetShader(AlphaMode ,g_nativeVertexFmt->m_components)) + { + GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");}); + goto shader_fail; + } + if (!VertexShaderCache::SetShader(g_nativeVertexFmt->m_components)) + { + GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set vertex shader\n");}); + goto shader_fail; - } - PrepareDrawBuffers(stride); - g_nativeVertexFmt->SetupVertexPointers(); - g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); - if(m_buffers_count) - { - DrawVertexBuffer(stride); - } - else - { - DrawVertexArray(stride); - } - g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); - if (useDstAlpha && !useDualSource) - { - if (!PixelShaderCache::SetShader(DSTALPHA_ALPHA_PASS, g_nativeVertexFmt->m_components)) - { - GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");}); - goto shader_fail; - } - // update alpha only - g_renderer->ApplyState(true); - if(m_buffers_count) - { - DrawVertexBuffer(stride); - } - else - { - DrawVertexArray(stride); - } - g_renderer->RestoreState(); - } - GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true); + } + PrepareDrawBuffers(stride); + g_nativeVertexFmt->SetupVertexPointers(); + g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); + if(m_buffers_count) + { + DrawVertexBuffer(stride); + } + else + { + DrawVertexArray(stride); + } + g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); + if (useDstAlpha && !useDualSource) + { + if (!PixelShaderCache::SetShader(DSTALPHA_ALPHA_PASS, g_nativeVertexFmt->m_components)) + { + GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");}); + goto shader_fail; + } + // update alpha only + g_renderer->ApplyState(true); + if(m_buffers_count) + { + DrawVertexBuffer(stride); + } + else + { + DrawVertexArray(stride); + } + g_renderer->RestoreState(); + } + GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true); shader_fail: - if(m_buffers_count) - { - m_index_buffer_cursor += IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen(); - m_vertex_buffer_cursor += IndexGenerator::GetNumVerts() * stride; - } + if(m_buffers_count) + { + m_index_buffer_cursor += IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen(); + m_vertex_buffer_cursor += IndexGenerator::GetNumVerts() * stride; + } } }