filter.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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. #ifdef HAVE_DIX_CONFIG_H
  24. #include <dix-config.h>
  25. #endif
  26. #include "misc.h"
  27. #include "scrnintstr.h"
  28. #include "os.h"
  29. #include "regionstr.h"
  30. #include "validate.h"
  31. #include "windowstr.h"
  32. #include "input.h"
  33. #include "resource.h"
  34. #include "colormapst.h"
  35. #include "cursorstr.h"
  36. #include "dixstruct.h"
  37. #include "gcstruct.h"
  38. #include "servermd.h"
  39. #include "picturestr.h"
  40. static char **filterNames;
  41. static int nfilterNames;
  42. /*
  43. * standard but not required filters don't have constant indices
  44. */
  45. int
  46. PictureGetFilterId(char *filter, int len, Bool makeit)
  47. {
  48. int i;
  49. char *name;
  50. char **names;
  51. if (len < 0)
  52. len = strlen(filter);
  53. for (i = 0; i < nfilterNames; i++)
  54. if (!CompareISOLatin1Lowered
  55. ((unsigned char *) filterNames[i], -1, (unsigned char *) filter,
  56. len))
  57. return i;
  58. if (!makeit)
  59. return -1;
  60. name = malloc(len + 1);
  61. if (!name)
  62. return -1;
  63. memcpy(name, filter, len);
  64. name[len] = '\0';
  65. if (filterNames)
  66. names = realloc(filterNames, (nfilterNames + 1) * sizeof(char *));
  67. else
  68. names = malloc(sizeof(char *));
  69. if (!names) {
  70. free(name);
  71. return -1;
  72. }
  73. filterNames = names;
  74. i = nfilterNames++;
  75. filterNames[i] = name;
  76. return i;
  77. }
  78. static Bool
  79. PictureSetDefaultIds(void)
  80. {
  81. /* careful here -- this list must match the #define values */
  82. if (PictureGetFilterId(FilterNearest, -1, TRUE) != PictFilterNearest)
  83. return FALSE;
  84. if (PictureGetFilterId(FilterBilinear, -1, TRUE) != PictFilterBilinear)
  85. return FALSE;
  86. if (PictureGetFilterId(FilterFast, -1, TRUE) != PictFilterFast)
  87. return FALSE;
  88. if (PictureGetFilterId(FilterGood, -1, TRUE) != PictFilterGood)
  89. return FALSE;
  90. if (PictureGetFilterId(FilterBest, -1, TRUE) != PictFilterBest)
  91. return FALSE;
  92. if (PictureGetFilterId(FilterConvolution, -1, TRUE) !=
  93. PictFilterConvolution)
  94. return FALSE;
  95. return TRUE;
  96. }
  97. char *
  98. PictureGetFilterName(int id)
  99. {
  100. if (0 <= id && id < nfilterNames)
  101. return filterNames[id];
  102. else
  103. return 0;
  104. }
  105. static void
  106. PictureFreeFilterIds(void)
  107. {
  108. int i;
  109. for (i = 0; i < nfilterNames; i++)
  110. free(filterNames[i]);
  111. free(filterNames);
  112. nfilterNames = 0;
  113. filterNames = 0;
  114. }
  115. _X_EXPORT int
  116. PictureAddFilter(ScreenPtr pScreen,
  117. char *filter, PictFilterValidateParamsProcPtr ValidateParams)
  118. {
  119. PictureScreenPtr ps = GetPictureScreen(pScreen);
  120. int id = PictureGetFilterId(filter, -1, TRUE);
  121. int i;
  122. PictFilterPtr filters;
  123. if (id < 0)
  124. return -1;
  125. /*
  126. * It's an error to attempt to reregister a filter
  127. */
  128. for (i = 0; i < ps->nfilters; i++)
  129. if (ps->filters[i].id == id)
  130. return -1;
  131. if (ps->filters)
  132. filters =
  133. realloc(ps->filters, (ps->nfilters + 1) * sizeof(PictFilterRec));
  134. else
  135. filters = malloc(sizeof(PictFilterRec));
  136. if (!filters)
  137. return -1;
  138. ps->filters = filters;
  139. i = ps->nfilters++;
  140. ps->filters[i].name = PictureGetFilterName(id);
  141. ps->filters[i].id = id;
  142. ps->filters[i].ValidateParams = ValidateParams;
  143. return id;
  144. }
  145. _X_EXPORT Bool
  146. PictureSetFilterAlias(ScreenPtr pScreen, char *filter, char *alias)
  147. {
  148. PictureScreenPtr ps = GetPictureScreen(pScreen);
  149. int filter_id = PictureGetFilterId(filter, -1, FALSE);
  150. int alias_id = PictureGetFilterId(alias, -1, TRUE);
  151. int i;
  152. if (filter_id < 0 || alias_id < 0)
  153. return FALSE;
  154. for (i = 0; i < ps->nfilterAliases; i++)
  155. if (ps->filterAliases[i].alias_id == alias_id)
  156. break;
  157. if (i == ps->nfilterAliases) {
  158. PictFilterAliasPtr aliases;
  159. if (ps->filterAliases)
  160. aliases = realloc(ps->filterAliases,
  161. (ps->nfilterAliases + 1) *
  162. sizeof(PictFilterAliasRec));
  163. else
  164. aliases = malloc(sizeof(PictFilterAliasRec));
  165. if (!aliases)
  166. return FALSE;
  167. ps->filterAliases = aliases;
  168. ps->filterAliases[i].alias = PictureGetFilterName(alias_id);
  169. ps->filterAliases[i].alias_id = alias_id;
  170. ps->nfilterAliases++;
  171. }
  172. ps->filterAliases[i].filter_id = filter_id;
  173. return TRUE;
  174. }
  175. PictFilterPtr
  176. PictureFindFilter(ScreenPtr pScreen, char *name, int len)
  177. {
  178. PictureScreenPtr ps = GetPictureScreen(pScreen);
  179. int id = PictureGetFilterId(name, len, FALSE);
  180. int i;
  181. if (id < 0)
  182. return 0;
  183. /* Check for an alias, allow them to recurse */
  184. for (i = 0; i < ps->nfilterAliases; i++)
  185. if (ps->filterAliases[i].alias_id == id) {
  186. id = ps->filterAliases[i].filter_id;
  187. i = 0;
  188. }
  189. /* find the filter */
  190. for (i = 0; i < ps->nfilters; i++)
  191. if (ps->filters[i].id == id)
  192. return &ps->filters[i];
  193. return 0;
  194. }
  195. static Bool
  196. convolutionFilterValidateParams(PicturePtr pPicture,
  197. int filter, xFixed * params, int nparams)
  198. {
  199. if (nparams < 3)
  200. return FALSE;
  201. if (xFixedFrac(params[0]) || xFixedFrac(params[1]))
  202. return FALSE;
  203. nparams -= 2;
  204. if ((xFixedToInt(params[0]) * xFixedToInt(params[1])) > nparams)
  205. return FALSE;
  206. return TRUE;
  207. }
  208. Bool
  209. PictureSetDefaultFilters(ScreenPtr pScreen)
  210. {
  211. if (!filterNames)
  212. if (!PictureSetDefaultIds())
  213. return FALSE;
  214. if (PictureAddFilter(pScreen, FilterNearest, 0) < 0)
  215. return FALSE;
  216. if (PictureAddFilter(pScreen, FilterBilinear, 0) < 0)
  217. return FALSE;
  218. if (!PictureSetFilterAlias(pScreen, FilterNearest, FilterFast))
  219. return FALSE;
  220. if (!PictureSetFilterAlias(pScreen, FilterBilinear, FilterGood))
  221. return FALSE;
  222. if (!PictureSetFilterAlias(pScreen, FilterBilinear, FilterBest))
  223. return FALSE;
  224. if (PictureAddFilter
  225. (pScreen, FilterConvolution, convolutionFilterValidateParams) < 0)
  226. return FALSE;
  227. return TRUE;
  228. }
  229. void
  230. PictureResetFilters(ScreenPtr pScreen)
  231. {
  232. PictureScreenPtr ps = GetPictureScreen(pScreen);
  233. free(ps->filters);
  234. free(ps->filterAliases);
  235. PictureFreeFilterIds();
  236. }
  237. int
  238. SetPictureFilter(PicturePtr pPicture, char *name, int len, xFixed * params,
  239. int nparams)
  240. {
  241. PictFilterPtr pFilter;
  242. xFixed *new_params;
  243. int i, s, result;
  244. pFilter = PictureFindFilter(screenInfo.screens[0], name, len);
  245. if (!pFilter)
  246. return BadName;
  247. if (pPicture->pDrawable == NULL) {
  248. /* For source pictures, the picture isn't tied to a screen. So, ensure
  249. * that all screens can handle a filter we set for the picture.
  250. */
  251. for (s = 0; s < screenInfo.numScreens; s++) {
  252. PictFilterPtr tmp = PictureFindFilter(screenInfo.screens[s], name, len);
  253. if (!tmp) return BadName;
  254. if (tmp->id != pFilter->id) {
  255. return BadMatch;
  256. }
  257. }
  258. }
  259. if (pFilter->ValidateParams) {
  260. if (!(*pFilter->ValidateParams)
  261. (pPicture, pFilter->id, params, nparams))
  262. return BadMatch;
  263. }
  264. else if (nparams)
  265. return BadMatch;
  266. if (nparams != pPicture->filter_nparams) {
  267. new_params = malloc(nparams * sizeof(xFixed));
  268. if (!new_params)
  269. return BadAlloc;
  270. free(pPicture->filter_params);
  271. pPicture->filter_params = new_params;
  272. pPicture->filter_nparams = nparams;
  273. }
  274. for (i = 0; i < nparams; i++)
  275. pPicture->filter_params[i] = params[i];
  276. pPicture->filter = pFilter->id;
  277. if (pPicture->pDrawable) {
  278. ScreenPtr pScreen = pPicture->pDrawable->pScreen;
  279. PictureScreenPtr ps = GetPictureScreen(pScreen);
  280. result = (*ps->ChangePictureFilter) (pPicture, pPicture->filter,
  281. params, nparams);
  282. return result;
  283. }
  284. return Success;
  285. }