可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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 #include 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 #include 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); } }
回答1:
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.
回答2:
The problem is with DefaultGC()
which return a GC with bit depth of system default screen. If you look at line 53 of your gist paste you see that this is 24:
depth of root window: 24 planes
On line 63 you see that it uses 0x22 as default which is shown in more detail in line 64 to 70:
visual: visual id: 0x22 class: TrueColor depth: 24 planes available colormap entries: 256 per subfield red, green, blue masks: 0xff0000, 0xff00, 0xff significant bits in color specification: 8 bits
You could probably do this a bit nicer but as a start you can try this:
Note: This uses system visuals so most probably only support depth of 24 or 32.
#include #include #include #include #ifdef DEBUG int dbg = 1; #else int dbg = 0; #endif /* Return a GC based on depth */ int gc_depth(int depth, Display *dpy, Window scr, Window root, GC *gc) { Window win; Visual *visual; XVisualInfo vis_info; XSetWindowAttributes win_attr; unsigned long win_mask; if(!XMatchVisualInfo(dpy, scr, depth, TrueColor, &vis_info)) { fprintf(stderr, " * ERR: %d depth not supported\n", depth ); return 1; } visual = vis_info.visual; win_attr.colormap = XCreateColormap(dpy, root, visual, AllocNone); win_attr.background_pixel = 0; win_attr.border_pixel = 0; win_mask = CWBackPixel | CWColormap | CWBorderPixel; win = XCreateWindow( dpy, root, 0, 0, 100, 100, /* dummy size */ 0, depth, InputOutput, visual, win_mask, &win_attr); /* To flush out any errors */ if (dbg) XSync(dpy, True); *gc = XCreateGC(dpy, win, 0, 0); if (dbg) XSync(dpy, True); XDestroyWindow(dpy, win); if (dbg) XSync(dpy, True); return 0; } int main(void) { int w = 100; int h = 100; int depth = 32; int bitmap_pad = 32; int bpl = 0; Display *dpy; Window root; Window scr; GC gc; int root_depth; Pixmap pm; XImage *img; unsigned char *buf_img; if(!(dpy = XOpenDisplay(NULL))) { fprintf(stderr, " * ERR: Failed to open display.\n"); return 1; } #ifdef DEBUG /* To get errors in order, slows down * One can also define int _Xdebug = 1; * */ XSynchronize(dpy, True); #endif root = XDefaultRootWindow(dpy); scr = XDefaultScreen(dpy); if ((buf_img = malloc(w * h * 4)) == NULL) { fprintf(stderr, " * ERR: Unable to alloacte %d bytes\n", w * h * 4); return 1; } root_depth = DefaultDepth(dpy, scr); fprintf(stderr, "Default depth: %d\n", root_depth); /* This should be doen more nice */ if (depth != root_depth) { if (gc_depth(depth, dpy, scr, root, &gc) != 0) return 1; } else { gc = DefaultGC(dpy, 0); } img = XCreateImage( dpy, CopyFromParent, depth, ZPixmap, 0, (char *)buf_img, w, h, bitmap_pad, bpl); /* To flush out any errors */ if (dbg) XSync(dpy, True); pm = XCreatePixmap( dpy, root, w, h, depth); if (dbg) XSync(dpy, True); XPutImage( dpy, pm, gc, img, 0, 0, 0, 0, w, h); if (dbg) XSync(dpy, True); XFreePixmap(dpy, pm); XDestroyImage(img); XFreeGC(dpy, gc); if (dbg) XSync(dpy, True); fprintf(stderr, "OK!\n"); return 0; }