2 * Copyright © 2002 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
28 #include "scrnintstr.h"
30 #include "regionstr.h"
32 #include "windowstr.h"
35 #include "colormapst.h"
36 #include "cursorstr.h"
37 #include "dixstruct.h"
40 #include "picturestr.h"
42 static char **filterNames
;
43 static int nfilterNames
;
46 * standard but not required filters don't have constant indices
50 PictureGetFilterId(const char *filter
, int len
, Bool makeit
)
58 for (i
= 0; i
< nfilterNames
; i
++)
59 if (!CompareISOLatin1Lowered((const unsigned char *) filterNames
[i
], -1,
60 (const unsigned char *) filter
, len
))
64 name
= malloc(len
+ 1);
67 memcpy(name
, filter
, len
);
70 names
= realloc(filterNames
, (nfilterNames
+ 1) * sizeof(char *));
72 names
= malloc(sizeof(char *));
79 filterNames
[i
] = name
;
84 PictureSetDefaultIds(void)
86 /* careful here -- this list must match the #define values */
88 if (PictureGetFilterId(FilterNearest
, -1, TRUE
) != PictFilterNearest
)
90 if (PictureGetFilterId(FilterBilinear
, -1, TRUE
) != PictFilterBilinear
)
93 if (PictureGetFilterId(FilterFast
, -1, TRUE
) != PictFilterFast
)
95 if (PictureGetFilterId(FilterGood
, -1, TRUE
) != PictFilterGood
)
97 if (PictureGetFilterId(FilterBest
, -1, TRUE
) != PictFilterBest
)
100 if (PictureGetFilterId(FilterConvolution
, -1, TRUE
) !=
101 PictFilterConvolution
)
107 PictureGetFilterName(int id
)
109 if (0 <= id
&& id
< nfilterNames
)
110 return filterNames
[id
];
116 PictureFreeFilterIds(void)
120 for (i
= 0; i
< nfilterNames
; i
++)
121 free(filterNames
[i
]);
128 PictureAddFilter(ScreenPtr pScreen
,
130 PictFilterValidateParamsProcPtr ValidateParams
,
131 int width
, int height
)
133 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
134 int id
= PictureGetFilterId(filter
, -1, TRUE
);
136 PictFilterPtr filters
;
141 * It's an error to attempt to reregister a filter
143 for (i
= 0; i
< ps
->nfilters
; i
++)
144 if (ps
->filters
[i
].id
== id
)
148 realloc(ps
->filters
, (ps
->nfilters
+ 1) * sizeof(PictFilterRec
));
150 filters
= malloc(sizeof(PictFilterRec
));
153 ps
->filters
= filters
;
155 ps
->filters
[i
].name
= PictureGetFilterName(id
);
156 ps
->filters
[i
].id
= id
;
157 ps
->filters
[i
].ValidateParams
= ValidateParams
;
158 ps
->filters
[i
].width
= width
;
159 ps
->filters
[i
].height
= height
;
164 PictureSetFilterAlias(ScreenPtr pScreen
, const char *filter
, const char *alias
)
166 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
167 int filter_id
= PictureGetFilterId(filter
, -1, FALSE
);
168 int alias_id
= PictureGetFilterId(alias
, -1, TRUE
);
171 if (filter_id
< 0 || alias_id
< 0)
173 for (i
= 0; i
< ps
->nfilterAliases
; i
++)
174 if (ps
->filterAliases
[i
].alias_id
== alias_id
)
176 if (i
== ps
->nfilterAliases
) {
177 PictFilterAliasPtr aliases
;
179 if (ps
->filterAliases
)
180 aliases
= realloc(ps
->filterAliases
,
181 (ps
->nfilterAliases
+ 1) *
182 sizeof(PictFilterAliasRec
));
184 aliases
= malloc(sizeof(PictFilterAliasRec
));
187 ps
->filterAliases
= aliases
;
188 ps
->filterAliases
[i
].alias
= PictureGetFilterName(alias_id
);
189 ps
->filterAliases
[i
].alias_id
= alias_id
;
190 ps
->nfilterAliases
++;
192 ps
->filterAliases
[i
].filter_id
= filter_id
;
197 PictureFindFilter(ScreenPtr pScreen
, char *name
, int len
)
199 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
200 int id
= PictureGetFilterId(name
, len
, FALSE
);
205 /* Check for an alias, allow them to recurse */
206 for (i
= 0; i
< ps
->nfilterAliases
; i
++)
207 if (ps
->filterAliases
[i
].alias_id
== id
) {
208 id
= ps
->filterAliases
[i
].filter_id
;
211 /* find the filter */
212 for (i
= 0; i
< ps
->nfilters
; i
++)
213 if (ps
->filters
[i
].id
== id
)
214 return &ps
->filters
[i
];
219 convolutionFilterValidateParams(ScreenPtr pScreen
,
222 int nparams
, int *width
, int *height
)
229 if (xFixedFrac(params
[0]) || xFixedFrac(params
[1]))
232 w
= xFixedToInt(params
[0]);
233 h
= xFixedToInt(params
[1]);
245 PictureSetDefaultFilters(ScreenPtr pScreen
)
248 if (!PictureSetDefaultIds())
250 if (PictureAddFilter(pScreen
, FilterNearest
, 0, 1, 1) < 0)
252 if (PictureAddFilter(pScreen
, FilterBilinear
, 0, 2, 2) < 0)
255 if (!PictureSetFilterAlias(pScreen
, FilterNearest
, FilterFast
))
257 if (!PictureSetFilterAlias(pScreen
, FilterBilinear
, FilterGood
))
259 if (!PictureSetFilterAlias(pScreen
, FilterBilinear
, FilterBest
))
263 (pScreen
, FilterConvolution
, convolutionFilterValidateParams
, 0, 0) < 0)
270 PictureResetFilters(ScreenPtr pScreen
)
272 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
275 free(ps
->filterAliases
);
277 /* Free the filters when the last screen is closed */
278 if (pScreen
->myNum
== 0)
279 PictureFreeFilterIds();
283 SetPictureFilter(PicturePtr pPicture
, char *name
, int len
, xFixed
* params
,
286 PictFilterPtr pFilter
;
289 if (pPicture
->pDrawable
!= NULL
)
290 pScreen
= pPicture
->pDrawable
->pScreen
;
292 pScreen
= screenInfo
.screens
[0];
294 pFilter
= PictureFindFilter(pScreen
, name
, len
);
299 if (pPicture
->pDrawable
== NULL
) {
302 /* For source pictures, the picture isn't tied to a screen. So, ensure
303 * that all screens can handle a filter we set for the picture.
305 for (s
= 1; s
< screenInfo
.numScreens
; s
++) {
306 PictFilterPtr pScreenFilter
;
308 pScreenFilter
= PictureFindFilter(screenInfo
.screens
[s
], name
, len
);
309 if (!pScreenFilter
|| pScreenFilter
->id
!= pFilter
->id
)
313 return SetPicturePictFilter(pPicture
, pFilter
, params
, nparams
);
317 SetPicturePictFilter(PicturePtr pPicture
, PictFilterPtr pFilter
,
318 xFixed
* params
, int nparams
)
323 if (pPicture
->pDrawable
)
324 pScreen
= pPicture
->pDrawable
->pScreen
;
326 pScreen
= screenInfo
.screens
[0];
328 if (pFilter
->ValidateParams
) {
331 if (!(*pFilter
->ValidateParams
)
332 (pScreen
, pFilter
->id
, params
, nparams
, &width
, &height
))
338 if (nparams
!= pPicture
->filter_nparams
) {
339 xFixed
*new_params
= malloc(nparams
* sizeof(xFixed
));
341 if (!new_params
&& nparams
)
343 free(pPicture
->filter_params
);
344 pPicture
->filter_params
= new_params
;
345 pPicture
->filter_nparams
= nparams
;
347 for (i
= 0; i
< nparams
; i
++)
348 pPicture
->filter_params
[i
] = params
[i
];
349 pPicture
->filter
= pFilter
->id
;
351 if (pPicture
->pDrawable
) {
352 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
355 result
= (*ps
->ChangePictureFilter
) (pPicture
, pPicture
->filter
,