xlib-surface.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. * Copyright © 2005 Red Hat, Inc.
  3. *
  4. * Permission to use, copy, modify, distribute, and sell this software
  5. * and its documentation for any purpose is hereby granted without
  6. * fee, provided that the above copyright notice appear in all copies
  7. * and that both that copyright notice and this permission notice
  8. * appear in supporting documentation, and that the name of
  9. * Red Hat, Inc. not be used in advertising or publicity pertaining to
  10. * distribution of the software without specific, written prior
  11. * permission. Red Hat, Inc. makes no representations about the
  12. * suitability of this software for any purpose. It is provided "as
  13. * is" without express or implied warranty.
  14. *
  15. * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  16. * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
  18. * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  19. * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
  21. * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22. *
  23. * Author: Carl D. Worth <cworth@cworth.org>
  24. */
  25. #include "cairo-test.h"
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include "cairo.h"
  29. #include "cairo-xlib.h"
  30. #include "cairo-boilerplate-xlib.h"
  31. #include "buffer-diff.h"
  32. #define SIZE 100
  33. #define OFFSCREEN_OFFSET 50
  34. cairo_bool_t result = 0;
  35. #if CAIRO_HAS_XLIB_XRENDER_SURFACE
  36. #include "cairo-xlib-xrender.h"
  37. /* Vladimir Vukicevic reported that surfaces were being created with
  38. * mismatching Visuals and XRenderPictFormats.
  39. */
  40. static cairo_bool_t
  41. surface_compare_visual_and_format (cairo_surface_t *surface)
  42. {
  43. Display *dpy;
  44. Visual *visual;
  45. XRenderPictFormat *format;
  46. dpy = cairo_xlib_surface_get_display (surface);
  47. visual = cairo_xlib_surface_get_visual (surface);
  48. if (visual == NULL)
  49. return TRUE;
  50. format = cairo_xlib_surface_get_xrender_format (surface);
  51. if (format == NULL)
  52. return TRUE;
  53. return format == XRenderFindVisualFormat (dpy, visual);
  54. }
  55. #else
  56. static cairo_bool_t
  57. surface_compare_visual_and_format (cairo_surface_t *surface)
  58. {
  59. return TRUE;
  60. }
  61. #endif
  62. static cairo_bool_t
  63. check_similar_visual_and_format (cairo_surface_t *surface)
  64. {
  65. cairo_surface_t *similar;
  66. cairo_bool_t ret;
  67. similar = cairo_surface_create_similar (surface,
  68. CAIRO_CONTENT_COLOR_ALPHA,
  69. 1, 1);
  70. if (cairo_surface_status (similar))
  71. return FALSE;
  72. ret = surface_compare_visual_and_format (similar);
  73. cairo_surface_destroy (similar);
  74. return ret;
  75. }
  76. static void
  77. draw_pattern (cairo_surface_t *surface)
  78. {
  79. cairo_t *cr = cairo_create (surface);
  80. int i;
  81. cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
  82. cairo_paint (cr);
  83. cairo_set_source_rgba (cr, 0, 0.0, 0.0, 0.50); /* half-alpha-black */
  84. for (i = 1; i <= 3; i++) {
  85. int inset = SIZE / 8 * i;
  86. cairo_rectangle (cr,
  87. inset, inset,
  88. SIZE - 2 * inset, SIZE - 2 * inset);
  89. cairo_fill (cr);
  90. }
  91. cairo_destroy (cr);
  92. }
  93. static void
  94. erase_pattern (cairo_surface_t *surface)
  95. {
  96. cairo_t *cr = cairo_create (surface);
  97. cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
  98. cairo_paint (cr);
  99. cairo_destroy (cr);
  100. }
  101. static cairo_test_status_t
  102. do_test (const cairo_test_context_t *ctx,
  103. Display *dpy,
  104. unsigned char *reference_data,
  105. unsigned char *test_data,
  106. unsigned char *diff_data,
  107. cairo_bool_t use_pixmap,
  108. cairo_bool_t set_size,
  109. cairo_bool_t offscreen)
  110. {
  111. cairo_surface_t *surface;
  112. cairo_surface_t *test_surface;
  113. cairo_t *test_cr;
  114. buffer_diff_result_t result;
  115. Drawable drawable;
  116. int screen = DefaultScreen (dpy);
  117. if (use_pixmap && offscreen)
  118. return CAIRO_TEST_SUCCESS;
  119. if (use_pixmap) {
  120. drawable = XCreatePixmap (dpy, DefaultRootWindow (dpy),
  121. SIZE, SIZE, DefaultDepth (dpy, screen));
  122. } else {
  123. XSetWindowAttributes xwa;
  124. int x, y;
  125. xwa.override_redirect = True;
  126. if (offscreen) {
  127. x = - OFFSCREEN_OFFSET;
  128. y = - OFFSCREEN_OFFSET;
  129. } else {
  130. x = 0;
  131. y = 0;
  132. }
  133. drawable = XCreateWindow (dpy, DefaultRootWindow (dpy),
  134. x, y, SIZE, SIZE, 0,
  135. DefaultDepth (dpy, screen), InputOutput,
  136. DefaultVisual (dpy, screen),
  137. CWOverrideRedirect, &xwa);
  138. XMapWindow (dpy, drawable);
  139. }
  140. surface = cairo_xlib_surface_create (dpy,
  141. drawable,
  142. DefaultVisual (dpy, screen),
  143. SIZE, SIZE);
  144. if (! surface_compare_visual_and_format (surface))
  145. return CAIRO_TEST_FAILURE;
  146. if (set_size) {
  147. cairo_xlib_surface_set_size (surface, SIZE, SIZE);
  148. if (cairo_xlib_surface_get_width (surface) != SIZE ||
  149. cairo_xlib_surface_get_height (surface) != SIZE)
  150. return CAIRO_TEST_FAILURE;
  151. }
  152. if (! check_similar_visual_and_format (surface))
  153. return CAIRO_TEST_FAILURE;
  154. draw_pattern (surface);
  155. test_surface = cairo_image_surface_create_for_data (test_data,
  156. CAIRO_FORMAT_RGB24,
  157. SIZE, SIZE,
  158. SIZE * 4);
  159. test_cr = cairo_create (test_surface);
  160. cairo_set_source_surface (test_cr, surface, 0, 0);
  161. cairo_paint (test_cr);
  162. cairo_destroy (test_cr);
  163. cairo_surface_destroy (test_surface);
  164. /* We erase the surface to black in case we get the same
  165. * memory back again for the pixmap case.
  166. */
  167. erase_pattern (surface);
  168. cairo_surface_destroy (surface);
  169. if (use_pixmap)
  170. XFreePixmap (dpy, drawable);
  171. else
  172. XDestroyWindow (dpy, drawable);
  173. if (offscreen) {
  174. size_t offset = 4 * (SIZE * OFFSCREEN_OFFSET + OFFSCREEN_OFFSET);
  175. buffer_diff_noalpha (reference_data + offset,
  176. test_data + offset,
  177. diff_data + offset,
  178. SIZE - OFFSCREEN_OFFSET,
  179. SIZE - OFFSCREEN_OFFSET,
  180. 4 * SIZE,
  181. &result);
  182. } else {
  183. buffer_diff_noalpha (reference_data,
  184. test_data,
  185. diff_data,
  186. SIZE,
  187. SIZE,
  188. 4 * SIZE,
  189. &result);
  190. }
  191. cairo_test_log (ctx, "xlib-surface: %s, %s, %s: %s\n",
  192. set_size ? " size" : "no-size",
  193. use_pixmap ? "pixmap" : "window",
  194. use_pixmap ? " " : (offscreen ? ", offscreen" : ", onscreen"),
  195. image_diff_is_failure (&result, 0) ? "FAIL" : "PASS");
  196. if (image_diff_is_failure (&result, 0))
  197. return CAIRO_TEST_FAILURE;
  198. else
  199. return CAIRO_TEST_SUCCESS;
  200. }
  201. static cairo_bool_t
  202. check_visual (Display *dpy)
  203. {
  204. Visual *visual = DefaultVisual (dpy, DefaultScreen (dpy));
  205. if ((visual->red_mask == 0xff0000 &&
  206. visual->green_mask == 0x00ff00 &&
  207. visual->blue_mask == 0x0000ff) ||
  208. (visual->red_mask == 0x0000ff &&
  209. visual->green_mask == 0x00ff00 &&
  210. visual->blue_mask == 0xff0000))
  211. return 1;
  212. else
  213. return 0;
  214. }
  215. #undef xcalloc
  216. static void *
  217. xcalloc (const cairo_test_context_t *ctx, size_t a, size_t b)
  218. {
  219. void *ptr = calloc (a, b);
  220. if (ptr == NULL) {
  221. cairo_test_log (ctx, "xlib-surface: unable to allocate memory, skipping\n");
  222. abort ();
  223. }
  224. return ptr;
  225. }
  226. static cairo_test_status_t
  227. preamble (cairo_test_context_t *ctx)
  228. {
  229. Display *dpy;
  230. unsigned char *reference_data;
  231. unsigned char *test_data;
  232. unsigned char *diff_data;
  233. cairo_surface_t *reference_surface;
  234. cairo_bool_t use_pixmap;
  235. cairo_bool_t set_size;
  236. cairo_bool_t offscreen;
  237. cairo_test_status_t status, result = CAIRO_TEST_UNTESTED;
  238. int stride;
  239. if (! cairo_test_is_target_enabled (ctx, "xlib"))
  240. goto CLEANUP_TEST;
  241. dpy = XOpenDisplay (NULL);
  242. if (!dpy) {
  243. cairo_test_log (ctx, "xlib-surface: Cannot open display, skipping\n");
  244. goto CLEANUP_TEST;
  245. }
  246. if (!check_visual (dpy)) {
  247. cairo_test_log (ctx, "xlib-surface: default visual is not RGB24 or BGR24, skipping\n");
  248. goto CLEANUP_DISPLAY;
  249. }
  250. stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, SIZE);
  251. reference_data = xcalloc (ctx, SIZE, stride);
  252. test_data = xcalloc (ctx, SIZE, stride);
  253. diff_data = xcalloc (ctx, SIZE, stride);
  254. reference_surface = cairo_image_surface_create_for_data (reference_data,
  255. CAIRO_FORMAT_RGB24,
  256. SIZE, SIZE,
  257. stride);
  258. draw_pattern (reference_surface);
  259. cairo_surface_destroy (reference_surface);
  260. result = CAIRO_TEST_SUCCESS;
  261. for (set_size = 0; set_size <= 1; set_size++)
  262. for (use_pixmap = 0; use_pixmap <= 1; use_pixmap++)
  263. for (offscreen = 0; offscreen <= 1; offscreen++) {
  264. status = do_test (ctx, dpy,
  265. reference_data, test_data, diff_data,
  266. use_pixmap, set_size, offscreen);
  267. if (status)
  268. result = status;
  269. }
  270. free (reference_data);
  271. free (test_data);
  272. free (diff_data);
  273. CLEANUP_DISPLAY:
  274. XCloseDisplay (dpy);
  275. CLEANUP_TEST:
  276. return result;
  277. }
  278. CAIRO_TEST (xlib_surface,
  279. "Check creating surfaces for various XWindows",
  280. "xlib", /* keywords */
  281. NULL, /* requirements */
  282. 0, 0,
  283. preamble, NULL)