1 /* Copyright © 2014 Keith Packard <keithp@keithp.com>
2 * Copyright © 2014 Intel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 /** @file t_libreoffice_xrgb.c
20 *
21 * Test Render's XRGB behavior when the pixmap is initialized with PutImage.
22 * Catches a bug in glamor where the Render acceleration was relying on the
23 * high bits of the pixmap having been set to 0xff, which is certainly not
24 * guaranteed. The rest of rendercheck didn't catch the bug, because it uses
25 * XRenderFillRectangle() to initialize the common XRGB pictures, and
26 * apparently that was setting the unused bits to 1 at the time.
27 */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 #include <strings.h>
33 #include "rendercheck.h"
34
35 #define WIDTH 1
36 #define HEIGHT 1
37
38 #define PIXEL_XRGB 0x11886644
39 #define PIXEL_ARGB 0xff886644
40 #define INVERT_PIXEL_ARGB 0xff7799bb
41
42 Bool
libreoffice_xrgb_test(Display * dpy,Bool invert)43 libreoffice_xrgb_test(Display *dpy, Bool invert)
44 {
45 int x, y;
46 Pixmap src_pix, dst_pix;
47 Picture src_pict, dst_pict;
48 XRenderPictFormat templ;
49 XRenderPictFormat *pic_xrgb_format;
50 XRenderPictFormat *pic_argb_format;
51 XRenderPictFormat *pic_rgb_format;
52 GC gc;
53 XImage *image;
54
55 templ.type = PictTypeDirect;
56 templ.depth = 32;
57 templ.direct.alphaMask = 0;
58 templ.direct.red = 16;
59 templ.direct.green = 8;
60 templ.direct.blue = 0;
61
62 pic_xrgb_format = XRenderFindFormat(dpy,
63 PictFormatType |
64 PictFormatDepth |
65 PictFormatAlphaMask |
66 PictFormatRed |
67 PictFormatGreen |
68 PictFormatBlue,
69 &templ, 0);
70
71 templ.type = PictTypeDirect;
72 templ.depth = 32;
73 templ.direct.alpha = 24;
74 templ.direct.red = 16;
75 templ.direct.green = 8;
76 templ.direct.blue = 0;
77
78 pic_argb_format = XRenderFindFormat(dpy,
79 PictFormatType |
80 PictFormatDepth |
81 PictFormatAlpha |
82 PictFormatRed |
83 PictFormatGreen |
84 PictFormatBlue,
85 &templ, 0);
86
87 templ.type = PictTypeDirect;
88 templ.depth = 24;
89 templ.direct.red = 16;
90 templ.direct.green = 8;
91 templ.direct.blue = 0;
92
93 pic_rgb_format = XRenderFindFormat(dpy,
94 PictFormatType |
95 PictFormatDepth |
96 PictFormatRed |
97 PictFormatGreen |
98 PictFormatBlue,
99 &templ, 0);
100
101 if (!pic_argb_format || !pic_xrgb_format || !pic_rgb_format) {
102 printf("Couldn't find xRGB and ARGB formats\n");
103 return FALSE;
104 }
105
106 src_pix = XCreatePixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)),
107 WIDTH, HEIGHT, 32);
108
109 dst_pix = XCreatePixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)),
110 WIDTH, HEIGHT, 32);
111
112 src_pict = XRenderCreatePicture(dpy, src_pix, pic_xrgb_format, 0,
113 NULL);
114 dst_pict = XRenderCreatePicture(dpy, dst_pix, pic_argb_format, 0,
115 NULL);
116
117 image = XCreateImage(dpy,
118 NULL,
119 32,
120 ZPixmap,
121 0,
122 NULL,
123 WIDTH, HEIGHT, 32, 0);
124
125 image->data = malloc(HEIGHT * image->bytes_per_line);
126
127 for (y = 0; y < HEIGHT; y++)
128 for (x = 0; x < WIDTH; x++)
129 XPutPixel(image, x, y, PIXEL_XRGB);
130
131 gc = XCreateGC(dpy, src_pix, 0, NULL);
132
133 XPutImage(dpy, src_pix, gc, image, 0, 0, 0, 0, WIDTH, HEIGHT);
134
135 if (invert) {
136 XSetFunction(dpy, gc, GXinvert);
137
138 XFillRectangle(dpy, src_pix, gc, 0, 0, WIDTH, HEIGHT);
139 }
140
141 XDestroyImage(image);
142
143 XRenderComposite(dpy, PictOpOver, src_pict, None, dst_pict,
144 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
145
146 image = XGetImage(dpy, dst_pix, 0, 0, WIDTH, HEIGHT, 0xffffffff,
147 ZPixmap);
148 for (y = 0; y < HEIGHT; y++) {
149 for (x = 0; x < WIDTH; x++) {
150 unsigned long expected = (invert ? INVERT_PIXEL_ARGB :
151 PIXEL_ARGB);
152 unsigned long pixel = XGetPixel(image, x, y);
153
154 if (pixel != expected) {
155 printf("fail: pixel value is %08lx, "
156 "should be %08lx\n",
157 pixel, expected);
158 return FALSE;
159 }
160 }
161 }
162 XDestroyImage(image);
163
164 return TRUE;
165 }
166