filter.c (10050B)
1 /* 2 * Copyright © 2002 Keith Packard 3 * 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. 13 * 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. 21 */ 22 23 #ifdef HAVE_DIX_CONFIG_H 24 #include <dix-config.h> 25 #endif 26 27 #include "misc.h" 28 #include "scrnintstr.h" 29 #include "os.h" 30 #include "regionstr.h" 31 #include "validate.h" 32 #include "windowstr.h" 33 #include "input.h" 34 #include "resource.h" 35 #include "colormapst.h" 36 #include "cursorstr.h" 37 #include "dixstruct.h" 38 #include "gcstruct.h" 39 #include "servermd.h" 40 #include "picturestr.h" 41 42 static char **filterNames; 43 static int nfilterNames; 44 45 /* 46 * standard but not required filters don't have constant indices 47 */ 48 49 int 50 PictureGetFilterId(const char *filter, int len, Bool makeit) 51 { 52 int i; 53 char *name; 54 char **names; 55 56 if (len < 0) 57 len = strlen(filter); 58 for (i = 0; i < nfilterNames; i++) 59 if (!CompareISOLatin1Lowered((const unsigned char *) filterNames[i], -1, 60 (const unsigned char *) filter, len)) 61 return i; 62 if (!makeit) 63 return -1; 64 name = malloc(len + 1); 65 if (!name) 66 return -1; 67 memcpy(name, filter, len); 68 name[len] = '\0'; 69 if (filterNames) 70 names = reallocarray(filterNames, nfilterNames + 1, sizeof(char *)); 71 else 72 names = malloc(sizeof(char *)); 73 if (!names) { 74 free(name); 75 return -1; 76 } 77 filterNames = names; 78 i = nfilterNames++; 79 filterNames[i] = name; 80 return i; 81 } 82 83 static Bool 84 PictureSetDefaultIds(void) 85 { 86 /* careful here -- this list must match the #define values */ 87 88 if (PictureGetFilterId(FilterNearest, -1, TRUE) != PictFilterNearest) 89 return FALSE; 90 if (PictureGetFilterId(FilterBilinear, -1, TRUE) != PictFilterBilinear) 91 return FALSE; 92 93 if (PictureGetFilterId(FilterFast, -1, TRUE) != PictFilterFast) 94 return FALSE; 95 if (PictureGetFilterId(FilterGood, -1, TRUE) != PictFilterGood) 96 return FALSE; 97 if (PictureGetFilterId(FilterBest, -1, TRUE) != PictFilterBest) 98 return FALSE; 99 100 if (PictureGetFilterId(FilterConvolution, -1, TRUE) != 101 PictFilterConvolution) 102 return FALSE; 103 return TRUE; 104 } 105 106 char * 107 PictureGetFilterName(int id) 108 { 109 if (0 <= id && id < nfilterNames) 110 return filterNames[id]; 111 else 112 return 0; 113 } 114 115 static void 116 PictureFreeFilterIds(void) 117 { 118 int i; 119 120 for (i = 0; i < nfilterNames; i++) 121 free(filterNames[i]); 122 free(filterNames); 123 nfilterNames = 0; 124 filterNames = 0; 125 } 126 127 int 128 PictureAddFilter(ScreenPtr pScreen, 129 const char *filter, 130 PictFilterValidateParamsProcPtr ValidateParams, 131 int width, int height) 132 { 133 PictureScreenPtr ps = GetPictureScreen(pScreen); 134 int id = PictureGetFilterId(filter, -1, TRUE); 135 int i; 136 PictFilterPtr filters; 137 138 if (id < 0) 139 return -1; 140 /* 141 * It's an error to attempt to reregister a filter 142 */ 143 for (i = 0; i < ps->nfilters; i++) 144 if (ps->filters[i].id == id) 145 return -1; 146 if (ps->filters) 147 filters = 148 reallocarray(ps->filters, ps->nfilters + 1, sizeof(PictFilterRec)); 149 else 150 filters = malloc(sizeof(PictFilterRec)); 151 if (!filters) 152 return -1; 153 ps->filters = filters; 154 i = ps->nfilters++; 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; 160 return id; 161 } 162 163 Bool 164 PictureSetFilterAlias(ScreenPtr pScreen, const char *filter, const char *alias) 165 { 166 PictureScreenPtr ps = GetPictureScreen(pScreen); 167 int filter_id = PictureGetFilterId(filter, -1, FALSE); 168 int alias_id = PictureGetFilterId(alias, -1, TRUE); 169 int i; 170 171 if (filter_id < 0 || alias_id < 0) 172 return FALSE; 173 for (i = 0; i < ps->nfilterAliases; i++) 174 if (ps->filterAliases[i].alias_id == alias_id) 175 break; 176 if (i == ps->nfilterAliases) { 177 PictFilterAliasPtr aliases; 178 179 if (ps->filterAliases) 180 aliases = reallocarray(ps->filterAliases, 181 ps->nfilterAliases + 1, 182 sizeof(PictFilterAliasRec)); 183 else 184 aliases = malloc(sizeof(PictFilterAliasRec)); 185 if (!aliases) 186 return FALSE; 187 ps->filterAliases = aliases; 188 ps->filterAliases[i].alias = PictureGetFilterName(alias_id); 189 ps->filterAliases[i].alias_id = alias_id; 190 ps->nfilterAliases++; 191 } 192 ps->filterAliases[i].filter_id = filter_id; 193 return TRUE; 194 } 195 196 PictFilterPtr 197 PictureFindFilter(ScreenPtr pScreen, char *name, int len) 198 { 199 PictureScreenPtr ps = GetPictureScreen(pScreen); 200 int id = PictureGetFilterId(name, len, FALSE); 201 int i; 202 203 if (id < 0) 204 return 0; 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; 209 i = 0; 210 } 211 /* find the filter */ 212 for (i = 0; i < ps->nfilters; i++) 213 if (ps->filters[i].id == id) 214 return &ps->filters[i]; 215 return 0; 216 } 217 218 static Bool 219 convolutionFilterValidateParams(ScreenPtr pScreen, 220 int filter, 221 xFixed * params, 222 int nparams, int *width, int *height) 223 { 224 int w, h; 225 226 if (nparams < 3) 227 return FALSE; 228 229 if (xFixedFrac(params[0]) || xFixedFrac(params[1])) 230 return FALSE; 231 232 w = xFixedToInt(params[0]); 233 h = xFixedToInt(params[1]); 234 235 nparams -= 2; 236 if (w * h > nparams) 237 return FALSE; 238 239 *width = w; 240 *height = h; 241 return TRUE; 242 } 243 244 Bool 245 PictureSetDefaultFilters(ScreenPtr pScreen) 246 { 247 if (!filterNames) 248 if (!PictureSetDefaultIds()) 249 return FALSE; 250 if (PictureAddFilter(pScreen, FilterNearest, 0, 1, 1) < 0) 251 return FALSE; 252 if (PictureAddFilter(pScreen, FilterBilinear, 0, 2, 2) < 0) 253 return FALSE; 254 255 if (!PictureSetFilterAlias(pScreen, FilterNearest, FilterFast)) 256 return FALSE; 257 if (!PictureSetFilterAlias(pScreen, FilterBilinear, FilterGood)) 258 return FALSE; 259 if (!PictureSetFilterAlias(pScreen, FilterBilinear, FilterBest)) 260 return FALSE; 261 262 if (PictureAddFilter 263 (pScreen, FilterConvolution, convolutionFilterValidateParams, 0, 0) < 0) 264 return FALSE; 265 266 return TRUE; 267 } 268 269 void 270 PictureResetFilters(ScreenPtr pScreen) 271 { 272 PictureScreenPtr ps = GetPictureScreen(pScreen); 273 274 free(ps->filters); 275 free(ps->filterAliases); 276 277 /* Free the filters when the last screen is closed */ 278 if (pScreen->myNum == 0) 279 PictureFreeFilterIds(); 280 } 281 282 int 283 SetPictureFilter(PicturePtr pPicture, char *name, int len, xFixed * params, 284 int nparams) 285 { 286 PictFilterPtr pFilter; 287 ScreenPtr pScreen; 288 289 if (pPicture->pDrawable != NULL) 290 pScreen = pPicture->pDrawable->pScreen; 291 else 292 pScreen = screenInfo.screens[0]; 293 294 pFilter = PictureFindFilter(pScreen, name, len); 295 296 if (!pFilter) 297 return BadName; 298 299 if (pPicture->pDrawable == NULL) { 300 int s; 301 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. 304 */ 305 for (s = 1; s < screenInfo.numScreens; s++) { 306 PictFilterPtr pScreenFilter; 307 308 pScreenFilter = PictureFindFilter(screenInfo.screens[s], name, len); 309 if (!pScreenFilter || pScreenFilter->id != pFilter->id) 310 return BadMatch; 311 } 312 } 313 return SetPicturePictFilter(pPicture, pFilter, params, nparams); 314 } 315 316 int 317 SetPicturePictFilter(PicturePtr pPicture, PictFilterPtr pFilter, 318 xFixed * params, int nparams) 319 { 320 ScreenPtr pScreen; 321 int i; 322 323 if (pPicture->pDrawable) 324 pScreen = pPicture->pDrawable->pScreen; 325 else 326 pScreen = screenInfo.screens[0]; 327 328 if (pFilter->ValidateParams) { 329 int width, height; 330 331 if (!(*pFilter->ValidateParams) 332 (pScreen, pFilter->id, params, nparams, &width, &height)) 333 return BadMatch; 334 } 335 else if (nparams) 336 return BadMatch; 337 338 if (nparams != pPicture->filter_nparams) { 339 xFixed *new_params = xallocarray(nparams, sizeof(xFixed)); 340 341 if (!new_params && nparams) 342 return BadAlloc; 343 free(pPicture->filter_params); 344 pPicture->filter_params = new_params; 345 pPicture->filter_nparams = nparams; 346 } 347 for (i = 0; i < nparams; i++) 348 pPicture->filter_params[i] = params[i]; 349 pPicture->filter = pFilter->id; 350 351 if (pPicture->pDrawable) { 352 PictureScreenPtr ps = GetPictureScreen(pScreen); 353 int result; 354 355 result = (*ps->ChangePictureFilter) (pPicture, pPicture->filter, 356 params, nparams); 357 return result; 358 } 359 return Success; 360 }