Search code examples
cx11xlib

How to upload 32 bit image to server-side pixmap


I'm trying to create server-side RGBA pixmap from client side buffer. CreatePixmap & CreateImage work ok for 32 and 24 bit, but XPutImage result in Match Error returned by server

X Error of failed request:  BadMatch (invalid parameter attributes)
  Major opcode of failed request:  72 (X_PutImage)
  Serial number of failed request:  8
  Current serial number in output stream:  8

server does support 32 bit pixmaps (xdpyinfo output: https://gist.github.com/2582961). Same behaviour on ubuntu 12.04 (X.Org version: 1.11.3) and OSX with X.app (X.Org version: 1.10.3)

Why following code fails?

#include     <stdlib.h>
#include     <X11/Xlib.h>

int main(int argc, char **argv)
{
    int width = 100;
    int height = 100;
    int depth = 32; // works fine with depth = 24
    int bitmap_pad = 32; // 32 for 24 and 32 bpp, 16, for 15&16
    int bytes_per_line = 0; // number of bytes in the client image between the start of one scanline and the start of the next
    Display *display=XOpenDisplay(0);
    unsigned char *image32=(unsigned char *)malloc(width*height*4);
    XImage *img = XCreateImage(display, CopyFromParent, depth, ZPixmap, 0, image32, width, height, bitmap_pad, bytes_per_line);
    Pixmap p = XCreatePixmap(display, XDefaultRootWindow(display), width, height, depth);
    XPutImage(display, p, DefaultGC(display, 0), img, 0, 0, 0, 0, width, height); // 0, 0, 0, 0 are src x,y and dst x,y
    XEvent ev;
    while (1) {
       XNextEvent(display, &ev);
    }
}

Update: It looks like I finally got answer: use GC associated with pixmap instead of DefaultGC (which has depth of root window)

#include     <stdlib.h>
#include     <X11/Xlib.h>

int main(int argc, char **argv)
{
    int width = 100;
    int height = 100;
    int depth = 32; // works fine with depth = 24
    int bitmap_pad = 32; // 32 for 24 and 32 bpp, 16, for 15&16
    int bytes_per_line = 0; // number of bytes in the client image between the start of one scanline and the start of the next
    Display *display=XOpenDisplay(0);
    unsigned char *image32=(unsigned char *)malloc(width*height*4);
    XImage *img = XCreateImage(display, CopyFromParent, depth, ZPixmap, 0, image32, width, height, bitmap_pad, bytes_per_line);
    Pixmap p = XCreatePixmap(display, XDefaultRootWindow(display), width, height, depth);
    XGCValues gcvalues;
    GC gc = XCreateGC(display, p, 0, &gcvalues);
    XPutImage(display, p, gc, img, 0, 0, 0, 0, width, height); // 0, 0, 0, 0 are src x,y and dst x,y
    XEvent ev;
    while (1) {
       XNextEvent(display, &ev);
    }
}

Solution

  • Well, your code works for 32 bits images if you just create a GC passing a drawable on argument which is 32 bits. XCreateGC(dpy, drawable, 0, 0), where drawable can be a pixmap with 32 bits depth. It works perfect with me.