1/*
2 *
3 * Copyright © 2002 Keith Packard
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Keith Packard not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission.  Keith Packard makes no
12 * representations about the suitability of this software for any purpose.  It
13 * is provided "as is" without express or implied warranty.
14 *
15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27#include "Xrenderint.h"
28#include <limits.h>
29
30XFilters *
31XRenderQueryFilters (Display *dpy, Drawable drawable)
32{
33    XRenderExtDisplayInfo	*info = XRenderFindDisplay (dpy);
34    XRenderInfo			*xri;
35    xRenderQueryFiltersReq	*req;
36    xRenderQueryFiltersReply	rep;
37    XFilters			*filters;
38    char			*name;
39    char			len;
40    unsigned int		i;
41    unsigned long		nbytesName, reply_left;
42
43    if (!RenderHasExtension (info))
44	return NULL;
45
46    if (!XRenderQueryFormats (dpy))
47	return NULL;
48
49    xri = info->info;
50    if (xri->minor_version < 6)
51	return NULL;
52
53    LockDisplay (dpy);
54    GetReq (RenderQueryFilters, req);
55    req->reqType = (CARD8) info->codes->major_opcode;
56    req->renderReqType = X_RenderQueryFilters;
57    req->drawable = (CARD32) drawable;
58    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
59    {
60	UnlockDisplay (dpy);
61	SyncHandle ();
62	return NULL;
63    }
64
65    /*
66     * Limit each component of combined size to 1/4 the max, which is far
67     * more than they should ever possibly need.
68     */
69    if ((rep.length < (INT_MAX >> 2)) &&
70	(rep.numFilters < ((INT_MAX / 4) / sizeof (char *))) &&
71	(rep.numAliases < ((INT_MAX / 4) / sizeof (short)))) {
72	unsigned long		nbytes, nbytesAlias;
73
74	/*
75	 * Compute total number of bytes for filter names
76	 */
77	nbytes = (unsigned long)rep.length << 2;
78	nbytesAlias = rep.numAliases * 2;
79	if (rep.numAliases & 1)
80	    nbytesAlias += 2;
81	nbytesName = nbytes - nbytesAlias;
82
83	/*
84	 * Allocate one giant block for the whole data structure
85	 */
86	filters = Xmalloc (sizeof (XFilters) +
87			   (rep.numFilters * sizeof (char *)) +
88			   (rep.numAliases * sizeof (short)) +
89			   nbytesName);
90    } else
91	filters = NULL;
92
93    if (!filters)
94    {
95	_XEatDataWords(dpy, rep.length);
96	UnlockDisplay (dpy);
97	SyncHandle ();
98	return NULL;
99    }
100
101    /*
102     * Layout:
103     *	XFilters
104     *	numFilters  char * pointers to filter names
105     *	numAliases  short alias values
106     *	nbytesName  char strings
107     */
108
109    filters->nfilter = (int) rep.numFilters;
110    filters->nalias = (int) rep.numAliases;
111    filters->filter = (char **) (filters + 1);
112    filters->alias = (short *) (filters->filter + rep.numFilters);
113    name = (char *) (filters->alias + rep.numAliases);
114
115    /*
116     * Read the filter aliases
117     */
118    _XRead16Pad (dpy, filters->alias, 2 * rep.numAliases);
119    reply_left = 8 + rep.length - 2 * rep.numAliases;;
120
121    /*
122     * Read the filter names
123     */
124    for (i = 0; i < rep.numFilters; i++)
125    {
126	int	l;
127	_XRead (dpy, &len, 1);
128	reply_left--;
129	l = len & 0xff;
130	if ((unsigned long)l + 1 > nbytesName) {
131            _XEatDataWords(dpy, reply_left);
132	    Xfree(filters);
133	    UnlockDisplay (dpy);
134	    SyncHandle ();
135	    return NULL;
136	}
137	nbytesName -= (unsigned long) (l + 1);
138	filters->filter[i] = name;
139	_XRead (dpy, name, l);
140        reply_left -= (unsigned long) l;
141	name[l] = '\0';
142	name += l + 1;
143    }
144    i = (unsigned) (name - (char *) (filters->alias + rep.numAliases));
145
146    if (i & 3)
147	_XEatData (dpy, 4 - (i & 3));
148
149    UnlockDisplay (dpy);
150    SyncHandle ();
151    return filters;
152}
153
154void
155XRenderSetPictureFilter  (Display   *dpy,
156			  Picture   picture,
157			  const char *filter,
158			  XFixed    *params,
159			  int	    nparams)
160{
161    XRenderExtDisplayInfo	*info = XRenderFindDisplay (dpy);
162    xRenderSetPictureFilterReq	*req;
163    int				nbytes = (int) strlen (filter);
164
165    RenderSimpleCheckExtension (dpy, info);
166    LockDisplay(dpy);
167    GetReq(RenderSetPictureFilter, req);
168    req->reqType = (CARD8) info->codes->major_opcode;
169    req->renderReqType = X_RenderSetPictureFilter;
170    req->picture = (CARD32) picture;
171    req->nbytes = (CARD16) nbytes;
172    req->length = (CARD16) (req->length + (((nbytes + 3) >> 2) + nparams));
173    Data (dpy, filter, nbytes);
174    Data (dpy, (_Xconst char *)params, (nparams << 2));
175    UnlockDisplay(dpy);
176    SyncHandle();
177}
178