xenocara/driver/xf86-video-intel/test/lowlevel-blt-bench.c
matthieu d031df2719 Update to xf86-video-intel 2.99.916
Fixes a display bug seenby ajacoutot@, ok jsg@ and kettenis@.
newer X.Org (2.99.917 or master) version cause corruption on older
machines (X40, i965), probably caused by a bug in our kernel,
under investigation by kettenis@.
2015-04-12 19:41:54 +00:00

466 lines
12 KiB
C

/*
* Copyright © 2009 Nokia Corporation
* Copyright © 2010 Movial Creative Technologies Oy
* Copyright © 2013 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <X11/X.h>
#include <X11/Xutil.h> /* for XDestroyImage */
#include <X11/Xlibint.h>
#include <X11/extensions/Xrender.h>
#if HAVE_MIT_SHM
#include <X11/extensions/XShm.h>
#if HAVE_X11_EXTENSIONS_SHMPROTO_H
#include <X11/extensions/shmproto.h>
#elif HAVE_X11_EXTENSIONS_SHMSTR_H
#include <X11/extensions/shmstr.h>
#else
#error Failed to find the right header for X11 MIT-SHM protocol definitions
#endif
#include <sys/ipc.h>
#include <sys/shm.h>
#endif
#include <pixman.h> /* for pixman blt functions */
#include "test.h"
static const struct format {
const char *name;
pixman_format_code_t pixman_format;
} formats[] = {
{ "a8r8g8b8", PIXMAN_a8r8g8b8 },
{ "x8r8g8b8", PIXMAN_x8r8g8b8 },
{ "a8", PIXMAN_a8 },
{ "a4", PIXMAN_a4 },
{ "a1", PIXMAN_a1 },
};
static const struct op {
int value;
const char *name;
} ops[] = {
{ PictOpClear, "Clear" },
{ PictOpSrc, "Src" },
{ PictOpDst, "Dst" },
{ PictOpOver, "Over" },
{ PictOpOverReverse, "OverReverse" },
{ PictOpIn, "In" },
{ PictOpInReverse, "InReverse" },
{ PictOpOut, "Out" },
{ PictOpOutReverse, "OutReverse" },
{ PictOpAtop, "Atop" },
{ PictOpAtopReverse, "AtopReverse" },
{ PictOpXor, "Xor" },
{ PictOpAdd, "Add" },
{ PictOpSaturate, "Saturate" },
{ PictOpMultiply, "Multiply" },
{ PictOpScreen, "Screen" },
{ PictOpOverlay, "Overlay" },
{ PictOpDarken, "Darken" },
{ PictOpLighten, "Lighten" },
{ PictOpColorDodge, "Dodge" },
{ PictOpColorBurn, "Burn" },
{ PictOpHardLight, "HardLight" },
{ PictOpSoftLight, "SoftLight" },
};
static Picture source_pixmap(struct test_display *t, struct test_target *target, int format)
{
XRenderColor render_color[2] = {
{ 0x8000, 0x8000, 0x8000, 0x8000 },
{ 0xffff, 0xffff, 0xffff, 0xffff },
};
Pixmap pixmap;
Picture picture;
pixmap = XCreatePixmap(t->dpy, t->root,
target->width, target->height,
PIXMAN_FORMAT_DEPTH(formats[format].pixman_format));
picture = XRenderCreatePicture(t->dpy, pixmap,
XRenderFindStandardFormat(t->dpy, format),
0, NULL);
XFreePixmap(t->dpy, pixmap);
XRenderFillRectangle(t->dpy, PictOpSrc, picture, &render_color[0],
0, 0, target->width, target->height/2);
XRenderFillRectangle(t->dpy, PictOpSrc, picture, &render_color[1],
0, target->height/2, target->width, target->height/2);
return picture;
}
static Picture source_a8r8g8b8(struct test_display *t, struct test_target *target)
{
return source_pixmap(t, target, 0);
}
static Picture source_x8r8g8b8(struct test_display *t, struct test_target *target)
{
return source_pixmap(t, target, 1);
}
static Picture source_a8(struct test_display *t, struct test_target *target)
{
return source_pixmap(t, target, 2);
}
static Picture source_a4(struct test_display *t, struct test_target *target)
{
return source_pixmap(t, target, 3);
}
static Picture source_a1(struct test_display *t, struct test_target *target)
{
return source_pixmap(t, target, 3);
}
static Picture source_1x1r(struct test_display *t, struct test_target *target)
{
XRenderColor render_color = { 0x8000, 0x8000, 0x8000, 0x8000 };
XRenderPictureAttributes pa;
Pixmap pixmap;
Picture picture;
pa.repeat = RepeatNormal;
pixmap = XCreatePixmap(t->dpy, t->root, 1, 1, 32);
picture = XRenderCreatePicture(t->dpy, pixmap,
XRenderFindStandardFormat(t->dpy, 0),
CPRepeat, &pa);
XFreePixmap(t->dpy, pixmap);
XRenderFillRectangle(t->dpy, PictOpSrc, picture, &render_color,
0, 0, 1, 1);
return picture;
}
static Picture source_solid(struct test_display *t, struct test_target *target)
{
XRenderColor render_color = { 0x8000, 0x8000, 0x8000, 0x8000 };
return XRenderCreateSolidFill(t->dpy, &render_color);
}
static Picture source_linear_horizontal(struct test_display *t, struct test_target *target)
{
XRenderColor colors[2] = {{0}, {0xffff, 0xffff, 0xffff, 0xffff}};
XFixed stops[2] = {0, 0xffff};
XLinearGradient gradient = { {0, 0}, {target->width << 16, 0}};
return XRenderCreateLinearGradient(t->dpy, &gradient, stops, colors, 2);
}
static Picture source_linear_vertical(struct test_display *t, struct test_target *target)
{
XRenderColor colors[2] = {{0}, {0xffff, 0xffff, 0xffff, 0xffff}};
XFixed stops[2] = {0, 0xffff};
XLinearGradient gradient = { {0, 0}, {0, target->height << 16}};
return XRenderCreateLinearGradient(t->dpy, &gradient, stops, colors, 2);
}
static Picture source_linear_diagonal(struct test_display *t, struct test_target *target)
{
XRenderColor colors[2] = {{0}, {0xffff, 0xffff, 0xffff, 0xffff}};
XFixed stops[2] = {0, 0xffff};
XLinearGradient gradient = { {0, 0}, {target->width << 16, target->height << 16}};
return XRenderCreateLinearGradient(t->dpy, &gradient, stops, colors, 2);
}
static Picture source_radial_concentric(struct test_display *t, struct test_target *target)
{
XRenderColor colors[2] = {{0}, {0xffff, 0xffff, 0xffff, 0xffff}};
XFixed stops[2] = {0, 0xffff};
XRadialGradient gradient = {
{
((target->width << 16) + 1) / 2,
((target->height << 16) + 1) / 2,
0,
},
{
((target->width << 16) + 1) / 2,
((target->height << 16) + 1) / 2,
target->width << 15,
}
};
return XRenderCreateRadialGradient(t->dpy, &gradient, stops, colors, 2);
}
static Picture source_radial_generic(struct test_display *t, struct test_target *target)
{
XRenderColor colors[2] = {{0}, {0xffff, 0xffff, 0xffff, 0xffff}};
XFixed stops[2] = {0, 0xffff};
XRadialGradient gradient = {
{ 0, 0, target->width << 14, },
{ target->width << 16, target->height << 16, target->width << 14, }
};
return XRenderCreateRadialGradient(t->dpy, &gradient, stops, colors, 2);
}
#if HAVE_MIT_SHM
static XShmSegmentInfo shmref, shmout;
static void setup_shm(struct test *t)
{
XShmSegmentInfo shm;
int size;
shm.shmid = -1;
if (!(t->ref.has_shm_pixmaps && t->out.has_shm_pixmaps))
return;
size = t->ref.width * t->ref.height * 4;
size = (size + 4095) & -4096;
shm.shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0666);
if (shm.shmid == -1)
return;
shm.shmaddr = shmat(shm.shmid, 0, 0);
if (shm.shmaddr == (char *) -1) {
shmctl(shm.shmid, IPC_RMID, NULL);
shm.shmid = -1;
return;
}
shm.readOnly = False;
shmref = shm;
XShmAttach(t->ref.dpy, &shmref);
XSync(t->ref.dpy, True);
shmout = shm;
XShmAttach(t->out.dpy, &shmout);
XSync(t->out.dpy, True);
}
static Picture source_shm(struct test_display *t, struct test_target *target)
{
XShmSegmentInfo *shm = t->target == REF ? &shmref : &shmout;
Pixmap pixmap;
Picture picture;
int size;
if (shm->shmid == -1)
return 0;
pixmap = XShmCreatePixmap(t->dpy, t->root,
shm->shmaddr, shm,
target->width, target->height, 32);
picture = XRenderCreatePicture(t->dpy, pixmap,
XRenderFindStandardFormat(t->dpy, 0),
0, NULL);
XFreePixmap(t->dpy, pixmap);
size = target->width * target->height * 4;
memset(shm->shmaddr, 0x80, size/2);
memset(shm->shmaddr+size/2, 0xff, size/2);
return picture;
}
#else
static void setup_shm(struct test *t) { }
static Picture source_shm(struct test_display *t, struct test_target *target) { return 0; }
#endif
static const struct {
Picture (*create)(struct test_display *, struct test_target *);
const char *name;
} source[] = {
{ source_a8r8g8b8, "a8r8g8b8 pixmap" },
{ source_x8r8g8b8, "x8r8g8b8 pixmap" },
{ source_a8, "a8 pixmap" },
{ source_a4, "a4 pixmap" },
{ source_a1, "a1 pixmap" },
{ source_1x1r, "a8r8g8b8 1x1R pixmap" },
{ source_solid, "solid" },
{ source_shm, "a8r8g8b8 shm" },
{ source_linear_horizontal, "linear (horizontal gradient)" },
{ source_linear_vertical, "linear (vertical gradient)" },
{ source_linear_diagonal, "linear (diagonal gradient)" },
{ source_radial_concentric, "radial (concentric)" },
{ source_radial_generic, "radial (generic)" },
};
static double _bench_source(struct test_display *t, enum target target_type,
int op, int src, int loops)
{
XRenderColor render_color = { 0x8000, 0x8000, 0x8000, 0x8000 };
struct test_target target;
Picture picture;
struct timespec tv;
double elapsed;
test_target_create_render(t, target_type, &target);
XRenderFillRectangle(t->dpy, PictOpClear, target.picture, &render_color,
0, 0, target.width, target.height);
picture = source[src].create(t, &target);
if (picture) {
test_timer_start(t, &tv);
while (loops--)
XRenderComposite(t->dpy, op,
picture, 0, target.picture,
0, 0,
0, 0,
0, 0,
target.width, target.height);
elapsed = test_timer_stop(t, &tv);
XRenderFreePicture(t->dpy, picture);
} else
elapsed = -1;
test_target_destroy_render(t, &target);
return elapsed;
}
static void bench_source(struct test *t, enum target target, int op, int src)
{
double out, ref;
fprintf(stdout, "%28s with %s: ", source[src].name, ops[op].name);
fflush(stdout);
op = ops[op].value;
ref = _bench_source(&t->ref, target, op, src, 1000);
if (ref < 0) {
fprintf(stdout, "SKIP\n");
return;
}
fprintf(stdout, "ref=%f, ", ref);
fflush(stdout);
out = _bench_source(&t->out, target, op, src, 1000);
if (out < 0) {
fprintf(stdout, "SKIP\n");
return;
}
fprintf(stdout, "out=%f\n", out);
}
static double _bench_mask(struct test_display *t, enum target target_type,
int op, int src, int mask, int loops)
{
XRenderColor render_color = { 0x8000, 0x8000, 0x8000, 0x8000 };
struct test_target target;
Picture ps, pm;
struct timespec tv;
double elapsed;
test_target_create_render(t, target_type, &target);
XRenderFillRectangle(t->dpy, PictOpClear, target.picture, &render_color,
0, 0, target.width, target.height);
ps = source[src].create(t, &target);
pm = source[mask].create(t, &target);
if (ps && pm) {
test_timer_start(t, &tv);
while (loops--)
XRenderComposite(t->dpy, op,
ps, pm, target.picture,
0, 0,
0, 0,
0, 0,
target.width, target.height);
elapsed = test_timer_stop(t, &tv);
} else
elapsed = -1;
if (ps)
XRenderFreePicture(t->dpy, ps);
if (pm)
XRenderFreePicture(t->dpy, pm);
test_target_destroy_render(t, &target);
return elapsed;
}
static void bench_mask(struct test *t, enum target target, int op, int src, int mask)
{
double out, ref;
fprintf(stdout, "%28s In %28s with %s: ",
source[src].name, source[mask].name, ops[op].name);
fflush(stdout);
op = ops[op].value;
ref = _bench_mask(&t->ref, target, op, src, mask, 1000);
if (ref < 0) {
fprintf(stdout, "SKIP\n");
return;
}
fprintf(stdout, "ref=%f, ", ref);
fflush(stdout);
out = _bench_mask(&t->out, target, op, src, mask, 1000);
if (out < 0) {
fprintf(stdout, "SKIP\n");
return;
}
fprintf(stdout, "out=%f\n", out);
}
int main(int argc, char **argv)
{
struct test test;
unsigned op, src, mask;
test_init(&test, argc, argv);
setup_shm(&test);
for (op = 0; op < sizeof(ops)/sizeof(ops[0]); op++) {
for (src = 0; src < sizeof(source)/sizeof(source[0]); src++)
bench_source(&test, ROOT, op, src);
fprintf (stdout, "\n");
for (src = 0; src < sizeof(source)/sizeof(source[0]); src++)
for (mask = 0; mask < sizeof(source)/sizeof(source[0]); mask++)
bench_mask(&test, ROOT, op, src, mask);
fprintf (stdout, "\n");
}
return 0;
}