1
0
forked from 0ad/0ad

Moves glReadPixels to GL backend.

This was SVN commit r26802.
This commit is contained in:
Vladislav Belov 2022-04-17 14:55:00 +00:00
parent 5de50c447c
commit 7bd075d570
4 changed files with 36 additions and 30 deletions

View File

@ -413,7 +413,7 @@ void CRenderer::RenderFrame(const bool needsPresent)
if (m_ShouldPreloadResourcesBeforeNextFrame) if (m_ShouldPreloadResourcesBeforeNextFrame)
{ {
m_ShouldPreloadResourcesBeforeNextFrame = false; m_ShouldPreloadResourcesBeforeNextFrame = false;
// We don't meed to render logger for the preload. // We don't need to render logger for the preload.
RenderFrameImpl(true, false); RenderFrameImpl(true, false);
} }
@ -421,12 +421,13 @@ void CRenderer::RenderFrame(const bool needsPresent)
{ {
RenderBigScreenShot(needsPresent); RenderBigScreenShot(needsPresent);
} }
else if (m_ScreenShotType == ScreenShotType::DEFAULT)
{
RenderScreenShot(needsPresent);
}
else else
{ {
if (m_ScreenShotType == ScreenShotType::DEFAULT) RenderFrameImpl(true, true);
RenderScreenShot();
else
RenderFrameImpl(true, true);
m->deviceCommandContext->Flush(); m->deviceCommandContext->Flush();
if (needsPresent) if (needsPresent)
@ -541,7 +542,7 @@ void CRenderer::RenderFrame2D(const bool renderGUI, const bool renderLogger)
} }
} }
void CRenderer::RenderScreenShot() void CRenderer::RenderScreenShot(const bool needsPresent)
{ {
m_ScreenShotType = ScreenShotType::NONE; m_ScreenShotType = ScreenShotType::NONE;
@ -551,23 +552,25 @@ void CRenderer::RenderScreenShot()
VfsPath filename; VfsPath filename;
vfs::NextNumberedFilename(g_VFS, filenameFormat, g_NextScreenShotNumber, filename); vfs::NextNumberedFilename(g_VFS, filenameFormat, g_NextScreenShotNumber, filename);
const size_t w = (size_t)g_xres, h = (size_t)g_yres; const size_t width = static_cast<size_t>(g_xres), height = static_cast<size_t>(g_yres);
const size_t bpp = 24; const size_t bpp = 24;
GLenum fmt = GL_RGB;
int flags = TEX_BOTTOM_UP;
// Hide log messages and re-render // Hide log messages and re-render
RenderFrameImpl(true, false); RenderFrameImpl(true, false);
const size_t img_size = w * h * bpp / 8; const size_t img_size = width * height * bpp / 8;
const size_t hdr_size = tex_hdr_size(filename); const size_t hdr_size = tex_hdr_size(filename);
std::shared_ptr<u8> buf; std::shared_ptr<u8> buf;
AllocateAligned(buf, hdr_size + img_size, maxSectorSize); AllocateAligned(buf, hdr_size + img_size, maxSectorSize);
GLvoid* img = buf.get() + hdr_size; void* img = buf.get() + hdr_size;
Tex t; Tex t;
if (t.wrap(w, h, bpp, flags, buf, hdr_size) < 0) if (t.wrap(width, height, bpp, TEX_BOTTOM_UP, buf, hdr_size) < 0)
return; return;
glReadPixels(0, 0, (GLsizei)w, (GLsizei)h, fmt, GL_UNSIGNED_BYTE, img);
m->deviceCommandContext->ReadbackFramebufferSync(0, 0, width, height, img);
m->deviceCommandContext->Flush();
if (needsPresent)
g_VideoMode.GetBackendDevice()->Present();
if (tex_write(&t, filename) == INFO::OK) if (tex_write(&t, filename) == INFO::OK)
{ {
@ -590,7 +593,7 @@ void CRenderer::RenderBigScreenShot(const bool needsPresent)
// If the game hasn't started yet then use WriteScreenshot to generate the image. // If the game hasn't started yet then use WriteScreenshot to generate the image.
if (!g_Game) if (!g_Game)
return RenderScreenShot(); return RenderScreenShot(needsPresent);
int tiles = 4, tileWidth = 256, tileHeight = 256; int tiles = 4, tileWidth = 256, tileHeight = 256;
CFG_GET_VAL("screenshot.tiles", tiles); CFG_GET_VAL("screenshot.tiles", tiles);
@ -614,15 +617,6 @@ void CRenderer::RenderBigScreenShot(const bool needsPresent)
const int imageWidth = tileWidth * tiles, imageHeight = tileHeight * tiles; const int imageWidth = tileWidth * tiles, imageHeight = tileHeight * tiles;
const int bpp = 24; const int bpp = 24;
// we want writing BMP to be as fast as possible,
// so read data from OpenGL in BMP format to obviate conversion.
#if CONFIG2_GLES // GLES doesn't support BGR
const GLenum fmt = GL_RGB;
const int flags = TEX_BOTTOM_UP;
#else
const GLenum fmt = GL_BGR;
const int flags = TEX_BOTTOM_UP | TEX_BGR;
#endif
const size_t imageSize = imageWidth * imageHeight * bpp / 8; const size_t imageSize = imageWidth * imageHeight * bpp / 8;
const size_t tileSize = tileWidth * tileHeight * bpp / 8; const size_t tileSize = tileWidth * tileHeight * bpp / 8;
@ -638,7 +632,7 @@ void CRenderer::RenderBigScreenShot(const bool needsPresent)
Tex t; Tex t;
GLvoid* img = imageBuffer.get() + headerSize; GLvoid* img = imageBuffer.get() + headerSize;
if (t.wrap(imageWidth, imageHeight, bpp, flags, imageBuffer, headerSize) < 0) if (t.wrap(imageWidth, imageHeight, bpp, TEX_BOTTOM_UP, imageBuffer, headerSize) < 0)
{ {
free(tileData); free(tileData);
return; return;
@ -672,18 +666,18 @@ void CRenderer::RenderBigScreenShot(const bool needsPresent)
RenderFrameImpl(false, false); RenderFrameImpl(false, false);
m->deviceCommandContext->ReadbackFramebufferSync(0, 0, tileWidth, tileHeight, tileData);
m->deviceCommandContext->Flush();
if (needsPresent)
g_VideoMode.GetBackendDevice()->Present();
// Copy the tile pixels into the main image // Copy the tile pixels into the main image
glReadPixels(0, 0, tileWidth, tileHeight, fmt, GL_UNSIGNED_BYTE, tileData);
for (int y = 0; y < tileHeight; ++y) for (int y = 0; y < tileHeight; ++y)
{ {
void* dest = static_cast<char*>(img) + ((tileY * tileHeight + y) * imageWidth + (tileX * tileWidth)) * bpp / 8; void* dest = static_cast<char*>(img) + ((tileY * tileHeight + y) * imageWidth + (tileX * tileWidth)) * bpp / 8;
void* src = static_cast<char*>(tileData) + y * tileWidth * bpp / 8; void* src = static_cast<char*>(tileData) + y * tileWidth * bpp / 8;
memcpy(dest, src, tileWidth * bpp / 8); memcpy(dest, src, tileWidth * bpp / 8);
} }
m->deviceCommandContext->Flush();
if (needsPresent)
g_VideoMode.GetBackendDevice()->Present();
} }
} }

View File

@ -150,7 +150,7 @@ protected:
void RenderFrameImpl(const bool renderGUI, const bool renderLogger); void RenderFrameImpl(const bool renderGUI, const bool renderLogger);
void RenderFrame2D(const bool renderGUI, const bool renderLogger); void RenderFrame2D(const bool renderGUI, const bool renderLogger);
void RenderScreenShot(); void RenderScreenShot(const bool needsPresent);
void RenderBigScreenShot(const bool needsPresent); void RenderBigScreenShot(const bool needsPresent);
// SetRenderPath: Select the preferred render path. // SetRenderPath: Select the preferred render path.

View File

@ -725,6 +725,15 @@ void CDeviceCommandContext::SetFramebuffer(CFramebuffer* framebuffer)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->GetHandle()); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->GetHandle());
} }
void CDeviceCommandContext::ReadbackFramebufferSync(
const uint32_t x, const uint32_t y, const uint32_t width, const uint32_t height,
void* data)
{
ENSURE(m_Framebuffer);
glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
ogl_WarnIfError();
}
void CDeviceCommandContext::SetScissors(const uint32_t scissorCount, const Rect* scissors) void CDeviceCommandContext::SetScissors(const uint32_t scissorCount, const Rect* scissors)
{ {
ENSURE(scissorCount <= 1); ENSURE(scissorCount <= 1);

View File

@ -57,6 +57,9 @@ public:
void ClearFramebuffer(); void ClearFramebuffer();
void ClearFramebuffer(const bool color, const bool depth, const bool stencil); void ClearFramebuffer(const bool color, const bool depth, const bool stencil);
void SetFramebuffer(CFramebuffer* framebuffer); void SetFramebuffer(CFramebuffer* framebuffer);
void ReadbackFramebufferSync(
const uint32_t x, const uint32_t y, const uint32_t width, const uint32_t height,
void* data);
void UploadTexture(CTexture* texture, const Format dataFormat, void UploadTexture(CTexture* texture, const Format dataFormat,
const void* data, const size_t dataSize, const void* data, const size_t dataSize,