summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Rusin <zack@ppc64.localdomain>2006-03-16 15:48:03 -0500
committerZack Rusin <zack@ppc64.localdomain>2006-03-16 15:48:03 -0500
commit088058e06160944a83e171efecb9c88ec1e46891 (patch)
tree57224ea144b526217f89770b98b5c9b3e5355a85
initial version of xrender benchmarker
-rw-r--r--images/bg1.jpgbin0 -> 23771 bytes
-rw-r--r--images/kde_gear_64.pngbin0 -> 16480 bytes
-rw-r--r--images/qtlogo.pngbin0 -> 1067 bytes
-rw-r--r--main.cpp280
-rw-r--r--renderops.cpp42
-rw-r--r--renderops.h26
-rw-r--r--surface.cpp132
-rw-r--r--surface.h29
-rw-r--r--xrenderbenchmark.pro11
-rw-r--r--xrenderbenchmark.qrc7
10 files changed, 527 insertions, 0 deletions
diff --git a/images/bg1.jpg b/images/bg1.jpg
new file mode 100644
index 0000000..dfc7cee
--- /dev/null
+++ b/images/bg1.jpg
Binary files differ
diff --git a/images/kde_gear_64.png b/images/kde_gear_64.png
new file mode 100644
index 0000000..bd4e199
--- /dev/null
+++ b/images/kde_gear_64.png
Binary files differ
diff --git a/images/qtlogo.png b/images/qtlogo.png
new file mode 100644
index 0000000..4eb2175
--- /dev/null
+++ b/images/qtlogo.png
Binary files differ
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..129d852
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,280 @@
+#include <QApplication>
+#include <QImage>
+#include <QPixmap>
+#include <QX11Info>
+#include <QPainter>
+#include <QString>
+
+#include <iostream>
+#include <iomanip>
+using std::cout;
+using std::endl;
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/Xrender.h>
+#include <X11/extensions/XShm.h>
+
+#include <sys/time.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "surface.h"
+#include "renderops.h"
+
+#define REPS 1024
+
+double get_time(void);
+void time_test(char *description, void (*func) (void));
+
+void populate_from_file(Display *disp, XRenderSurf *rs, char *file);
+void main_loop(void);
+void setup_window(void);
+
+int win_w = 320;
+int win_h = 320;
+static Display *disp = NULL;
+static Window win;
+RenderOp current_op;
+int transformations = 0;
+
+
+RenderOp all_render_ops[] = {
+ {"PictOpClear", PictOpClear, 1},
+ {"PictOpSrc", PictOpSrc, 1},
+ {"PictOpDst", PictOpDst, 1},
+ {"PictOpOver", PictOpOver, 1},
+ {"PictOpOverReverse", PictOpOverReverse, 1},
+ {"PictOpIn", PictOpIn, 1},
+ {"PictOpInReverse", PictOpInReverse, 1},
+ {"PictOpOut", PictOpOut, 1},
+ {"PictOpOutReverse", PictOpOutReverse, 1},
+ {"PictOpAtop", PictOpAtop, 1},
+ {"PictOpAtopReverse", PictOpAtopReverse, 1},
+ {"PictOpXor", PictOpXor, 1},
+ {"PictOpAdd", PictOpAdd, 1},
+ {"PictOpSaturate", PictOpSaturate, 1},
+ {"PictOpDisjointClear", PictOpDisjointClear, 1},
+ {"PictOpDisjointSrc", PictOpDisjointSrc, 0},
+ {"PictOpDisjointDst", PictOpDisjointDst, 0},
+ {"PictOpDisjointOver", PictOpDisjointOver, 0},
+ {"PictOpDisjointOverReverse", PictOpDisjointOverReverse, 0},
+ {"PictOpDisjointIn", PictOpDisjointIn, 0},
+ {"PictOpDisjointInReverse", PictOpDisjointInReverse, 0},
+ {"PictOpDisjointOut", PictOpDisjointOut, 0},
+ {"PictOpDisjointOutReverse", PictOpDisjointOutReverse, 0},
+ {"PictOpDisjointAtop", PictOpDisjointAtop, 0},
+ {"PictOpDisjointAtopReverse", PictOpDisjointAtopReverse, 0},
+ {"PictOpDisjointXor", PictOpDisjointXor, 0},
+ {"PictOpConjointClear", PictOpConjointClear, 0},
+ {"PictOpConjointSrc", PictOpConjointSrc, 0},
+ {"PictOpConjointDst", PictOpConjointDst, 0},
+ {"PictOpConjointOver", PictOpConjointOver, 0},
+ {"PictOpConjointOverReverse", PictOpConjointOverReverse, 0},
+ {"PictOpConjointIn", PictOpConjointIn, 0},
+ {"PictOpConjointInReverse", PictOpConjointInReverse, 0},
+ {"PictOpConjointOut", PictOpConjointOut, 0},
+ {"PictOpConjointOutReverse", PictOpConjointOutReverse, 0},
+ {"PictOpConjointAtop", PictOpConjointAtop, 0},
+ {"PictOpConjointAtopReverse", PictOpConjointAtopReverse, 0},
+ {"PictOpConjointXor", PictOpConjointXor, 0},
+ {NULL, 0, 0}
+};
+
+PictureFactory picture_factories[] = {
+ {"PictStandardARGB32", ARGB32Creator},
+ {"PictStandardRGB24", RGB24Creator},
+ {"PictStandardA8", A8Creator},
+ {"PictStandardA4", A4Creator},
+ {"PictStandardA1", A1Creator}
+};
+
+double
+get_time(void)
+{
+ struct timeval timev;
+
+ gettimeofday(&timev, NULL);
+ return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
+}
+
+
+void
+time_test2(char *description, void (*func) (void))
+{
+ double t1, t2, t;
+ int i;
+
+ cout<<"Test: "<<std::setw(48)<< std::setiosflags(std::ios::left)<<description;
+
+ t1 = get_time();
+ for (i = 0; i < REPS; ++i)
+ func();
+ XSync(disp, False);
+ t2 = get_time();
+ t = t2 - t1;
+ printf(" Time: %3.3f sec.\n", t);
+}
+
+void
+populate_from_file(Display *disp, XRenderSurf *rs, const char *file)
+{
+ QImage im;
+ int w, h;
+
+ im.load(QString(file));
+ w = im.width();
+ h = im.height();
+ xrender_surf_populate(disp, rs, w, h, im);
+}
+
+XRenderSurf *surf_win = NULL;
+XRenderSurf *surf_off = NULL;
+XRenderSurf *surf_img = NULL;
+
+void
+test_oper(void)
+{
+ int x, y;
+
+ x = rand() % (surf_win->w - (surf_img->w/2));
+ y = rand() % (surf_win->h - (surf_img->h/2));
+ xrender_surf_simple_blend(disp, current_op.op,
+ surf_img, surf_win, x, y, surf_img->w, surf_img->h, transformations);
+}
+
+void
+main_loop(void)
+{
+ /* printf query filters */
+ printf("Available XRENDER filters:\n");
+ {
+ int i;
+ XFilters *flt;
+
+ flt = XRenderQueryFilters(disp, win);
+ for (i = 0; i < flt->nfilter; i++) printf("%s\n", flt->filter[i]);
+ }
+ printf("Setup...\n");
+ /* setup */
+ surf_win = xrender_surf_adopt(disp, win, DefaultVisual(disp, DefaultScreen(disp)), win_w, win_h);
+ surf_off = xrender_surf_new(disp, win, DefaultVisual(disp, DefaultScreen(disp)), win_w, win_h, 0);
+ surf_img = xrender_surf_new(disp, win, DefaultVisual(disp, DefaultScreen(disp)), 128, 128, 1);
+ populate_from_file(disp, surf_win, ":/res/images/bg1.jpg");
+ populate_from_file(disp, surf_off, ":/res/images/kde_gear_64.png");
+ populate_from_file(disp, surf_img, ":/res/images/kde_gear_64.png");
+
+ // Create a background tile pixmap
+ QPixmap bg( 40, 40 );
+ QPainter p( &bg );
+ p.fillRect( bg.rect(), QColor( 90, 90, 90 ) );
+ p.fillRect( QRect(0,0,20,20), QColor( 200, 200, 200 ) );
+ p.fillRect( QRect(20,20,20,20), QColor( 200, 200, 200 ) );
+ p.end();
+
+ // Change the repeat setting for the bg pixmap so it tiles, and clear the window with it
+ XRenderPictureAttributes pa;
+ pa.repeat = true;
+ XRenderChangePicture(QX11Info::display(), bg.x11PictureHandle(), CPRepeat, &pa );
+ XRenderComposite(QX11Info::display(), PictOpSrc, bg.x11PictureHandle(), None,
+ surf_win->pic, 0, 0, 0, 0, 0, 0, win_w, win_h);
+ XFlush(disp);
+
+ int i = 0;
+ current_op = all_render_ops[i++];
+ while (current_op.name)
+ {
+ char buf[256];
+ snprintf(buf, 255, "'%s' ", current_op.name);
+ time_test2(buf, test_oper);
+ current_op = all_render_ops[i++];
+ XSync(disp, False);
+
+ // Change the repeat setting for the bg pixmap so it tiles, and clear the window with it
+ XRenderPictureAttributes pa;
+ pa.repeat = true;
+ XRenderChangePicture(QX11Info::display(), bg.x11PictureHandle(), CPRepeat, &pa );
+ XRenderComposite(QX11Info::display(), PictOpSrc, bg.x11PictureHandle(), None,
+ surf_win->pic, 0, 0, 0, 0, 0, 0, win_w, win_h);
+
+ srand(7);
+ }
+
+ transformations = 1;
+ i = 0;
+ current_op = all_render_ops[i++];
+ while (current_op.name)
+ {
+ char buf[256];
+ snprintf(buf, 255, "'%s (transformation)' ", current_op.name);
+ time_test2(buf, test_oper);
+ current_op = all_render_ops[i++];
+ XSync(disp, False);
+
+ // Change the repeat setting for the bg pixmap so it tiles, and clear the window with it
+ XRenderPictureAttributes pa;
+ pa.repeat = true;
+ XRenderChangePicture(QX11Info::display(), bg.x11PictureHandle(), CPRepeat, &pa );
+ XRenderComposite(QX11Info::display(), PictOpSrc, bg.x11PictureHandle(), None,
+ surf_win->pic, 0, 0, 0, 0, 0, 0, win_w, win_h);
+
+ srand(7);
+ }
+
+ XSync(disp, False);
+}
+
+void
+setup_window(void)
+{
+ XSetWindowAttributes att;
+ XClassHint *xch;
+
+ att.background_pixmap = None;
+ att.colormap = DefaultColormap(disp, DefaultScreen(disp));
+ att.border_pixel = 0;
+ att.event_mask =
+ ButtonPressMask |
+ ButtonReleaseMask |
+ EnterWindowMask |
+ LeaveWindowMask |
+ PointerMotionMask |
+ ExposureMask |
+ StructureNotifyMask |
+ KeyPressMask |
+ KeyReleaseMask;
+ win = XCreateWindow(disp,
+ RootWindow(disp, DefaultScreen(disp)),
+ 0, 0, win_w, win_h, 0,
+ DefaultDepth(disp, DefaultScreen(disp)),
+ InputOutput,
+ DefaultVisual(disp, DefaultScreen(disp)),
+ CWColormap | CWBorderPixel | CWEventMask | CWBackPixmap,
+ &att);
+ XStoreName(disp, win, "Render Benchmarking Program");
+ xch = XAllocClassHint();
+ xch->res_name = "Main";
+ xch->res_class = "RenderBenchmark";
+ XSetClassHint(disp, win, xch);
+ XFree(xch);
+ XMapWindow(disp, win);
+ XSync(disp, False);
+ usleep(200000);
+ XSync(disp, False);
+}
+
+int
+main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ disp = QX11Info::display();
+ if (!disp)
+ {
+ printf("ERROR: Cannot connect to display!\n");
+ exit(-1);
+ }
+ setup_window();
+ main_loop();
+ return 0;
+}
diff --git a/renderops.cpp b/renderops.cpp
new file mode 100644
index 0000000..562734a
--- /dev/null
+++ b/renderops.cpp
@@ -0,0 +1,42 @@
+#include <QX11Info>
+#include "renderops.h"
+
+#include <X11/extensions/Xrender.h>
+
+
+Picture ARGB32Creator(int w, int h)
+{
+ XRenderPictFormat *fmt = XRenderFindStandardFormat(QX11Info::display(), PictStandardARGB32);
+ XRenderPictureAttributes att;
+
+ Drawable draw = XCreatePixmap(QX11Info::display(), draw, w, h, fmt->depth);
+ att.dither = 1;
+ att.component_alpha = 1;
+ att.repeat = 0;
+ return XRenderCreatePicture(QX11Info::display(), draw, fmt,
+ CPRepeat | CPDither | CPComponentAlpha, &att);
+}
+
+
+Picture RGB24Creator(int w, int h)
+{
+ return ARGB32Creator(w, h);
+}
+
+
+Picture A8Creator(int w, int h)
+{
+ return ARGB32Creator(w, h);
+}
+
+
+Picture A4Creator(int w, int h)
+{
+ return ARGB32Creator(w, h);
+}
+
+
+Picture A1Creator(int w, int h)
+{
+ return ARGB32Creator(w, h);
+}
diff --git a/renderops.h b/renderops.h
new file mode 100644
index 0000000..07f9b8d
--- /dev/null
+++ b/renderops.h
@@ -0,0 +1,26 @@
+#ifndef RENDEROPS_H
+#define RENDEROPS_H
+
+#include <X11/extensions/Xrender.h>
+
+struct RenderOp
+{
+ const char *name;
+ int op;
+ int baseOp;
+};
+
+typedef Picture (*PictureCreator)(int, int);
+struct PictureFactory
+{
+ const char *format;
+ PictureCreator creator;
+};
+
+Picture ARGB32Creator(int w, int h);
+Picture RGB24Creator(int w, int h);
+Picture A8Creator(int w, int h);
+Picture A4Creator(int w, int h);
+Picture A1Creator(int w, int h);
+
+#endif
diff --git a/surface.cpp b/surface.cpp
new file mode 100644
index 0000000..8390d6a
--- /dev/null
+++ b/surface.cpp
@@ -0,0 +1,132 @@
+#include <QImage>
+
+#include "surface.h"
+
+
+#include <stdlib.h>
+#include <stdio.h>
+
+XRenderSurf *
+xrender_surf_new(Display *disp, Drawable draw, Visual *vis, int w, int h, int alpha)
+{
+ XRenderSurf *rs;
+ XRenderPictFormat *fmt;
+ XRenderPictureAttributes att;
+
+ rs = (XRenderSurf*)calloc(1, sizeof(XRenderSurf));
+ if (alpha)
+ fmt = XRenderFindStandardFormat(disp, PictStandardARGB32);
+ else
+ fmt = XRenderFindStandardFormat(disp, PictStandardRGB24);
+ rs->w = w;
+ rs->h = h;
+ rs->depth = fmt->depth;
+ rs->vis = vis;
+ rs->draw = XCreatePixmap(disp, draw, w, h, fmt->depth);
+ att.dither = 1;
+ att.component_alpha = 1;
+ att.repeat = 0;
+ rs->pic = XRenderCreatePicture(disp, rs->draw, fmt,
+ CPRepeat | CPDither | CPComponentAlpha, &att);
+ rs->allocated = 1;
+ return rs;
+}
+
+XRenderSurf *
+xrender_surf_adopt(Display *disp, Drawable draw, Visual *vis, int w, int h)
+{
+ XRenderSurf *rs;
+ XRenderPictFormat *fmt;
+ XRenderPictureAttributes att;
+
+ rs = (XRenderSurf*)calloc(1, sizeof(XRenderSurf));
+ fmt = XRenderFindVisualFormat(disp, vis);
+ rs->w = w;
+ rs->h = h;
+ rs->depth = fmt->depth;
+ rs->vis = vis;
+ rs->draw = draw;
+ att.dither = 1;
+ att.component_alpha = 1;
+ att.repeat = 0;
+ rs->pic = XRenderCreatePicture(disp, rs->draw, fmt, CPRepeat | CPDither | CPComponentAlpha, &att);
+ rs->allocated = 0;
+ return rs;
+}
+
+void
+xrender_surf_free(Display *disp, XRenderSurf *rs)
+{
+ if (rs->allocated) XFreePixmap(disp, rs->draw);
+ XRenderFreePicture(disp, rs->pic);
+ free(rs);
+}
+
+void
+xrender_surf_populate(Display *disp, XRenderSurf *rs, int w, int h, const QImage &img_data)
+{
+ GC gc;
+ XGCValues gcv;
+ XImage *xim;
+ int x, y;
+
+ /* yes this isn't optimal - i know.. i just want some data for now */
+ gc = XCreateGC(disp, rs->draw, 0, &gcv);
+ xim = XCreateImage(disp, rs->vis, rs->depth, ZPixmap, 0, NULL, w, h, 32, 0);
+ xim->data = (char*)malloc(xim->bytes_per_line * xim->height);
+ for (y = 0; y < h; y++)
+ {
+ for (x = 0; x < w; x++)
+ {
+ QRgb pixel;
+ int a, r, g, b;
+
+ pixel = img_data.pixel(x, y);
+ a = (pixel >> 24) & 0xff;
+ r = (pixel >> 16) & 0xff;
+ g = (pixel >> 8 ) & 0xff;
+ b = (pixel ) & 0xff;
+ r = (r * (a + 1)) / 256;
+ g = (g * (a + 1)) / 256;
+ b = (b * (a + 1)) / 256;
+ XPutPixel(xim, x, y, (a << 24) | (r << 16) | (g << 8) | b);
+ }
+ }
+ XPutImage(disp, rs->draw, gc, xim, 0, 0, 0, 0, w, h);
+ free(xim->data);
+ xim->data = NULL;
+ XDestroyImage(xim);
+ XFreeGC(disp, gc);
+}
+
+void
+xrender_surf_blend(Display *disp, XRenderSurf *src, XRenderSurf *dst, int x, int y, int w, int h, int smooth)
+{
+ //XFilters *flt;
+ XTransform xf;
+
+ xf.matrix[0][0] = (65536 * src->w) / (w*2); xf.matrix[0][1] = 0; xf.matrix[0][2] = 0;
+ xf.matrix[1][0] = 0; xf.matrix[1][1] = (65536 * src->h) / h; xf.matrix[1][2] = 0;
+ xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = 65536;
+ if (smooth) XRenderSetPictureFilter(disp, src->pic, "bilinear", NULL, 0);
+ else XRenderSetPictureFilter(disp, src->pic, "nearest", NULL, 0);
+ XRenderSetPictureTransform(disp, src->pic, &xf);
+ XRenderComposite(disp, PictOpOver, src->pic, None, dst->pic, 0, 0, 0, 0, x, y, w, h);
+}
+
+
+void
+xrender_surf_simple_blend(Display *disp, int op, XRenderSurf *src, XRenderSurf *dst,
+ int x, int y, int w, int h, int transformations)
+{
+ if (transformations) {
+ XTransform xf;
+
+ xf.matrix[0][0] = (65536 * src->w) / (w*2); xf.matrix[0][1] = 0; xf.matrix[0][2] = 0;
+ xf.matrix[1][0] = 0; xf.matrix[1][1] = (65536 * src->h) / h; xf.matrix[1][2] = 0;
+ xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = 65536;
+ XRenderSetPictureFilter(disp, src->pic, "nearest", NULL, 0);
+ XRenderSetPictureTransform(disp, src->pic, &xf);
+ }
+ XRenderComposite(disp, op, src->pic, None, dst->pic, 0, 0, 0, 0, x, y, w, h);
+}
diff --git a/surface.h b/surface.h
new file mode 100644
index 0000000..0c1a191
--- /dev/null
+++ b/surface.h
@@ -0,0 +1,29 @@
+#ifndef SURFACE_H
+#define SURFACE_H
+
+#include <X11/extensions/Xrender.h>
+#include <X11/Xlib.h>
+
+class QImage;
+
+typedef struct _XRenderSurf {
+ int w, h;
+ int depth;
+ Visual *vis;
+ Drawable draw;
+ Picture pic;
+ int allocated : 1;
+} XRenderSurf;
+
+
+XRenderSurf *xrender_surf_new(Display *disp, Drawable draw, Visual *vis, int w, int h, int alpha);
+XRenderSurf *xrender_surf_adopt(Display *disp, Drawable draw, Visual *vis, int w, int h);
+void xrender_surf_free(Display *disp, XRenderSurf *rs);
+void xrender_surf_populate(Display *disp, XRenderSurf *rs, int w, int h,
+ const QImage &img_data);
+void xrender_surf_blend(Display *disp, XRenderSurf *src, XRenderSurf *dst,
+ int x, int y, int w, int h, int smooth);
+void xrender_surf_simple_blend(Display *disp, int op, XRenderSurf *src, XRenderSurf *dst,
+ int x, int y, int w, int h, int transformations);
+
+#endif
diff --git a/xrenderbenchmark.pro b/xrenderbenchmark.pro
new file mode 100644
index 0000000..f322c9c
--- /dev/null
+++ b/xrenderbenchmark.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+INCLUDEPATH += .
+
+# Input
+SOURCES += surface.cpp main.cpp renderops.cpp
+
+RESOURCES = xrenderbenchmark.qrc
+
+OBJECTS_DIR = .tmp
+MOC_DIR = .tmp
+RESOURCES_DIR = .tmp
diff --git a/xrenderbenchmark.qrc b/xrenderbenchmark.qrc
new file mode 100644
index 0000000..12293da
--- /dev/null
+++ b/xrenderbenchmark.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/res">
+ <file>images/bg1.jpg</file>
+ <file>images/qtlogo.png</file>
+ <file>images/kde_gear_64.png</file>
+</qresource>
+</RCC>