Hi,
 Recently I have made a piglit case that can test the behaviors of buffer swap, 
they are 1) test whether we can get swap events. 2) verify whether the swap is 
asynchronous 3) verify the swap frequency of swap interval being 0 is larger 
than interval being 1. Jesse has helped me have brief look on it and give me 
some advice. I have modified it. Can you help to add it into piglit tests? 
Thanks for help and comments!


Best regards,
Zhao Jian

/*
 *  * This is a simple test case on the intel_swap_event.
 *   * Port by Jian Zhao  08 Sep 2010
 *    *              jian.j.z...@intel.com
 *     *
 *      * See usage() below for command line options.
 */

#include "piglit-util.h"
#include "GL/glx.h"
#include <sys/time.h>

/* return current time (in seconds) */
static double
current_time(void)
{
        struct timeval tv;
#ifdef __VMS
        (void) gettimeofday(&tv, NULL );
#else
        struct timezone tz;
        (void) gettimeofday(&tv, &tz);
#endif
        return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
}

PFNGLXSWAPINTERVALMESAPROC pglXSwapIntervalMESA;
PFNGLXGETSWAPINTERVALMESAPROC pglXGetSwapIntervalMESA;

#define STACK_L 10

static GLboolean fullscreen = GL_FALSE; /* Create a single fullscreen window */
static GLboolean verbose = GL_FALSE;    /* Disable verbose.  */
static GLboolean Automatic = GL_FALSE;  /* Disable verbose.  */
static GLboolean test_events = GL_FALSE;        /* Disable verbose.  */
static GLboolean interval_diff = GL_FALSE;      /* Disable verbose.  */
static GLboolean async = GL_FALSE;      /* Disable verbose.  */
int event_base, Glx_event, count=0;
static int Intel_swap_event=0;
int swap_count=0, event_count=0, event_count_total=0, frames_total=0, 
message_count=0;
static double time_call=0.0, time_fin=0.0, time_val=0.0;
double swap_start[STACK_L],swap_returned[STACK_L];
int interval=1;
char * swap_event_type=NULL;
/**
 * Determine whether or not a GLX extension is supported.
 */
static int
is_glx_extension_supported(Display *dpy, const char *query)
{
        const int scrnum = DefaultScreen(dpy);
        const char *glx_extensions = NULL;
        const size_t len = strlen(query);
        const char *ptr;
        
        if (glx_extensions == NULL) {
                glx_extensions = glXQueryExtensionsString(dpy, scrnum);
        }
        
        ptr = strstr(glx_extensions, query);
        return ((ptr != NULL) && ((ptr[len] == ' ') || (ptr[len] == '\0')));
}

static void
query_swap_event(Display *dpy)
{

        if ( ! is_glx_extension_supported(dpy, "GLX_INTEL_swap_event")) {
                printf("The GLX_INTEL_swap_event is not supported in current 
version.\n");
                exit(0);
        }else{
                printf("The GLX_INTEL_swap_event is supported in current 
version.\n");
        }
        
        if (is_glx_extension_supported(dpy, "GLX_MESA_swap_control")) {
                pglXGetSwapIntervalMESA = (PFNGLXGETSWAPINTERVALMESAPROC) 
glXGetProcAddressARB((const GLubyte *) "glXGetSwapIntervalMESA");
                pglXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) 
glXGetProcAddressARB((const GLubyte *) "glXSwapIntervalMESA");
        }else{
                printf("GLX_MESA_swap_control was not supported by the 
driver.\n");
        }
}

/** Draw single frame, do SwapBuffers, compute FPS */
static void
draw_frame(Display *dpy, Window win)
{
        static int frames = 0, async_swap;
        static double tRot0 = -1.0, tRate0 = -1.0;
        static double swap_freq[2];
        double dt, t = current_time();
        int tem;
        
        if (tRot0 < 0.0)
                tRot0 = t;
        dt = t - tRot0;
        tRot0 = t;
        
        if (tRate0 < 0.0)
                tRate0 = t;
        if (t - tRate0 >= 3.0) {
                if (message_count & 0x1){
                        (*pglXSwapIntervalMESA)(1);
                        interval=(*pglXGetSwapIntervalMESA)();
                        if ( !  interval == 1 ){
                                printf("Failed to set swap interval to 1 by 
glXSwapIntervalMESA.\n");
                                exit(0);
                        }
                }else{
                        (*pglXSwapIntervalMESA)(0);
                        interval=(*pglXGetSwapIntervalMESA)();
                        if ( !  interval == 0 ){
                                printf("Failed to set swap interval to 0 by 
glXSwapIntervalMESA.\n");
                                exit(0);
                        }
                }
                message_count++;
                GLfloat seconds = t - tRate0;
                if ( (time_val / frames) < 0.0016 ){  // 0.0016 <=> 60Hz * 10 
or 100Hz * 6 
                        async_swap=1;
                }else{
                        async_swap=0;
                }
                interval=1-interval;
                swap_freq[interval] = frames / seconds;
                if(Automatic){
                        if (message_count==2){
                                if (test_events){
                                        if( ! Intel_swap_event == 0 ){
                                                if (verbose){
                                                        printf("glXSwapBuffers 
is called %d times and there is %d Intel_swap_event received in past %3.1f 
seconds.\n", swap_count, event_count, seconds);
                                                        printf("There is swap 
events received, and the swap type is %s.\n", swap_event_type);
                                                }
                                                
piglit_report_result(PIGLIT_SUCCESS);
                                                exit(0);
                                        }else{
                                                if (verbose){
                                                        printf("glXSwapBuffers 
is called %d times and there is %d Intel_swap_event received in past %3.1f 
seconds.\n", swap_count, event_count, seconds);
                                                        printf("There is no 
swap event received, and the swap type is %s.\n", swap_event_type);
                                                }
                                                
piglit_report_result(PIGLIT_FAILURE);
                                                exit(1);
                                        }
                                        
                                }
                                if (interval_diff){
                                        tem = 1.5 * swap_freq[1];
                                        if ( swap_freq[0] >= tem ){
                                                if (verbose){
                                                        printf("The swap 
frequency of no swap interval is much larger than swap interval being 1.\n");
                                                }
                                                
piglit_report_result(PIGLIT_SUCCESS);
                                                exit(0);
                                        }else{
                                                if (verbose){
                                                        printf("The swap 
frequency of no swap interval is not much larger than swap interval being 1. 
They are %lf and %lf.\n", swap_freq[0], swap_freq[1]);
                                                }
                                                
piglit_report_result(PIGLIT_FAILURE);
                                                exit(1);
                                        }
                                }
                                if (async){
                                        if (verbose){
                                                printf("It takes about %lf 
seconds returning back from the glXSwapBuffers call on average.\n", (time_val / 
frames));
                                        }
                                        if (async_swap ==1 ){
                                                
piglit_report_result(PIGLIT_SUCCESS);
                                                exit(0);
                                        }else{
                                                
piglit_report_result(PIGLIT_FAILURE);
                                                exit(1);
                                        }
                                }
                        }       
                }
                tRate0 = t;
                frames = 0;
                time_val = 0;
                swap_count= 0;
                event_count= 0;
        }
             
        if (frames_total & 1) {
                glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
                glColor3f(1.0f, 1.0f, 1.0f);
        } else {
                glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
                glColor3f(1.0f, 0.0f, 0.0f);
        }
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        count=frames_total%STACK_L;
        time_call=current_time();
        swap_start[count]=time_call;
        glXSwapBuffers(dpy, win);
        time_fin=current_time();
        swap_returned[count]=time_fin;
        time_val+=(time_fin-time_call);
        
        frames++;
        frames_total++;
        swap_count++;
}

/**
 * Remove window border/decorations.
 */
static void
no_border( Display *dpy, Window w)
{
        static const unsigned MWM_HINTS_DECORATIONS = (1 << 1);
        static const int PROP_MOTIF_WM_HINTS_ELEMENTS = 5;
        
        typedef struct
        {
                unsigned long       flags;
                unsigned long       functions;
                unsigned long       decorations;
                long                inputMode;
                unsigned long       status;
        } PropMotifWmHints;
        
        PropMotifWmHints motif_hints;
        Atom prop, proptype;
        unsigned long flags = 0;
        
        /* setup the property */
        motif_hints.flags = MWM_HINTS_DECORATIONS;
        motif_hints.decorations = flags;
        
        /* get the atom for the property */
        prop = XInternAtom( dpy, "_MOTIF_WM_HINTS", True );
        if (!prop) {
                /* something went wrong! */
                return;
        }
        
        /* not sure this is correct, seems to work, XA_WM_HINTS didn't work */
        proptype = prop;
        
        XChangeProperty( dpy, w,                         /* display, window */
                         prop, proptype,                 /* property, type */
                         32,                             /* format: 32-bit 
datums */
                         PropModeReplace,                /* mode */
                         (unsigned char *) &motif_hints, /* data */
                         PROP_MOTIF_WM_HINTS_ELEMENTS    /* nelements */
                       );
}


/*
 * Create an RGB, double-buffered window.
 * Return the window and context handles.
 */
static void
make_window( Display *dpy, const char *name,
             int x, int y, int width, int height,
             Window *winRet, GLXContext *ctxRet)
{
        int attribs[] = { GLX_RGBA,
                          GLX_RED_SIZE, 1,
                          GLX_GREEN_SIZE, 1,
                          GLX_BLUE_SIZE, 1,
                          GLX_DOUBLEBUFFER,
                          GLX_DEPTH_SIZE, 1,
                          None };
        int scrnum;
        XSetWindowAttributes attr;
        unsigned long mask;
        Window root;
        Window win;
        GLXContext ctx;
        XVisualInfo *visinfo;
        
        scrnum = DefaultScreen( dpy );
        root = RootWindow( dpy, scrnum );
        
        if (fullscreen) {
                x = 0; y = 0;
                width = DisplayWidth( dpy, scrnum );
                height = DisplayHeight( dpy, scrnum );
        }
        
        visinfo = glXChooseVisual( dpy, scrnum, attribs );
        if (!visinfo) {
                printf("Error: couldn't get an RGB, Double-buffered visual\n");
                exit(1);
        }
        
        /* window attributes */
        attr.background_pixel = 0;
        attr.border_pixel = 0;
        attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
        attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
        /* XXX this is a bad way to get a borderless window! */
        mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
        
        win = XCreateWindow( dpy, root, x, y, width, height,
                        0, visinfo->depth, InputOutput,
                        visinfo->visual, mask, &attr );
        
        if (fullscreen)
                no_border(dpy, win);
        
        /* set hints and properties */
        {
                XSizeHints sizehints;
                sizehints.x = x;
                sizehints.y = y;
                sizehints.width  = width;
                sizehints.height = height;
                sizehints.flags = USSize | USPosition;
                XSetNormalHints(dpy, win, &sizehints);
                XSetStandardProperties(dpy, win, name, name,
                                        None, (char **)NULL, 0, &sizehints);
        }
        
        ctx = glXCreateContext( dpy, visinfo, NULL, True );
        if (!ctx) {
                printf("Error: glXCreateContext failed\n");
                exit(1);
        }
        
        XFree(visinfo);
        
        *winRet = win;
        *ctxRet = ctx;
}



/**
 * Only handle one glx event.
 */
void
handle_event(Display *dpy, Window win, XEvent *event)
{
        (void) dpy;
        (void) win;
        if( Glx_event == event->type){
                XEvent * event_p=event;
                GLXBufferSwapComplete * glx_event=(GLXBufferSwapComplete *) 
event_p;
                static double t_last=-1.0;
                time_fin=current_time();
                if (t_last < 0){
                        t_last=time_fin;
                }
                if ( time_fin - t_last >= 3.0){
                        if ( verbose ){
                                count=event_count_total%STACK_L;
                                printf("It receives the recent event at %lf 
seconds, and that glXSwapBuffers was called at %lf seconds, its swap returned 
at %lf seconds, so the total time of glXSwapBuffers takes is %lf seconds.\n", 
time_fin, swap_start[count], swap_returned[count], 
(time_fin-swap_start[count]));
                        }
                        t_last=time_fin;
                }
                switch (glx_event->event_type){
                case GLX_EXCHANGE_COMPLETE_INTEL:
                        Intel_swap_event=GLX_EXCHANGE_COMPLETE_INTEL;
                        swap_event_type="GLX_EXCHANGE_COMPLETE_INTEL";
                        event_count++;
                        event_count_total++;
                        break;
                case GLX_COPY_COMPLETE_INTEL:
                        Intel_swap_event=GLX_COPY_COMPLETE_INTEL;
                        swap_event_type="GLX_COPY_COMPLETE_INTEL";
                        event_count++;
                        event_count_total++;
                        break;
                case GLX_FLIP_COMPLETE_INTEL:
                        Intel_swap_event=GLX_FLIP_COMPLETE_INTEL;
                        swap_event_type="GLX_FLIP_COMPLETE_INTEL";
                        event_count++;
                        event_count_total++;
                        break;
                }
        }
}


static void
event_loop(Display *dpy, Window win)
{
        while (1) {
                while (XPending(dpy) > 0) {
                        XEvent event;
                        XNextEvent(dpy, &event);
                        Glx_event=event_base + GLX_BufferSwapComplete;
                        handle_event(dpy, win, &event);
                }
                
                draw_frame(dpy, win);
        }
}


static void
usage(void)
{
        printf("Usage:\n");
        printf("  -fullscreen             run in fullscreen mode\n");
        printf("  -v       verbose mode, have more log\n");
        printf("  -auto       test automatically \n");
        printf("        --event         test whether we can get swap events\n");
        printf("        --interval      we expect that swap interval set to 0 
should have higher swap frequency than interval to 1\n");
        printf("        --async         test whether glXSwapBuffers is done in 
asynchronous\n");
}
 

int
main(int argc, char *argv[])
{
        unsigned int winWidth = 30, winHeight = 30;
        int x = 0, y = 0;
        Display *dpy;
        Window win;
        GLXContext ctx;
        char *dpyName = NULL;
        int i, error_base;
        
        for (i = 1; i < argc; i++) {
                if (strcmp(argv[i], "-auto") == 0) {
                        Automatic = GL_TRUE;
                }
                else if (strcmp(argv[i], "-v") == 0) {
                        verbose = GL_TRUE;
                }
                else if (strcmp(argv[i], "-fullscreen") == 0) {
                        fullscreen = GL_TRUE;
                }
                else if (strcmp(argv[i], "--event") == 0) {
                        test_events=GL_TRUE;
                }
                else if (strcmp(argv[i], "--async") == 0) {
                        async = GL_TRUE;
                }
                else if (strcmp(argv[i], "--interval") == 0) {
                        interval_diff = GL_TRUE;
                }
                else {
                        usage();
                        return -1;
                }
        }
        
        dpy = XOpenDisplay(dpyName);
        if (!dpy) {
                printf("Error: couldn't open display %s\n",
                        dpyName ? dpyName : getenv("DISPLAY"));
                return -1;
        }
        
        make_window(dpy, "Swap event test", x, y, winWidth, winHeight, &win, 
&ctx);
        XMapWindow(dpy, win);
        glXMakeCurrent(dpy, win, ctx);
        query_swap_event(dpy);
        
        glXQueryExtension(dpy, &error_base, &event_base);
        
        (*pglXSwapIntervalMESA)(1);
        interval=(*pglXGetSwapIntervalMESA)();
        event_loop(dpy, win);
        
        glXDestroyContext(dpy, ctx);
        XDestroyWindow(dpy, win);
        XCloseDisplay(dpy);
        
        return 0;
}
------------------------------------------------------------------------------
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2 & L3.
Spend less time writing and  rewriting code and more time creating great
experiences on the web. Be a part of the beta today.
http://p.sf.net/sfu/beautyoftheweb
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to