Apply patch from jmorton
authorMikko Rasa <mikko.rasa@movial.fi>
Mon, 20 Apr 2009 08:13:00 +0000 (11:13 +0300)
committerMikko Rasa <mikko.rasa@movial.fi>
Mon, 20 Apr 2009 08:13:00 +0000 (11:13 +0300)
Makefile
benchcompare.py
main.c
synthetic.bench

index 26dc86d..8824a66 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
 VERSION=\"mx11mark-$(shell git rev-parse --short HEAD)\"
 
 mx11mark: main.c
-       $(CC) -o $@ $< -DVERSION=$(VERSION) $(shell pkg-config --cflags --libs xrender xft) -lm -ggdb -Wall -Wextra
+       $(CC) $(CFLAGS) -o $@ $< -DVERSION=$(VERSION) $(shell pkg-config --cflags --libs xrender xft) -lm -ggdb -Wall -Wextra
index 9f020c6..35cd841 100755 (executable)
@@ -6,8 +6,10 @@ import optparse
 
 parser=optparse.OptionParser()
 parser.add_option("-t", "--html", dest="html_output", action="store_true", default=False)
+parser.add_option("-p", "--pixelrate", dest="score_pixelrate", action="store_true", default=False)
 (options, args)=parser.parse_args()
 html_output=options.html_output
+score_pixelrate=options.score_pixelrate
 data=[]
 for fn in args:
        data.append([l[:-1].split(',') for l in file(fn)])
@@ -19,15 +21,17 @@ for i in range(len(data)):
                if len(b)==5:
                        score=int(b[0])
                        margin=int(b[1])
+                       pixelrate=float(b[3])/1000000
                        label=b[4]
                elif len(b)==3:
                        score=float(b[0])
-                       margin=None
+                       margin=0
+                       pixelrate=0
                        label="Overall"
                if label not in marks:
-                       marks[label]=[(0, 0)]*len(data)
+                       marks[label]=[(0, 0, 0)]*len(data)
                        order.append(label)
-               marks[label][i]=(score, margin)
+               marks[label][i]=(score, margin, pixelrate)
 
 if html_output:
        print """<?xml version="1.0" encoding="utf-8" ?>
@@ -53,29 +57,41 @@ if not html_output:
        table=[]
 for m in order:
        v=marks[m]
-       scores=[i[0] for i in v if i[0]>0]
+       scores=[]
+       if score_pixelrate and not scores:
+               scores=[i[2] for i in v if i[2]>0]
+       if not scores:
+               scores=[i[0] for i in v if i[0]>0]
        if not scores:
                continue
        high=max(scores)
        low=min(scores)
        baseline=scores[0]
 
+       if score_pixelrate:
+               score_index=2
+       else:
+               score_index=0
+
        if html_output:
                print "<tr><td>%s</td>"%m
                for i in range(len(data)):
                        klass=""
-                       if v[i][0]==high:
+                       if v[i][score_index]==high:
                                klass="best"
-                       elif v[i][0]==low:
+                       elif v[i][score_index]==low:
                                klass="worst"
 
                        cell="<td class=\"%s\">"%klass
-                       cell+="%s"%(v[i][0])
+                       if score_pixelrate:
+                               cell+="%.2f"%(v[i][2])
+                       else:
+                               cell+="%s"%(v[i][0])
                        if v[i][1]!=None and v[i][0]:
                                cell+=" <span class=\"detail\">±%.1f%%</span>"%(v[i][1]*100.0/v[i][0])
 
-                       if v[i][0]!=baseline:
-                               diff=v[i][0]*100.0/baseline-100
+                       if v[i][score_index]!=baseline:
+                               diff=v[i][score_index]*100.0/baseline-100
                                if diff<0:
                                        klass="decrease"
                                elif diff>0:
@@ -88,11 +104,14 @@ for m in order:
                row=[(m, None)]
                for i in range(len(data)):
                        attr=None
-                       if v[i][0]==high:
+                       if v[i][score_index]==high:
                                attr="32"
-                       elif v[i][0]==low:
+                       elif v[i][score_index]==low:
                                attr="31"
-                       row.append(("%s"%(v[i][0]), attr))
+                       if score_pixelrate:
+                               row.append(("%.2f"%(v[i][2]*1.0), attr))
+                       else:
+                               row.append(("%s"%(v[i][0]), attr))
                table.append(row)
 
 if html_output:
diff --git a/main.c b/main.c
index ee10cb2..241ff40 100644 (file)
--- a/main.c
+++ b/main.c
@@ -41,20 +41,21 @@ typedef struct sResult
 {
        unsigned ops_per_sec;
        unsigned error_margin;
+       unsigned long long pixels_per_sec;
 } Result;
 
 void update_crc32(unsigned *crc32, const char *data, unsigned size);
-Result measure(void (*func)(), unsigned batch, unsigned time, MeasureType type);
-void sync();
-void nop();
-void create_destroy_pixmap();
-void create_destroy_picture();
+Result measure(unsigned (*func)(), unsigned batch, unsigned time, MeasureType type);
+unsigned doSync();
+unsigned nop();
+unsigned create_destroy_pixmap();
+unsigned create_destroy_picture();
 void random_color(XRenderColor *color, int alpha);
-void fill_rectangle();
-void composite_trapezoid();
-void draw_string8();
-void copy_area();
-void composite_copy_area();
+unsigned fill_rectangle();
+unsigned composite_trapezoid();
+unsigned draw_string8();
+unsigned copy_area();
+unsigned composite_copy_area();
 
 Display *dpy;
 Window wnd;
@@ -62,6 +63,10 @@ Pixmap pxm;
 GC gc;
 int depth;
 XRenderPictFormat *pfmt;
+XRenderPictFormat *pfmtWin;
+XRenderPictFormat *pfmt16;
+XRenderPictFormat *pfmt24;
+XRenderPictFormat *pfmt32;
 Picture pict;
 Picture srcpict;
 int op;
@@ -73,6 +78,7 @@ char *text;
 unsigned textlen;
 int copymode;
 int verbosity;
+static unsigned metrics[256] = {0};
 
 int main(int argc, char **argv)
 {
@@ -153,9 +159,35 @@ int main(int argc, char **argv)
                        break;
        }
 
-       pft.depth=depth;
-       pfmt=XRenderFindFormat(dpy, PictFormatDepth, &pft, 1);
-       pict=XRenderCreatePicture(dpy, wnd, pfmt, 0, NULL);
+       pfmt24=XRenderFindStandardFormat(dpy, PictStandardRGB24);
+       pfmt32=XRenderFindStandardFormat(dpy, PictStandardARGB32);
+
+       pft.depth=16;
+       pft.direct.redMask   = 0x1F;
+       pft.direct.greenMask = 0x3F;
+       pft.direct.blueMask  = 0x1F;
+       pfmt16=XRenderFindFormat(dpy, PictFormatDepth | PictFormatRedMask | PictFormatGreenMask | PictFormatBlueMask, &pft, 1);
+
+       if(!pfmt16)
+       {
+               fprintf(stderr, "Warning: 16-bit pixel format not found.\n");
+               pfmt16 = pfmt24;
+       }
+
+       pfmtWin=XRenderFindVisualFormat(dpy, visual);
+       pict=XRenderCreatePicture(dpy, wnd, pfmtWin, 0, NULL);
+
+       pfmt = pfmtWin;
+
+       if(verbosity)
+       {
+               printf("PictFormat: id %X, type %X, depth %d, RGB%d%d%d A%d\n",
+                       (unsigned int) pfmtWin->id, pfmtWin->type, pfmtWin->depth,
+                       pfmtWin->direct.red, pfmtWin->direct.green, pfmtWin->direct.blue, pfmtWin->direct.alpha);
+               printf("            R=%08X G=%08X B=%08X A=%08X\n",
+                       pfmtWin->direct.redMask, pfmtWin->direct.greenMask, pfmtWin->direct.blueMask, pfmtWin->direct.alphaMask);
+
+       }
 
        op=PictOpSrc;
        while(1)
@@ -192,9 +224,20 @@ int main(int argc, char **argv)
                                sscanf(delim+1, "%dx%d", &width, &height);
                        else if(!strncmp(line, "font", delim-line))
                        {
+                               unsigned char c;
+
                                if(font)
                                        XftFontClose(dpy, font);
                                font=XftFontOpenName(dpy, screen, delim+1);
+
+                               for(c=32; c < 127; c++)
+                               {
+                                       XGlyphInfo extents;
+                                       unsigned char textptr[2] = {0,0};
+                                       textptr[0] = c;
+                                       XftTextExtents8(dpy, font, textptr, 1, &extents);
+                                       metrics[c] = extents.width * extents.height;
+                               }
                        }
                        else if(!strncmp(line, "text", delim-line))
                        {
@@ -236,6 +279,19 @@ int main(int argc, char **argv)
                                else
                                        fprintf(stderr, "Unknown copy mode '%s'\n", delim+1);
                        }
+                       else if(!strncmp(line, "depth", delim-line))
+                       {
+                               if(!strcmp(delim+1, "window"))
+                                       pfmt = pfmtWin;
+                               else if(!strcmp(delim+1, "16"))
+                                       pfmt = pfmt16;
+                               else if(!strcmp(delim+1, "24"))
+                                       pfmt = pfmt24;
+                               else if(!strcmp(delim+1, "32"))
+                                       pfmt = pfmt32;
+                               else
+                                       fprintf(stderr, "Unknown pixmap depth '%s'\n", delim+1);
+                       }
                        else
                                fprintf(stderr, "Unknown assignment '%s'\n", line);
                        continue;
@@ -258,34 +314,29 @@ int main(int argc, char **argv)
                        if(!strncmp(line, "run", delim-line))
                        {
                                Result res;
-                               unsigned size=0;
                                update_crc32(&crc32, line, strlen(line));
                                printf("%s:\n", test_name);
                                if(!strcmp(delim+1, "rect") || !strcmp(delim+1, "rectangle"))
                                {
-                                       size=width*height;
                                        res=measure(fill_rectangle, batch, time, type);
                                }
                                else if(!strcmp(delim+1, "trapezoid"))
                                {
                                        XRenderColor color;
                                        random_color(&color, 0);
-                                       size=width*height;
                                        srcpict=XRenderCreateSolidFill(dpy, &color);
                                        res=measure(composite_trapezoid, batch, time, type);
                                        XRenderFreePicture(dpy, srcpict);
                                }
                                else if(!strcmp(delim+1, "text"))
                                {
-                                       size=textlen;
                                        ftdraw=XftDrawCreate(dpy, wnd, visual, cmap);
                                        res=measure(draw_string8, batch, time, type);
                                        XftDrawDestroy(ftdraw);
                                }
                                else if(!strcmp(delim+1, "copy"))
                                {
-                                       size=width*height;
-                                       pxm=XCreatePixmap(dpy, wnd, 640, 480, depth);
+                                       pxm=XCreatePixmap(dpy, wnd, 640, 480, pfmtWin->depth);
                                        gc=XCreateGC(dpy, wnd, 0, NULL);
                                        XCopyArea(dpy, wnd, pxm, gc, 0, 0, 640, 480, 0, 0);
                                        res=measure(copy_area, batch, time, type);
@@ -294,12 +345,11 @@ int main(int argc, char **argv)
                                }
                                else if(!strcmp(delim+1, "composite"))
                                {
-                                       size=width*height;
-                                       pxm=XCreatePixmap(dpy, wnd, 640, 480, depth);
-                                       gc=XCreateGC(dpy, wnd, 0, NULL);
-                                       XCopyArea(dpy, wnd, pxm, gc, 0, 0, 640, 480, 0, 0);
-                                       XFreeGC(dpy, gc);
-                                       srcpict=XRenderCreatePicture(dpy, pxm, pfmt, 0, NULL);
+                                       XRenderPictureAttributes attrib;
+                                       attrib.component_alpha = !!(pfmt->direct.alphaMask);
+                                       pxm=XCreatePixmap(dpy, wnd, 640, 480, pfmt->depth);
+                                       srcpict=XRenderCreatePicture(dpy, pxm, pfmt, CPComponentAlpha, &attrib);
+                                       XRenderComposite(dpy, PictOpSrc, pict, None, srcpict, 0,0,0,0,0,0,640,480);
                                        res=measure(composite_copy_area, batch, time, type);
                                        XFreePixmap(dpy, pxm);
                                }
@@ -307,19 +357,19 @@ int main(int argc, char **argv)
                                        res=measure(create_destroy_pixmap, batch, time, type);
                                else if(!strcmp(delim+1, "picture"))
                                {
-                                       pxm=XCreatePixmap(dpy, wnd, width, height, depth);
+                                       pxm=XCreatePixmap(dpy, wnd, width, height, pfmt->depth);
                                        res=measure(create_destroy_picture, batch, time, type);
                                        XFreePixmap(dpy, pxm);
                                }
                                else if(!strcmp(delim+1, "sync"))
-                                       res=measure(sync, batch, time, type);
+                                       res=measure(doSync, batch, time, type);
                                else if(!strcmp(delim+1, "nop"))
                                        res=measure(nop, batch, time, type);
                                if(res.ops_per_sec>0)
                                {
                                        float score=(res.ops_per_sec-res.error_margin)/weight;
                                        if(out)
-                                               fprintf(out, "%d,%d,%.0f,%lld,%s\n", res.ops_per_sec, res.error_margin, score, (long long)res.ops_per_sec*size, test_name);
+                                               fprintf(out, "%d,%d,%.0f,%lld,%s\n", res.ops_per_sec, res.error_margin, score, res.pixels_per_sec, test_name);
                                        total+=1/score;
                                }
                        }
@@ -356,31 +406,31 @@ void update_crc32(unsigned *crc32, const char *data, unsigned size)
        }
 }
 
-unsigned filter_outliers(unsigned *data, unsigned count)
+unsigned filter_outliers(Result *data, unsigned count)
 {
        unsigned i;
        float average=0;
        unsigned n_out=0;
 
        for(i=0; i<count; ++i)
-               average+=data[i];
-       average/=count;
+               average += data[i].ops_per_sec;
+       average /= count;
 
        for(i=0; i<count; ++i)
-               if(fabs(data[i]-average)/average>0.05)
+               if(fabs(data[i].ops_per_sec - average) / average > 0.05)
                        ++n_out;
        if(n_out==0 || n_out>count/10)
                return 0;
 
        for(i=0; i<count; ++i)
-               if(fabs(data[i]-average)/average>0.05)
-                       data[i]=0;
+               if(fabs(data[i].ops_per_sec - average) / average > 0.05)
+                       data[i].ops_per_sec = 0;
        printf("  Filtered %d outliers\n", n_out);
 
        return n_out;
 }
 
-Result measure(void (*func)(), unsigned batch, unsigned time, MeasureType type)
+Result measure(unsigned (*func)(), unsigned batch, unsigned time, MeasureType type)
 {
        if(type==SINGLE_BATCH)
        {
@@ -391,36 +441,41 @@ Result measure(void (*func)(), unsigned batch, unsigned time, MeasureType type)
        {
                unsigned speed;
                unsigned i;
-               unsigned *data;
+               Result *data;
                Result res;
                unsigned nbatches;
                unsigned ngood;
                float average=0;
                float stddev=0;
+               float average_pixels=0;
 
                nbatches=batch;
                i=time/nbatches;
                speed=measure(func, 100, (i<1000 ? i<100 ? 100 : i : 1000), NORMAL).ops_per_sec;
                batch=(long long)speed*time/1000/nbatches;
 
-               data=(unsigned *)malloc(nbatches*sizeof(unsigned));
+               data = (Result*) malloc(nbatches*sizeof(Result));
                for(i=0; i<nbatches; ++i)
-                       data[i]=measure(func, batch, 1, NORMAL).ops_per_sec;
+                       data[i]=measure(func, batch, 1, NORMAL);
 
-               ngood=nbatches-filter_outliers(data, nbatches);
+               ngood = nbatches - filter_outliers(data, nbatches);
 
                for(i=0; i<nbatches; ++i)
-                       if(data[i])
+                       if(data[i].ops_per_sec)
                        {
-                               average+=data[i];
-                               stddev+=(float)data[i]*data[i];
+                               float n = data[i].ops_per_sec;
+                               average += n;
+                               stddev += n*n;
+                               average_pixels += data[i].pixels_per_sec;
                        }
-               average/=ngood;
-               stddev=sqrt(stddev/ngood-average*average);
+               average /= ngood;
+               average_pixels /= ngood;
+               stddev = sqrt(stddev/ngood - average*average);
 
                res.ops_per_sec=(unsigned)(average+0.5);
                res.error_margin=(unsigned)(stddev*2+0.5);
-               printf("  Average: %.0lf/sec  Std.dev.: %.0lf\n", average, stddev);
+               res.pixels_per_sec=(unsigned long long)(average_pixels+0.5);
+               printf("  Average: %.0lf/sec  (%.2lf Mpix/s)  Std.dev.: %.0lf\n", average, average_pixels/1000000, stddev);
                printf("  95%% confidence margin: %d (%.1lf%%)\n", res.error_margin, res.error_margin*100.0/res.ops_per_sec);
                return res;
        }
@@ -430,6 +485,7 @@ Result measure(void (*func)(), unsigned batch, unsigned time, MeasureType type)
                unsigned count=0;
                unsigned delta=0;
                Result res;
+               unsigned long long pixels = 0;
 
                srand(0);
 
@@ -437,8 +493,10 @@ Result measure(void (*func)(), unsigned batch, unsigned time, MeasureType type)
                while(delta<time)
                {
                        unsigned i;
-                       for(i=0; i<batch; ++i)
-                               func();
+                       for(i=0; i<batch; ++i) {
+                               pixels += func();
+                               // XFlush(dpy);
+                       }
                        XSync(dpy, True);
                        count+=batch;
                        gettimeofday(&end, NULL);
@@ -446,32 +504,41 @@ Result measure(void (*func)(), unsigned batch, unsigned time, MeasureType type)
                }
                res.ops_per_sec=count*1000/delta;
                res.error_margin=0;
+               res.pixels_per_sec=pixels*1000/delta;
                if(verbosity>=1)
                        printf("  %d calls in %d ms = %d/sec\n", count, delta, res.ops_per_sec);
                return res;
        }
 }
 
-void sync()
+unsigned doSync()
 {
        XSync(dpy, True);
+
+       return 0;
 }
 
-void nop()
+unsigned nop()
 {
        XMapWindow(dpy, wnd);
+
+       return 0;
 }
 
-void create_destroy_pixmap()
+unsigned create_destroy_pixmap()
 {
-       Pixmap p=XCreatePixmap(dpy, wnd, width, height, depth);
+       Pixmap p=XCreatePixmap(dpy, wnd, width, height, pfmt->depth);
        XFreePixmap(dpy, p);
+
+       return 0;
 }
 
-void create_destroy_picture()
+unsigned create_destroy_picture()
 {
        Picture p=XRenderCreatePicture(dpy, pxm, pfmt, 0, NULL);
        XRenderFreePicture(dpy, p);
+
+       return 0;
 }
 
 void random_color(XRenderColor *color, int alpha)
@@ -488,7 +555,7 @@ void random_color(XRenderColor *color, int alpha)
        }
 }
 
-void fill_rectangle()
+unsigned fill_rectangle()
 {
        int x, y;
        XRenderColor color;
@@ -497,9 +564,11 @@ void fill_rectangle()
        y=rand()%(481-height);
        random_color(&color, op==PictOpOver);
        XRenderFillRectangle(dpy, op, pict, &color, x, y, width, height);
+
+       return width*height;
 }
 
-void composite_trapezoid()
+unsigned composite_trapezoid()
 {
        int x, y;
        unsigned w;
@@ -523,9 +592,11 @@ void composite_trapezoid()
 
        XRenderCompositeTrapezoids(dpy, op, srcpict, pict, NULL, 0, 0, &trap, 1);
        XFlush(dpy);
+
+       return (((trap.right.p1.x - trap.left.p1.x) + (trap.right.p2.x - trap.left.p2.x)) >> 17) * height;
 }
 
-void draw_string8()
+unsigned draw_string8()
 {
        unsigned char textbuf[128];
        unsigned char *textptr;
@@ -537,14 +608,18 @@ void draw_string8()
        XftColor ftcolor;
        XGlyphInfo extents;
        int x, y;
+       unsigned pixels = 0;
 
        if(text)
                textptr=(unsigned char *)text;
        else
        {
                textptr=textbuf;
-               for(i=0; i<textlen; ++i)
-                       textbuf[i]=33+rand()%94;
+               for(i=0; i<textlen; ++i) {
+                       unsigned char c = 33+rand()%94;
+                       textbuf[i] = c;
+                       pixels += metrics[c];
+               }
        }
 
        screen=DefaultScreen(dpy);
@@ -554,12 +629,14 @@ void draw_string8()
        XftColorAllocValue(dpy, visual, cmap, &rcolor, &ftcolor);
 
        XftTextExtents8(dpy, font, textptr, textlen, &extents);
-       x=rand()%(641-extents.width);
-       y=rand()%(481-extents.height);
+       x = (rand()%(641-extents.width)) + extents.x;
+       y = (rand()%(481-extents.height)) + extents.y;
        XftDrawString8(ftdraw, &ftcolor, font, x, y, textptr, textlen);
+
+       return pixels;
 }
 
-void copy_area()
+unsigned copy_area()
 {
        int x1, y1;
        int x2, y2;
@@ -576,9 +653,11 @@ void copy_area()
        case 2: XCopyArea(dpy, wnd, wnd, gc, x1, y1, width, height, x2, y2); break;
        case 3: XCopyArea(dpy, wnd, pxm, gc, x1, y1, width, height, x2, y2); break;
        }
+
+       return width*height;
 }
 
-void composite_copy_area()
+unsigned composite_copy_area()
 {
        int x1, y1;
        int x2, y2;
@@ -595,4 +674,6 @@ void composite_copy_area()
        case 2: XRenderComposite(dpy, op, pict, None, pict, x1, y1, 0, 0, x2, y2, width, height); break;
        case 3: XRenderComposite(dpy, op, pict, None, srcpict, x1, y1, 0, 0, x2, y2, width, height); break;
        }
+
+       return width*height;
 }
index e82020e..b28f107 100644 (file)
@@ -1,4 +1,4 @@
-time=5000
+time=10000
 type=statistical
 batch=10
 
@@ -10,30 +10,6 @@ Sync:
 Nop:
        run nop
 
-Pixmap 16x16:
-       size=16x16
-       run pixmap
-
-Pixmap 256x256:
-       size=256x256
-       run pixmap
-
-Pixmap 1024x1024:
-       size=1024x1024
-       run pixmap
-
-Picture 16x16:
-       size=16x16
-       run picture
-
-Picture 256x256:
-       size=256x256
-       run picture
-
-Picture 1024x1024:
-       size=1024x1024
-       run picture
-
 op=src
 
 Rect 8x8 Src:
@@ -86,35 +62,87 @@ Rect 8x128 Over:
        size=8x128
        run rect
 
-copymode=pxm>wnd
+copymode=wnd>wnd
+op=src
 
-Copy 32x32:
+Copy (X) 32x32:
        size=32x32
        run copy
 
-Copy 128x128:
+Copy (X) 128x128:
        size=128x128
        run copy
 
-Composite 32x32:
+Copy (Render) 32x32:
        size=32x32
        run composite
 
-Composite 128x128:
+Copy (Render) 128x128:
        size=128x128
        run composite
 
-copymode=pxm>pxm
+copymode=pxm>wnd
+depth=16
+
+Composite (Src 16) 32x32:
+       size=32x32
+       run composite
 
-Copy 128x128 pixmap:
+Composite (Src 16) 128x128:
        size=128x128
-       run copy
+       run composite
+
+Composite (Src 16) 512x256:
+       size=512x256
+       run composite
+
+copymode=pxm>wnd
+depth=32
+
+Composite (Src 32) 32x32:
+       size=32x32
+       run composite
 
-Composite 128x128 pixmap:
+Composite (Src 32) 128x128:
        size=128x128
        run composite
 
+Composite (Src 32) 512x256:
+       size=512x256
+       run composite
+
+op=over
+depth=32
+
+Composite (Over 32) 32x32:
+       size=32x32
+       run composite
+
+Composite (Over 32) 128x128:
+       size=128x128
+       run composite
+
+Composite (Over 32) 512x256:
+       size=512x256
+       run composite
+
+op=over
+depth=24
+
+Composite (Over 24) 32x32:
+       size=32x32
+       run composite
+
+Composite (Over 24) 128x128:
+       size=128x128
+       run composite
+
+Composite (Over 24) 512x256:
+       size=512x256
+       run composite
+
 randomtext=20
+depth=window
 
 Text 8px:
        font=Sans Serif:pixelsize=8