Xlib / GLX窗口调整滞后

时间:2013-11-30 22:17:59

标签: 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+窗口并没有那么难,所以我想应该有办法摆脱这种滞后。

2 个答案:

答案 0 :(得分:1)

首先,您必须忽略所有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;
}

为了更好地处理Resizing,您必须捕获ConfigureNotify事件。

答案 1 :(得分:0)

可能和我在这里写的相同:Is there a way to change ConfigureNotify event frequency in X11?

基本修复:不要在每次调整大小事件时重新绘制,鼠标生成事件的速度要比重绘屏幕快得多。