void GSDevice10::DoMerge(Texture* st, GSVector4* sr, GSVector4* dr, Texture& dt, bool slbg, bool mmod, GSVector4& c) { ClearRenderTarget(dt, c); if(st[1] && !slbg) { StretchRect(st[1], sr[1], dt, dr[1], m_merge.ps[0], NULL, true); } if(st[0]) { m_dev->UpdateSubresource(m_merge.cb, 0, NULL, &c, 0, 0); StretchRect(st[0], sr[0], dt, dr[0], m_merge.ps[mmod ? 1 : 0], m_merge.cb, m_merge.bs, true); } }
void GSDevice11::DoMerge(GSTexture* sTex[2], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, bool slbg, bool mmod, const GSVector4& c) { ClearRenderTarget(dTex, c); if(sTex[1] && !slbg) { StretchRect(sTex[1], sRect[1], dTex, dRect[1], m_merge.ps[0], NULL, true); } if(sTex[0]) { m_ctx->UpdateSubresource(m_merge.cb, 0, NULL, &c, 0, 0); StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge.ps[mmod ? 1 : 0], m_merge.cb, m_merge.bs, true); } }
bool GSDevice10::CopyOffscreen(Texture& src, const GSVector4& sr, Texture& dst, int w, int h, int format) { dst = Texture(); if(format == 0) { format = DXGI_FORMAT_R8G8B8A8_UNORM; } if(format != DXGI_FORMAT_R8G8B8A8_UNORM && format != DXGI_FORMAT_R16_UINT) { ASSERT(0); return false; } Texture rt; if(CreateRenderTarget(rt, w, h, format)) { GSVector4 dr(0, 0, w, h); StretchRect(src, sr, rt, dr, m_convert.ps[format == DXGI_FORMAT_R16_UINT ? 1 : 0], NULL); if(CreateOffscreen(dst, w, h, format)) { m_dev->CopyResource(dst, rt); } } Recycle(rt); return !!dst; }
void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c) { bool slbg = PMODE.SLBG; bool mmod = PMODE.MMOD; ClearRenderTarget(dTex, c); if(sTex[1] && !slbg) { StretchRect(sTex[1], sRect[1], dTex, dRect[1], m_merge.ps[0], NULL, true); } if(sTex[0]) { m_ctx->UpdateSubresource(m_merge.cb, 0, NULL, &c, 0, 0); StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge.ps[mmod ? 1 : 0], m_merge.cb, m_merge.bs, true); } }
void GSDevice10::DoInterlace(Texture& st, Texture& dt, int shader, bool linear, float yoffset) { GSVector4 sr(0, 0, 1, 1); GSVector4 dr(0.0f, yoffset, (float)dt.GetWidth(), (float)dt.GetHeight() + yoffset); InterlaceConstantBuffer cb; cb.ZrH = GSVector2(0, 1.0f / dt.GetHeight()); cb.hH = (float)dt.GetHeight() / 2; m_dev->UpdateSubresource(m_interlace.cb, 0, NULL, &cb, 0, 0); StretchRect(st, sr, dt, dr, m_interlace.ps[shader], m_interlace.cb, linear); }
void GSDevice11::DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset) { GSVector4 s = GSVector4(dTex->GetSize()); GSVector4 sRect(0, 0, 1, 1); GSVector4 dRect(0.0f, yoffset, s.x, s.y + yoffset); InterlaceConstantBuffer cb; cb.ZrH = GSVector2(0, 1.0f / s.y); cb.hH = s.y / 2; m_ctx->UpdateSubresource(m_interlace.cb, 0, NULL, &cb, 0, 0); StretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[shader], m_interlace.cb, linear); }
void GSDevice11::DoShadeBoost(GSTexture* sTex, GSTexture* dTex) { GSVector2i s = dTex->GetSize(); GSVector4 sRect(0, 0, 1, 1); GSVector4 dRect(0, 0, s.x, s.y); ShadeBoostConstantBuffer cb; cb.rcpFrame = GSVector4(1.0f / s.x, 1.0f / s.y, 0.0f, 0.0f); cb.rcpFrameOpt = GSVector4::zero(); m_ctx->UpdateSubresource(m_shadeboost.cb, 0, NULL, &cb, 0, 0); StretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps, m_shadeboost.cb, true); }
void GSDevice::ExternalFX() { GSVector2i s = m_current->GetSize(); if (m_shaderfx == NULL || m_shaderfx->GetSize() != s) { delete m_shaderfx; m_shaderfx = CreateRenderTarget(s.x, s.y, false); } if (m_shaderfx != NULL) { GSVector4 sRect(0, 0, 1, 1); GSVector4 dRect(0, 0, s.x, s.y); StretchRect(m_current, sRect, m_shaderfx, dRect, 7, false); DoExternalFX(m_shaderfx, m_current); } }
void GSDevice::ShadeBoost() { GSVector2i s = m_current->GetSize(); if(m_shadeboost == NULL || m_shadeboost->GetSize() != s) { delete m_shadeboost; m_shadeboost = CreateRenderTarget(s.x, s.y, false); } if(m_shadeboost != NULL) { GSVector4 sRect(0, 0, 1, 1); GSVector4 dRect(0, 0, s.x, s.y); StretchRect(m_current, sRect, m_shadeboost, dRect, 0, false); DoShadeBoost(m_shadeboost, m_current); } }
void GSDevice::FXAA() { GSVector2i s = m_current->GetSize(); if(m_fxaa == NULL || m_fxaa->GetSize() != s) { delete m_fxaa; m_fxaa = CreateRenderTarget(s.x, s.y, false); } if(m_fxaa != NULL) { GSVector4 sRect(0, 0, 1, 1); GSVector4 dRect(0, 0, s.x, s.y); StretchRect(m_current, sRect, m_fxaa, dRect, 7, false); DoFXAA(m_fxaa, m_current); } }
void GSDevice11::DoExternalFX(GSTexture* sTex, GSTexture* dTex) { GSVector2i s = dTex->GetSize(); GSVector4 sRect(0, 0, 1, 1); GSVector4 dRect(0, 0, s.x, s.y); ExternalFXConstantBuffer cb; InitExternalFX(); cb.xyFrame = GSVector2((float)s.x, (float)s.y); cb.rcpFrame = GSVector4(1.0f / (float)s.x, 1.0f / (float)s.y, 0.0f, 0.0f); cb.rcpFrameOpt = GSVector4::zero(); m_ctx->UpdateSubresource(m_shaderfx.cb, 0, NULL, &cb, 0, 0); StretchRect(sTex, sRect, dTex, dRect, m_shaderfx.ps, m_shaderfx.cb, true); }
void GSDevice11::DoFXAA(GSTexture* sTex, GSTexture* dTex) { GSVector2i s = dTex->GetSize(); GSVector4 sRect(0, 0, 1, 1); GSVector4 dRect(0, 0, s.x, s.y); FXAAConstantBuffer cb; InitFXAA(); cb.rcpFrame = GSVector4(1.0f / s.x, 1.0f / s.y, 0.0f, 0.0f); cb.rcpFrameOpt = GSVector4::zero(); m_ctx->UpdateSubresource(m_fxaa.cb, 0, NULL, &cb, 0, 0); StretchRect(sTex, sRect, dTex, dRect, m_fxaa.ps, m_fxaa.cb, true); //sTex->Save("c:\\temp1\\1.bmp"); //dTex->Save("c:\\temp1\\2.bmp"); }
GSTexture* GSDevice11::CopyOffscreen(GSTexture* src, const GSVector4& sRect, int w, int h, int format, int ps_shader) { GSTexture* dst = NULL; if(format == 0) { format = DXGI_FORMAT_R8G8B8A8_UNORM; } if(format != DXGI_FORMAT_R8G8B8A8_UNORM && format != DXGI_FORMAT_R16_UINT) { ASSERT(0); return false; } if(GSTexture* rt = CreateRenderTarget(w, h, false, format)) { GSVector4 dRect(0, 0, w, h); if(GSTexture* src2 = src->IsMSAA() ? Resolve(src) : src) { StretchRect(src2, sRect, rt, dRect, m_convert.ps[format == DXGI_FORMAT_R16_UINT ? 1 : 0], NULL); if(src2 != src) Recycle(src2); } dst = CreateOffscreen(w, h, format); if(dst) { m_ctx->CopyResource(*(GSTexture11*)dst, *(GSTexture11*)rt); } Recycle(rt); } return dst; }
void GSDevice10::Present(const CRect& r) { CRect cr; GetClientRect(m_hWnd, &cr); if(m_backbuffer.GetWidth() != cr.Width() || m_backbuffer.GetHeight() != cr.Height()) { Reset(cr.Width(), cr.Height(), false); } float color[4] = {0, 0, 0, 0}; m_dev->ClearRenderTargetView(m_backbuffer, color); if(m_current) { StretchRect(m_current, m_backbuffer, GSVector4(r)); } m_swapchain->Present(m_vsync ? 1 : 0, 0); }
void GSDevice10::StretchRect(Texture& st, const GSVector4& sr, Texture& dt, const GSVector4& dr, bool linear) { StretchRect(st, sr, dt, dr, m_convert.ps[0], NULL, linear); }
void GSDevice::StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, int shader, bool linear) { StretchRect(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, shader, linear); }
void GSDevice::Present(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, int shader) { StretchRect(sTex, dTex, dRect, shader); }
void GSDevice::StretchRect(GSTexture* st, GSTexture* dt, const GSVector4& dr, int shader, bool linear) { StretchRect(st, GSVector4(0, 0, 1, 1), dt, dr, shader, linear); }
void Graphics::TakeScaledScreenshot(const std::string& filename, int width, int height) { logger->debug("Creating screenshot with size {}x{} in {}", width, height, filename); auto device = mDevice; auto sceneSurface = mSceneSurface; D3DSURFACE_DESC desc; sceneSurface->GetDesc(&desc); // Support taking unscaled screenshots auto stretch = true; if (width == 0 || height == 0) { width = desc.Width; height = desc.Height; stretch = false; } // Create system memory surface to copy the screenshot to CComPtr<IDirect3DSurface9> sysMemSurface; if (D3DLOG(device->CreateOffscreenPlainSurface(width, height, desc.Format, D3DPOOL_SYSTEMMEM, &sysMemSurface, nullptr)) != D3D_OK) { logger->error("Unable to create offscreen surface for copying the screenshot"); return; } if (stretch) { CComPtr<IDirect3DSurface9> stretchedScene; if (D3DLOG(device->CreateRenderTarget(width, height, desc.Format, desc.MultiSampleType, desc.MultiSampleQuality, false, &stretchedScene, NULL)) != D3D_OK) { return; } if (D3DLOG(device->StretchRect(sceneSurface, nullptr, stretchedScene, nullptr, D3DTEXF_LINEAR)) != D3D_OK) { logger->error("Unable to copy front buffer to target surface for screenshot"); return; } if (D3DLOG(device->GetRenderTargetData(stretchedScene, sysMemSurface))) { logger->error("Unable to copy stretched render target to system memory."); return; } } else { if (D3DLOG(device->GetRenderTargetData(sceneSurface, sysMemSurface))) { logger->error("Unable to copy scene render target to system memory."); return; } } /* Get access to the pixel data for the surface and encode it to a JPEG. */ D3DLOCKED_RECT locked; if (D3DLOG(sysMemSurface->LockRect(&locked, nullptr, 0))) { logger->error("Unable to lock screenshot surface."); return; } // Quality is between 1 and 100 auto quality = std::min(100, std::max(1, config.screenshotQuality)); auto jpegData(gfx::EncodeJpeg(reinterpret_cast<uint8_t*>(locked.pBits), gfx::JpegPixelFormat::BGRX, width, height, quality, locked.Pitch)); if (D3DLOG(sysMemSurface->UnlockRect())) { logger->error("Unable to unlock screenshot surface."); return; } // We have to write using tio or else it goes god knows where auto fh = tio_fopen(filename.c_str(), "w+b"); if (tio_fwrite(jpegData.data(), 1, jpegData.size(), fh) != jpegData.size()) { logger->error("Unable to write screenshot to disk due to an IO error."); tio_fclose(fh); tio_remove(filename.c_str()); } else { tio_fclose(fh); } }
void GSDevice11::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader, bool linear) { StretchRect(st, sr, dt, dr, m_convert.ps[shader], NULL, linear); }
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear) { StretchRect(sTex, sRect, dTex, dRect, ps, ps_cb, m_convert.bs, linear); }
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, int shader, bool linear) { StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[shader], NULL, linear); }
void GSDevice::Present(GSTexture* st, GSTexture* dt, const GSVector4& dr, int shader) { StretchRect(st, dt, dr, shader); }
void GSDevice10::StretchRect(Texture& st, Texture& dt, const GSVector4& dr, bool linear) { StretchRect(st, GSVector4(0, 0, 1, 1), dt, dr, linear); }
void GSDevice11::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear) { StretchRect(st, sr, dt, dr, ps, ps_cb, m_convert.bs, linear); }
void GSDevice10::StretchRect(Texture& st, const GSVector4& sr, Texture& dt, const GSVector4& dr, ID3D10PixelShader* ps, ID3D10Buffer* ps_cb, bool linear) { StretchRect(st, sr, dt, dr, ps, ps_cb, m_convert.bs, linear); }
int __cdecl HookedPlayMovieSlide(const char* imageFile, const char* soundFile, const SubtitleLine* subtitles, int flags, int soundtrackId) { logger->info("Play Movie Slide {} {} {} {}", imageFile, soundFile, flags, soundtrackId); // Load img into memory using TIO unique_ptr<vector<uint8_t>> imgData(TioReadBinaryFile(imageFile)); if (!imgData) { logger->error("Unable to load the image file {}", imageFile); return 1; // Can't play because we cant load the file } auto device = graphics->device(); gfx::ImageFileInfo info; auto surface(gfx::LoadImageToSurface(graphics->device(), *imgData.get(), info)); movieFuncs.MovieIsPlaying = true; device->ShowCursor(FALSE); // Clear screen with black color and present immediately device->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 0, 0); device->Present(nullptr, nullptr, nullptr, nullptr); SubtitleRenderer subtitleRenderer(subtitles); TigRect bbRect(0, 0, graphics->backBufferDesc().Width, graphics->backBufferDesc().Height); TigRect destRect(0, 0, info.width, info.height); destRect.FitInto(bbRect); RECT fitDestRect = destRect.ToRect(); Stopwatch sw; TigSoundStreamWrapper stream; if (soundFile) { if (!stream.Play(soundFile, TigSoundType::Voice)) { logger->error("Unable to play sound {} during slideshow.", soundFile); } else { stream.SetVolume(*tigSoundAddresses.movieVolume); } } bool keyPressed = false; while (!keyPressed && (!stream.IsValid() || stream.IsPlaying() || sw.GetElapsedMs() < 3000)) { D3DLOG(device->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 0, 0)); D3DLOG(device->BeginScene()); D3DLOG(device->StretchRect(surface, NULL, graphics->backBuffer(), &fitDestRect, D3DTEXF_LINEAR)); subtitleRenderer.Render(); D3DLOG(device->EndScene()); D3DLOG(device->Present(NULL, NULL, NULL, NULL)); templeFuncs.ProcessSystemEvents(); TigMsg msg; while (!msgFuncs.Process(&msg)) { // Flags 1 seems to disable skip via keyboard. Also seems unused. if (!(flags & 1) && msg.type == TigMsgType::KEYSTATECHANGE && LOBYTE(msg.arg2) == 1) { // TODO Wait for the key to be unpressed again keyPressed = true; break; } } } movieFuncs.MovieIsPlaying = false; device->ShowCursor(TRUE); return 0; }