fixed shutdown and screenshot functionallity

This commit is contained in:
Magnus Auvinen 2012-01-01 14:15:35 +01:00
parent c1942ca6cb
commit d7fe3ddaab
2 changed files with 98 additions and 51 deletions

View file

@ -203,6 +203,43 @@ class CCommandProcessorFragment_OpenGL
};
}
void Cmd_Screenshot(const CCommandBuffer::SCommand_Screenshot *pCommand)
{
// fetch image data
GLint aViewport[4] = {0,0,0,0};
glGetIntegerv(GL_VIEWPORT, aViewport);
int w = aViewport[2];
int h = aViewport[3];
dbg_msg("graphics", "grabbing %d x %d", w, h);
// we allocate one more row to use when we are flipping the texture
unsigned char *pPixelData = (unsigned char *)mem_alloc(w*(h+1)*3, 1);
unsigned char *pTempRow = pPixelData+w*h*3;
// fetch the pixels
GLint Alignment;
glGetIntegerv(GL_PACK_ALIGNMENT, &Alignment);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pPixelData);
glPixelStorei(GL_PACK_ALIGNMENT, Alignment);
// flip the pixel because opengl works from bottom left corner
for(int y = 0; y < h/2; y++)
{
mem_copy(pTempRow, pPixelData+y*w*3, w*3);
mem_copy(pPixelData+y*w*3, pPixelData+(h-y-1)*w*3, w*3);
mem_copy(pPixelData+(h-y-1)*w*3, pTempRow,w*3);
}
// fill in the information
pCommand->m_pImage->m_Width = w;
pCommand->m_pImage->m_Height = h;
pCommand->m_pImage->m_Format = CImageInfo::FORMAT_RGB;
pCommand->m_pImage->m_pData = pPixelData;
}
public:
CCommandProcessorFragment_OpenGL()
{
@ -218,6 +255,7 @@ public:
case CCommandBuffer::CMD_TEXTURE_UPDATE: Cmd_Texture_Update(static_cast<const CCommandBuffer::SCommand_Texture_Update *>(pBaseCommand)); break;
case CCommandBuffer::CMD_CLEAR: Cmd_Clear(static_cast<const CCommandBuffer::SCommand_Clear *>(pBaseCommand)); break;
case CCommandBuffer::CMD_RENDER: Cmd_Render(static_cast<const CCommandBuffer::SCommand_Render *>(pBaseCommand)); break;
case CCommandBuffer::CMD_SCREENSHOT: Cmd_Screenshot(static_cast<const CCommandBuffer::SCommand_Screenshot *>(pBaseCommand)); break;
default: return false;
}
@ -415,6 +453,14 @@ void CCommandProcessorHandler::Start(ICommandProcessor *pProcessor)
m_BufferDone.signal();
}
void CCommandProcessorHandler::Stop()
{
m_Shutdown = true;
m_Activity.signal();
thread_wait(m_pThread);
thread_destroy(m_pThread);
}
void CCommandProcessorHandler::RunBuffer(CCommandBuffer *pBuffer)
{
WaitForIdle();
@ -428,7 +474,7 @@ void CCommandProcessorHandler::WaitForIdle()
m_BufferDone.wait();
}
void CGraphics_Threaded::Flush()
void CGraphics_Threaded::FlushVertices()
{
if(m_NumVertices == 0)
return;
@ -464,7 +510,7 @@ void CGraphics_Threaded::AddVertices(int Count)
{
m_NumVertices += Count;
if((m_NumVertices + Count) >= MAX_VERTICES)
Flush();
FlushVertices();
}
void CGraphics_Threaded::Rotate4(const CCommandBuffer::SPoint &rCenter, CCommandBuffer::SVertex *pPoints)
@ -622,7 +668,7 @@ void CGraphics_Threaded::LinesBegin()
void CGraphics_Threaded::LinesEnd()
{
dbg_assert(m_Drawing == DRAWING_LINES, "called Graphics()->LinesEnd without begin");
Flush();
FlushVertices();
m_Drawing = 0;
}
@ -828,34 +874,33 @@ int CGraphics_Threaded::LoadPNG(CImageInfo *pImg, const char *pFilename, int Sto
return 1;
}
void CGraphics_Threaded::KickCommandBuffer()
{
m_Handler.RunBuffer(m_pCommandBuffer);
// swap buffer
m_CurrentCommandBuffer ^= 1;
m_pCommandBuffer = m_apCommandBuffers[m_CurrentCommandBuffer];
m_pCommandBuffer->Reset();
}
void CGraphics_Threaded::ScreenshotDirect(const char *pFilename)
{
// TODO: screenshot support
return;
// add swap command
CImageInfo Image;
mem_zero(&Image, sizeof(Image));
/*
// fetch image data
int y;
int w = m_ScreenWidth;
int h = m_ScreenHeight;
unsigned char *pPixelData = (unsigned char *)mem_alloc(w*(h+1)*3, 1);
unsigned char *pTempRow = pPixelData+w*h*3;
GLint Alignment;
glGetIntegerv(GL_PACK_ALIGNMENT, &Alignment);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pPixelData);
glPixelStorei(GL_PACK_ALIGNMENT, Alignment);
CCommandBuffer::SCommand_Screenshot Cmd;
Cmd.m_pImage = &Image;
m_pCommandBuffer->AddCommand(Cmd);
// flip the pixel because opengl works from bottom left corner
for(y = 0; y < h/2; y++)
{
mem_copy(pTempRow, pPixelData+y*w*3, w*3);
mem_copy(pPixelData+y*w*3, pPixelData+(h-y-1)*w*3, w*3);
mem_copy(pPixelData+(h-y-1)*w*3, pTempRow,w*3);
}
// find filename
// kick the buffer and wait for the result
KickCommandBuffer();
WaitForIdle();
if(Image.m_pData)
{
// find filename
char aWholePath[1024];
png_t Png; // ignore_convention
@ -868,13 +913,11 @@ void CGraphics_Threaded::ScreenshotDirect(const char *pFilename)
str_format(aBuf, sizeof(aBuf), "saved screenshot to '%s'", aWholePath);
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf);
png_open_file_write(&Png, aWholePath); // ignore_convention
png_set_data(&Png, w, h, 8, PNG_TRUECOLOR, (unsigned char *)pPixelData); // ignore_convention
png_set_data(&Png, Image.m_Width, Image.m_Height, 8, PNG_TRUECOLOR, (unsigned char *)Image.m_pData); // ignore_convention
png_close_file(&Png); // ignore_convention
}
// clean up
mem_free(pPixelData);
*/
mem_free(Image.m_pData);
}
}
void CGraphics_Threaded::TextureSet(int TextureID)
@ -906,7 +949,7 @@ void CGraphics_Threaded::QuadsBegin()
void CGraphics_Threaded::QuadsEnd()
{
dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsEnd without begin");
Flush();
FlushVertices();
m_Drawing = 0;
}
@ -1154,8 +1197,8 @@ bool CGraphics_Threaded::Init()
m_aTextures[MAX_TEXTURES-1].m_Next = -1;
// start the command processor
ICommandProcessor *pProcessor = new CCommandProcessor_SDL_OpenGL;
m_Handler.Start(pProcessor);
m_pProcessor = new CCommandProcessor_SDL_OpenGL;
m_Handler.Start(m_pProcessor);
// create command buffers
m_apCommandBuffers[0] = new CCommandBuffer(1024*512, 1024*1024);
@ -1184,9 +1227,16 @@ bool CGraphics_Threaded::Init()
void CGraphics_Threaded::Shutdown()
{
// TODO: SDL, is this correct?
//
// add swap command
CCommandBuffer::SCommand_Shutdown Cmd;
m_pCommandBuffer->AddCommand(Cmd);
m_Handler.RunBuffer(m_pCommandBuffer);
// wait for everything to process and then stop the command processor
m_Handler.WaitForIdle();
m_Handler.Stop();
delete m_pProcessor;
m_pProcessor = 0;
}
void CGraphics_Threaded::Minimize()
@ -1213,34 +1263,27 @@ int CGraphics_Threaded::WindowOpen()
void CGraphics_Threaded::TakeScreenshot(const char *pFilename)
{
// TODO: screenshot support
return;
/*
char aDate[20];
str_timestamp(aDate, sizeof(aDate));
str_format(m_aScreenshotName, sizeof(m_aScreenshotName), "screenshots/%s_%s.png", pFilename?pFilename:"screenshot", aDate);
m_DoScreenshot = true;
*/
}
void CGraphics_Threaded::Swap()
{
// TODO: screenshot support
/*
if(m_DoScreenshot)
{
ScreenshotDirect(m_aScreenshotName);
m_DoScreenshot = false;
}*/
}
// add swap command
CCommandBuffer::SCommand_Swap Cmd;
m_pCommandBuffer->AddCommand(Cmd);
m_Handler.RunBuffer(m_pCommandBuffer);
// swap buffer
m_CurrentCommandBuffer ^= 1;
m_pCommandBuffer = m_apCommandBuffers[m_CurrentCommandBuffer];
m_pCommandBuffer->Reset();
// kick the command buffer
KickCommandBuffer();
}
// syncronization

View file

@ -124,7 +124,7 @@ public:
SPoint m_Pos;
STexCoord m_Tex;
SColor m_Color;
} ;
};
struct SCommand
{
@ -198,8 +198,7 @@ public:
struct SCommand_Screenshot : public SCommand
{
SCommand_Screenshot() : SCommand(CMD_SCREENSHOT) {}
CImageInfo *m_pImage; // processor will fill this out
CImageInfo *m_pImage; // processor will fill this out, the one who adds this command must free the data as well
};
struct SCommand_Swap : public SCommand
@ -307,6 +306,8 @@ class CCommandProcessorHandler
public:
CCommandProcessorHandler();
void Start(ICommandProcessor *pProcessor);
void Stop();
void RunBuffer(CCommandBuffer *pBuffer);
bool IsIdle() const { return m_pBuffer == 0; }
void WaitForIdle();
@ -316,6 +317,7 @@ class CGraphics_Threaded : public IEngineGraphics
{
CCommandBuffer::SState m_State;
CCommandProcessorHandler m_Handler;
ICommandProcessor *m_pProcessor;
CCommandBuffer *m_apCommandBuffers[2];
CCommandBuffer *m_pCommandBuffer;
@ -361,13 +363,15 @@ class CGraphics_Threaded : public IEngineGraphics
int m_FirstFreeTexture;
int m_TextureMemoryUsage;
void Flush();
void FlushVertices();
void AddVertices(int Count);
void Rotate4(const CCommandBuffer::SPoint &rCenter, CCommandBuffer::SVertex *pPoints);
static unsigned char Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp);
static unsigned char *Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData);
void KickCommandBuffer();
int IssueInit();
int InitWindow();
public: