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)
{
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);
}
@ -421,12 +421,13 @@ void CRenderer::RenderFrame(const bool needsPresent)
{
RenderBigScreenShot(needsPresent);
}
else if (m_ScreenShotType == ScreenShotType::DEFAULT)
{
RenderScreenShot(needsPresent);
}
else
{
if (m_ScreenShotType == ScreenShotType::DEFAULT)
RenderScreenShot();
else
RenderFrameImpl(true, true);
RenderFrameImpl(true, true);
m->deviceCommandContext->Flush();
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;
@ -551,23 +552,25 @@ void CRenderer::RenderScreenShot()
VfsPath 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;
GLenum fmt = GL_RGB;
int flags = TEX_BOTTOM_UP;
// Hide log messages and re-render
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);
std::shared_ptr<u8> buf;
AllocateAligned(buf, hdr_size + img_size, maxSectorSize);
GLvoid* img = buf.get() + hdr_size;
void* img = buf.get() + hdr_size;
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;
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)
{
@ -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 (!g_Game)
return RenderScreenShot();
return RenderScreenShot(needsPresent);
int tiles = 4, tileWidth = 256, tileHeight = 256;
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 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 tileSize = tileWidth * tileHeight * bpp / 8;
@ -638,7 +632,7 @@ void CRenderer::RenderBigScreenShot(const bool needsPresent)
Tex t;
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);
return;
@ -672,18 +666,18 @@ void CRenderer::RenderBigScreenShot(const bool needsPresent)
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
glReadPixels(0, 0, tileWidth, tileHeight, fmt, GL_UNSIGNED_BYTE, tileData);
for (int y = 0; y < tileHeight; ++y)
{
void* dest = static_cast<char*>(img) + ((tileY * tileHeight + y) * imageWidth + (tileX * tileWidth)) * bpp / 8;
void* src = static_cast<char*>(tileData) + y * 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 RenderFrame2D(const bool renderGUI, const bool renderLogger);
void RenderScreenShot();
void RenderScreenShot(const bool needsPresent);
void RenderBigScreenShot(const bool needsPresent);
// SetRenderPath: Select the preferred render path.

View File

@ -725,6 +725,15 @@ void CDeviceCommandContext::SetFramebuffer(CFramebuffer* framebuffer)
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)
{
ENSURE(scissorCount <= 1);

View File

@ -57,6 +57,9 @@ public:
void ClearFramebuffer();
void ClearFramebuffer(const bool color, const bool depth, const bool stencil);
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,
const void* data, const size_t dataSize,