scrolling XOR benchmark
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 17 May 2021 01:38:35 +0000 (04:38 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 17 May 2021 01:38:35 +0000 (04:38 +0300)
GNUmakefile
src/rbench.c
src/rbench.h
src/x11/main.c

index 8bb2548..450b272 100644 (file)
@@ -8,8 +8,8 @@ dbg = -g
 #opt = -O3 -ffast-math
 inc = -Isrc
 
-CFLAGS = -pedantic $(warn) $(dbg) $(opt) $(inc) -fcommon -MMD
-LDFLAGS = -lX11 -lm
+CFLAGS = -pedantic $(warn) $(dbg) $(opt) $(inc) -MMD
+LDFLAGS = -lX11 -lXext -lm
 
 $(bin): $(obj)
        $(CC) -o $@ $(obj) $(LDFLAGS)
index c72dca4..005013c 100644 (file)
@@ -1,5 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
+#include <math.h>
 #include "rbench.h"
 #include "treestor.h"
 
@@ -11,8 +13,86 @@ struct options opt = {
        DEF_WIDTH, DEF_HEIGHT, DEF_BPP
 };
 
+int fb_width, fb_height, fb_bpp, fb_pitch;
+void *framebuf;
+unsigned int time_msec;
+
+int init(void)
+{
+       return 0;
+}
+
+void cleanup(void)
+{
+}
+
+#define XORRGB(x, y, zoom, r, g, b) \
+       do { \
+               int xor = (((x) - fb_width/2) * (zoom) >> 10) ^ (((y) - fb_height/2) * (zoom) >> 10); \
+               (r) = xor >> 2; \
+               (g) = xor >> 1; \
+               (b) = xor; \
+       } while(0)
+
 void redraw(void)
 {
+       int i, j, r, g, b, xoffs, yoffs, zoom;
+       unsigned char *fbptr;
+       uint16_t *fbptr16;
+       uint32_t *fbptr32;
+       float t = (float)time_msec / 1000.0f;
+
+       xoffs = cos(t * 0.5f) * DEF_WIDTH * 2;
+       yoffs = sin(t) * DEF_HEIGHT;
+       zoom = (sin(t * 0.75f) * 0.5f + 1.0f) * 1024.0f;
+
+       switch(fb_bpp) {
+       case 15:
+               fbptr16 = framebuf;
+               for(i=0; i<fb_height; i++) {
+                       for(j=0; j<fb_width; j++) {
+                               XORRGB(j + xoffs, i + yoffs, zoom, r, g, b);
+                               *fbptr16++ = ((r & 0x1f) << 10) | ((g & 0x1f) << 5) | (b & 0x1f);
+                       }
+                       fbptr16 += (fb_pitch >> 1) - fb_width;
+               }
+               break;
+
+       case 16:
+               fbptr16 = framebuf;
+               for(i=0; i<fb_height; i++) {
+                       for(j=0; j<fb_width; j++) {
+                               XORRGB(j + xoffs, i + yoffs, zoom, r, g, b);
+                               *fbptr16++ = ((r & 0x1f) << 11) | ((g & 0x3f) << 5) | (b & 0x1f);
+                       }
+                       fbptr16 += (fb_pitch >> 1) - fb_width;
+               }
+               break;
+
+       case 24:
+               fbptr = framebuf;
+               for(i=0; i<fb_height; i++) {
+                       for(j=0; j<fb_width; j++) {
+                               XORRGB(j + xoffs, i + yoffs, zoom, r, g, b);
+                               *fbptr++ = r;
+                               *fbptr++ = g;
+                               *fbptr++ = b;
+                       }
+                       fbptr += fb_pitch - fb_width * 3;
+               }
+               break;
+
+       case 32:
+               fbptr32 = framebuf;
+               for(i=0; i<fb_height; i++) {
+                       for(j=0; j<fb_width; j++) {
+                               XORRGB(j + xoffs, i + yoffs, zoom, r, g, b);
+                               *fbptr32++ = ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
+                       }
+                       fbptr32 += (fb_pitch >> 2) - fb_width;
+               }
+               break;
+       }
 }
 
 void key_event(int key, int press)
index 551b93e..8efb0d1 100644 (file)
@@ -6,6 +6,12 @@ struct options {
 };
 
 extern struct options opt;
+extern int fb_width, fb_height, fb_bpp, fb_pitch;
+extern void *framebuf;
+extern unsigned int time_msec;
+
+int init(void);
+void cleanup(void);
 
 void redraw(void);
 void key_event(int key, int press);
index a3cc050..036e765 100644 (file)
@@ -1,8 +1,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/time.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/extensions/XShm.h>
 #include "rbench.h"
 
 enum { QUIT = 1, REDRAW = 2 };
@@ -17,11 +22,23 @@ static int mapped;
 static unsigned int pending;
 static Display *dpy;
 static Window win, root;
+static GC gc;
+static Visual *vis;
 static Atom xa_wm_proto, xa_wm_delwin;
 
+static XImage *ximg;
+static XShmSegmentInfo shm;
+static int wait_putimg;
+static int xshm_ev_completion;
+
 int main(int argc, char **argv)
 {
+       int num_frames;
        XEvent ev;
+       struct timeval tv, tv0;
+
+       shm.shmid = -1;
+       shm.shmaddr = (void*)-1;
 
        read_config("rbench.cfg");
 
@@ -37,18 +54,65 @@ int main(int argc, char **argv)
        xa_wm_proto = XInternAtom(dpy, "WM_PROTOCOLS", 0);
        xa_wm_delwin = XInternAtom(dpy, "WM_DELETE_WINDOW", 0);
 
+       if(!XShmQueryExtension(dpy)) {
+               fprintf(stderr, "X shared memory extension is not available\n");
+               XCloseDisplay(dpy);
+               return 1;
+       }
+       xshm_ev_completion = XShmGetEventBase(dpy) + ShmCompletion;
+
        if(!(win = create_win(opt.width, opt.height, opt.bpp))) {
                return 1;
        }
+       gc = XCreateGC(dpy, win, 0, 0);
+
+       if(!(ximg = XShmCreateImage(dpy, vis, opt.bpp, ZPixmap, 0, &shm, opt.width, opt.height))) {
+               fprintf(stderr, "failed to create shared memory image\n");
+               goto end;
+       }
+       if((shm.shmid = shmget(IPC_PRIVATE, ximg->bytes_per_line * ximg->height, IPC_CREAT | 0777)) == -1) {
+               fprintf(stderr, "failed to create shared memory block\n");
+               goto end;
+       }
+       if((shm.shmaddr = ximg->data = shmat(shm.shmid, 0, 0)) == (void*)-1) {
+               fprintf(stderr, "failed to attach shared memory block\n");
+               goto end;
+       }
+       shm.readOnly = True;
+       if(!XShmAttach(dpy, &shm)) {
+               fprintf(stderr, "XShmAttach failed");
+               goto end;
+       }
+
+       fb_width = opt.width;
+       fb_height = opt.height;
+       fb_bpp = opt.bpp >= 24 ? 32 : opt.bpp;
+       framebuf = ximg->data;
+       fb_pitch = ximg->bytes_per_line;
+
+       if(init() == -1) {
+               goto end;
+       }
+
+       gettimeofday(&tv0, 0);
+       num_frames = 0;
 
        for(;;) {
-               if(mapped) {
+               if(mapped) {/* && !wait_putimg) { */
                        while(XPending(dpy)) {
                                XNextEvent(dpy, &ev);
                                handle_event(&ev);
                                if(pending & QUIT) goto end;
                        }
+
+                       gettimeofday(&tv, 0);
+                       time_msec = (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
+                       num_frames++;
+
                        redraw();
+
+                       XShmPutImage(dpy, win, gc, ximg, 0, 0, 0, 0, ximg->width, ximg->height, False);
+                       /*wait_putimg = 1;*/
                } else {
                        XNextEvent(dpy, &ev);
                        handle_event(&ev);
@@ -57,8 +121,26 @@ int main(int argc, char **argv)
        }
 
 end:
-       XDestroyWindow(dpy, win);
+       cleanup();
+       if(ximg) {
+               XShmDetach(dpy, &shm);
+               XDestroyImage(ximg);
+               if(shm.shmaddr != (void*)-1) {
+                       shmdt(shm.shmaddr);
+               }
+               if(shm.shmid != -1) {
+                       shmctl(shm.shmid, IPC_RMID, 0);
+               }
+       }
+       if(win) {
+               XFreeGC(dpy, gc);
+               XDestroyWindow(dpy, win);
+       }
        XCloseDisplay(dpy);
+
+       if(num_frames) {
+               printf("avg framerate: %.1f fps\n", (10000 * num_frames / time_msec) / 10.0f);
+       }
        return 0;
 }
 
@@ -66,7 +148,7 @@ static Window create_win(int width, int height, int bpp)
 {
        int scr, num_vis;
        Window win;
-       XVisualInfo *vis, vinf;
+       XVisualInfo *vinf, vtmpl;
        unsigned int vinf_mask;
        XSetWindowAttributes xattr;
        XTextProperty txname;
@@ -75,24 +157,25 @@ static Window create_win(int width, int height, int bpp)
 
        scr = DefaultScreen(dpy);
 
-       vinf.screen = scr;
-       vinf.depth = bpp;
-       vinf.class = bpp <= 8 ? PseudoColor : TrueColor;
+       vtmpl.screen = scr;
+       vtmpl.depth = bpp;
+       vtmpl.class = bpp <= 8 ? PseudoColor : TrueColor;
        vinf_mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
-       if(!(vis = XGetVisualInfo(dpy, vinf_mask, &vinf, &num_vis))) {
+       if(!(vinf = XGetVisualInfo(dpy, vinf_mask, &vtmpl, &num_vis))) {
                fprintf(stderr, "failed to find appropriate visual for %d bpp\n", bpp);
                return 0;
        }
+       vis = vinf->visual;
 
-       if(!(cmap = XCreateColormap(dpy, root, vis->visual, bpp <= 8 ? AllocAll : AllocNone))) {
+       if(!(cmap = XCreateColormap(dpy, root, vis, bpp <= 8 ? AllocAll : AllocNone))) {
                fprintf(stderr, "failed to allocate colormap\n");
                return 0;
        }
 
        xattr.background_pixel = BlackPixel(dpy, scr);
        xattr.colormap = cmap;
-       win = XCreateWindow(dpy, root, 0, 0, width, height, 0, vis->depth,
-                       InputOutput, vis->visual, CWColormap | CWBackPixel, &xattr);
+       win = XCreateWindow(dpy, root, 0, 0, width, height, 0, vinf->depth,
+                       InputOutput, vis, CWColormap | CWBackPixel, &xattr);
        if(!win) return 0;
 
        XSelectInput(dpy, win, StructureNotifyMask | ExposureMask | KeyPressMask |
@@ -157,6 +240,9 @@ static void handle_event(XEvent *ev)
                break;
 
        default:
+               if(ev->type == xshm_ev_completion) {
+                       wait_putimg = 0;
+               }
                break;
        }
 }