[rlgl] Optimize rlReadScreenPixels (#4667)
This optimization works in the following ways: 1. Reduces calls to malloc to 1. Instead of needing an extra array, we can just swap the top half with the bottom half of the one array. 2. Unroll the inner for loop and remove a condition. Unrolling loops buys some performance wins, but the real goal was to remove the if check and just set the alpha channel to 255. On my hidpi arm64 laptop, I saw ~60% improvement in performance in my debug build (29 FPS vs 47 FPS). When optimized, the gains were roughly 10% (75 FPS vs 83%). Signed-off-by: K. Adam Christensen <pope@shifteleven.com>
This commit is contained in:
parent
fc29bc27fd
commit
5d9aed5d40
1 changed files with 20 additions and 12 deletions
38
src/rlgl.h
38
src/rlgl.h
|
@ -3666,28 +3666,36 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
|
|||
// Read screen pixel data (color buffer)
|
||||
unsigned char *rlReadScreenPixels(int width, int height)
|
||||
{
|
||||
unsigned char *screenData = (unsigned char *)RL_CALLOC(width*height*4, sizeof(unsigned char));
|
||||
unsigned char *imgData = (unsigned char *)RL_CALLOC(width*height*4, sizeof(unsigned char));
|
||||
|
||||
// NOTE 1: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
|
||||
// NOTE 2: We are getting alpha channel! Be careful, it can be transparent if not cleared properly!
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, screenData);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, imgData);
|
||||
|
||||
// Flip image vertically!
|
||||
unsigned char *imgData = (unsigned char *)RL_MALLOC(width*height*4*sizeof(unsigned char));
|
||||
|
||||
for (int y = height - 1; y >= 0; y--)
|
||||
{
|
||||
for (int x = 0; x < (width*4); x++)
|
||||
{
|
||||
imgData[((height - 1) - y)*width*4 + x] = screenData[(y*width*4) + x]; // Flip line
|
||||
|
||||
// Set alpha component value to 255 (no trasparent image retrieval)
|
||||
// NOTE: Alpha value has already been applied to RGB in framebuffer, we don't need it!
|
||||
if (((x + 1)%4) == 0) imgData[((height - 1) - y)*width*4 + x] = 255;
|
||||
}
|
||||
}
|
||||
for (int y = height - 1; y >= height / 2; y--)
|
||||
{
|
||||
for (int x = 0; x < (width*4); x += 4)
|
||||
{
|
||||
size_t s = ((height - 1) - y)*width*4 + x;
|
||||
size_t e = y*width*4 + x;
|
||||
|
||||
RL_FREE(screenData);
|
||||
unsigned char r = imgData[s];
|
||||
unsigned char g = imgData[s+1];
|
||||
unsigned char b = imgData[s+2];
|
||||
|
||||
imgData[s] = imgData[e];
|
||||
imgData[s+1] = imgData[e+1];
|
||||
imgData[s+2] = imgData[e+2];
|
||||
imgData[s+3] = 255; // Set alpha component value to 255 (no trasparent image retrieval)
|
||||
|
||||
imgData[e] = r;
|
||||
imgData[e+1] = g;
|
||||
imgData[e+2] = b;
|
||||
imgData[e+3] = 255; // Ditto
|
||||
}
|
||||
}
|
||||
|
||||
return imgData; // NOTE: image data should be freed
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue