mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-29 15:32:54 +00:00
Use OpenGL to allocate the canvas buffer to avoid a costly memcpy
This commit is contained in:
parent
cd21d017fb
commit
df3f5ae882
2 changed files with 77 additions and 37 deletions
|
@ -1093,7 +1093,24 @@ bool OpenGLSWFrameBuffer::Lock(bool buffered)
|
|||
}
|
||||
assert(!In2D);
|
||||
Accel2D = vid_hw2d;
|
||||
Buffer = MemBuffer;
|
||||
if (UseMappedMemBuffer)
|
||||
{
|
||||
if (!MappedMemBuffer)
|
||||
{
|
||||
BindFBBuffer();
|
||||
|
||||
MappedMemBuffer = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE);
|
||||
Pitch = Width;
|
||||
if (MappedMemBuffer == nullptr)
|
||||
return true;
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
Buffer = (uint8_t*)MappedMemBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer = MemBuffer;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1269,54 +1286,73 @@ bool OpenGLSWFrameBuffer::PaintToWindow()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void OpenGLSWFrameBuffer::BindFBBuffer()
|
||||
{
|
||||
int usage = UseMappedMemBuffer ? GL_DYNAMIC_DRAW : GL_STREAM_DRAW;
|
||||
|
||||
int pixelsize = IsBgra() ? 4 : 1;
|
||||
int size = Width * Height * pixelsize;
|
||||
|
||||
if (FBTexture->Buffers[0] == 0)
|
||||
{
|
||||
glGenBuffers(2, (GLuint*)FBTexture->Buffers);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, FBTexture->Buffers[1]);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, size, nullptr, usage);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, FBTexture->Buffers[0]);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, size, nullptr, usage);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, FBTexture->Buffers[FBTexture->CurrentBuffer]);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
|
||||
{
|
||||
if (copy3d)
|
||||
{
|
||||
int pixelsize = IsBgra() ? 4 : 1;
|
||||
int size = Width * Height * pixelsize;
|
||||
BindFBBuffer();
|
||||
FBTexture->CurrentBuffer = (FBTexture->CurrentBuffer + 1) & 1;
|
||||
|
||||
if (FBTexture->Buffers[0] == 0)
|
||||
if (!UseMappedMemBuffer)
|
||||
{
|
||||
glGenBuffers(2, (GLuint*)FBTexture->Buffers);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, FBTexture->Buffers[0]);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, size, nullptr, GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, FBTexture->Buffers[1]);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, size, nullptr, GL_STREAM_DRAW);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, FBTexture->Buffers[FBTexture->CurrentBuffer]);
|
||||
FBTexture->CurrentBuffer = (FBTexture->CurrentBuffer + 1) & 1;
|
||||
}
|
||||
int pixelsize = IsBgra() ? 4 : 1;
|
||||
int size = Width * Height * pixelsize;
|
||||
|
||||
uint8_t *dest = (uint8_t*)MapBuffer(GL_PIXEL_UNPACK_BUFFER, size);
|
||||
if (dest)
|
||||
{
|
||||
if (Pitch == Width)
|
||||
uint8_t *dest = (uint8_t*)MapBuffer(GL_PIXEL_UNPACK_BUFFER, size);
|
||||
if (dest)
|
||||
{
|
||||
memcpy(dest, MemBuffer, Width * Height * pixelsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *src = MemBuffer;
|
||||
for (int y = 0; y < Height; y++)
|
||||
if (Pitch == Width)
|
||||
{
|
||||
memcpy(dest, src, Width * pixelsize);
|
||||
dest += Width * pixelsize;
|
||||
src += Pitch * pixelsize;
|
||||
memcpy(dest, MemBuffer, Width * Height * pixelsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *src = MemBuffer;
|
||||
for (int y = 0; y < Height; y++)
|
||||
{
|
||||
memcpy(dest, src, Width * pixelsize);
|
||||
dest += Width * pixelsize;
|
||||
src += Pitch * pixelsize;
|
||||
}
|
||||
}
|
||||
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||
}
|
||||
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||
GLint oldBinding = 0;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding);
|
||||
glBindTexture(GL_TEXTURE_2D, FBTexture->Texture);
|
||||
if (IsBgra())
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
||||
else
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, GL_RED, GL_UNSIGNED_BYTE, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, oldBinding);
|
||||
}
|
||||
else if (MappedMemBuffer)
|
||||
{
|
||||
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||
MappedMemBuffer = nullptr;
|
||||
}
|
||||
|
||||
GLint oldBinding = 0;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding);
|
||||
glBindTexture(GL_TEXTURE_2D, FBTexture->Texture);
|
||||
if (IsBgra())
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
||||
else
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, GL_RED, GL_UNSIGNED_BYTE, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, oldBinding);
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
|
|
@ -194,6 +194,10 @@ private:
|
|||
void DrawTriangleList(int minIndex, int numVertices, int startIndex, int primitiveCount);
|
||||
void Present();
|
||||
|
||||
void BindFBBuffer();
|
||||
void *MappedMemBuffer = nullptr;
|
||||
bool UseMappedMemBuffer = true;
|
||||
|
||||
static uint32_t ColorARGB(uint32_t a, uint32_t r, uint32_t g, uint32_t b) { return ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b) & 0xff); }
|
||||
static uint32_t ColorRGBA(uint32_t r, uint32_t g, uint32_t b, uint32_t a) { return ColorARGB(a, r, g, b); }
|
||||
static uint32_t ColorXRGB(uint32_t r, uint32_t g, uint32_t b) { return ColorARGB(0xff, r, g, b); }
|
||||
|
|
Loading…
Reference in a new issue