From dee0f6aebe2faae7f5b05136beec802b20740514 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Mon, 17 May 2021 04:38:35 +0300 Subject: [PATCH] scrolling XOR benchmark --- GNUmakefile | 4 +-- src/rbench.c | 80 ++++++++++++++++++++++++++++++++++++++++++ src/rbench.h | 6 ++++ src/x11/main.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 184 insertions(+), 12 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 8bb2548..450b272 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -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) diff --git a/src/rbench.c b/src/rbench.c index c72dca4..005013c 100644 --- a/src/rbench.c +++ b/src/rbench.c @@ -1,5 +1,7 @@ #include #include +#include +#include #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> 1) - fb_width; + } + break; + + case 16: + fbptr16 = framebuf; + for(i=0; i> 1) - fb_width; + } + break; + + case 24: + fbptr = framebuf; + for(i=0; i> 2) - fb_width; + } + break; + } } void key_event(int key, int press) diff --git a/src/rbench.h b/src/rbench.h index 551b93e..8efb0d1 100644 --- a/src/rbench.h +++ b/src/rbench.h @@ -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); diff --git a/src/x11/main.c b/src/x11/main.c index a3cc050..036e765 100644 --- a/src/x11/main.c +++ b/src/x11/main.c @@ -1,8 +1,13 @@ #include #include #include +#include +#include +#include #include #include +#include +#include #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; } } -- 1.7.10.4