使用帧缓冲区创建 xlib window 我可以直接绘制并使用 XPutImage
Create xlib window with a frame buffer i can draw directly and use XPutImage
我正在尝试创建一个 xlib window,创建一个深度为 32 的帧缓冲区并将该缓冲区绘制到 window,但是。在调用 XPutImage 之前一切正常,window 永远不会显示并且控制台输出:
Process returned -1 (0xFFFFFFFF) execution time : ?.??? s
Press ENTER to continue;
如果我在 Expose 事件中注释掉 XPutImage 行,那么我会得到一个 window,它具有所需的透明客户区。所以我正在寻找如何解决这个问题的答案。
请注意,我是 Linux 编程的新手,但从事 windows 编程已有很长时间了。所以我还不熟悉 Linux 函数和协议 ;)
我在 Fedora 32(64 位)上使用 Code::Blocks 20.03。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
int main(int argc, char **argv)
{
Display *dpy;
XVisualInfo vinfo;
int depth;
XVisualInfo *visual_list;
XVisualInfo visual_template;
int nxvisuals;
int i;
XSetWindowAttributes attrs;
Window parent;
Visual *visual;
int width, height;
Window win;
int *framebuf;
XImage *ximage;
XEvent event;
dpy = XOpenDisplay(NULL);
nxvisuals = 0;
visual_template.screen = DefaultScreen(dpy);
visual_list = XGetVisualInfo (dpy, VisualScreenMask, &visual_template, &nxvisuals);
for (i = 0; i < nxvisuals; ++i)
{
printf(" %3d: visual 0x%lx class %d (%s) depth %d\n",
i,
visual_list[i].visualid,
visual_list[i].class,
visual_list[i].class == TrueColor ? "TrueColor" : "unknown",
visual_list[i].depth);
}
if (!XMatchVisualInfo(dpy, XDefaultScreen(dpy), 32, TrueColor, &vinfo))
{
fprintf(stderr, "no such visual\n");
return 1;
}
printf("Matched visual 0x%lx class %d (%s) depth %d\n",
vinfo.visualid,
vinfo.class,
vinfo.class == TrueColor ? "TrueColor" : "unknown",
vinfo.depth);
parent = XDefaultRootWindow(dpy);
XSync(dpy, True);
printf("creating RGBA child\n");
visual = vinfo.visual;
depth = vinfo.depth;
attrs.colormap = XCreateColormap(dpy, XDefaultRootWindow(dpy), visual, AllocNone);
attrs.background_pixel = 0;
attrs.border_pixel = 0;
width = 1000;
height = 700;
framebuf = malloc((width*height)*4);
for (i = 0; i < (width*height); i++)
{
framebuf[i] = 0xFFFFFFFF;
}
win = XCreateWindow(dpy, parent, 100, 100, width, height, 0, depth, InputOutput,
visual, CWBackPixel | CWColormap | CWBorderPixel, &attrs);
ximage = XCreateImage(dpy, vinfo.visual, 32, XYPixmap, 0, (char *)framebuf, width, height, 8, width*4);
if (ximage == 0)
{
printf("ximage is null!\n");
}
XSync(dpy, True);
XSelectInput(dpy, win, ExposureMask | KeyPressMask);
XGCValues gcv;
unsigned long gcm;
GC NormalGC;
//gcm = GCForeground | GCBackground | GCGraphicsExposures;
//gcv.foreground = BlackPixel(dpy, parent);
//gcv.background = WhitePixel(dpy, parent);
gcm = GCGraphicsExposures;
gcv.graphics_exposures = 0;
NormalGC = XCreateGC(dpy, parent, gcm, &gcv);
XMapWindow(dpy, win);
while(!XNextEvent(dpy, &event))
{
switch(event.type)
{
case Expose:
printf("I have been exposed!\n");
XPutImage(dpy, win, NormalGC, ximage, 0, 0, 0, 0, width, height);
break;
}
}
printf("No error\n");
return 0;
}
为了让它工作,我不得不更改代码中的两行。您可能会不高兴,因为要让它工作,我必须将它从 RGBA 更改为 BGRX。每当我使用 xlib 时,我总是不得不使用 24 位深度,即使数据以 32 位存储。它还存储 BGRX 而不是 RGBX...
这是更改后的代码。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
int main(int argc, char **argv)
{
Display *dpy;
XVisualInfo vinfo;
int depth;
XVisualInfo *visual_list;
XVisualInfo visual_template;
int nxvisuals;
int i;
XSetWindowAttributes attrs;
Window parent;
Visual *visual;
int width, height;
Window win;
int *framebuf;
XImage *ximage;
XEvent event;
dpy = XOpenDisplay(NULL);
nxvisuals = 0;
visual_template.screen = DefaultScreen(dpy);
visual_list = XGetVisualInfo (dpy, VisualScreenMask, &visual_template, &nxvisuals);
//Change to this line
//if (!XMatchVisualInfo(dpy, XDefaultScreen(dpy), 32, TrueColor, &vinfo))
if (!XMatchVisualInfo(dpy, XDefaultScreen(dpy), 24, TrueColor, &vinfo))
{
fprintf(stderr, "no such visual\n");
return 1;
}
parent = XDefaultRootWindow(dpy);
XSync(dpy, True);
printf("creating RGBA child\n");
visual = vinfo.visual;
depth = vinfo.depth;
attrs.colormap = XCreateColormap(dpy, XDefaultRootWindow(dpy), visual, AllocNone);
attrs.background_pixel = 0;
attrs.border_pixel = 0;
width = 1000;
height = 700;
framebuf = (int *) malloc((width*height)*4);
for (i = 0; i < (width*height); i++)
{
framebuf[i] = 0xFF00FFFF;
}
win = XCreateWindow(dpy, parent, 100, 100, width, height, 0, depth, InputOutput,
visual, CWBackPixel | CWColormap | CWBorderPixel, &attrs);
//Change to this line
//ximage = XCreateImage(dpy, vinfo.visual, 32, XYPixmap, 0, (char *)framebuf, width, height, 8, width*4);
ximage = XCreateImage(dpy, vinfo.visual, depth, ZPixmap, 0, (char *)framebuf, width, height, 8, width*4);
if (ximage == 0)
{
printf("ximage is null!\n");
}
XSync(dpy, True);
XSelectInput(dpy, win, ExposureMask | KeyPressMask);
XGCValues gcv;
unsigned long gcm;
GC NormalGC;
//gcm = GCForeground | GCBackground | GCGraphicsExposures;
//gcv.foreground = BlackPixel(dpy, parent);
//gcv.background = WhitePixel(dpy, parent);
gcm = GCGraphicsExposures;
gcv.graphics_exposures = 0;
NormalGC = XCreateGC(dpy, parent, gcm, &gcv);
XMapWindow(dpy, win);
while(!XNextEvent(dpy, &event))
{
switch(event.type)
{
case Expose:
printf("I have been exposed!\n");
XPutImage(dpy, win, NormalGC, ximage, 0, 0, 0, 0, width, height);
break;
}
}
printf("No error\n");
return 0;
}
我正在尝试创建一个 xlib window,创建一个深度为 32 的帧缓冲区并将该缓冲区绘制到 window,但是。在调用 XPutImage 之前一切正常,window 永远不会显示并且控制台输出:
Process returned -1 (0xFFFFFFFF) execution time : ?.??? s
Press ENTER to continue;
如果我在 Expose 事件中注释掉 XPutImage 行,那么我会得到一个 window,它具有所需的透明客户区。所以我正在寻找如何解决这个问题的答案。
请注意,我是 Linux 编程的新手,但从事 windows 编程已有很长时间了。所以我还不熟悉 Linux 函数和协议 ;)
我在 Fedora 32(64 位)上使用 Code::Blocks 20.03。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
int main(int argc, char **argv)
{
Display *dpy;
XVisualInfo vinfo;
int depth;
XVisualInfo *visual_list;
XVisualInfo visual_template;
int nxvisuals;
int i;
XSetWindowAttributes attrs;
Window parent;
Visual *visual;
int width, height;
Window win;
int *framebuf;
XImage *ximage;
XEvent event;
dpy = XOpenDisplay(NULL);
nxvisuals = 0;
visual_template.screen = DefaultScreen(dpy);
visual_list = XGetVisualInfo (dpy, VisualScreenMask, &visual_template, &nxvisuals);
for (i = 0; i < nxvisuals; ++i)
{
printf(" %3d: visual 0x%lx class %d (%s) depth %d\n",
i,
visual_list[i].visualid,
visual_list[i].class,
visual_list[i].class == TrueColor ? "TrueColor" : "unknown",
visual_list[i].depth);
}
if (!XMatchVisualInfo(dpy, XDefaultScreen(dpy), 32, TrueColor, &vinfo))
{
fprintf(stderr, "no such visual\n");
return 1;
}
printf("Matched visual 0x%lx class %d (%s) depth %d\n",
vinfo.visualid,
vinfo.class,
vinfo.class == TrueColor ? "TrueColor" : "unknown",
vinfo.depth);
parent = XDefaultRootWindow(dpy);
XSync(dpy, True);
printf("creating RGBA child\n");
visual = vinfo.visual;
depth = vinfo.depth;
attrs.colormap = XCreateColormap(dpy, XDefaultRootWindow(dpy), visual, AllocNone);
attrs.background_pixel = 0;
attrs.border_pixel = 0;
width = 1000;
height = 700;
framebuf = malloc((width*height)*4);
for (i = 0; i < (width*height); i++)
{
framebuf[i] = 0xFFFFFFFF;
}
win = XCreateWindow(dpy, parent, 100, 100, width, height, 0, depth, InputOutput,
visual, CWBackPixel | CWColormap | CWBorderPixel, &attrs);
ximage = XCreateImage(dpy, vinfo.visual, 32, XYPixmap, 0, (char *)framebuf, width, height, 8, width*4);
if (ximage == 0)
{
printf("ximage is null!\n");
}
XSync(dpy, True);
XSelectInput(dpy, win, ExposureMask | KeyPressMask);
XGCValues gcv;
unsigned long gcm;
GC NormalGC;
//gcm = GCForeground | GCBackground | GCGraphicsExposures;
//gcv.foreground = BlackPixel(dpy, parent);
//gcv.background = WhitePixel(dpy, parent);
gcm = GCGraphicsExposures;
gcv.graphics_exposures = 0;
NormalGC = XCreateGC(dpy, parent, gcm, &gcv);
XMapWindow(dpy, win);
while(!XNextEvent(dpy, &event))
{
switch(event.type)
{
case Expose:
printf("I have been exposed!\n");
XPutImage(dpy, win, NormalGC, ximage, 0, 0, 0, 0, width, height);
break;
}
}
printf("No error\n");
return 0;
}
为了让它工作,我不得不更改代码中的两行。您可能会不高兴,因为要让它工作,我必须将它从 RGBA 更改为 BGRX。每当我使用 xlib 时,我总是不得不使用 24 位深度,即使数据以 32 位存储。它还存储 BGRX 而不是 RGBX...
这是更改后的代码。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
int main(int argc, char **argv)
{
Display *dpy;
XVisualInfo vinfo;
int depth;
XVisualInfo *visual_list;
XVisualInfo visual_template;
int nxvisuals;
int i;
XSetWindowAttributes attrs;
Window parent;
Visual *visual;
int width, height;
Window win;
int *framebuf;
XImage *ximage;
XEvent event;
dpy = XOpenDisplay(NULL);
nxvisuals = 0;
visual_template.screen = DefaultScreen(dpy);
visual_list = XGetVisualInfo (dpy, VisualScreenMask, &visual_template, &nxvisuals);
//Change to this line
//if (!XMatchVisualInfo(dpy, XDefaultScreen(dpy), 32, TrueColor, &vinfo))
if (!XMatchVisualInfo(dpy, XDefaultScreen(dpy), 24, TrueColor, &vinfo))
{
fprintf(stderr, "no such visual\n");
return 1;
}
parent = XDefaultRootWindow(dpy);
XSync(dpy, True);
printf("creating RGBA child\n");
visual = vinfo.visual;
depth = vinfo.depth;
attrs.colormap = XCreateColormap(dpy, XDefaultRootWindow(dpy), visual, AllocNone);
attrs.background_pixel = 0;
attrs.border_pixel = 0;
width = 1000;
height = 700;
framebuf = (int *) malloc((width*height)*4);
for (i = 0; i < (width*height); i++)
{
framebuf[i] = 0xFF00FFFF;
}
win = XCreateWindow(dpy, parent, 100, 100, width, height, 0, depth, InputOutput,
visual, CWBackPixel | CWColormap | CWBorderPixel, &attrs);
//Change to this line
//ximage = XCreateImage(dpy, vinfo.visual, 32, XYPixmap, 0, (char *)framebuf, width, height, 8, width*4);
ximage = XCreateImage(dpy, vinfo.visual, depth, ZPixmap, 0, (char *)framebuf, width, height, 8, width*4);
if (ximage == 0)
{
printf("ximage is null!\n");
}
XSync(dpy, True);
XSelectInput(dpy, win, ExposureMask | KeyPressMask);
XGCValues gcv;
unsigned long gcm;
GC NormalGC;
//gcm = GCForeground | GCBackground | GCGraphicsExposures;
//gcv.foreground = BlackPixel(dpy, parent);
//gcv.background = WhitePixel(dpy, parent);
gcm = GCGraphicsExposures;
gcv.graphics_exposures = 0;
NormalGC = XCreateGC(dpy, parent, gcm, &gcv);
XMapWindow(dpy, win);
while(!XNextEvent(dpy, &event))
{
switch(event.type)
{
case Expose:
printf("I have been exposed!\n");
XPutImage(dpy, win, NormalGC, ximage, 0, 0, 0, 0, width, height);
break;
}
}
printf("No error\n");
return 0;
}