I'm having trouble displaying an image (PNG extracted with libpng) into an XCB window, it is always entirely empty/white. I'm pretty sure the PNG extraction is correct since I can perfectly re-write it into another file.
I've tried everything I found (explanations, guides, documentation) and I'm running out of ideas:
- Creating an
xcb_pixmap_t
callingxcb_create_pixmap_from_bitmap_data()
with the data taken from the PNG, then callingxcb_copy_area()
into the EXPOSE part of the event loop. - Creating an
xcb_image_t*
callingxcb_image_create_from_bitmap_data()
then trying to map it to the window withxcb_image_put()
. I've even tried to display each pixel withxcb_image_put_pixel()
, but without success.
Code sample:
xcb_pixmap_t pixmap = xcb_create_pixmap_from_bitmap_data(
connection, // xcb_connect(0, 0) (type: xcb_connection_t*)
window, // xcb_generate_id(connection) (type: xcb_window_t)
img.getData(), // uint8_t*
img.getWidth(), // 128
img.getHeight(), // 128
img.getBitDepth(), // 8
screen->black_pixel, // screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data (type: xcb_screen_t*)
screen->white_pixel,
nullptr);
// "img" is an instance of my own custom class, result of PNG reading
xcb_image_t* image = xcb_image_create_from_bitmap_data(
img.getData(),
img.getWidth(),
img.getHeight()); // image->data seems fine
xcb_image_put(connection,
window,
graphicsContext,
image, 0, 0, 0); // This does nothing
for (unsigned int i = 0; i < screen->height_in_pixels; ++i)
for (unsigned int j = 0; j < screen->width_in_pixels; ++j)
xcb_image_put_pixel(image, j, i, 0); // Displays nothing
[...]
// Into event loop
case XCB_EXPOSE: {
xcb_expose_event_t* exposeEvent = reinterpret_cast<xcb_expose_event_t*>(event);
xcb_copy_area(connection,
pixmap,
window,
graphicsContext,
exposeEvent->x, exposeEvent->y, // Top left x & y coordinates of the source's region to copy
exposeEvent->x, exposeEvent->y, // Top left x & y coordinates of the destination's region to copy to
exposeEvent->width,
exposeEvent->height);
xcb_flush(connection);
break;
}
From the examples I found I saw that it didn't need a colormap, but could that be the case? Could anyone tell me where I've gone wrong?
img.getBitDepth(), // 8
this could be your problem. The depth must be the same as your window depth, orxcb_copy_area
will fail. Do you really have 8-bit deep windows by default? In general you should be prepared to handle all depths. – ProtonXCB_COPY_FROM_PARENT
to the window while creating it. By replacing this field with8
, the window does not even appear. – Rayleneraylessxcb_create_pixmap_from_bitmap_data
doesn't do what you think it does. It is for source data of depth of one bit. Same thing aboutxcb_image_create_from_bitmap_data
. It's for one bit deep bitmaps. You wantxcb_image_create
only. This is an intimidating function. Look up usage examples on the net before trying to call it. – Protonxcb_image_create
(which I already tried earlier if I recall correctly) and I keep getting a segfault. I've been on it for two days already, just because XCB isn't able to make a proper documentation. I think I'll simply make GLX windows (I'll need OpenGL later anyway). – Rayleneraylessxcb_image_put
onwindow
. This will put the image to the screen if the window is mapped or not at all if the window is not mapped. You will also loose anything put to the window when it is partly covered by an other window or unmaped. Instead you probably want to callxcb_image_put
on thepixmap
you created. The pixmap have a permanent buffer and you can from there copy the data to the window whenever the window is exposed (witch you already do). – Hensel