diff options
author | Zack Rusin <zack@ppc64.localdomain> | 2006-03-16 15:48:03 -0500 |
---|---|---|
committer | Zack Rusin <zack@ppc64.localdomain> | 2006-03-16 15:48:03 -0500 |
commit | 088058e06160944a83e171efecb9c88ec1e46891 (patch) | |
tree | 57224ea144b526217f89770b98b5c9b3e5355a85 |
initial version of xrender benchmarker
-rw-r--r-- | images/bg1.jpg | bin | 0 -> 23771 bytes | |||
-rw-r--r-- | images/kde_gear_64.png | bin | 0 -> 16480 bytes | |||
-rw-r--r-- | images/qtlogo.png | bin | 0 -> 1067 bytes | |||
-rw-r--r-- | main.cpp | 280 | ||||
-rw-r--r-- | renderops.cpp | 42 | ||||
-rw-r--r-- | renderops.h | 26 | ||||
-rw-r--r-- | surface.cpp | 132 | ||||
-rw-r--r-- | surface.h | 29 | ||||
-rw-r--r-- | xrenderbenchmark.pro | 11 | ||||
-rw-r--r-- | xrenderbenchmark.qrc | 7 |
10 files changed, 527 insertions, 0 deletions
diff --git a/images/bg1.jpg b/images/bg1.jpg Binary files differnew file mode 100644 index 0000000..dfc7cee --- /dev/null +++ b/images/bg1.jpg diff --git a/images/kde_gear_64.png b/images/kde_gear_64.png Binary files differnew file mode 100644 index 0000000..bd4e199 --- /dev/null +++ b/images/kde_gear_64.png diff --git a/images/qtlogo.png b/images/qtlogo.png Binary files differnew file mode 100644 index 0000000..4eb2175 --- /dev/null +++ b/images/qtlogo.png 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> |