Revert "Be less dumb."

Revert "Actually, filename really does need to be a parameter because of some random debug thing."
Revert "fix non-HAVE_WX case"
Revert "Handle screenshot saving in RenderBase.  Removes dependency on D3DX11 for screenshots (texture dumping is still broken)."

This reverts commits 00fe5057f1, 74b5fb3ab4, cd46138d29 and 5f72542e06 because taking screenshots in D3D still crashed for me so there was no point in the code changes (which I found ugly anyway).
This commit is contained in:
Tony Wasserka 2013-11-10 00:10:20 +01:00
parent 3de2ee5d46
commit 0b02880b76
7 changed files with 148 additions and 111 deletions

View File

@ -680,7 +680,7 @@ void Renderer::SetBlendMode(bool forceUpdate)
} }
} }
void Renderer::TakeScreenshot(const TargetRectangle &rc, std::string filename) bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle& rc)
{ {
if (!s_screenshot_texture) if (!s_screenshot_texture)
CreateScreenshotTexture(rc); CreateScreenshotTexture(rc);
@ -689,26 +689,34 @@ void Renderer::TakeScreenshot(const TargetRectangle &rc, std::string filename)
D3D11_BOX box = CD3D11_BOX(rc.left, rc.top, 0, rc.right, rc.bottom, 1); D3D11_BOX box = CD3D11_BOX(rc.left, rc.top, 0, rc.right, rc.bottom, 1);
D3D::context->CopySubresourceRegion(s_screenshot_texture, 0, 0, 0, 0, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex(), 0, &box); D3D::context->CopySubresourceRegion(s_screenshot_texture, 0, 0, 0, 0, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex(), 0, &box);
u8* __restrict dest = (u8*) malloc(rc.GetWidth() * rc.GetHeight() * 3); // D3DX11SaveTextureToFileA doesn't allow us to ignore the alpha channel, so we need to strip it out ourselves
D3D11_MAPPED_SUBRESOURCE map; D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map); D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map);
u8* src = (u8*) map.pData; for (unsigned int y = 0; y < rc.GetHeight(); ++y)
for (int y = 0; y < rc.GetHeight(); ++y)
{ {
u8* __restrict row = src; u8* ptr = (u8*)map.pData + y * map.RowPitch + 3;
for (int x = 0; x < rc.GetWidth(); ++x) for (unsigned int x = 0; x < rc.GetWidth(); ++x)
{ {
*dest++ = *row++; *ptr = 0xFF;
*dest++ = *row++; ptr += 4;
*dest++ = *row++;
row++;
} }
src += map.RowPitch;
} }
D3D::context->Unmap(s_screenshot_texture, 0); D3D::context->Unmap(s_screenshot_texture, 0);
SaveScreenshot(dest, rc.GetWidth(), rc.GetHeight(), filename); // ready to be saved
//HRESULT hr = PD3DX11SaveTextureToFileA(D3D::context, s_screenshot_texture, D3DX11_IFF_PNG, filename.c_str());
HRESULT hr = 0;
if (SUCCEEDED(hr))
{
OSD::AddMessage(StringFromFormat("Saved %i x %i %s", rc.GetWidth(),
rc.GetHeight(), filename.c_str()));
}
else
{
OSD::AddMessage(StringFromFormat("Error saving %s", filename.c_str()));
}
return SUCCEEDED(hr);
} }
void formatBufferDump(const u8* in, u8* out, int w, int h, int p) void formatBufferDump(const u8* in, u8* out, int w, int h, int p)
@ -846,7 +854,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r
// done with drawing the game stuff, good moment to save a screenshot // done with drawing the game stuff, good moment to save a screenshot
if (s_bScreenshot) if (s_bScreenshot)
{ {
TakeScreenshot(GetTargetRectangle(), s_sScreenshotName); SaveScreenshot(s_sScreenshotName, GetTargetRectangle());
s_bScreenshot = false; s_bScreenshot = false;
} }

View File

@ -48,10 +48,9 @@ public:
void UpdateViewport(); void UpdateViewport();
static void TakeScreenshot(const TargetRectangle &rc, std::string filename); bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc);
static bool CheckForResize(); static bool CheckForResize();
}; };
} }

View File

@ -11,6 +11,9 @@
#include <cstdio> #include <cstdio>
#include "GLUtil.h" #include "GLUtil.h"
#if defined(HAVE_WX) && HAVE_WX
#include "WxUtils.h"
#endif
#include "FileUtil.h" #include "FileUtil.h"
@ -22,6 +25,7 @@
#include "DriverDetails.h" #include "DriverDetails.h"
#include "VideoConfig.h" #include "VideoConfig.h"
#include "Statistics.h" #include "Statistics.h"
#include "ImageWrite.h"
#include "PixelEngine.h" #include "PixelEngine.h"
#include "Render.h" #include "Render.h"
#include "BPStructs.h" #include "BPStructs.h"
@ -58,6 +62,10 @@
#include "AVIDump.h" #include "AVIDump.h"
#endif #endif
#if defined(HAVE_WX) && HAVE_WX
#include <wx/image.h>
#endif
// glew1.8 doesn't define KHR_debug // glew1.8 doesn't define KHR_debug
#ifndef GL_DEBUG_OUTPUT #ifndef GL_DEBUG_OUTPUT
#define GL_DEBUG_OUTPUT 0x92E0 #define GL_DEBUG_OUTPUT 0x92E0
@ -70,6 +78,17 @@ void VideoConfig::UpdateProjectionHack()
} }
#if defined(HAVE_WX) && HAVE_WX
// Screenshot thread struct
typedef struct
{
int W, H;
std::string filename;
wxImage *img;
} ScrStrct;
#endif
int OSDInternalW, OSDInternalH; int OSDInternalW, OSDInternalH;
namespace OGL namespace OGL
@ -108,6 +127,10 @@ static u32 s_blendMode;
static bool s_vsync; static bool s_vsync;
#if defined(HAVE_WX) && HAVE_WX
static std::thread scrshotThread;
#endif
// EFB cache related // EFB cache related
static const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks. static const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks.
static const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up static const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up
@ -616,6 +639,11 @@ Renderer::Renderer()
Renderer::~Renderer() Renderer::~Renderer()
{ {
#if defined(HAVE_WX) && HAVE_WX
if (scrshotThread.joinable())
scrshotThread.join();
#endif
} }
void Renderer::Shutdown() void Renderer::Shutdown()
@ -1391,9 +1419,11 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r
// Save screenshot // Save screenshot
if (s_bScreenshot) if (s_bScreenshot)
{ {
TakeScreenshot(flipped_trc, s_sScreenshotName); std::lock_guard<std::mutex> lk(s_criticalScreenshot);
s_bScreenshot = false; SaveScreenshot(s_sScreenshotName, flipped_trc);
// Reset settings // Reset settings
s_sScreenshotName.clear();
s_bScreenshot = false;
} }
// Frame dumps are handled a little differently in Windows // Frame dumps are handled a little differently in Windows
@ -1771,22 +1801,71 @@ void Renderer::SetInterlacingMode()
void Renderer::FlipImageData(u8 *data, int w, int h) void Renderer::FlipImageData(u8 *data, int w, int h)
{ {
// XXX make this faster // Flip image upside down. Damn OpenGL.
u8* __restrict top = data;
u8* bot = data + w * h * 3;
for (int y = 0; y < h / 2; y++) for (int y = 0; y < h / 2; y++)
{ {
size_t stride = w * 3; for(int x = 0; x < w; x++)
bot -= stride;
u8* __restrict brow = bot;
for(size_t x = 0; x < stride; x++)
{ {
std::swap(*top++, *brow++); std::swap(data[(y * w + x) * 3], data[((h - 1 - y) * w + x) * 3]);
std::swap(data[(y * w + x) * 3 + 1], data[((h - 1 - y) * w + x) * 3 + 1]);
std::swap(data[(y * w + x) * 3 + 2], data[((h - 1 - y) * w + x) * 3 + 2]);
} }
} }
} }
void Renderer::TakeScreenshot(const TargetRectangle &back_rc, std::string filename) }
// TODO: remove
extern bool g_aspect_wide;
#if defined(HAVE_WX) && HAVE_WX
void TakeScreenshot(ScrStrct* threadStruct)
{
// These will contain the final image size
float FloatW = (float)threadStruct->W;
float FloatH = (float)threadStruct->H;
// Handle aspect ratio for the final ScrStrct to look exactly like what's on screen.
if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH)
{
bool use16_9 = g_aspect_wide;
// Check for force-settings and override.
if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_16_9)
use16_9 = true;
else if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_4_3)
use16_9 = false;
float Ratio = (FloatW / FloatH) / (!use16_9 ? (4.0f / 3.0f) : (16.0f / 9.0f));
// If ratio > 1 the picture is too wide and we have to limit the width.
if (Ratio > 1)
FloatW /= Ratio;
// ratio == 1 or the image is too high, we have to limit the height.
else
FloatH *= Ratio;
// This is a bit expensive on high resolutions
threadStruct->img->Rescale((int)FloatW, (int)FloatH, wxIMAGE_QUALITY_HIGH);
}
// Save the screenshot and finally kill the wxImage object
// This is really expensive when saving to PNG, but not at all when using BMP
threadStruct->img->SaveFile(StrToWxStr(threadStruct->filename),
wxBITMAP_TYPE_PNG);
threadStruct->img->Destroy();
// Show success messages
OSD::AddMessage(StringFromFormat("Saved %i x %i %s", (int)FloatW, (int)FloatH,
threadStruct->filename.c_str()), 2000);
delete threadStruct;
}
#endif
namespace OGL
{
bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle &back_rc)
{ {
u32 W = back_rc.GetWidth(); u32 W = back_rc.GetWidth();
u32 H = back_rc.GetHeight(); u32 H = back_rc.GetHeight();
@ -1800,13 +1879,38 @@ void Renderer::TakeScreenshot(const TargetRectangle &back_rc, std::string filena
{ {
free(data); free(data);
OSD::AddMessage("Error capturing or saving screenshot.", 2000); OSD::AddMessage("Error capturing or saving screenshot.", 2000);
return; return false;
} }
// Turn image upside down // Turn image upside down
FlipImageData(data, W, H); FlipImageData(data, W, H);
SaveScreenshot(data, W, H, filename); #if defined(HAVE_WX) && HAVE_WX
// Create wxImage
wxImage *a = new wxImage(W, H, data);
if (scrshotThread.joinable())
scrshotThread.join();
ScrStrct *threadStruct = new ScrStrct;
threadStruct->filename = filename;
threadStruct->img = a;
threadStruct->H = H; threadStruct->W = W;
scrshotThread = std::thread(TakeScreenshot, threadStruct);
#ifdef _WIN32
SetThreadPriority(scrshotThread.native_handle(), THREAD_PRIORITY_BELOW_NORMAL);
#endif
bool result = true;
OSD::AddMessage("Saving Screenshot... ", 2000);
#else
bool result = SaveTGA(filename.c_str(), W, H, data);
free(data);
#endif
return result;
} }
} }

View File

@ -63,7 +63,7 @@ public:
void RenderText(const char* pstr, int left, int top, u32 color) override; void RenderText(const char* pstr, int left, int top, u32 color) override;
void DrawDebugInfo(); void DrawDebugInfo();
static void FlipImageData(u8 *data, int w, int h); void FlipImageData(u8 *data, int w, int h);
u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override; u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override;
@ -80,7 +80,7 @@ public:
void UpdateViewport() override; void UpdateViewport() override;
static void TakeScreenshot(const TargetRectangle &rc, std::string filename); bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc);
private: private:
void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc, const TargetRectangle& targetPixelRc, const u32* data); void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc, const TargetRectangle& targetPixelRc, const u32* data);

View File

@ -341,7 +341,7 @@ void VertexManager::vFlush()
tr.right = Renderer::GetTargetWidth(); tr.right = Renderer::GetTargetWidth();
tr.top = 0; tr.top = 0;
tr.bottom = Renderer::GetTargetHeight(); tr.bottom = Renderer::GetTargetHeight();
Renderer::TakeScreenshot(tr, str); g_renderer->SaveScreenshot(str, tr);
} }
#endif #endif
g_Config.iSaveTargetId++; g_Config.iSaveTargetId++;

View File

@ -30,12 +30,6 @@
#include "XFMemory.h" #include "XFMemory.h"
#include "FifoPlayer/FifoRecorder.h" #include "FifoPlayer/FifoRecorder.h"
#include "AVIDump.h" #include "AVIDump.h"
#include "OnScreenDisplay.h"
#if defined(HAVE_WX) && HAVE_WX
#include "WxUtils.h"
#include <wx/image.h>
#endif
#include "ImageWrite.h"
#include <cmath> #include <cmath>
#include <string> #include <string>
@ -73,8 +67,6 @@ unsigned int Renderer::efb_scale_numeratorY = 1;
unsigned int Renderer::efb_scale_denominatorX = 1; unsigned int Renderer::efb_scale_denominatorX = 1;
unsigned int Renderer::efb_scale_denominatorY = 1; unsigned int Renderer::efb_scale_denominatorY = 1;
// TODO: remove
extern bool g_aspect_wide;
Renderer::Renderer() Renderer::Renderer()
: frame_data() : frame_data()
@ -250,72 +242,6 @@ void Renderer::SetScreenshot(const char *filename)
s_bScreenshot = true; s_bScreenshot = true;
} }
#if defined(HAVE_WX) && HAVE_WX
void Renderer::SaveScreenshotOnThread(u8* data, size_t width, size_t height, std::string filename)
{
wxImage *img = new wxImage(width, height, data);
// These will contain the final image size
float FloatW = (float)width;
float FloatH = (float)height;
// Handle aspect ratio for the final ScrStrct to look exactly like what's on screen.
if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH)
{
bool use16_9 = g_aspect_wide;
// Check for force-settings and override.
if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_16_9)
use16_9 = true;
else if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_4_3)
use16_9 = false;
float Ratio = (FloatW / FloatH) / (!use16_9 ? (4.0f / 3.0f) : (16.0f / 9.0f));
// If ratio > 1 the picture is too wide and we have to limit the width.
if (Ratio > 1)
FloatW /= Ratio;
// ratio == 1 or the image is too high, we have to limit the height.
else
FloatH *= Ratio;
// This is a bit expensive on high resolutions
img->Rescale((int)FloatW, (int)FloatH, wxIMAGE_QUALITY_HIGH);
}
// Save the screenshot and finally kill the wxImage object
// This is really expensive when saving to PNG, but not at all when using BMP
img->SaveFile(StrToWxStr(filename), wxBITMAP_TYPE_PNG);
img->Destroy();
// Show success messages
OSD::AddMessage(StringFromFormat("Saved %i x %i %s", (int)FloatW, (int)FloatH,
filename.c_str()), 2000);
}
#endif
void Renderer::SaveScreenshot(u8* ptr, size_t width, size_t height, std::string filename)
{
std::lock_guard<std::mutex> lk(s_criticalScreenshot);
#if defined(HAVE_WX) && HAVE_WX
// Create wxImage
std::thread thread(SaveScreenshotOnThread, ptr, width, height, filename);
#ifdef _WIN32
SetThreadPriority(thread.native_handle(), THREAD_PRIORITY_BELOW_NORMAL);
#endif
thread.detach();
OSD::AddMessage("Saving Screenshot... ", 2000);
#else
SaveTGA(filename.c_str(), width, height, ptr);
free(ptr);
#endif
s_bScreenshot = false;
}
// Create On-Screen-Messages // Create On-Screen-Messages
void Renderer::DrawDebugText() void Renderer::DrawDebugText()
{ {
@ -421,6 +347,9 @@ void Renderer::DrawDebugText()
g_renderer->RenderText(final_yellow.c_str(), 20, 20, 0xFFFFFF00); g_renderer->RenderText(final_yellow.c_str(), 20, 20, 0xFFFFFF00);
} }
// TODO: remove
extern bool g_aspect_wide;
void Renderer::UpdateDrawRectangle(int backbuffer_width, int backbuffer_height) void Renderer::UpdateDrawRectangle(int backbuffer_width, int backbuffer_height)
{ {
float FloatGLWidth = (float)backbuffer_width; float FloatGLWidth = (float)backbuffer_width;

View File

@ -110,6 +110,8 @@ public:
virtual void UpdateViewport() = 0; virtual void UpdateViewport() = 0;
virtual bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc) = 0;
static unsigned int GetPrevPixelFormat() { return prev_efb_format; } static unsigned int GetPrevPixelFormat() { return prev_efb_format; }
static void StorePixelFormat(unsigned int new_format) { prev_efb_format = new_format; } static void StorePixelFormat(unsigned int new_format) { prev_efb_format = new_format; }
@ -121,11 +123,6 @@ protected:
static void CheckFifoRecording(); static void CheckFifoRecording();
static void RecordVideoMemory(); static void RecordVideoMemory();
#if defined(HAVE_WX) && HAVE_WX
static void SaveScreenshotOnThread(u8* data, size_t width, size_t height, std::string filename);
#endif
static void SaveScreenshot(u8* ptr, size_t width, size_t height, std::string filename);
static volatile bool s_bScreenshot; static volatile bool s_bScreenshot;
static std::mutex s_criticalScreenshot; static std::mutex s_criticalScreenshot;
static std::string s_sScreenshotName; static std::string s_sScreenshotName;