c - Xlib/GLX 窗口调整大小滞后

标签 c resize x11 xlib

我尝试使用 gl 3.3 上下文创建窗口,但当我尝试调整它的大小时,它正在消耗 cpu 并出现滞后。

<强> My Code :

#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#include <GL/glext.h>

struct _WGelWindowX11{
    Display *XDspl;
    Window XWin;
    Colormap XCMap;
    GLXContext glContext;
};

typedef struct _WGelWindowX11 WGelWindowX11;
#define WGEL_WINDOWX11(obj) ((WGelWindowX11*)obj)

int aiAttr[]={
    GLX_X_RENDERABLE,       True,
    GLX_X_VISUAL_TYPE,      GLX_TRUE_COLOR,
    GLX_RED_SIZE,           8,
    GLX_GREEN_SIZE,         8,
    GLX_BLUE_SIZE,          8,
    GLX_ALPHA_SIZE,         8,
    GLX_DEPTH_SIZE,         24,
    GLX_DOUBLEBUFFER,       True,
    None
};

int aiAttrGL[]={
    GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
    GLX_CONTEXT_MINOR_VERSION_ARB, 3,
    None
};

void *WGelWindowNew(void){
    WGelWindowX11 *Result=malloc(sizeof(WGelWindowX11));

    Result->XDspl=XOpenDisplay(NULL);
    if (!Result->XDspl){
            perror("Cannot open display.\n");
            return NULL;
    }

    //Gettin' matchin' framebuffer configuration
    int iFBCount;
    GLXFBConfig *pFBConf=glXChooseFBConfig(Result->XDspl, DefaultScreen(Result->XDspl),    aiAttr, &iFBCount);
    if(!pFBConf){
            perror("Cannot get FBConfig.\n");
            return NULL;
    }

    int iBestFBC=-1, iWorstFBC=-1, iBestNSampl=-1, iWorstNSampl=999,iSamplBuff, iSampl, i;
    for(i=0; i<iFBCount; i++){
            XVisualInfo *vi=glXGetVisualFromFBConfig(Result->XDspl, pFBConf[i]);
            if (vi){
                    glXGetFBConfigAttrib(Result->XDspl, pFBConf[i], GLX_SAMPLE_BUFFERS, &iSamplBuff);
                    glXGetFBConfigAttrib(Result->XDspl, pFBConf[i], GLX_SAMPLES, &iSampl);
                    if (iBestFBC<0 || iSamplBuff && iSampl>iBestNSampl) iBestFBC=i, iBestNSampl=iSampl;
                    if (iWorstFBC<0 || !iSamplBuff || iSampl<iWorstNSampl) iWorstFBC=i, iWorstNSampl=iSampl;
            }
            XFree(vi);
    }

    GLXFBConfig FBConfBest=pFBConf[iBestFBC];
    XFree(pFBConf);

    XVisualInfo *XVslnfo=glXGetVisualFromFBConfig(Result->XDspl, FBConfBest);
    XSetWindowAttributes XWinAttr;

    Result->XCMap=XCreateColormap(Result->XDspl, RootWindow(Result->XDspl, XVslnfo->screen), XVslnfo->visual, AllocNone);
    XWinAttr.colormap=Result->XCMap;
    XWinAttr.background_pixmap=None;
    XWinAttr.border_pixel=0;
    XWinAttr.event_mask=StructureNotifyMask|ExposureMask|KeyPressMask;

    Atom wmDeleteMessage=XInternAtom(Result->XDspl, "WM_DELETE_WINDOW", FALSE);

    Result->XWin=XCreateWindow(Result->XDspl, RootWindow(Result->XDspl, XVslnfo->screen), 0, 0, 300, 300, 0, XVslnfo->depth, InputOutput, XVslnfo->visual, CWBorderPixel|CWColormap|CWEventMask, &XWinAttr);
    if(!Result->XWin){
            perror("Cannot create window.\n");
            return NULL;
    }

    XFree(XVslnfo);
    XStoreName(Result->XDspl, Result->XWin, "WGel Window" );
    XSetWMProtocols(Result->XDspl, Result->XWin, &wmDeleteMessage, 1);

    XMapWindow(Result->XDspl, Result->XWin);

    PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs=(PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((GLubyte*)"glXCreateContextAttribsARB");

    Result->glContext=glXCreateContextAttribs(Result->XDspl, FBConfBest, 0, True, aiAttrGL);
    if(!Result->glContext){
            perror("Cannot create GL 3.3 context\n");
            return NULL;
    }

    glXMakeCurrent(Result->XDspl, Result->XWin, Result->glContext);
    glClearColor(1.0f, 1.0f, 1.0f, 0.0f);

    return (void*)Result;}

 Display *WGelX11GetDisplay(ptr window){
    return WGEL_WINDOWX11(window)->XDspl;}

 Window *WGelX11GetWindow(ptr window){
    return &(WGEL_WINDOWX11(window)->XWin);
 }

 int main(void){
    ptr frmMain=WGelWindowNew();
    Display *dpy=WGelX11GetDisplay(frmMain);
    XEvent e;
    while(XNextEvent(dpy, &e)>=0){
            if ((!XPending(dpy))&&(e.type==Expose)){
                    glClear(GL_COLOR_BUFFER_BIT);
                    glXSwapBuffers(dpy, *WGelX11GetWindow(frmMain));
            }
            if (e.type==ClientMessage){
                    XDestroyWindow(dpy, e.xclient.window);
                    break;
            }
    }

    XCloseDisplay(dpy);

    return EXIT_SUCCESS;}

GTK+ 窗口在调整大小时并没有那么严重滞后,所以我想应该有一种方法可以消除这种滞后。

最佳答案

首先,您必须忽略所有 Expose 事件并仅处理最后一个事件。 你可以这样做:

XNextEvent(dpy, &e);
switch (e.type) 
{
    case Expose:
         /* Unless this is the last contiguous expose,
         * don’t draw the window */
         if (e.xexpose.count == 0)
         {
          // DRAW THINGS
         }
         break;
    case ClientMessage:
         XDestroyWindow(dpy, e.xclient.window);
         break;
    default:
         break;
}

为了更好地处理调整大小,您必须捕获ConfigureNotify 事件。

关于c - Xlib/GLX 窗口调整大小滞后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20306278/

相关文章:

javascript - 根据屏幕尺寸更改功能

c++ - 创建带有帧缓冲区的 xlib 窗口,我可以直接绘制并使用 XPutImage

c++ X11全局改变光标形状

c - 根据字母升序查找第一个和最后一个字符串单词

c - 如何在 C 中初始化仅 header 的全局变量

Java GUI 调整图像大小

linux - X/侏儒 : How to measure the geometry of an open window

c 变量作用域

c - 抑制 popen() 的输出

css - 调整浏览器大小时如何防止我的 div 层重叠?