Hello,
I've been annoying you with this issue on the IRC Chat, I'll continue here instead, I find it more practical for me and more people might help.
So here is the deal : I am trying to create a tiny libretro frontend using SFML, which point is to eventually run on a Raspberry Pi. I have an emulation core which gives me every frame the image that I'm supposed to display. The thing is that the pixel format is not the same as the one SFML's using.
libretro can support several emulation consoles, which can use three different pixel formats. For now I'll just focus on one : RGB565.
The core provides me, every frame, an uint16_t * containing the pixels this way : { rrrrrggggggbbbbb, rrrrrggggggbbbbb, rrrrrggggggbbbbb, etc...}.
On the other hand, SFML requires an RGBA8888 format, plus a weird uint8_t * array disposition : {rrrrrrrr, gggggggg, bbbbbbbb, aaaaaaaa, rrrrrrrr, gggggggg, bbbbbbbb, aaaaaaaa, rrrrrrrr, gggggggg, bbbbbbbb, aaaaaaaa, etc...}.
On the IRC we eventually came to a working method to convert each pixel to three uint8_t containing the red, green and blue channels (well, I think it works).
Here is the snippet I have - pixelsBuffer is the final array containing the pixels to be displayed, and videoRefreshCallback is the function called every frame to update pixelsBuffer :
//The final pixels buffer (the size is fixed for now), which should be RGBA8888
uint8_t pixelsBuffer[229376];
void videoRefreshCallback(const void *data, unsigned width, unsigned height, size_t pitch)
{
uint16_t * pixels = (uint16_t *) data; //the uint16_t array of RGB565 pixels
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
uint16_t actualPixel = pixels[(pitch*y)/2 + x];
uint8_t r = (actualPixel >> 8) & 0xF8;
uint8_t g = (actualPixel >> 3) & 0xFC;
uint8_t b = (actualPixel) << 3;
pixelsBuffer[?] = r;
pixelsBuffer[? * 4 + 1] = g;
pixelsBuffer[? * 4 + 2] = b;
pixelsBuffer[? * 4 + 3] = 0xFF;
}
}
gameTexture.update(pixelsBuffer, width, height, 0, 0); //we update the texture drawn in the main loop
}
Okay, so the pixel conversion works here (I guess), but I don't really know how to put them in pixelsBuffer (where the ? are).
Could you help me ? I also have few other questions :
- isn't there a more optimized solution to do this ? i think the double-loop solution is heavy, it's supposed to run on a Raspberry and I might need to implement some more high-qualities consoles (with more pixels to process each frame)
- wouldn't be more easy to extend SFML to support more pixels formats ? I looked at the Texture::update() code, and I think we can change GL_ARGB to pretty much every format supported by GL (RGB565 included), but this doesn't solve the array format problem, switching from one array of pixels (one entry per pixel) to one array of pixel colors (3 or 4 entry per pixel, depending on the alpha channel)
Thanks a lot !