Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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 00fe505, 74b5fb3, cd46138 and 5f72542 because taking screenshots in D3D still crashed for me so there was no point in the code changes (which I found ugly anyway).
  • Loading branch information
neobrain committed Nov 9, 2013
1 parent 3de2ee5 commit 0b02880
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 111 deletions.
36 changes: 22 additions & 14 deletions Source/Core/VideoBackends/D3D/Src/Render.cpp
Expand Up @@ -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)
CreateScreenshotTexture(rc);
Expand All @@ -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);
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;
D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map);
u8* src = (u8*) map.pData;
for (int y = 0; y < rc.GetHeight(); ++y)
for (unsigned int y = 0; y < rc.GetHeight(); ++y)
{
u8* __restrict row = src;
for (int x = 0; x < rc.GetWidth(); ++x)
u8* ptr = (u8*)map.pData + y * map.RowPitch + 3;
for (unsigned int x = 0; x < rc.GetWidth(); ++x)
{
*dest++ = *row++;
*dest++ = *row++;
*dest++ = *row++;
row++;
*ptr = 0xFF;
ptr += 4;
}
src += map.RowPitch;
}
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)
Expand Down Expand Up @@ -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
if (s_bScreenshot)
{
TakeScreenshot(GetTargetRectangle(), s_sScreenshotName);
SaveScreenshot(s_sScreenshotName, GetTargetRectangle());
s_bScreenshot = false;
}

Expand Down
3 changes: 1 addition & 2 deletions Source/Core/VideoBackends/D3D/Src/Render.h
Expand Up @@ -48,10 +48,9 @@ class Renderer : public ::Renderer

void UpdateViewport();

static void TakeScreenshot(const TargetRectangle &rc, std::string filename);
bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc);

static bool CheckForResize();

};

}
Expand Down
130 changes: 117 additions & 13 deletions Source/Core/VideoBackends/OGL/Src/Render.cpp
Expand Up @@ -11,6 +11,9 @@
#include <cstdio>

#include "GLUtil.h"
#if defined(HAVE_WX) && HAVE_WX
#include "WxUtils.h"
#endif

#include "FileUtil.h"

Expand All @@ -22,6 +25,7 @@
#include "DriverDetails.h"
#include "VideoConfig.h"
#include "Statistics.h"
#include "ImageWrite.h"
#include "PixelEngine.h"
#include "Render.h"
#include "BPStructs.h"
Expand Down Expand Up @@ -58,6 +62,10 @@
#include "AVIDump.h"
#endif

#if defined(HAVE_WX) && HAVE_WX
#include <wx/image.h>
#endif

// glew1.8 doesn't define KHR_debug
#ifndef GL_DEBUG_OUTPUT
#define GL_DEBUG_OUTPUT 0x92E0
Expand All @@ -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;

namespace OGL
Expand Down Expand Up @@ -108,6 +127,10 @@ static u32 s_blendMode;

static bool s_vsync;

#if defined(HAVE_WX) && HAVE_WX
static std::thread scrshotThread;
#endif

// EFB cache related
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
Expand Down Expand Up @@ -616,6 +639,11 @@ Renderer::Renderer()

Renderer::~Renderer()
{

#if defined(HAVE_WX) && HAVE_WX
if (scrshotThread.joinable())
scrshotThread.join();
#endif
}

void Renderer::Shutdown()
Expand Down Expand Up @@ -1391,9 +1419,11 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r
// Save screenshot
if (s_bScreenshot)
{
TakeScreenshot(flipped_trc, s_sScreenshotName);
s_bScreenshot = false;
std::lock_guard<std::mutex> lk(s_criticalScreenshot);
SaveScreenshot(s_sScreenshotName, flipped_trc);
// Reset settings
s_sScreenshotName.clear();
s_bScreenshot = false;
}

// Frame dumps are handled a little differently in Windows
Expand Down Expand Up @@ -1771,22 +1801,71 @@ void Renderer::SetInterlacingMode()

void Renderer::FlipImageData(u8 *data, int w, int h)
{
// XXX make this faster
u8* __restrict top = data;
u8* bot = data + w * h * 3;
// Flip image upside down. Damn OpenGL.
for (int y = 0; y < h / 2; y++)
{
size_t stride = w * 3;
bot -= stride;
u8* __restrict brow = bot;
for(size_t x = 0; x < stride; x++)
for(int x = 0; x < w; 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 H = back_rc.GetHeight();
Expand All @@ -1800,13 +1879,38 @@ void Renderer::TakeScreenshot(const TargetRectangle &back_rc, std::string filena
{
free(data);
OSD::AddMessage("Error capturing or saving screenshot.", 2000);
return;
return false;
}

// Turn image upside down
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;
}

}
4 changes: 2 additions & 2 deletions Source/Core/VideoBackends/OGL/Src/Render.h
Expand Up @@ -63,7 +63,7 @@ class Renderer : public ::Renderer

void RenderText(const char* pstr, int left, int top, u32 color) override;
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;

Expand All @@ -80,7 +80,7 @@ class Renderer : public ::Renderer

void UpdateViewport() override;

static void TakeScreenshot(const TargetRectangle &rc, std::string filename);
bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc);

private:
void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc, const TargetRectangle& targetPixelRc, const u32* data);
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/VideoBackends/OGL/Src/VertexManager.cpp
Expand Up @@ -341,7 +341,7 @@ void VertexManager::vFlush()
tr.right = Renderer::GetTargetWidth();
tr.top = 0;
tr.bottom = Renderer::GetTargetHeight();
Renderer::TakeScreenshot(tr, str);
g_renderer->SaveScreenshot(str, tr);
}
#endif
g_Config.iSaveTargetId++;
Expand Down

0 comments on commit 0b02880

Please sign in to comment.