2 commits in one:

fix frame dumping and screenshots in d3d9 and opengl
some improvements to the new efb to ram
please test to see if the issues introduced by the new efb to ram are solved by this commit

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5862 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Rodolfo Osvaldo Bogado 2010-07-09 20:56:16 +00:00
parent df32603ba4
commit d0c9a38681
8 changed files with 85 additions and 104 deletions

View File

@ -89,7 +89,7 @@ public:
static void DrawDebugText(); static void DrawDebugText();
static void SetScreenshot(const char *filename); static void SetScreenshot(const char *filename);
static void FlipImageData(u8 *data, int w, int h); static void FlipImageData(u8 *data, int w, int h);
static bool SaveRenderTarget(const char *filename, int w, int h, int YOffset = 0); static bool SaveRenderTarget(const char *filename, TargetRectangle back_rc);
static void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z); static void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
static void RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc); static void RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);

View File

@ -117,7 +117,7 @@ void InitPP(int adapter, int f, int aa_mode, D3DPRESENT_PARAMETERS *pp)
pp->EnableAutoDepthStencil = FALSE; pp->EnableAutoDepthStencil = FALSE;
pp->AutoDepthStencilFormat = D3DFMT_UNKNOWN; pp->AutoDepthStencilFormat = D3DFMT_UNKNOWN;
} }
pp->BackBufferFormat = D3DFMT_A8R8G8B8; pp->BackBufferFormat = D3DFMT_X8R8G8B8;
if (aa_mode >= (int)adapters[adapter].aa_levels.size()) if (aa_mode >= (int)adapters[adapter].aa_levels.size())
aa_mode = 0; aa_mode = 0;

View File

@ -357,7 +357,7 @@ bool Renderer::Init()
D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x0, 1.0f, 0); D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x0, 1.0f, 0);
D3D::BeginFrame(); D3D::BeginFrame();
D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, true); D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, true);
D3D::dev->CreateOffscreenPlainSurface(s_backbuffer_width,s_backbuffer_height, FBManager.GetEFBColorRTSurfaceFormat(), D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL ); D3D::dev->CreateOffscreenPlainSurface(s_backbuffer_width,s_backbuffer_height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL );
return true; return true;
} }
@ -531,6 +531,9 @@ void CheckForResize()
D3D::Reset(); D3D::Reset();
s_backbuffer_width = D3D::GetBackBufferWidth(); s_backbuffer_width = D3D::GetBackBufferWidth();
s_backbuffer_height = D3D::GetBackBufferHeight(); s_backbuffer_height = D3D::GetBackBufferHeight();
if(ScreenShootMEMSurface)
ScreenShootMEMSurface->Release();
D3D::dev->CreateOffscreenPlainSurface(s_backbuffer_width,s_backbuffer_height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL );
WindowResized = true; WindowResized = true;
} }
} }
@ -1082,28 +1085,26 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
if(s_bScreenshot) if(s_bScreenshot)
{ {
s_criticalScreenshot.Enter(); s_criticalScreenshot.Enter();
// create a R8G8B8 surface for the screenshot (no alpha channel) HRESULT hr = D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(),ScreenShootMEMSurface);//, NULL, dst_rect.AsRECT(), D3D::GetBackBufferSurface(), NULL, dst_rect.AsRECT(), D3DX_FILTER_NONE, 0);
// otherwise funky screenshots get saved if(FAILED(hr))
LPDIRECT3DSURFACE9 screenshot_surface;
if (D3D_OK == D3D::dev->CreateOffscreenPlainSurface(s_backbuffer_width, s_backbuffer_height, D3DFMT_R8G8B8, D3DPOOL_SCRATCH, &screenshot_surface, NULL))
{ {
D3DXLoadSurfaceFromSurface(screenshot_surface, NULL, NULL, D3D::GetBackBufferSurface(), NULL, NULL, D3DX_DEFAULT, 0); PanicAlert("Error dumping surface data.");
D3DXSaveSurfaceToFileA(s_sScreenshotName, D3DXIFF_PNG, screenshot_surface, NULL, NULL); }
screenshot_surface->Release(); hr = D3DXSaveSurfaceToFileA(s_sScreenshotName, D3DXIFF_PNG, ScreenShootMEMSurface, NULL, dst_rect.AsRECT());
if(FAILED(hr))
{
PanicAlert("Error saving screen.");
} }
else
PanicAlert("Failed to create surface for screenshot!");
s_bScreenshot = false; s_bScreenshot = false;
s_criticalScreenshot.Leave(); s_criticalScreenshot.Leave();
} }
if (g_ActiveConfig.bDumpFrames) if (g_ActiveConfig.bDumpFrames)
{ {
D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(), ScreenShootMEMSurface); HRESULT hr = D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(),ScreenShootMEMSurface);
if (!s_LastFrameDumped) if (!s_LastFrameDumped)
{ {
s_recordWidth = s_backbuffer_width; s_recordWidth = dst_rect.GetWidth();
s_recordHeight = s_backbuffer_height; s_recordHeight = dst_rect.GetHeight();
s_AVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight); s_AVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight);
if (!s_AVIDumping) if (!s_AVIDumping)
{ {
@ -1119,7 +1120,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
if (s_AVIDumping) if (s_AVIDumping)
{ {
D3DLOCKED_RECT rect; D3DLOCKED_RECT rect;
if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, NULL, D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY))) if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, dst_rect.AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY)))
{ {
char* data = (char*)malloc(3 * s_recordWidth * s_recordHeight); char* data = (char*)malloc(3 * s_recordWidth * s_recordHeight);
formatBufferDump((const char*)rect.pBits, data, s_recordWidth, s_recordHeight, rect.Pitch); formatBufferDump((const char*)rect.pBits, data, s_recordWidth, s_recordHeight, rect.Pitch);

View File

@ -111,14 +111,7 @@ void TextureCache::MakeRangeDynamic(u32 start_address, u32 size)
int rangePosition = iter->second.IntersectsMemoryRange(start_address, size); int rangePosition = iter->second.IntersectsMemoryRange(start_address, size);
if ( rangePosition == 0) if ( rangePosition == 0)
{ {
if(iter->second.addr != start_address) iter->second.hash = 0;
{
if(!iter->second.isRenderTarget)
{
iter->second.isDinamic = true;
}
iter->second.hash = 0;
}
} }
else else
{ {
@ -223,11 +216,15 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
if (!g_ActiveConfig.bSafeTextureCache) if (!g_ActiveConfig.bSafeTextureCache)
{ {
if(entry.isRenderTarget) if(entry.isRenderTarget || entry.isDinamic)
{ {
if(!g_ActiveConfig.bCopyEFBToTexture && g_ActiveConfig.bVerifyTextureModificationsByCPU) if(!g_ActiveConfig.bCopyEFBToTexture && g_ActiveConfig.bVerifyTextureModificationsByCPU)
{ {
hash_value = TexDecoder_GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples); hash_value = TexDecoder_GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
{
hash_value ^= TexDecoder_GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
}
} }
else else
{ {
@ -239,9 +236,17 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
hash_value = ((u32 *)ptr)[0]; hash_value = ((u32 *)ptr)[0];
} }
} }
else
{
if ((entry.isRenderTarget && hash_value == entry.hash && address == entry.addr) if(entry.isRenderTarget || entry.isDinamic)
{
if(g_ActiveConfig.bCopyEFBToTexture || !g_ActiveConfig.bVerifyTextureModificationsByCPU)
{
hash_value = 0;
}
}
}
if (((entry.isRenderTarget || entry.isDinamic) && hash_value == entry.hash && address == entry.addr)
|| ((address == entry.addr) || ((address == entry.addr)
&& (hash_value == entry.hash) && (hash_value == entry.hash)
&& FullFormat == entry.fmt/* && entry.MipLevels == maxlevel*/)) && FullFormat == entry.fmt/* && entry.MipLevels == maxlevel*/))
@ -255,7 +260,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
// Let's reload the new texture data into the same texture, // Let's reload the new texture data into the same texture,
// instead of destroying it and having to create a new one. // instead of destroying it and having to create a new one.
// Might speed up movie playback very, very slightly. // Might speed up movie playback very, very slightly.
TextureIsDinamic = true; TextureIsDinamic = (entry.isRenderTarget || entry.isDinamic) && !g_ActiveConfig.bCopyEFBToTexture;
if (!entry.isRenderTarget && if (!entry.isRenderTarget &&
((!entry.isDinamic && width == entry.w && height==entry.h && FullFormat == entry.fmt /* && entry.MipLevels < maxlevel*/) ((!entry.isDinamic && width == entry.w && height==entry.h && FullFormat == entry.fmt /* && entry.MipLevels < maxlevel*/)
@ -329,7 +334,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
} }
entry.oldpixel = ((u32 *)ptr)[0]; entry.oldpixel = ((u32 *)ptr)[0];
if (g_ActiveConfig.bSafeTextureCache) if (g_ActiveConfig.bSafeTextureCache || entry.isDinamic)
entry.hash = hash_value; entry.hash = hash_value;
else else
{ {
@ -464,7 +469,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
{ {
TCacheEntry entry; TCacheEntry entry;
entry.addr = address; entry.addr = address;
entry.isRenderTarget = !TextureIsDinamic; entry.isRenderTarget = true;
entry.hash = 0; entry.hash = 0;
entry.frameCount = frameCount; entry.frameCount = frameCount;
entry.w = tex_w; entry.w = tex_w;
@ -484,7 +489,6 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
// We have to run a pixel shader, for color conversion. // We have to run a pixel shader, for color conversion.
Renderer::ResetAPIState(); // reset any game specific settings Renderer::ResetAPIState(); // reset any game specific settings
if(!TextureIsDinamic || g_ActiveConfig.bCopyEFBToTexture) if(!TextureIsDinamic || g_ActiveConfig.bCopyEFBToTexture)
{ {
@ -662,7 +666,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
if(!g_ActiveConfig.bCopyEFBToTexture) if(!g_ActiveConfig.bCopyEFBToTexture)
{ {
TextureConverter::EncodeToRamFromTexture( textures[address].hash = TextureConverter::EncodeToRamFromTexture(
address, address,
read_texture, read_texture,
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetWidth(),
@ -676,22 +680,6 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
copyfmt, copyfmt,
bScaleByHalf, bScaleByHalf,
source_rect); source_rect);
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address);
int bsw = TexDecoder_GetBlockWidthInTexels(copyfmt) - 1;
int bsh = TexDecoder_GetBlockHeightInTexels(copyfmt) - 1;
int expandedWidth = (tex_w + bsw) & (~bsw);
int expandedHeight = (tex_h + bsh) & (~bsh);
u32 textureSize = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, copyfmt);
MakeRangeDynamic(address,textureSize);
if(g_ActiveConfig.bVerifyTextureModificationsByCPU)
{
textures[address].hash = TexDecoder_GetHash64(ptr,textureSize,g_ActiveConfig.iSafeTextureCache_ColorSamples);
}
else
{
textures[address].hash = 0;
}
} }
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);

View File

@ -389,7 +389,7 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
Renderer::RestoreAPIState(); Renderer::RestoreAPIState();
} }
void EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 SourceW, u32 SourceH,float MValueX,float MValueY,float Xstride, float Ystride , bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 SourceW, u32 SourceH,float MValueX,float MValueY,float Xstride, float Ystride , bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
{ {
u32 format = copyfmt; u32 format = copyfmt;
@ -407,7 +407,7 @@ void EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 So
LPDIRECT3DPIXELSHADER9 texconv_shader = GetOrCreateEncodingShader(format); LPDIRECT3DPIXELSHADER9 texconv_shader = GetOrCreateEncodingShader(format);
if (!texconv_shader) if (!texconv_shader)
return; return 0;
u8 *dest_ptr = Memory_GetPtr(address); u8 *dest_ptr = Memory_GetPtr(address);
@ -448,6 +448,13 @@ void EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 So
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight,readStride, true, bScaleByHalf > 0); EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight,readStride, true, bScaleByHalf > 0);
TextureCache::MakeRangeDynamic(address,size_in_bytes);
u64 Hashvalue = 0;
if(g_ActiveConfig.bVerifyTextureModificationsByCPU)
{
Hashvalue = TexDecoder_GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples);
}
return Hashvalue;
} }

View File

@ -40,7 +40,7 @@ void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourc
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture); void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture);
void EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 SourceW, u32 SourceH,float MValueX,float MValueY,float Xstride, float Ystride , bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 SourceW, u32 SourceH,float MValueX,float MValueY,float Xstride, float Ystride , bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
} }

View File

@ -114,8 +114,6 @@ static int m_CustomHeight;
static int m_FrameBufferWidth; static int m_FrameBufferWidth;
static int m_FrameBufferHeight; static int m_FrameBufferHeight;
static GLuint s_tempScreenshotFramebuffer = 0;
static unsigned int s_XFB_width; static unsigned int s_XFB_width;
static unsigned int s_XFB_height; static unsigned int s_XFB_height;
@ -485,9 +483,6 @@ void Renderer::Shutdown(void)
cgDestroyContext(g_cgcontext); cgDestroyContext(g_cgcontext);
g_cgcontext = 0; g_cgcontext = 0;
} }
if(s_tempScreenshotFramebuffer)
glDeleteFramebuffersEXT(1, &s_tempScreenshotFramebuffer);
s_tempScreenshotFramebuffer = 0;
g_framebufferManager.Shutdown(); g_framebufferManager.Shutdown();
@ -1031,41 +1026,25 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
// Save screenshot // Save screenshot
if (s_bScreenshot) if (s_bScreenshot)
{ {
if (!s_tempScreenshotFramebuffer)
glGenFramebuffersEXT(1, &s_tempScreenshotFramebuffer);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, s_tempScreenshotFramebuffer);
glFramebufferTexture2DEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, xfbSource->texture, 0);
s_criticalScreenshot.Enter(); s_criticalScreenshot.Enter();
// Save screenshot // Save screenshot
SaveRenderTarget(s_sScreenshotName.c_str(), xfbSource->sourceRc.GetWidth(), xfbSource->sourceRc.GetHeight()); SaveRenderTarget(s_sScreenshotName.c_str(), back_rc);
// Reset settings // Reset settings
s_sScreenshotName = ""; s_sScreenshotName = "";
s_bScreenshot = false; s_bScreenshot = false;
s_criticalScreenshot.Leave(); s_criticalScreenshot.Leave();
glFramebufferTexture2DEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, g_framebufferManager.GetEFBFramebuffer());
} }
// Frame dumps are handled a little differently in Windows // Frame dumps are handled a little differently in Windows
#ifdef _WIN32 #ifdef _WIN32
if (g_ActiveConfig.bDumpFrames) if (g_ActiveConfig.bDumpFrames)
{ {
if (!s_tempScreenshotFramebuffer)
glGenFramebuffersEXT(1, &s_tempScreenshotFramebuffer);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, s_tempScreenshotFramebuffer);
glFramebufferTexture2DEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, xfbSource->texture, 0);
s_criticalScreenshot.Enter(); s_criticalScreenshot.Enter();
int w = xfbSource->sourceRc.GetWidth(); int w = back_rc.GetWidth();
int h = xfbSource->sourceRc.GetHeight(); int h = back_rc.GetHeight();
u8 *data = (u8 *) malloc(3 * w * h); u8 *data = (u8 *) malloc(3 * w * h);
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, Renderer::GetTargetHeight() - h, w, h, GL_BGR, GL_UNSIGNED_BYTE, data); glReadPixels(back_rc.left, back_rc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, data);
if (glGetError() == GL_NO_ERROR && w > 0 && h > 0) if (glGetError() == GL_NO_ERROR && w > 0 && h > 0)
{ {
if (!s_bLastFrameDumped) if (!s_bLastFrameDumped)
@ -1090,9 +1069,6 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
} }
free(data); free(data);
s_criticalScreenshot.Leave(); s_criticalScreenshot.Leave();
glFramebufferTexture2DEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, g_framebufferManager.GetEFBFramebuffer());
} }
else else
{ {
@ -1108,11 +1084,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
if (g_ActiveConfig.bDumpFrames) { if (g_ActiveConfig.bDumpFrames) {
s_criticalScreenshot.Enter(); s_criticalScreenshot.Enter();
char movie_file_name[255]; char movie_file_name[255];
int w = OpenGL_GetBackbufferWidth(); int w = back_rc.GetWidth();
int h = OpenGL_GetBackbufferHeight(); int h = back_rc.GetHeight();
u8 *data = (u8 *) malloc(3 * w * h); u8 *data = (u8 *) malloc(3 * w * h);
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, Renderer::GetTargetHeight() - h, w, h, GL_RGB, GL_UNSIGNED_BYTE, data); glReadPixels(back_rc.left, back_rc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, data);
if (glGetError() == GL_NO_ERROR) { if (glGetError() == GL_NO_ERROR) {
if (!s_bLastFrameDumped) { if (!s_bLastFrameDumped) {
sprintf(movie_file_name, "%sframedump.raw", File::GetUserPath(D_DUMPFRAMES_IDX)); sprintf(movie_file_name, "%sframedump.raw", File::GetUserPath(D_DUMPFRAMES_IDX));
@ -1509,12 +1485,28 @@ THREAD_RETURN TakeScreenshot(void *pArgs)
} }
#endif #endif
bool Renderer::SaveRenderTarget(const char *filename, int W, int H, int YOffset) void Renderer::FlipImageData(u8 *data, int w, int h)
{ {
// Flip image upside down. Damn OpenGL.
for (int y = 0; y < h / 2; y++)
{
for(int x = 0; x < w; x++)
{
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]);
}
}
}
bool Renderer::SaveRenderTarget(const char *filename, TargetRectangle back_rc)
{
u32 W = back_rc.GetWidth();
u32 H = back_rc.GetHeight();
u8 *data = (u8 *)malloc(3 * W * H); u8 *data = (u8 *)malloc(3 * W * H);
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, Renderer::GetTargetHeight() - H + YOffset, W, H, GL_RGB, GL_UNSIGNED_BYTE, data); glReadPixels(back_rc.left, back_rc.bottom, W, H, GL_RGB, GL_UNSIGNED_BYTE, data);
// Show failure message // Show failure message
if (glGetError() != GL_NO_ERROR) if (glGetError() != GL_NO_ERROR)
@ -1558,19 +1550,7 @@ bool Renderer::SaveRenderTarget(const char *filename, int W, int H, int YOffset)
} }
void Renderer::FlipImageData(u8 *data, int w, int h)
{
// Flip image upside down. Damn OpenGL.
for (int y = 0; y < h / 2; y++)
{
for(int x = 0; x < w; x++)
{
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]);
}
}
}
// Called from VertexShaderManager // Called from VertexShaderManager
void UpdateViewport() void UpdateViewport()

View File

@ -360,7 +360,12 @@ void Flush()
{ {
char str[128]; char str[128];
sprintf(str, "%starg%.3d.tga", File::GetUserPath(D_DUMPFRAMES_IDX), g_ActiveConfig.iSaveTargetId); sprintf(str, "%starg%.3d.tga", File::GetUserPath(D_DUMPFRAMES_IDX), g_ActiveConfig.iSaveTargetId);
Renderer::SaveRenderTarget(str, Renderer::GetTargetWidth(), Renderer::GetTargetHeight()); TargetRectangle tr;
tr.left = 0;
tr.right = Renderer::GetTargetWidth();
tr.top = 0;
tr.bottom = Renderer::GetTargetHeight();
Renderer::SaveRenderTarget(str, tr);
} }
#endif #endif
g_Config.iSaveTargetId++; g_Config.iSaveTargetId++;