diff options
author | Eric Anholt <anholt@freebsd.org> | 2004-05-10 07:21:19 +0000 |
---|---|---|
committer | Eric Anholt <anholt@freebsd.org> | 2004-05-10 07:21:19 +0000 |
commit | 258f238ae94782fa1c0e1d8b6280d8d61c9c0c40 (patch) | |
tree | a273cc3885629976bf82d35c20f071ac271550e6 |
Initial revision
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | COPYING | 19 | ||||
-rw-r--r-- | ChangeLog | 0 | ||||
-rw-r--r-- | INSTALL | 229 | ||||
-rw-r--r-- | Makefile.am | 12 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | README | 12 | ||||
-rw-r--r-- | TODO | 5 | ||||
-rwxr-xr-x | autogen.sh | 3 | ||||
-rw-r--r-- | configure.ac | 30 | ||||
-rw-r--r-- | main.c | 163 | ||||
-rw-r--r-- | ops.c | 243 | ||||
-rw-r--r-- | rendercheck.h | 55 | ||||
-rw-r--r-- | tests.c | 650 |
14 files changed, 1424 insertions, 0 deletions
@@ -0,0 +1 @@ +Written in 2004 by Eric Anholt.
\ No newline at end of file @@ -0,0 +1,19 @@ +Copyright 2004 Eric Anholt + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of Eric Anholt not be used in +advertising or publicity pertaining to distribution of the software without +specific, written prior permission. Eric Anholt makes no +representations about the suitability of this software for any purpose. It +is provided "as is" without express or implied warranty. + +ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..1d5db7c --- /dev/null +++ b/Makefile.am @@ -0,0 +1,12 @@ +bin_PROGRAMS = rendercheck + +rendercheck_SOURCES = \ + main.c \ + ops.c \ + rendercheck.h \ + tests.c + +rendercheck_CFLAGS = $(RC_CFLAGS) +rendercheck_LDADD = $(RC_LIBS) + +EXTRA_DIST = autogen.sh @@ -0,0 +1,2 @@ +9 May 2004: +First release of renderext. @@ -0,0 +1,12 @@ +rendercheck is a program to test a Render extension implementation against +separate calculations of expected output. + +Tests currently include: +- Destination coordinates correctness +- Source coordinates correctness +- Composite with and without mask (with/without component alpha), with 1x1 + repeating Pictures and 10x10 Pictures. + +Unfortunately, there are currently no command-line arguments to control +its execution. Options, such as verbosity or number of iterations to encourage +pixmap migration, are controlled only in source. @@ -0,0 +1,5 @@ +- Fix dest coords check (get_pixel broken) +- Get a useful number being produced for error values, and correct eval_diff's limit. +- Check transforms +- check source/mask pixels falling outside the drawable. +- Command line args for verbosity, what tests, move iter, etc. diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..b1376df --- /dev/null +++ b/autogen.sh @@ -0,0 +1,3 @@ +#! /bin/sh +autoreconf -v --install || exit 1 +./configure --enable-maintainer-mode "$@" diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..f1fd779 --- /dev/null +++ b/configure.ac @@ -0,0 +1,30 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.57) +AC_INIT([rendercheck], + 1.0, + [anholt@FreeBSD.org], + rendercheck) + +AC_CONFIG_SRCDIR([Makefile.am]) +AM_INIT_AUTOMAKE([dist-bzip2]) + +AC_CONFIG_AUX_DIR(.) + +AM_MAINTAINER_MODE + +# Checks for programs. +AC_PROG_CC + +# Checks for pkg-config packages +PKG_CHECK_MODULES(RC, xrender) +AC_SUBST(RC_CFLAGS) +AC_SUBST(RC_LIBS) + +# Checks for libraries. + +# Checks for header files. +AC_HEADER_STDC + +AC_OUTPUT([Makefile]) @@ -0,0 +1,163 @@ +/* + * $Id$ + * + * Copyright © 2004 Eric Anholt + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Eric Anholt not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Eric Anholt makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "rendercheck.h" +#include <stdlib.h> +#include <stdio.h> +#include <err.h> +#include <string.h> + +extern int num_ops; +extern int num_colors; +extern color4d colors[]; + +int is_verbose = FALSE; /* XXX: Make me a command line arg */ + +/* Number of times to repeat operations so that pixmaps will tend to get moved + * into offscreen memory and allow hardware acceleration. + */ +int pixmap_move_iter = 1; + +int win_width = 10; +int win_height = 10; + +static int +bit_count(int i) +{ + int count; + + count = (i >> 1) & 033333333333; + count = i - count - ((count >> 1) & 033333333333); + count = (((count + (count >> 3)) & 030707070707) % 077); + /* HAKMEM 169 */ + return count; +} + +/* This is not complete, but decent enough for now.*/ +void +describe_format(char *desc, int len, XRenderPictFormat *format) +{ + char ad[4] = "", rd[4] = "", gd[4] = "", bd[4] = ""; + int ac, rc, gc, bc; + int ashift; + + ac = bit_count(format->direct.alphaMask); + rc = bit_count(format->direct.redMask); + gc = bit_count(format->direct.greenMask); + bc = bit_count(format->direct.blueMask); + + if (ac != 0) { + snprintf(ad, 4, "a%d", ac); + ashift = format->direct.alpha; + } else if (rc + bc + gc < format->depth) { + /* There are bits that are not part of A,R,G,B. Mark them with + * an x. + */ + snprintf(ad, 4, "x%d", format->depth - (format->direct.red + + format->direct.green + format->direct.blue)); + if (format->direct.red == 0 || format->direct.green == 0) + ashift = format->depth; + else + ashift = 0; + } else + ashift = 0; + + if (rc != 0) + snprintf(rd, 4, "r%d", rc); + if (gc != 0) + snprintf(gd, 4, "g%d", gc); + if (bc != 0) + snprintf(bd, 4, "b%d", bc); + + if (ashift > format->direct.red) { + if (format->direct.red > format->direct.blue) + snprintf(desc, len, "%s%s%s%s", ad, rd, gd, bd); + else + snprintf(desc, len, "%s%s%s%s", ad, bd, gd, rd); + } else { + if (format->direct.red > format->direct.blue) + snprintf(desc, len, "%s%s%s%s", rd, gd, bd, ad); + else + snprintf(desc, len, "%s%s%s%s", bd, gd, rd, ad); + } +} + +int main(int argc, char **argv) +{ + Display *dpy; + XEvent ev; + int i, maj, min; + XWindowAttributes a; + picture_info window; + char window_desc[20]; + + dpy = XOpenDisplay(0); + + if (!XRenderQueryExtension(dpy, &i, &i)) + errx(1, "Render extension missing."); + + XRenderQueryVersion(dpy, &maj, &min); + if (maj != 0 || min < 1) + errx(1, "Render extension version too low (%d.%d).", maj, min); + + printf("Render extension version %d.%d\n", maj, min); + + /* Conjoint/Disjoint were added in version 0.2, so disable those ops if + * the server doesn't support them. + */ + if (min < 2) { + printf("Server doesn't support conjoint/disjoint ops, disabling.\n"); + num_ops = PictOpSaturate; + } + + window.d = XCreateSimpleWindow(dpy, RootWindow(dpy, 0), 0, 0, win_width, + win_height, 0, 0, WhitePixel(dpy, 0)); + XGetWindowAttributes(dpy, window.d, &a); + window.format = XRenderFindVisualFormat(dpy, a.visual); + window.pict = XRenderCreatePicture(dpy, window.d, + window.format, 0, 0); + XSelectInput(dpy, window.d, ExposureMask); + XMapWindow(dpy, window.d); + + describe_format(window_desc, 20, window.format); + printf("Window format: %s\n", window_desc); + + /* We have to premultiply the alpha into the r, g, b values of the + * sample colors. Render colors are premultiplied with alpha, so r,g,b + * can never be greater than alpha. + */ + for (i = 0; i < num_colors; i++) { + colors[i].r *= colors[i].a; + colors[i].g *= colors[i].a; + colors[i].b *= colors[i].a; + } + + while (XNextEvent(dpy, &ev) == 0) { + if (ev.type == Expose && !ev.xexpose.count) { + begin_test(dpy, &window); + exit(0); + } + } + return 0; +} @@ -0,0 +1,243 @@ +/* + * $Id$ + * + * Copyright © 2004 Eric Anholt + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Eric Anholt not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Eric Anholt makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "rendercheck.h" + +#define mult_chan(src, dst, Fa, Fb) \ + min((double)(src) * (double)(Fa) + (double)(dst) * (double)(Fb), 1.0) + +static double +calc_op(int op, double src, double dst, double srca, double dsta) +{ + double Fa, Fb; + + switch (op) { + case PictOpClear: + case PictOpDisjointClear: + case PictOpConjointClear: + return mult_chan(src, dst, 0.0, 0.0); + case PictOpSrc: + case PictOpDisjointSrc: + case PictOpConjointSrc: + return mult_chan(src, dst, 1.0, 0.0); + case PictOpDst: + case PictOpDisjointDst: + case PictOpConjointDst: + return mult_chan(src, dst, 0.0, 1.0); + case PictOpOver: + return mult_chan(src, dst, 1.0, 1.0 - srca); + case PictOpOverReverse: + return mult_chan(src, dst, 1.0 - dsta, 1.0); + case PictOpIn: + return mult_chan(src, dst, dsta, 0.0); + case PictOpInReverse: + return mult_chan(src, dst, 0.0, srca); + case PictOpOut: + return mult_chan(src, dst, 1.0 - dsta, 0.0); + case PictOpOutReverse: + return mult_chan(src, dst, 0.0, 1.0 - srca); + case PictOpAtop: + return mult_chan(src, dst, dsta, 1.0 - srca); + case PictOpAtopReverse: + return mult_chan(src, dst, 1.0 - dsta, srca); + case PictOpXor: + return mult_chan(src, dst, 1.0 - dsta, 1.0 - srca); + case PictOpAdd: + return mult_chan(src, dst, 1.0, 1.0); + break; + case PictOpSaturate: + case PictOpDisjointOverReverse: + if (srca == 0.0) + Fa = 1.0; + else + Fa = min(1.0, (1.0 - dsta) / srca); + return mult_chan(src, dst, Fa, 1.0); + case PictOpDisjointOver: + if (dsta == 0.0) + Fb = 1.0; + else + Fb = min(1.0, (1.0 - srca) / dsta); + return mult_chan(src, dst, 1.0, Fb); + case PictOpDisjointIn: + if (srca == 0.0) + Fa = 0.0; + else + Fa = max(0.0, 1.0 - (1.0 - dsta) / srca); + return mult_chan(src, dst, Fa, 0.0); + case PictOpDisjointInReverse: + if (dsta == 0.0) + Fb = 0.0; + else + Fb = max(0.0, 1.0 - (1.0 - srca) / dsta); + return mult_chan(src, dst, 0.0, Fb); + case PictOpDisjointOut: + if (srca == 0.0) + Fa = 1.0; + else + Fa = min(1.0, (1.0 - dsta) / srca); + return mult_chan(src, dst, Fa, 0.0); + case PictOpDisjointOutReverse: + if (dsta == 0.0) + Fb = 1.0; + else + Fb = min(1.0, (1.0 - srca) / dsta); + return mult_chan(src, dst, 0.0, Fb); + case PictOpDisjointAtop: + if (srca == 0.0) + Fa = 0.0; + else + Fa = max(0.0, 1.0 - (1.0 - dsta) / srca); + if (dsta == 0.0) + Fb = 1.0; + else + Fb = min(1.0, (1.0 - srca) / dsta); + return mult_chan(src, dst, Fa, Fb); + case PictOpDisjointAtopReverse: + if (srca == 0.0) + Fa = 1.0; + else + Fa = min(1.0, (1.0 - dsta) / srca); + if (dsta == 0.0) + Fb = 0.0; + else + Fb = max(0.0, 1.0 - (1.0 - srca) / dsta); + return mult_chan(src, dst, Fa, Fb); + case PictOpDisjointXor: + if (srca == 0.0) + Fa = 1.0; + else + Fa = min(1.0, (1.0 - dsta) / srca); + if (dsta == 0.0) + Fb = 1.0; + else + Fb = min(1.0, (1.0 - srca) / dsta); + return mult_chan(src, dst, Fa, Fb); + case PictOpConjointOver: + if (dsta == 0.0) + Fb = 0.0; + else + Fb = max(0.0, 1.0 - srca / dsta); + return mult_chan(src, dst, 1.0, Fb); + case PictOpConjointOverReverse: + if (srca == 0.0) + Fa = 0.0; + else + Fa = max(0.0, 1.0 - dsta / srca); + return mult_chan(src, dst, Fa, 1.0); + case PictOpConjointIn: + if (srca == 0.0) + Fa = 1.0; + else + Fa = min(1.0, dsta / srca); + return mult_chan(src, dst, Fa, 0.0); + case PictOpConjointInReverse: + if (dsta == 0.0) + Fb = 1.0; + else + Fb = min(1.0, srca / dsta); + return mult_chan(src, dst, 0.0, Fb); + case PictOpConjointOut: + if (srca == 0.0) + Fa = 0.0; + else + Fa = max(0.0, 1.0 - dsta / srca); + return mult_chan(src, dst, Fa, 0.0); + case PictOpConjointOutReverse: + if (dsta == 0.0) + Fb = 0.0; + else + Fb = max(0.0, 1.0 - srca / dsta); + return mult_chan(src, dst, 0.0, Fb); + case PictOpConjointAtop: + if (srca == 0.0) + Fa = 1.0; + else + Fa = min(1.0, dsta / srca); + if (dsta == 0.0) + Fb = 0.0; + else + Fb = max(0.0, 1.0 - srca / dsta); + return mult_chan(src, dst, Fa, Fb); + case PictOpConjointAtopReverse: + if (srca == 0.0) + Fa = 0.0; + else + Fa = max(0.0, 1.0 - dsta / srca); + if (dsta == 0.0) + Fb = 1.0; + else + Fb = min(1.0, srca / dsta); + return mult_chan(src, dst, Fa, Fb); + case PictOpConjointXor: + if (srca == 0.0) + Fa = 0.0; + else + Fa = max(0.0, 1.0 - dsta / srca); + if (dsta == 0.0) + Fb = 0.0; + else + Fb = max(0.0, 1.0 - srca / dsta); + return mult_chan(src, dst, Fa, Fb); + default: + abort(); + } +} + +void +do_composite(int op, color4d *src, color4d *mask, color4d *dst, color4d *result, + Bool componentAlpha) +{ + color4d srcval, srcalpha; + + if (mask != NULL && componentAlpha) { + srcval.r = src->r * mask->r; + srcval.g = src->g * mask->g; + srcval.b = src->b * mask->b; + srcval.a = src->a * mask->a; + srcalpha.r = src->a * mask->r; + srcalpha.g = src->a * mask->g; + srcalpha.b = src->a * mask->b; + srcalpha.a = src->a * mask->a; + } else if (mask != NULL) { + srcval.r = src->r * mask->a; + srcval.g = src->g * mask->a; + srcval.b = src->b * mask->a; + srcval.a = src->a * mask->a; + srcalpha.r = src->a * mask->a; + srcalpha.g = src->a * mask->a; + srcalpha.b = src->a * mask->a; + srcalpha.a = src->a * mask->a; + } else { + srcval = *src; + srcalpha.r = src->a; + srcalpha.g = src->a; + srcalpha.b = src->a; + srcalpha.a = src->a; + } + + result->r = calc_op(op, srcval.r, dst->r, srcalpha.r, dst->a); + result->g = calc_op(op, srcval.g, dst->g, srcalpha.g, dst->a); + result->b = calc_op(op, srcval.b, dst->b, srcalpha.b, dst->a); + result->a = calc_op(op, srcval.a, dst->a, srcalpha.a, dst->a); +} diff --git a/rendercheck.h b/rendercheck.h new file mode 100644 index 0000000..0686a9d --- /dev/null +++ b/rendercheck.h @@ -0,0 +1,55 @@ +/* + * $Id$ + * + * Copyright © 2004 Eric Anholt + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Eric Anholt not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Eric Anholt makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include <X11/extensions/Xrender.h> + +#define min(a, b) (a < b ? a : b) +#define max(a, b) (a > b ? a : b) + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +typedef struct _color4d +{ + double r, g, b, a; +} color4d; + +typedef struct _picture_info { + Drawable d; + Picture pict; + XRenderPictFormat *format; + char *name; /* Possibly, some descriptive name. */ + color4d color; /* If a 1x1R pict, the (corrected) color.*/ +} picture_info; + +/* tests.c */ +void +begin_test(Display *dpy, picture_info *win); + +/* ops.c */ +void +do_composite(int op, color4d *src, color4d *mask, color4d *dst, color4d *result, + Bool componentAlpha); @@ -0,0 +1,650 @@ +/* + * $Id$ + * + * Copyright © 2004 Eric Anholt + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Eric Anholt not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Eric Anholt makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "rendercheck.h" + +extern int win_width, win_height; +extern int pixmap_move_iter; +extern Bool is_verbose; + +color4d colors[] = { + {1.0, 1.0, 1.0, 1.0}, + {1.0, 0, 0, 1.0}, + {0, 1.0, 0, 1.0}, + {0, 0, 1.0, 1.0}, + {0.5, 0, 0, 0.25}, + {0.5, 0, 0, .5}, + {0.0, .5, 1.0, .5}, + {0.0, .5, 1.0, 0} +}; + +int num_colors = sizeof(colors) / sizeof(colors[0]); + +struct op_info { + int op; + 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"}, + {PictOpDisjointClear, "DisjointClear"}, + {PictOpDisjointSrc, "DisjointSrc"}, + {PictOpDisjointDst, "DisjointDst"}, + {PictOpDisjointOver, "DisjointOver"}, + {PictOpDisjointOverReverse, "DisjointOverReverse"}, + {PictOpDisjointIn, "DisjointIn"}, + {PictOpDisjointInReverse, "DisjointInReverse"}, + {PictOpDisjointOut, "DisjointOut"}, + {PictOpDisjointOutReverse, "DisjointOutReverse"}, + {PictOpDisjointAtop, "DisjointAtop"}, + {PictOpDisjointAtopReverse, "DisjointAtopReverse"}, + {PictOpDisjointXor, "DisjointXor"}, + {PictOpConjointClear, "ConjointClear"}, + {PictOpConjointSrc, "ConjointSrc"}, + {PictOpConjointDst, "ConjointDst"}, + {PictOpConjointOver, "ConjointOver"}, + {PictOpConjointOverReverse, "ConjointOverReverse"}, + {PictOpConjointIn, "ConjointIn"}, + {PictOpConjointInReverse, "ConjointInReverse"}, + {PictOpConjointOut, "ConjointOut"}, + {PictOpConjointOutReverse, "ConjointOutReverse"}, + {PictOpConjointAtop, "ConjointAtop"}, + {PictOpConjointAtopReverse, "ConjointAtopReverse"}, + {PictOpConjointXor, "ConjointXor"}, +}; + +int num_ops = sizeof(ops) / sizeof(ops[0]); + +/* Originally a bullseye, this pattern has been modified so that flipping + * will result in errors as well. + */ +int target_colors[5][5] = { + {1, 1, 1, 1, 1}, + {1, 0, 0, 0, 1}, + {1, 1, 1, 0, 1}, + {1, 0, 0, 1, 1}, + {1, 1, 1, 1, 1}, +}; + +#define round_pix(pix, mask) \ + ((double)((int)(pix * (mask ) + .5)) / (double)(mask)) + +static void +color_correct(picture_info *pi, color4d *color) +{ + if (!pi->format->direct.redMask) { + color->r = 0.0; + color->g = 0.0; + color->b = 0.0; + } else { + color->r = round_pix(color->r, pi->format->direct.redMask); + color->g = round_pix(color->g, pi->format->direct.greenMask); + color->b = round_pix(color->b, pi->format->direct.blueMask); + } + if (!pi->format->direct.alphaMask) + color->a = 1.0; + else + color->a = round_pix(color->a, pi->format->direct.alphaMask); +} + +static void +get_pixel(Display *dpy, picture_info *pi, int x, int y, color4d *color) +{ + XImage *image; + unsigned long val; + unsigned long rm, gm, bm, am; + + /* XXX: I am xlib clueless, and this function appears to not work right. + * I think it just always gets the 0,0 pixel, but I'm not sure. + */ + image = XGetImage(dpy, pi->d, x, y, 1, 1, 0xffffffff, ZPixmap); + /*val = image->f.get_pixel(image, x, y);*/ + + val = *(unsigned long *)image->data; + + rm = pi->format->direct.redMask << pi->format->direct.red; + gm = pi->format->direct.greenMask << pi->format->direct.green; + bm = pi->format->direct.blueMask << pi->format->direct.blue; + am = pi->format->direct.alphaMask << pi->format->direct.alpha; + if (am != 0) + color->a = (double)(val & am) / (double)am; + else + color->a = 1.0; + if (rm != 0) { + color->r = (double)(val & rm) / (double)rm; + color->g = (double)(val & gm) / (double)gm; + color->b = (double)(val & bm) / (double)bm; + } else { + color->r = 0.0; + color->g = 0.0; + color->b = 0.0; + } +} + +static int +eval_diff(char *name, color4d *expected, color4d *test, int x, int y, + Bool verbose) +{ + double rscale, gscale, bscale, ascale; + double rdiff, gdiff, bdiff, adiff, diff; + + /* XXX: Need to be provided mask shifts so we can produce useful error + * values. + */ + rscale = 1.0 * (1 << 5); + gscale = 1.0 * (1 << 6); + bscale = 1.0 * (1 << 5); + ascale = 1.0; + rdiff = fabs(test->r - expected->r) * rscale; + bdiff = fabs(test->g - expected->g) * gscale; + gdiff = fabs(test->b - expected->b) * bscale; + adiff = fabs(test->a - expected->a) * ascale; + /*rdiff = log2(1.0 + rdiff); + gdiff = log2(1.0 + gdiff); + bdiff = log2(1.0 + bdiff); + adiff = log2(1.0 + adiff);*/ + diff = max(max(max(rdiff, gdiff), bdiff), adiff); + if (diff > 3.0) { + printf("%s test error of %.4f at (%d, %d) --\n" + "got: %.2f %.2f %.2f %.2f\n" + "expected: %.2f %.2f %.2f %.2f\n", name, diff, x, y, + test->r, test->g, test->b, test->a, + expected->r, expected->g, expected->b, expected->a); + return FALSE; + } else if (verbose) { + printf("%s test succeeded at (%d, %d) with %.4f: " + "%.2f %.2f %.2f %.2f\n", name, x, y, diff, + expected->r, expected->g, expected->b, expected->a); + } + return TRUE; +} + +static Bool +fill_test(Display *dpy, picture_info *win, picture_info *src, picture_info *dst) +{ + color4d expected, tested; + + XRenderComposite(dpy, PictOpSrc, src->pict, 0, dst->pict, 0, 0, 0, 0, + 0, 0, win_width, win_height); + get_pixel(dpy, dst, 0, 0, &tested); + /* Copy the output to the window, so the user sees something visual. */ + XRenderComposite(dpy, PictOpSrc, dst->pict, 0, win->pict, 0, 0, 0, 0, + 0, 0, win_width, win_height); + + expected = src->color; + color_correct(dst, &expected); + return eval_diff("fill", &expected, &tested, 0, 0, is_verbose); +} + +static Bool +destcoords_test(Display *dpy, picture_info *win, picture_info *dst, + picture_info *bg, picture_info *fg) +{ + color4d expected, tested; + int x, y; + Bool failed = FALSE; + + XRenderComposite(dpy, PictOpSrc, bg->pict, 0, dst->pict, 0, 0, 0, 0, + 0, 0, win_width, win_height); + XRenderComposite(dpy, PictOpSrc, fg->pict, 0, dst->pict, 0, 0, 0, 0, + 1, 1, 1, 1); + /* Copy the output to the window, so the user sees something visual. */ + XRenderComposite(dpy, PictOpSrc, dst->pict, 0, win->pict, 0, 0, 0, 0, + 0, 0, win_width, win_height); + + for (x = 0; x < 3; x++) { + for (y = 0; y < 3; y++) { + get_pixel(dpy, dst, 0, 0, &tested); + if (x == 1 && y == 1) + expected = fg->color; + else + expected = bg->color; + color_correct(dst, &expected); + if (!eval_diff("dst coords", &expected, &tested, x, y, + is_verbose)) + failed = TRUE; + } + } + + return !failed; +} + +static Bool +srccoords_test(Display *dpy, picture_info *win, picture_info *src, + picture_info *white, Bool test_mask) +{ + color4d expected, tested; + int i; + XRenderPictureAttributes pa; + Bool failed = FALSE; + int tested_colors[5][5]; + + for (i = 0; i < 25; i++) { + char name[20]; + int x = i % 5, y = i / 5; + + if (!test_mask) + XRenderComposite(dpy, PictOpSrc, src->pict, 0, + win->pict, x, y, 0, 0, 0, 0, 1, 1); + else { + /* Using PictOpSrc, color 0 (white), and component + * alpha, the mask color should be written to the + * destination. + */ + pa.component_alpha = TRUE; + XRenderChangePicture(dpy, src->pict, CPComponentAlpha, + &pa); + XRenderComposite(dpy, PictOpSrc, white->pict, src->pict, + win->pict, 0, 0, x, y, 0, 0, 1, 1); + pa.component_alpha = FALSE; + XRenderChangePicture(dpy, src->pict, CPComponentAlpha, + &pa); + } + get_pixel(dpy, win, 0, 0, &tested); + + expected = colors[target_colors[x][y]]; + color_correct(win, &expected); + if (tested.r == 1.0) { + if (tested.g == 1.0 && tested.b == 1.0) + tested_colors[x][y] = 0; + else if (tested.g == 0.0 && tested.b == 0.0) + tested_colors[x][y] = 1; + else tested_colors[x][y] = 9; + } else + tested_colors[x][y] = 9; + + if (test_mask) + snprintf(name, 20, "mask coords"); + else + snprintf(name, 20, "src coords"); + if (!eval_diff(name, &expected, &tested, x, y, + is_verbose)) + failed = TRUE; + } + if (failed) { + int j; + + printf("expected vs tested:\n"); + for (i = 0; i < 5; i++) { + for (j = 0; j < 5; j++) + printf("%d", target_colors[j][i]); + printf(" "); + for (j = 0; j < 5; j++) + printf("%d", tested_colors[j][i]); + printf("\n"); + } + } + + return !failed; +} + +static Bool +blend_test(Display *dpy, picture_info *win, picture_info *dst, int op, + picture_info *src_color, picture_info *dst_color) +{ + color4d expected, tested, tdst; + char testname[20]; + int i; + + for (i = 0; i < pixmap_move_iter; i++) { + XRenderComposite(dpy, PictOpSrc, dst_color->pict, 0, dst->pict, 0, 0, + 0, 0, 0, 0, win_width, win_height); + XRenderComposite(dpy, ops[op].op, src_color->pict, 0, dst->pict, 0, 0, + 0, 0, 0, 0, win_width, win_height); + } + get_pixel(dpy, dst, 0, 0, &tested); + /* Copy the output to the window, so the user sees something visual. */ + XRenderComposite(dpy, PictOpSrc, dst->pict, 0, win->pict, 0, 0, 0, 0, + 0, 0, win_width, win_height); + + tdst = dst_color->color; + color_correct(dst, &tdst); + do_composite(ops[op].op, &src_color->color, NULL, &tdst, &expected, + FALSE); + color_correct(dst, &expected); + + snprintf(testname, 20, "%s blend", ops[op].name); + if (!eval_diff(testname, &expected, &tested, 0, 0, is_verbose)) { + printf("src color: %.2f %.2f %.2f %.2f\n" + "dst color: %.2f %.2f %.2f %.2f\n", + src_color->color.r, src_color->color.g, + src_color->color.b, src_color->color.a, + dst_color->color.r, dst_color->color.g, + dst_color->color.b, dst_color->color.a); + printf("src: %s, dst: %s\n", src_color->name, dst->name); + return FALSE; + } else if (is_verbose) { + printf("src: %s, dst: %s\n", src_color->name, dst->name); + } + return TRUE; +} + +static Bool +composite_test(Display *dpy, picture_info *win, picture_info *dst, int op, + picture_info *src_color, picture_info *mask_color, picture_info *dst_color, + Bool componentAlpha, Bool print_errors) +{ + color4d expected, tested, tdst, tmsk; + char testname[40]; + XRenderPictureAttributes pa; + Bool success = TRUE; + + if (componentAlpha) { + pa.component_alpha = TRUE; + XRenderChangePicture(dpy, mask_color->pict, CPComponentAlpha, + &pa); + } + XRenderComposite(dpy, PictOpSrc, dst_color->pict, 0, dst->pict, 0, 0, + 0, 0, 0, 0, win_width, win_height); + XRenderComposite(dpy, ops[op].op, src_color->pict, mask_color->pict, + dst->pict, 0, 0, 0, 0, 0, 0, win_width, win_height); + get_pixel(dpy, dst, 0, 0, &tested); + /* Copy the output to the window, so the user sees something visual. */ + XRenderComposite(dpy, PictOpSrc, dst->pict, 0, win->pict, 0, 0, 0, 0, + 0, 0, win_width, win_height); + if (componentAlpha) { + pa.component_alpha = FALSE; + XRenderChangePicture(dpy, mask_color->pict, CPComponentAlpha, + &pa); + } + + if (componentAlpha && mask_color->format->direct.redMask == 0) { + /* Ax component-alpha masks expand alpha into all color + * channels. XXX: This should be located somewhere generic. + */ + tmsk.a = mask_color->color.a; + tmsk.r = mask_color->color.a; + tmsk.g = mask_color->color.a; + tmsk.b = mask_color->color.a; + } else + tmsk = mask_color->color; + + tdst = dst_color->color; + color_correct(dst, &tdst); + do_composite(ops[op].op, &src_color->color, &tmsk, &tdst, + &expected, componentAlpha); + color_correct(dst, &expected); + + snprintf(testname, 40, "%s %scomposite", ops[op].name, + componentAlpha ? "CA " : ""); + if (!eval_diff(testname, &expected, &tested, 0, 0, is_verbose && + print_errors)) { + if (print_errors) + printf("src color: %.2f %.2f %.2f %.2f\n" + "msk color: %.2f %.2f %.2f %.2f\n" + "dst color: %.2f %.2f %.2f %.2f\n", + src_color->color.r, src_color->color.g, + src_color->color.b, src_color->color.a, + mask_color->color.r, mask_color->color.g, + mask_color->color.b, mask_color->color.a, + dst_color->color.r, dst_color->color.g, + dst_color->color.b, dst_color->color.a); + printf("src: %s, mask: %s, dst: %s\n", src_color->name, + mask_color->name, dst->name); + success = FALSE; + } else if (is_verbose) { + printf("src: %s, mask: %s, dst: %s\n", src_color->name, + mask_color->name, dst->name); + } + return success; +} + + +void +begin_test(Display *dpy, picture_info *win) +{ + int i, j, src, dst, mask; + int num_dests, num_formats; + picture_info *dests, *pictures_1x1, *pictures_10x10, picture_3x3; + picture_info picture_target; + + num_dests = 3; + dests = (picture_info *)malloc(num_dests * sizeof(dests[0])); + if (dests == NULL) + errx(1, "malloc error"); + + dests[0].format = XRenderFindStandardFormat(dpy, PictStandardARGB32); + dests[1].format = XRenderFindStandardFormat(dpy, PictStandardRGB24); + dests[2].format = XRenderFindStandardFormat(dpy, PictStandardA8); + /* + dests[3].format = XRenderFindStandardFormat(dpy, PictStandardA4); + dests[4].format = XRenderFindStandardFormat(dpy, PictStandardA1); + */ + + for (i = 0; i < num_dests; i++) { + dests[i].d = XCreatePixmap(dpy, RootWindow(dpy, 0), + win_width, win_height, dests[i].format->depth); + dests[i].pict = XRenderCreatePicture(dpy, dests[i].d, + dests[i].format, 0, NULL); + + dests[i].name = (char *)malloc(20); + if (dests[i].name == NULL) + errx(1, "malloc error"); + describe_format(dests[i].name, 20, dests[i].format); + } + + num_formats = 3; + + pictures_1x1 = (picture_info *)malloc(num_colors * num_formats * + sizeof(picture_info)); + if (pictures_1x1 == NULL) + errx(1, "malloc error"); + + for (i = 0; i < num_colors * num_formats; i++) { + XRenderPictureAttributes pa; + XRenderColor rendercolor; + + /* The standard PictFormat numbers go from 0 to 4 */ + pictures_1x1[i].format = XRenderFindStandardFormat(dpy, + i % num_formats); + pictures_1x1[i].d = XCreatePixmap(dpy, RootWindow(dpy, 0), 1, + 1, pictures_1x1[i].format->depth); + pa.repeat = TRUE; + pictures_1x1[i].pict = XRenderCreatePicture(dpy, + pictures_1x1[i].d, pictures_1x1[i].format, CPRepeat, &pa); + + pictures_1x1[i].name = (char *)malloc(20); + if (pictures_1x1[i].name == NULL) + errx(1, "malloc error"); + sprintf(pictures_1x1[i].name, "1x1R "); + describe_format(pictures_1x1[i].name + + strlen(pictures_1x1[i].name), 20 - + strlen(pictures_1x1[i].name), pictures_1x1[i].format); + + rendercolor.red = colors[i / num_formats].r * 65535; + rendercolor.green = colors[i / num_formats].g * 65535; + rendercolor.blue = colors[i / num_formats].b * 65535; + rendercolor.alpha = colors[i / num_formats].a * 65535; + XRenderFillRectangle(dpy, PictOpSrc, pictures_1x1[i].pict, + &rendercolor, 0, 0, 1, 1); + + pictures_1x1[i].color.r = colors[i / num_formats].r; + pictures_1x1[i].color.g = colors[i / num_formats].g; + pictures_1x1[i].color.b = colors[i / num_formats].b; + pictures_1x1[i].color.a = colors[i / num_formats].a; + color_correct(&pictures_1x1[i], &pictures_1x1[i].color); + } + + pictures_10x10 = (picture_info *)malloc(num_colors * num_formats * + sizeof(picture_info)); + if (pictures_10x10 == NULL) + errx(1, "malloc error"); + + for (i = 0; i < num_colors * num_formats; i++) { + XRenderPictureAttributes pa; + XRenderColor rendercolor; + + /* The standard PictFormat numbers go from 0 to 4 */ + pictures_10x10[i].format = XRenderFindStandardFormat(dpy, + i % num_formats); + pictures_10x10[i].d = XCreatePixmap(dpy, RootWindow(dpy, 0), 10, + 10, pictures_10x10[i].format->depth); + pa.repeat = TRUE; + pictures_10x10[i].pict = XRenderCreatePicture(dpy, + pictures_10x10[i].d, pictures_10x10[i].format, 0, NULL); + + pictures_10x10[i].name = (char *)malloc(20); + if (pictures_10x10[i].name == NULL) + errx(1, "malloc error"); + sprintf(pictures_10x10[i].name, "10x10 "); + describe_format(pictures_10x10[i].name + + strlen(pictures_10x10[i].name), 20 - + strlen(pictures_10x10[i].name), pictures_10x10[i].format); + + rendercolor.red = colors[i / num_formats].r * 65535; + rendercolor.green = colors[i / num_formats].g * 65535; + rendercolor.blue = colors[i / num_formats].b * 65535; + rendercolor.alpha = colors[i / num_formats].a * 65535; + XRenderFillRectangle(dpy, PictOpSrc, pictures_10x10[i].pict, + &rendercolor, 0, 0, 10, 10); + + pictures_10x10[i].color.r = colors[i / num_formats].r; + pictures_10x10[i].color.g = colors[i / num_formats].g; + pictures_10x10[i].color.b = colors[i / num_formats].b; + pictures_10x10[i].color.a = colors[i / num_formats].a; + color_correct(&pictures_10x10[i], &pictures_10x10[i].color); + } + + picture_3x3.d = XCreatePixmap(dpy, RootWindow(dpy, 0), 3, 3, 32); + picture_3x3.format = XRenderFindStandardFormat(dpy, PictStandardARGB32); + picture_3x3.pict = XRenderCreatePicture(dpy, picture_3x3.d, + picture_3x3.format, 0, NULL); + picture_3x3.name = "3x3 sample picture"; + for (i = 0; i < 9; i++) { + XRenderColor color; + + color.red = colors[i % num_colors].r * 65535; + color.green = colors[i % num_colors].g * 65535; + color.blue = colors[i % num_colors].b * 65535; + color.alpha = colors[i % num_colors].a * 65535; + XRenderFillRectangle(dpy, PictOpSrc, picture_3x3.pict, &color, + i % 3, i / 3, 1, 1); + } + picture_target.d = XCreatePixmap(dpy, RootWindow(dpy, 0), 5, 5, 32); + picture_target.format = XRenderFindStandardFormat(dpy, + PictStandardARGB32); + picture_target.pict = XRenderCreatePicture(dpy, picture_target.d, + picture_target.format, 0, NULL); + picture_target.name = "target picture"; + for (i = 0; i < 25; i++) { + int x = i % 5; + int y = i / 5; + XRenderColor color; + int tc; + + tc = target_colors[x][y]; + + color.red = colors[tc].r * 65535; + color.green = colors[tc].g * 65535; + color.blue = colors[tc].b * 65535; + color.alpha = colors[tc].a * 65535; + XRenderFillRectangle(dpy, PictOpSrc, picture_target.pict, + &color, x, y, 1, 1); + } + + printf("Beginning fill test\n"); + for (i = 0; i < num_dests; i++) { + for (j = 0; j < num_colors * num_formats; j++) { + fill_test(dpy, win, &pictures_1x1[j], &dests[i]); + } + } + + printf("Beginning dest coords test\n"); + /* 0 and num_formats should result in ARGB8888 red on ARGB8888 white. */ + destcoords_test(dpy, win, &dests[0], &pictures_1x1[0], + &pictures_1x1[num_formats]); + + printf("Beginning src coords test\n"); + srccoords_test(dpy, win, &picture_target, &pictures_1x1[0], FALSE); + + printf("Beginning mask coords test\n"); + srccoords_test(dpy, win, &picture_target, &pictures_1x1[0], TRUE); + + for (i = 0; i < num_ops; i++) { + for (j = 0; j < num_dests; j++) { + printf("Beginning %s blend test on %s\n", ops[i].name, + dests[j].name); + for (src = 0; src < num_colors * num_formats; src++) { + for (dst = 0; dst < num_colors; dst++) { + blend_test(dpy, win, &dests[j], i, + &pictures_1x1[src], &pictures_1x1[dst]); + blend_test(dpy, win, &dests[j], i, + &pictures_10x10[src], &pictures_1x1[dst]); + } + } + } + } + + for (i = 0; i < num_ops; i++) { + for (j = 0; j < num_dests; j++) { + printf("Beginning %s composite mask test on %s\n", ops[i].name, + dests[j].name); + for (src = 0; src < num_colors; src++) { + for (mask = 0; mask < num_colors; mask++) { + for (dst = 0; dst < num_colors; dst++) { + composite_test(dpy, win, &dests[j], i, + &pictures_10x10[src], &pictures_10x10[mask], + &pictures_1x1[dst], FALSE, TRUE); + composite_test(dpy, win, &dests[j], i, + &pictures_1x1[src], &pictures_10x10[mask], + &pictures_1x1[dst], FALSE, TRUE); + composite_test(dpy, win, &dests[j], i, + &pictures_10x10[src], &pictures_1x1[mask], + &pictures_1x1[dst], FALSE, TRUE); + composite_test(dpy, win, &dests[j], i, + &pictures_1x1[src], &pictures_1x1[mask], + &pictures_1x1[dst], FALSE, TRUE); + } + } + } + } + } + + for (i = 0; i < num_ops; i++) { + for (j = 0; j < num_dests; j++) { + printf("Beginning %s composite CA mask test on %s\n", + ops[i].name, dests[j].name); + for (src = 0; src < num_colors; src++) { + for (mask = 0; mask < num_colors; mask++) { + for (dst = 0; dst < num_colors; dst++) { + composite_test(dpy, win, &dests[j], i, + &pictures_1x1[src], &pictures_1x1[mask], + &pictures_1x1[dst], TRUE, TRUE); + } + } + } + } + } +} |