utils.c 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110
  1. #define _GNU_SOURCE
  2. #include "utils.h"
  3. #include <math.h>
  4. #include <signal.h>
  5. #include <stdlib.h>
  6. #include <float.h>
  7. #include <ctype.h>
  8. #include <limits.h>
  9. #ifdef HAVE_GETTIMEOFDAY
  10. #include <sys/time.h>
  11. #else
  12. #include <time.h>
  13. #endif
  14. #ifdef HAVE_UNISTD_H
  15. #include <unistd.h>
  16. #endif
  17. #ifdef HAVE_SYS_MMAN_H
  18. #include <sys/mman.h>
  19. #endif
  20. #ifdef HAVE_FENV_H
  21. #include <fenv.h>
  22. #endif
  23. #ifdef HAVE_LIBPNG
  24. #include <png.h>
  25. #endif
  26. #define ROUND_UP(x, mult) (((x) + (mult) - 1) / (mult) * (mult))
  27. /* Random number generator state
  28. */
  29. prng_t prng_state_data;
  30. prng_t *prng_state;
  31. /*----------------------------------------------------------------------------*\
  32. * CRC-32 version 2.0.0 by Craig Bruce, 2006-04-29.
  33. *
  34. * This program generates the CRC-32 values for the files named in the
  35. * command-line arguments. These are the same CRC-32 values used by GZIP,
  36. * PKZIP, and ZMODEM. The Crc32_ComputeBuf () can also be detached and
  37. * used independently.
  38. *
  39. * THIS PROGRAM IS PUBLIC-DOMAIN SOFTWARE.
  40. *
  41. * Based on the byte-oriented implementation "File Verification Using CRC"
  42. * by Mark R. Nelson in Dr. Dobb's Journal, May 1992, pp. 64-67.
  43. *
  44. * v1.0.0: original release.
  45. * v1.0.1: fixed printf formats.
  46. * v1.0.2: fixed something else.
  47. * v1.0.3: replaced CRC constant table by generator function.
  48. * v1.0.4: reformatted code, made ANSI C. 1994-12-05.
  49. * v2.0.0: rewrote to use memory buffer & static table, 2006-04-29.
  50. \*----------------------------------------------------------------------------*/
  51. /*----------------------------------------------------------------------------*\
  52. * NAME:
  53. * Crc32_ComputeBuf () - computes the CRC-32 value of a memory buffer
  54. * DESCRIPTION:
  55. * Computes or accumulates the CRC-32 value for a memory buffer.
  56. * The 'inCrc32' gives a previously accumulated CRC-32 value to allow
  57. * a CRC to be generated for multiple sequential buffer-fuls of data.
  58. * The 'inCrc32' for the first buffer must be zero.
  59. * ARGUMENTS:
  60. * inCrc32 - accumulated CRC-32 value, must be 0 on first call
  61. * buf - buffer to compute CRC-32 value for
  62. * bufLen - number of bytes in buffer
  63. * RETURNS:
  64. * crc32 - computed CRC-32 value
  65. * ERRORS:
  66. * (no errors are possible)
  67. \*----------------------------------------------------------------------------*/
  68. uint32_t
  69. compute_crc32 (uint32_t in_crc32,
  70. const void *buf,
  71. size_t buf_len)
  72. {
  73. static const uint32_t crc_table[256] = {
  74. 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
  75. 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
  76. 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
  77. 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
  78. 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
  79. 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
  80. 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
  81. 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
  82. 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
  83. 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
  84. 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
  85. 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
  86. 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
  87. 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
  88. 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
  89. 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
  90. 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
  91. 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
  92. 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
  93. 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
  94. 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
  95. 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
  96. 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
  97. 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
  98. 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
  99. 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
  100. 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
  101. 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
  102. 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
  103. 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
  104. 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
  105. 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
  106. 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
  107. 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
  108. 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
  109. 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
  110. 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
  111. 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
  112. 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
  113. 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
  114. 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
  115. 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
  116. 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
  117. };
  118. uint32_t crc32;
  119. unsigned char * byte_buf;
  120. size_t i;
  121. /* accumulate crc32 for buffer */
  122. crc32 = in_crc32 ^ 0xFFFFFFFF;
  123. byte_buf = (unsigned char*) buf;
  124. for (i = 0; i < buf_len; i++)
  125. crc32 = (crc32 >> 8) ^ crc_table[(crc32 ^ byte_buf[i]) & 0xFF];
  126. return (crc32 ^ 0xFFFFFFFF);
  127. }
  128. static uint32_t
  129. compute_crc32_for_image_internal (uint32_t crc32,
  130. pixman_image_t *img,
  131. pixman_bool_t remove_alpha,
  132. pixman_bool_t remove_rgb)
  133. {
  134. pixman_format_code_t fmt = pixman_image_get_format (img);
  135. uint32_t *data = pixman_image_get_data (img);
  136. int stride = pixman_image_get_stride (img);
  137. int height = pixman_image_get_height (img);
  138. uint32_t mask = 0xffffffff;
  139. int i;
  140. if (stride < 0)
  141. {
  142. data += (stride / 4) * (height - 1);
  143. stride = - stride;
  144. }
  145. /* mask unused 'x' part */
  146. if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
  147. PIXMAN_FORMAT_DEPTH (fmt) != 0)
  148. {
  149. uint32_t m = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
  150. if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
  151. PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA)
  152. {
  153. m <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt));
  154. }
  155. mask &= m;
  156. }
  157. /* mask alpha channel */
  158. if (remove_alpha && PIXMAN_FORMAT_A (fmt))
  159. {
  160. uint32_t m;
  161. if (PIXMAN_FORMAT_BPP (fmt) == 32)
  162. m = 0xffffffff;
  163. else
  164. m = (1 << PIXMAN_FORMAT_BPP (fmt)) - 1;
  165. m >>= PIXMAN_FORMAT_A (fmt);
  166. if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
  167. PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA ||
  168. PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_A)
  169. {
  170. /* Alpha is at the bottom of the pixel */
  171. m <<= PIXMAN_FORMAT_A (fmt);
  172. }
  173. mask &= m;
  174. }
  175. /* mask rgb channels */
  176. if (remove_rgb && PIXMAN_FORMAT_RGB (fmt))
  177. {
  178. uint32_t m = ((uint32_t)~0) >> (32 - PIXMAN_FORMAT_BPP (fmt));
  179. uint32_t size = PIXMAN_FORMAT_R (fmt) + PIXMAN_FORMAT_G (fmt) + PIXMAN_FORMAT_B (fmt);
  180. m &= ~((1 << size) - 1);
  181. if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
  182. PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA)
  183. {
  184. /* RGB channels are at the top of the pixel */
  185. m >>= size;
  186. }
  187. mask &= m;
  188. }
  189. for (i = 0; i * PIXMAN_FORMAT_BPP (fmt) < 32; i++)
  190. mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
  191. for (i = 0; i < stride * height / 4; i++)
  192. data[i] &= mask;
  193. /* swap endiannes in order to provide identical results on both big
  194. * and litte endian systems
  195. */
  196. image_endian_swap (img);
  197. return compute_crc32 (crc32, data, stride * height);
  198. }
  199. uint32_t
  200. compute_crc32_for_image (uint32_t crc32,
  201. pixman_image_t *img)
  202. {
  203. if (img->common.alpha_map)
  204. {
  205. crc32 = compute_crc32_for_image_internal (crc32, img, TRUE, FALSE);
  206. crc32 = compute_crc32_for_image_internal (
  207. crc32, (pixman_image_t *)img->common.alpha_map, FALSE, TRUE);
  208. }
  209. else
  210. {
  211. crc32 = compute_crc32_for_image_internal (crc32, img, FALSE, FALSE);
  212. }
  213. return crc32;
  214. }
  215. void
  216. print_image (pixman_image_t *image)
  217. {
  218. int i, j;
  219. int width, height, stride;
  220. pixman_format_code_t format;
  221. uint8_t *buffer;
  222. int s;
  223. width = pixman_image_get_width (image);
  224. height = pixman_image_get_height (image);
  225. stride = pixman_image_get_stride (image);
  226. format = pixman_image_get_format (image);
  227. buffer = (uint8_t *)pixman_image_get_data (image);
  228. s = (stride >= 0)? stride : - stride;
  229. printf ("---\n");
  230. for (i = 0; i < height; i++)
  231. {
  232. for (j = 0; j < s; j++)
  233. {
  234. if (j == (width * PIXMAN_FORMAT_BPP (format) + 7) / 8)
  235. printf ("| ");
  236. printf ("%02X ", *((uint8_t *)buffer + i * stride + j));
  237. }
  238. printf ("\n");
  239. }
  240. printf ("---\n");
  241. }
  242. /* perform endian conversion of pixel data
  243. */
  244. void
  245. image_endian_swap (pixman_image_t *img)
  246. {
  247. int stride = pixman_image_get_stride (img);
  248. uint32_t *data = pixman_image_get_data (img);
  249. int height = pixman_image_get_height (img);
  250. int bpp = PIXMAN_FORMAT_BPP (pixman_image_get_format (img));
  251. int i, j;
  252. /* swap bytes only on big endian systems */
  253. if (is_little_endian())
  254. return;
  255. if (bpp == 8)
  256. return;
  257. for (i = 0; i < height; i++)
  258. {
  259. uint8_t *line_data = (uint8_t *)data + stride * i;
  260. int s = (stride >= 0)? stride : - stride;
  261. switch (bpp)
  262. {
  263. case 1:
  264. for (j = 0; j < s; j++)
  265. {
  266. line_data[j] =
  267. ((line_data[j] & 0x80) >> 7) |
  268. ((line_data[j] & 0x40) >> 5) |
  269. ((line_data[j] & 0x20) >> 3) |
  270. ((line_data[j] & 0x10) >> 1) |
  271. ((line_data[j] & 0x08) << 1) |
  272. ((line_data[j] & 0x04) << 3) |
  273. ((line_data[j] & 0x02) << 5) |
  274. ((line_data[j] & 0x01) << 7);
  275. }
  276. break;
  277. case 4:
  278. for (j = 0; j < s; j++)
  279. {
  280. line_data[j] = (line_data[j] >> 4) | (line_data[j] << 4);
  281. }
  282. break;
  283. case 16:
  284. for (j = 0; j + 2 <= s; j += 2)
  285. {
  286. char t1 = line_data[j + 0];
  287. char t2 = line_data[j + 1];
  288. line_data[j + 1] = t1;
  289. line_data[j + 0] = t2;
  290. }
  291. break;
  292. case 24:
  293. for (j = 0; j + 3 <= s; j += 3)
  294. {
  295. char t1 = line_data[j + 0];
  296. char t2 = line_data[j + 1];
  297. char t3 = line_data[j + 2];
  298. line_data[j + 2] = t1;
  299. line_data[j + 1] = t2;
  300. line_data[j + 0] = t3;
  301. }
  302. break;
  303. case 32:
  304. for (j = 0; j + 4 <= s; j += 4)
  305. {
  306. char t1 = line_data[j + 0];
  307. char t2 = line_data[j + 1];
  308. char t3 = line_data[j + 2];
  309. char t4 = line_data[j + 3];
  310. line_data[j + 3] = t1;
  311. line_data[j + 2] = t2;
  312. line_data[j + 1] = t3;
  313. line_data[j + 0] = t4;
  314. }
  315. break;
  316. default:
  317. assert (FALSE);
  318. break;
  319. }
  320. }
  321. }
  322. #define N_LEADING_PROTECTED 10
  323. #define N_TRAILING_PROTECTED 10
  324. typedef struct
  325. {
  326. void *addr;
  327. uint32_t len;
  328. uint8_t *trailing;
  329. int n_bytes;
  330. } info_t;
  331. #if FENCE_MALLOC_ACTIVE
  332. unsigned long
  333. fence_get_page_size ()
  334. {
  335. /* You can fake a page size here, if you want to test e.g. 64 kB
  336. * pages on a 4 kB page system. Just put a multiplier below.
  337. */
  338. return getpagesize ();
  339. }
  340. /* This is apparently necessary on at least OS X */
  341. #ifndef MAP_ANONYMOUS
  342. #define MAP_ANONYMOUS MAP_ANON
  343. #endif
  344. void *
  345. fence_malloc (int64_t len)
  346. {
  347. unsigned long page_size = fence_get_page_size ();
  348. unsigned long page_mask = page_size - 1;
  349. uint32_t n_payload_bytes = (len + page_mask) & ~page_mask;
  350. uint32_t n_bytes =
  351. (page_size * (N_LEADING_PROTECTED + N_TRAILING_PROTECTED + 2) +
  352. n_payload_bytes) & ~page_mask;
  353. uint8_t *initial_page;
  354. uint8_t *leading_protected;
  355. uint8_t *trailing_protected;
  356. uint8_t *payload;
  357. uint8_t *addr;
  358. if (len < 0)
  359. abort();
  360. addr = mmap (NULL, n_bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
  361. -1, 0);
  362. if (addr == MAP_FAILED)
  363. {
  364. printf ("mmap failed on %lld %u\n", (long long int)len, n_bytes);
  365. return NULL;
  366. }
  367. initial_page = (uint8_t *)(((uintptr_t)addr + page_mask) & ~page_mask);
  368. leading_protected = initial_page + page_size;
  369. payload = leading_protected + N_LEADING_PROTECTED * page_size;
  370. trailing_protected = payload + n_payload_bytes;
  371. ((info_t *)initial_page)->addr = addr;
  372. ((info_t *)initial_page)->len = len;
  373. ((info_t *)initial_page)->trailing = trailing_protected;
  374. ((info_t *)initial_page)->n_bytes = n_bytes;
  375. if ((mprotect (leading_protected, N_LEADING_PROTECTED * page_size,
  376. PROT_NONE) == -1) ||
  377. (mprotect (trailing_protected, N_TRAILING_PROTECTED * page_size,
  378. PROT_NONE) == -1))
  379. {
  380. munmap (addr, n_bytes);
  381. return NULL;
  382. }
  383. return payload;
  384. }
  385. void
  386. fence_free (void *data)
  387. {
  388. uint32_t page_size = fence_get_page_size ();
  389. uint8_t *payload = data;
  390. uint8_t *leading_protected = payload - N_LEADING_PROTECTED * page_size;
  391. uint8_t *initial_page = leading_protected - page_size;
  392. info_t *info = (info_t *)initial_page;
  393. munmap (info->addr, info->n_bytes);
  394. }
  395. static void
  396. fence_image_destroy (pixman_image_t *image, void *data)
  397. {
  398. fence_free (data);
  399. }
  400. /* Create an image with fence pages.
  401. *
  402. * Creates an image, where the data area is allocated with fence_malloc ().
  403. * Each row has an additional page in the stride.
  404. *
  405. * min_width is only a minimum width for the image. The width is aligned up
  406. * for the row size to be divisible by both page size and pixel size.
  407. *
  408. * If stride_fence is true, the additional page on each row will be
  409. * armed to cause SIGSEGV or SIGBUS on all accesses. This should catch
  410. * all accesses outside the valid row pixels.
  411. */
  412. pixman_image_t *
  413. fence_image_create_bits (pixman_format_code_t format,
  414. int min_width,
  415. int height,
  416. pixman_bool_t stride_fence)
  417. {
  418. unsigned page_size = fence_get_page_size ();
  419. unsigned page_mask = page_size - 1;
  420. unsigned bitspp = PIXMAN_FORMAT_BPP (format);
  421. unsigned bits_boundary;
  422. unsigned row_bits;
  423. int width; /* pixels */
  424. unsigned stride; /* bytes */
  425. void *pixels;
  426. pixman_image_t *image;
  427. int i;
  428. /* must be power of two */
  429. assert (page_size && (page_size & page_mask) == 0);
  430. if (bitspp < 1 || min_width < 1 || height < 1)
  431. abort ();
  432. /* least common multiple between page size * 8 and bitspp */
  433. bits_boundary = bitspp;
  434. while (! (bits_boundary & 1))
  435. bits_boundary >>= 1;
  436. bits_boundary *= page_size * 8;
  437. /* round up to bits_boundary */
  438. row_bits = ROUND_UP ( (unsigned)min_width * bitspp, bits_boundary);
  439. width = row_bits / bitspp;
  440. stride = row_bits / 8;
  441. if (stride_fence)
  442. stride += page_size; /* add fence page */
  443. if (UINT_MAX / stride < (unsigned)height)
  444. abort ();
  445. pixels = fence_malloc (stride * (unsigned)height);
  446. if (!pixels)
  447. return NULL;
  448. if (stride_fence)
  449. {
  450. uint8_t *guard = (uint8_t *)pixels + stride - page_size;
  451. /* arm row end fence pages */
  452. for (i = 0; i < height; i++)
  453. {
  454. if (mprotect (guard + i * stride, page_size, PROT_NONE) == -1)
  455. goto out_fail;
  456. }
  457. }
  458. assert (width >= min_width);
  459. image = pixman_image_create_bits_no_clear (format, width, height,
  460. pixels, stride);
  461. if (!image)
  462. goto out_fail;
  463. pixman_image_set_destroy_function (image, fence_image_destroy, pixels);
  464. return image;
  465. out_fail:
  466. fence_free (pixels);
  467. return NULL;
  468. }
  469. #else /* FENCE_MALLOC_ACTIVE */
  470. void *
  471. fence_malloc (int64_t len)
  472. {
  473. return malloc (len);
  474. }
  475. void
  476. fence_free (void *data)
  477. {
  478. free (data);
  479. }
  480. pixman_image_t *
  481. fence_image_create_bits (pixman_format_code_t format,
  482. int min_width,
  483. int height,
  484. pixman_bool_t stride_fence)
  485. {
  486. return pixman_image_create_bits (format, min_width, height, NULL, 0);
  487. /* Implicitly allocated storage does not need a destroy function
  488. * to get freed on refcount hitting zero.
  489. */
  490. }
  491. unsigned long
  492. fence_get_page_size ()
  493. {
  494. return 0;
  495. }
  496. #endif /* FENCE_MALLOC_ACTIVE */
  497. uint8_t *
  498. make_random_bytes (int n_bytes)
  499. {
  500. uint8_t *bytes = fence_malloc (n_bytes);
  501. if (!bytes)
  502. return NULL;
  503. prng_randmemset (bytes, n_bytes, 0);
  504. return bytes;
  505. }
  506. void
  507. a8r8g8b8_to_rgba_np (uint32_t *dst, uint32_t *src, int n_pixels)
  508. {
  509. uint8_t *dst8 = (uint8_t *)dst;
  510. int i;
  511. for (i = 0; i < n_pixels; ++i)
  512. {
  513. uint32_t p = src[i];
  514. uint8_t a, r, g, b;
  515. a = (p & 0xff000000) >> 24;
  516. r = (p & 0x00ff0000) >> 16;
  517. g = (p & 0x0000ff00) >> 8;
  518. b = (p & 0x000000ff) >> 0;
  519. if (a != 0)
  520. {
  521. #define DIVIDE(c, a) \
  522. do \
  523. { \
  524. int t = ((c) * 255) / a; \
  525. (c) = t < 0? 0 : t > 255? 255 : t; \
  526. } while (0)
  527. DIVIDE (r, a);
  528. DIVIDE (g, a);
  529. DIVIDE (b, a);
  530. }
  531. *dst8++ = r;
  532. *dst8++ = g;
  533. *dst8++ = b;
  534. *dst8++ = a;
  535. }
  536. }
  537. #ifdef HAVE_LIBPNG
  538. pixman_bool_t
  539. write_png (pixman_image_t *image, const char *filename)
  540. {
  541. int width = pixman_image_get_width (image);
  542. int height = pixman_image_get_height (image);
  543. int stride = width * 4;
  544. uint32_t *data = malloc (height * stride);
  545. pixman_image_t *copy;
  546. png_struct *write_struct;
  547. png_info *info_struct;
  548. pixman_bool_t result = FALSE;
  549. FILE *f = fopen (filename, "wb");
  550. png_bytep *row_pointers;
  551. int i;
  552. if (!f)
  553. return FALSE;
  554. row_pointers = malloc (height * sizeof (png_bytep));
  555. copy = pixman_image_create_bits (
  556. PIXMAN_a8r8g8b8, width, height, data, stride);
  557. pixman_image_composite32 (
  558. PIXMAN_OP_SRC, image, NULL, copy, 0, 0, 0, 0, 0, 0, width, height);
  559. a8r8g8b8_to_rgba_np (data, data, height * width);
  560. for (i = 0; i < height; ++i)
  561. row_pointers[i] = (png_bytep)(data + i * width);
  562. if (!(write_struct = png_create_write_struct (
  563. PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
  564. goto out1;
  565. if (!(info_struct = png_create_info_struct (write_struct)))
  566. goto out2;
  567. png_init_io (write_struct, f);
  568. png_set_IHDR (write_struct, info_struct, width, height,
  569. 8, PNG_COLOR_TYPE_RGB_ALPHA,
  570. PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
  571. PNG_FILTER_TYPE_BASE);
  572. png_write_info (write_struct, info_struct);
  573. png_write_image (write_struct, row_pointers);
  574. png_write_end (write_struct, NULL);
  575. result = TRUE;
  576. out2:
  577. png_destroy_write_struct (&write_struct, &info_struct);
  578. out1:
  579. if (fclose (f) != 0)
  580. result = FALSE;
  581. pixman_image_unref (copy);
  582. free (row_pointers);
  583. free (data);
  584. return result;
  585. }
  586. #else /* no libpng */
  587. pixman_bool_t
  588. write_png (pixman_image_t *image, const char *filename)
  589. {
  590. return FALSE;
  591. }
  592. #endif
  593. static void
  594. color8_to_color16 (uint32_t color8, pixman_color_t *color16)
  595. {
  596. color16->alpha = ((color8 & 0xff000000) >> 24);
  597. color16->red = ((color8 & 0x00ff0000) >> 16);
  598. color16->green = ((color8 & 0x0000ff00) >> 8);
  599. color16->blue = ((color8 & 0x000000ff) >> 0);
  600. color16->alpha |= color16->alpha << 8;
  601. color16->red |= color16->red << 8;
  602. color16->blue |= color16->blue << 8;
  603. color16->green |= color16->green << 8;
  604. }
  605. void
  606. draw_checkerboard (pixman_image_t *image,
  607. int check_size,
  608. uint32_t color1, uint32_t color2)
  609. {
  610. pixman_color_t check1, check2;
  611. pixman_image_t *c1, *c2;
  612. int n_checks_x, n_checks_y;
  613. int i, j;
  614. color8_to_color16 (color1, &check1);
  615. color8_to_color16 (color2, &check2);
  616. c1 = pixman_image_create_solid_fill (&check1);
  617. c2 = pixman_image_create_solid_fill (&check2);
  618. n_checks_x = (
  619. pixman_image_get_width (image) + check_size - 1) / check_size;
  620. n_checks_y = (
  621. pixman_image_get_height (image) + check_size - 1) / check_size;
  622. for (j = 0; j < n_checks_y; j++)
  623. {
  624. for (i = 0; i < n_checks_x; i++)
  625. {
  626. pixman_image_t *src;
  627. if (((i ^ j) & 1))
  628. src = c1;
  629. else
  630. src = c2;
  631. pixman_image_composite32 (PIXMAN_OP_SRC, src, NULL, image,
  632. 0, 0, 0, 0,
  633. i * check_size, j * check_size,
  634. check_size, check_size);
  635. }
  636. }
  637. }
  638. static uint32_t
  639. call_test_function (uint32_t (*test_function)(int testnum, int verbose),
  640. int testnum,
  641. int verbose)
  642. {
  643. uint32_t retval;
  644. #if defined (__GNUC__) && defined (_WIN32) && (defined (__i386) || defined (__i386__))
  645. __asm__ (
  646. /* Deliberately avoid aligning the stack to 16 bytes */
  647. "pushl %1\n\t"
  648. "pushl %2\n\t"
  649. "call *%3\n\t"
  650. "addl $8, %%esp\n\t"
  651. : "=a" (retval)
  652. : "r" (verbose),
  653. "r" (testnum),
  654. "r" (test_function)
  655. : "edx", "ecx"); /* caller save registers */
  656. #else
  657. retval = test_function (testnum, verbose);
  658. #endif
  659. return retval;
  660. }
  661. /*
  662. * A function, which can be used as a core part of the test programs,
  663. * intended to detect various problems with the help of fuzzing input
  664. * to pixman API (according to some templates, aka "smart" fuzzing).
  665. * Some general information about such testing can be found here:
  666. * http://en.wikipedia.org/wiki/Fuzz_testing
  667. *
  668. * It may help detecting:
  669. * - crashes on bad handling of valid or reasonably invalid input to
  670. * pixman API.
  671. * - deviations from the behavior of older pixman releases.
  672. * - deviations from the behavior of the same pixman release, but
  673. * configured in a different way (for example with SIMD optimizations
  674. * disabled), or running on a different OS or hardware.
  675. *
  676. * The test is performed by calling a callback function a huge number
  677. * of times. The callback function is expected to run some snippet of
  678. * pixman code with pseudorandom variations to the data feeded to
  679. * pixman API. A result of running each callback function should be
  680. * some deterministic value which depends on test number (test number
  681. * can be used as a seed for PRNG). When 'verbose' argument is nonzero,
  682. * callback function is expected to print to stdout some information
  683. * about what it does.
  684. *
  685. * Return values from many small tests are accumulated together and
  686. * used as final checksum, which can be compared to some expected
  687. * value. Running the tests not individually, but in a batch helps
  688. * to reduce process start overhead and also allows to parallelize
  689. * testing and utilize multiple CPU cores.
  690. *
  691. * The resulting executable can be run without any arguments. In
  692. * this case it runs a batch of tests starting from 1 and up to
  693. * 'default_number_of_iterations'. The resulting checksum is
  694. * compared with 'expected_checksum' and FAIL or PASS verdict
  695. * depends on the result of this comparison.
  696. *
  697. * If the executable is run with 2 numbers provided as command line
  698. * arguments, they specify the starting and ending numbers for a test
  699. * batch.
  700. *
  701. * If the executable is run with only one number provided as a command
  702. * line argument, then this number is used to call the callback function
  703. * once, and also with verbose flag set.
  704. */
  705. int
  706. fuzzer_test_main (const char *test_name,
  707. int default_number_of_iterations,
  708. uint32_t expected_checksum,
  709. uint32_t (*test_function)(int testnum, int verbose),
  710. int argc,
  711. const char *argv[])
  712. {
  713. int i, n1 = 1, n2 = 0;
  714. uint32_t checksum = 0;
  715. int verbose = getenv ("VERBOSE") != NULL;
  716. if (argc >= 3)
  717. {
  718. n1 = atoi (argv[1]);
  719. n2 = atoi (argv[2]);
  720. if (n2 < n1)
  721. {
  722. printf ("invalid test range\n");
  723. return 1;
  724. }
  725. }
  726. else if (argc >= 2)
  727. {
  728. n2 = atoi (argv[1]);
  729. checksum = call_test_function (test_function, n2, 1);
  730. printf ("%d: checksum=%08X\n", n2, checksum);
  731. return 0;
  732. }
  733. else
  734. {
  735. n1 = 1;
  736. n2 = default_number_of_iterations;
  737. }
  738. #ifdef USE_OPENMP
  739. #pragma omp parallel for reduction(+:checksum) default(none) \
  740. shared(n1, n2, test_function, verbose)
  741. #endif
  742. for (i = n1; i <= n2; i++)
  743. {
  744. uint32_t crc = call_test_function (test_function, i, 0);
  745. if (verbose)
  746. printf ("%d: %08X\n", i, crc);
  747. checksum += crc;
  748. }
  749. if (n1 == 1 && n2 == default_number_of_iterations)
  750. {
  751. if (checksum == expected_checksum)
  752. {
  753. printf ("%s test passed (checksum=%08X)\n",
  754. test_name, checksum);
  755. }
  756. else
  757. {
  758. printf ("%s test failed! (checksum=%08X, expected %08X)\n",
  759. test_name, checksum, expected_checksum);
  760. return 1;
  761. }
  762. }
  763. else
  764. {
  765. printf ("%d-%d: checksum=%08X\n", n1, n2, checksum);
  766. }
  767. return 0;
  768. }
  769. /* Try to obtain current time in seconds */
  770. double
  771. gettime (void)
  772. {
  773. #ifdef HAVE_GETTIMEOFDAY
  774. struct timeval tv;
  775. gettimeofday (&tv, NULL);
  776. return (double)((int64_t)tv.tv_sec * 1000000 + tv.tv_usec) / 1000000.;
  777. #else
  778. return (double)clock() / (double)CLOCKS_PER_SEC;
  779. #endif
  780. }
  781. uint32_t
  782. get_random_seed (void)
  783. {
  784. union { double d; uint32_t u32; } t;
  785. t.d = gettime();
  786. prng_srand (t.u32);
  787. return prng_rand ();
  788. }
  789. #ifdef HAVE_SIGACTION
  790. #ifdef HAVE_ALARM
  791. static const char *global_msg;
  792. static void
  793. on_alarm (int signo)
  794. {
  795. printf ("%s\n", global_msg);
  796. exit (1);
  797. }
  798. #endif
  799. #endif
  800. void
  801. fail_after (int seconds, const char *msg)
  802. {
  803. #ifdef HAVE_SIGACTION
  804. #ifdef HAVE_ALARM
  805. struct sigaction action;
  806. global_msg = msg;
  807. memset (&action, 0, sizeof (action));
  808. action.sa_handler = on_alarm;
  809. alarm (seconds);
  810. sigaction (SIGALRM, &action, NULL);
  811. #endif
  812. #endif
  813. }
  814. void
  815. enable_divbyzero_exceptions (void)
  816. {
  817. #ifdef HAVE_FENV_H
  818. #ifdef HAVE_FEENABLEEXCEPT
  819. #ifdef HAVE_FEDIVBYZERO
  820. feenableexcept (FE_DIVBYZERO);
  821. #endif
  822. #endif
  823. #endif
  824. }
  825. void
  826. enable_invalid_exceptions (void)
  827. {
  828. #ifdef HAVE_FENV_H
  829. #ifdef HAVE_FEENABLEEXCEPT
  830. feenableexcept (FE_INVALID);
  831. #endif
  832. #endif
  833. }
  834. void *
  835. aligned_malloc (size_t align, size_t size)
  836. {
  837. void *result;
  838. #ifdef HAVE_POSIX_MEMALIGN
  839. if (posix_memalign (&result, align, size) != 0)
  840. result = NULL;
  841. #else
  842. result = malloc (size);
  843. #endif
  844. return result;
  845. }
  846. #define CONVERT_15(c, is_rgb) \
  847. (is_rgb? \
  848. ((((c) >> 3) & 0x001f) | \
  849. (((c) >> 6) & 0x03e0) | \
  850. (((c) >> 9) & 0x7c00)) : \
  851. (((((c) >> 16) & 0xff) * 153 + \
  852. (((c) >> 8) & 0xff) * 301 + \
  853. (((c) ) & 0xff) * 58) >> 2))
  854. double
  855. convert_srgb_to_linear (double c)
  856. {
  857. if (c <= 0.04045)
  858. return c / 12.92;
  859. else
  860. return pow ((c + 0.055) / 1.055, 2.4);
  861. }
  862. double
  863. convert_linear_to_srgb (double c)
  864. {
  865. if (c <= 0.0031308)
  866. return c * 12.92;
  867. else
  868. return 1.055 * pow (c, 1.0/2.4) - 0.055;
  869. }
  870. void
  871. initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb)
  872. {
  873. int i;
  874. uint32_t mask = (1 << depth) - 1;
  875. for (i = 0; i < 32768; ++i)
  876. palette->ent[i] = prng_rand() & mask;
  877. memset (palette->rgba, 0, sizeof (palette->rgba));
  878. for (i = 0; i < mask + 1; ++i)
  879. {
  880. uint32_t rgba24;
  881. pixman_bool_t retry;
  882. uint32_t i15;
  883. /* We filled the rgb->index map with random numbers, but we
  884. * do need the ability to round trip, that is if some indexed
  885. * color expands to an argb24, then the 15 bit version of that
  886. * color must map back to the index. Anything else, we don't
  887. * care about too much.
  888. */
  889. do
  890. {
  891. uint32_t old_idx;
  892. rgba24 = prng_rand();
  893. i15 = CONVERT_15 (rgba24, is_rgb);
  894. old_idx = palette->ent[i15];
  895. if (CONVERT_15 (palette->rgba[old_idx], is_rgb) == i15)
  896. retry = 1;
  897. else
  898. retry = 0;
  899. } while (retry);
  900. palette->rgba[i] = rgba24;
  901. palette->ent[i15] = i;
  902. }
  903. for (i = 0; i < mask + 1; ++i)
  904. {
  905. assert (palette->ent[CONVERT_15 (palette->rgba[i], is_rgb)] == i);
  906. }
  907. }
  908. struct operator_entry {
  909. pixman_op_t op;
  910. const char *name;
  911. pixman_bool_t is_alias;
  912. };
  913. typedef struct operator_entry operator_entry_t;
  914. static const operator_entry_t op_list[] =
  915. {
  916. #define ENTRY(op) \
  917. { PIXMAN_OP_##op, "PIXMAN_OP_" #op, FALSE }
  918. #define ALIAS(op, nam) \
  919. { PIXMAN_OP_##op, nam, TRUE }
  920. /* operator_name () will return the first hit in this table,
  921. * so keep the list properly ordered between entries and aliases.
  922. * Aliases are not listed by list_operators ().
  923. */
  924. ENTRY (CLEAR),
  925. ENTRY (SRC),
  926. ENTRY (DST),
  927. ENTRY (OVER),
  928. ENTRY (OVER_REVERSE),
  929. ALIAS (OVER_REVERSE, "overrev"),
  930. ENTRY (IN),
  931. ENTRY (IN_REVERSE),
  932. ALIAS (IN_REVERSE, "inrev"),
  933. ENTRY (OUT),
  934. ENTRY (OUT_REVERSE),
  935. ALIAS (OUT_REVERSE, "outrev"),
  936. ENTRY (ATOP),
  937. ENTRY (ATOP_REVERSE),
  938. ALIAS (ATOP_REVERSE, "atoprev"),
  939. ENTRY (XOR),
  940. ENTRY (ADD),
  941. ENTRY (SATURATE),
  942. ENTRY (DISJOINT_CLEAR),
  943. ENTRY (DISJOINT_SRC),
  944. ENTRY (DISJOINT_DST),
  945. ENTRY (DISJOINT_OVER),
  946. ENTRY (DISJOINT_OVER_REVERSE),
  947. ENTRY (DISJOINT_IN),
  948. ENTRY (DISJOINT_IN_REVERSE),
  949. ENTRY (DISJOINT_OUT),
  950. ENTRY (DISJOINT_OUT_REVERSE),
  951. ENTRY (DISJOINT_ATOP),
  952. ENTRY (DISJOINT_ATOP_REVERSE),
  953. ENTRY (DISJOINT_XOR),
  954. ENTRY (CONJOINT_CLEAR),
  955. ENTRY (CONJOINT_SRC),
  956. ENTRY (CONJOINT_DST),
  957. ENTRY (CONJOINT_OVER),
  958. ENTRY (CONJOINT_OVER_REVERSE),
  959. ENTRY (CONJOINT_IN),
  960. ENTRY (CONJOINT_IN_REVERSE),
  961. ENTRY (CONJOINT_OUT),
  962. ENTRY (CONJOINT_OUT_REVERSE),
  963. ENTRY (CONJOINT_ATOP),
  964. ENTRY (CONJOINT_ATOP_REVERSE),
  965. ENTRY (CONJOINT_XOR),
  966. ENTRY (MULTIPLY),
  967. ENTRY (SCREEN),
  968. ENTRY (OVERLAY),
  969. ENTRY (DARKEN),
  970. ENTRY (LIGHTEN),
  971. ENTRY (COLOR_DODGE),
  972. ENTRY (COLOR_BURN),
  973. ENTRY (HARD_LIGHT),
  974. ENTRY (SOFT_LIGHT),
  975. ENTRY (DIFFERENCE),
  976. ENTRY (EXCLUSION),
  977. ENTRY (HSL_HUE),
  978. ENTRY (HSL_SATURATION),
  979. ENTRY (HSL_COLOR),
  980. ENTRY (HSL_LUMINOSITY),
  981. ALIAS (NONE, "<invalid operator 'none'>")
  982. #undef ENTRY
  983. #undef ALIAS
  984. };
  985. struct format_entry
  986. {
  987. pixman_format_code_t format;
  988. const char *name;
  989. pixman_bool_t is_alias;
  990. };
  991. typedef struct format_entry format_entry_t;
  992. static const format_entry_t format_list[] =
  993. {
  994. #define ENTRY(f) \
  995. { PIXMAN_##f, #f, FALSE }
  996. #define ALIAS(f, nam) \
  997. { PIXMAN_##f, nam, TRUE }
  998. /* format_name () will return the first hit in this table,
  999. * so keep the list properly ordered between entries and aliases.
  1000. * Aliases are not listed by list_formats ().
  1001. */
  1002. /* 32bpp formats */
  1003. ENTRY (a8r8g8b8),
  1004. ALIAS (a8r8g8b8, "8888"),
  1005. ENTRY (x8r8g8b8),
  1006. ALIAS (x8r8g8b8, "x888"),
  1007. ENTRY (a8b8g8r8),
  1008. ENTRY (x8b8g8r8),
  1009. ENTRY (b8g8r8a8),
  1010. ENTRY (b8g8r8x8),
  1011. ENTRY (r8g8b8a8),
  1012. ENTRY (r8g8b8x8),
  1013. ENTRY (x14r6g6b6),
  1014. ENTRY (x2r10g10b10),
  1015. ALIAS (x2r10g10b10, "2x10"),
  1016. ENTRY (a2r10g10b10),
  1017. ALIAS (a2r10g10b10, "2a10"),
  1018. ENTRY (x2b10g10r10),
  1019. ENTRY (a2b10g10r10),
  1020. /* sRGB formats */
  1021. ENTRY (a8r8g8b8_sRGB),
  1022. /* 24bpp formats */
  1023. ENTRY (r8g8b8),
  1024. ALIAS (r8g8b8, "0888"),
  1025. ENTRY (b8g8r8),
  1026. /* 16 bpp formats */
  1027. ENTRY (r5g6b5),
  1028. ALIAS (r5g6b5, "0565"),
  1029. ENTRY (b5g6r5),
  1030. ENTRY (a1r5g5b5),
  1031. ALIAS (a1r5g5b5, "1555"),
  1032. ENTRY (x1r5g5b5),
  1033. ENTRY (a1b5g5r5),
  1034. ENTRY (x1b5g5r5),
  1035. ENTRY (a4r4g4b4),
  1036. ALIAS (a4r4g4b4, "4444"),
  1037. ENTRY (x4r4g4b4),
  1038. ENTRY (a4b4g4r4),
  1039. ENTRY (x4b4g4r4),
  1040. /* 8bpp formats */
  1041. ENTRY (a8),
  1042. ALIAS (a8, "8"),
  1043. ENTRY (r3g3b2),
  1044. ENTRY (b2g3r3),
  1045. ENTRY (a2r2g2b2),
  1046. ALIAS (a2r2g2b2, "2222"),
  1047. ENTRY (a2b2g2r2),
  1048. ALIAS (c8, "x4c4 / c8"),
  1049. /* ENTRY (c8), */
  1050. ALIAS (g8, "x4g4 / g8"),
  1051. /* ENTRY (g8), */
  1052. ENTRY (x4a4),
  1053. /* These format codes are identical to c8 and g8, respectively. */
  1054. /* ENTRY (x4c4), */
  1055. /* ENTRY (x4g4), */
  1056. /* 4 bpp formats */
  1057. ENTRY (a4),
  1058. ENTRY (r1g2b1),
  1059. ENTRY (b1g2r1),
  1060. ENTRY (a1r1g1b1),
  1061. ENTRY (a1b1g1r1),
  1062. ALIAS (c4, "c4"),
  1063. /* ENTRY (c4), */
  1064. ALIAS (g4, "g4"),
  1065. /* ENTRY (g4), */
  1066. /* 1bpp formats */
  1067. ENTRY (a1),
  1068. ALIAS (g1, "g1"),
  1069. /* ENTRY (g1), */
  1070. /* YUV formats */
  1071. ALIAS (yuy2, "yuy2"),
  1072. /* ENTRY (yuy2), */
  1073. ALIAS (yv12, "yv12"),
  1074. /* ENTRY (yv12), */
  1075. /* Fake formats, not in pixman_format_code_t enum */
  1076. ALIAS (null, "null"),
  1077. ALIAS (solid, "solid"),
  1078. ALIAS (solid, "n"),
  1079. ALIAS (pixbuf, "pixbuf"),
  1080. ALIAS (rpixbuf, "rpixbuf"),
  1081. ALIAS (unknown, "unknown"),
  1082. #undef ENTRY
  1083. #undef ALIAS
  1084. };
  1085. pixman_format_code_t
  1086. format_from_string (const char *s)
  1087. {
  1088. int i;
  1089. for (i = 0; i < ARRAY_LENGTH (format_list); ++i)
  1090. {
  1091. const format_entry_t *ent = &format_list[i];
  1092. if (strcasecmp (ent->name, s) == 0)
  1093. return ent->format;
  1094. }
  1095. return PIXMAN_null;
  1096. }
  1097. static void
  1098. emit (const char *s, int *n_chars)
  1099. {
  1100. *n_chars += printf ("%s,", s);
  1101. if (*n_chars > 60)
  1102. {
  1103. printf ("\n ");
  1104. *n_chars = 0;
  1105. }
  1106. else
  1107. {
  1108. printf (" ");
  1109. (*n_chars)++;
  1110. }
  1111. }
  1112. void
  1113. list_formats (void)
  1114. {
  1115. int n_chars;
  1116. int i;
  1117. printf ("Formats:\n ");
  1118. n_chars = 0;
  1119. for (i = 0; i < ARRAY_LENGTH (format_list); ++i)
  1120. {
  1121. const format_entry_t *ent = &format_list[i];
  1122. if (ent->is_alias)
  1123. continue;
  1124. emit (ent->name, &n_chars);
  1125. }
  1126. printf ("\n\n");
  1127. }
  1128. void
  1129. list_operators (void)
  1130. {
  1131. char short_name [128] = { 0 };
  1132. int i, n_chars;
  1133. printf ("Operators:\n ");
  1134. n_chars = 0;
  1135. for (i = 0; i < ARRAY_LENGTH (op_list); ++i)
  1136. {
  1137. const operator_entry_t *ent = &op_list[i];
  1138. int j;
  1139. if (ent->is_alias)
  1140. continue;
  1141. snprintf (short_name, sizeof (short_name) - 1, "%s",
  1142. ent->name + strlen ("PIXMAN_OP_"));
  1143. for (j = 0; short_name[j] != '\0'; ++j)
  1144. short_name[j] = tolower (short_name[j]);
  1145. emit (short_name, &n_chars);
  1146. }
  1147. printf ("\n\n");
  1148. }
  1149. pixman_op_t
  1150. operator_from_string (const char *s)
  1151. {
  1152. int i;
  1153. for (i = 0; i < ARRAY_LENGTH (op_list); ++i)
  1154. {
  1155. const operator_entry_t *ent = &op_list[i];
  1156. if (ent->is_alias)
  1157. {
  1158. if (strcasecmp (ent->name, s) == 0)
  1159. return ent->op;
  1160. }
  1161. else
  1162. {
  1163. if (strcasecmp (ent->name + strlen ("PIXMAN_OP_"), s) == 0)
  1164. return ent->op;
  1165. }
  1166. }
  1167. return PIXMAN_OP_NONE;
  1168. }
  1169. const char *
  1170. operator_name (pixman_op_t op)
  1171. {
  1172. int i;
  1173. for (i = 0; i < ARRAY_LENGTH (op_list); ++i)
  1174. {
  1175. const operator_entry_t *ent = &op_list[i];
  1176. if (ent->op == op)
  1177. return ent->name;
  1178. }
  1179. return "<unknown operator>";
  1180. }
  1181. const char *
  1182. format_name (pixman_format_code_t format)
  1183. {
  1184. int i;
  1185. for (i = 0; i < ARRAY_LENGTH (format_list); ++i)
  1186. {
  1187. const format_entry_t *ent = &format_list[i];
  1188. if (ent->format == format)
  1189. return ent->name;
  1190. }
  1191. return "<unknown format>";
  1192. };
  1193. #define IS_ZERO(f) (-DBL_MIN < (f) && (f) < DBL_MIN)
  1194. typedef double (* blend_func_t) (double as, double s, double ad, double d);
  1195. static force_inline double
  1196. blend_multiply (double sa, double s, double da, double d)
  1197. {
  1198. return d * s;
  1199. }
  1200. static force_inline double
  1201. blend_screen (double sa, double s, double da, double d)
  1202. {
  1203. return d * sa + s * da - s * d;
  1204. }
  1205. static force_inline double
  1206. blend_overlay (double sa, double s, double da, double d)
  1207. {
  1208. if (2 * d < da)
  1209. return 2 * s * d;
  1210. else
  1211. return sa * da - 2 * (da - d) * (sa - s);
  1212. }
  1213. static force_inline double
  1214. blend_darken (double sa, double s, double da, double d)
  1215. {
  1216. s = s * da;
  1217. d = d * sa;
  1218. if (s > d)
  1219. return d;
  1220. else
  1221. return s;
  1222. }
  1223. static force_inline double
  1224. blend_lighten (double sa, double s, double da, double d)
  1225. {
  1226. s = s * da;
  1227. d = d * sa;
  1228. if (s > d)
  1229. return s;
  1230. else
  1231. return d;
  1232. }
  1233. static force_inline double
  1234. blend_color_dodge (double sa, double s, double da, double d)
  1235. {
  1236. if (IS_ZERO (d))
  1237. return 0.0f;
  1238. else if (d * sa >= sa * da - s * da)
  1239. return sa * da;
  1240. else if (IS_ZERO (sa - s))
  1241. return sa * da;
  1242. else
  1243. return sa * sa * d / (sa - s);
  1244. }
  1245. static force_inline double
  1246. blend_color_burn (double sa, double s, double da, double d)
  1247. {
  1248. if (d >= da)
  1249. return sa * da;
  1250. else if (sa * (da - d) >= s * da)
  1251. return 0.0f;
  1252. else if (IS_ZERO (s))
  1253. return 0.0f;
  1254. else
  1255. return sa * (da - sa * (da - d) / s);
  1256. }
  1257. static force_inline double
  1258. blend_hard_light (double sa, double s, double da, double d)
  1259. {
  1260. if (2 * s < sa)
  1261. return 2 * s * d;
  1262. else
  1263. return sa * da - 2 * (da - d) * (sa - s);
  1264. }
  1265. static force_inline double
  1266. blend_soft_light (double sa, double s, double da, double d)
  1267. {
  1268. if (2 * s <= sa)
  1269. {
  1270. if (IS_ZERO (da))
  1271. return d * sa;
  1272. else
  1273. return d * sa - d * (da - d) * (sa - 2 * s) / da;
  1274. }
  1275. else
  1276. {
  1277. if (IS_ZERO (da))
  1278. {
  1279. return d * sa;
  1280. }
  1281. else
  1282. {
  1283. if (4 * d <= da)
  1284. return d * sa + (2 * s - sa) * d * ((16 * d / da - 12) * d / da + 3);
  1285. else
  1286. return d * sa + (sqrt (d * da) - d) * (2 * s - sa);
  1287. }
  1288. }
  1289. }
  1290. static force_inline double
  1291. blend_difference (double sa, double s, double da, double d)
  1292. {
  1293. double dsa = d * sa;
  1294. double sda = s * da;
  1295. if (sda < dsa)
  1296. return dsa - sda;
  1297. else
  1298. return sda - dsa;
  1299. }
  1300. static force_inline double
  1301. blend_exclusion (double sa, double s, double da, double d)
  1302. {
  1303. return s * da + d * sa - 2 * d * s;
  1304. }
  1305. static double
  1306. clamp (double d)
  1307. {
  1308. if (d > 1.0)
  1309. return 1.0;
  1310. else if (d < 0.0)
  1311. return 0.0;
  1312. else
  1313. return d;
  1314. }
  1315. static double
  1316. blend_channel (double as, double s, double ad, double d,
  1317. blend_func_t blend)
  1318. {
  1319. return clamp ((1 - ad) * s + (1 - as) * d + blend (as, s, ad, d));
  1320. }
  1321. static double
  1322. calc_op (pixman_op_t op, double src, double dst, double srca, double dsta)
  1323. {
  1324. #define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0)
  1325. double Fa, Fb;
  1326. switch (op)
  1327. {
  1328. case PIXMAN_OP_CLEAR:
  1329. case PIXMAN_OP_DISJOINT_CLEAR:
  1330. case PIXMAN_OP_CONJOINT_CLEAR:
  1331. return mult_chan (src, dst, 0.0, 0.0);
  1332. case PIXMAN_OP_SRC:
  1333. case PIXMAN_OP_DISJOINT_SRC:
  1334. case PIXMAN_OP_CONJOINT_SRC:
  1335. return mult_chan (src, dst, 1.0, 0.0);
  1336. case PIXMAN_OP_DST:
  1337. case PIXMAN_OP_DISJOINT_DST:
  1338. case PIXMAN_OP_CONJOINT_DST:
  1339. return mult_chan (src, dst, 0.0, 1.0);
  1340. case PIXMAN_OP_OVER:
  1341. return mult_chan (src, dst, 1.0, 1.0 - srca);
  1342. case PIXMAN_OP_OVER_REVERSE:
  1343. return mult_chan (src, dst, 1.0 - dsta, 1.0);
  1344. case PIXMAN_OP_IN:
  1345. return mult_chan (src, dst, dsta, 0.0);
  1346. case PIXMAN_OP_IN_REVERSE:
  1347. return mult_chan (src, dst, 0.0, srca);
  1348. case PIXMAN_OP_OUT:
  1349. return mult_chan (src, dst, 1.0 - dsta, 0.0);
  1350. case PIXMAN_OP_OUT_REVERSE:
  1351. return mult_chan (src, dst, 0.0, 1.0 - srca);
  1352. case PIXMAN_OP_ATOP:
  1353. return mult_chan (src, dst, dsta, 1.0 - srca);
  1354. case PIXMAN_OP_ATOP_REVERSE:
  1355. return mult_chan (src, dst, 1.0 - dsta, srca);
  1356. case PIXMAN_OP_XOR:
  1357. return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca);
  1358. case PIXMAN_OP_ADD:
  1359. return mult_chan (src, dst, 1.0, 1.0);
  1360. case PIXMAN_OP_SATURATE:
  1361. case PIXMAN_OP_DISJOINT_OVER_REVERSE:
  1362. if (srca == 0.0)
  1363. Fa = 1.0;
  1364. else
  1365. Fa = MIN (1.0, (1.0 - dsta) / srca);
  1366. return mult_chan (src, dst, Fa, 1.0);
  1367. case PIXMAN_OP_DISJOINT_OVER:
  1368. if (dsta == 0.0)
  1369. Fb = 1.0;
  1370. else
  1371. Fb = MIN (1.0, (1.0 - srca) / dsta);
  1372. return mult_chan (src, dst, 1.0, Fb);
  1373. case PIXMAN_OP_DISJOINT_IN:
  1374. if (srca == 0.0)
  1375. Fa = 0.0;
  1376. else
  1377. Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
  1378. return mult_chan (src, dst, Fa, 0.0);
  1379. case PIXMAN_OP_DISJOINT_IN_REVERSE:
  1380. if (dsta == 0.0)
  1381. Fb = 0.0;
  1382. else
  1383. Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
  1384. return mult_chan (src, dst, 0.0, Fb);
  1385. case PIXMAN_OP_DISJOINT_OUT:
  1386. if (srca == 0.0)
  1387. Fa = 1.0;
  1388. else
  1389. Fa = MIN (1.0, (1.0 - dsta) / srca);
  1390. return mult_chan (src, dst, Fa, 0.0);
  1391. case PIXMAN_OP_DISJOINT_OUT_REVERSE:
  1392. if (dsta == 0.0)
  1393. Fb = 1.0;
  1394. else
  1395. Fb = MIN (1.0, (1.0 - srca) / dsta);
  1396. return mult_chan (src, dst, 0.0, Fb);
  1397. case PIXMAN_OP_DISJOINT_ATOP:
  1398. if (srca == 0.0)
  1399. Fa = 0.0;
  1400. else
  1401. Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
  1402. if (dsta == 0.0)
  1403. Fb = 1.0;
  1404. else
  1405. Fb = MIN (1.0, (1.0 - srca) / dsta);
  1406. return mult_chan (src, dst, Fa, Fb);
  1407. case PIXMAN_OP_DISJOINT_ATOP_REVERSE:
  1408. if (srca == 0.0)
  1409. Fa = 1.0;
  1410. else
  1411. Fa = MIN (1.0, (1.0 - dsta) / srca);
  1412. if (dsta == 0.0)
  1413. Fb = 0.0;
  1414. else
  1415. Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
  1416. return mult_chan (src, dst, Fa, Fb);
  1417. case PIXMAN_OP_DISJOINT_XOR:
  1418. if (srca == 0.0)
  1419. Fa = 1.0;
  1420. else
  1421. Fa = MIN (1.0, (1.0 - dsta) / srca);
  1422. if (dsta == 0.0)
  1423. Fb = 1.0;
  1424. else
  1425. Fb = MIN (1.0, (1.0 - srca) / dsta);
  1426. return mult_chan (src, dst, Fa, Fb);
  1427. case PIXMAN_OP_CONJOINT_OVER:
  1428. if (dsta == 0.0)
  1429. Fb = 0.0;
  1430. else
  1431. Fb = MAX (0.0, 1.0 - srca / dsta);
  1432. return mult_chan (src, dst, 1.0, Fb);
  1433. case PIXMAN_OP_CONJOINT_OVER_REVERSE:
  1434. if (srca == 0.0)
  1435. Fa = 0.0;
  1436. else
  1437. Fa = MAX (0.0, 1.0 - dsta / srca);
  1438. return mult_chan (src, dst, Fa, 1.0);
  1439. case PIXMAN_OP_CONJOINT_IN:
  1440. if (srca == 0.0)
  1441. Fa = 1.0;
  1442. else
  1443. Fa = MIN (1.0, dsta / srca);
  1444. return mult_chan (src, dst, Fa, 0.0);
  1445. case PIXMAN_OP_CONJOINT_IN_REVERSE:
  1446. if (dsta == 0.0)
  1447. Fb = 1.0;
  1448. else
  1449. Fb = MIN (1.0, srca / dsta);
  1450. return mult_chan (src, dst, 0.0, Fb);
  1451. case PIXMAN_OP_CONJOINT_OUT:
  1452. if (srca == 0.0)
  1453. Fa = 0.0;
  1454. else
  1455. Fa = MAX (0.0, 1.0 - dsta / srca);
  1456. return mult_chan (src, dst, Fa, 0.0);
  1457. case PIXMAN_OP_CONJOINT_OUT_REVERSE:
  1458. if (dsta == 0.0)
  1459. Fb = 0.0;
  1460. else
  1461. Fb = MAX (0.0, 1.0 - srca / dsta);
  1462. return mult_chan (src, dst, 0.0, Fb);
  1463. case PIXMAN_OP_CONJOINT_ATOP:
  1464. if (srca == 0.0)
  1465. Fa = 1.0;
  1466. else
  1467. Fa = MIN (1.0, dsta / srca);
  1468. if (dsta == 0.0)
  1469. Fb = 0.0;
  1470. else
  1471. Fb = MAX (0.0, 1.0 - srca / dsta);
  1472. return mult_chan (src, dst, Fa, Fb);
  1473. case PIXMAN_OP_CONJOINT_ATOP_REVERSE:
  1474. if (srca == 0.0)
  1475. Fa = 0.0;
  1476. else
  1477. Fa = MAX (0.0, 1.0 - dsta / srca);
  1478. if (dsta == 0.0)
  1479. Fb = 1.0;
  1480. else
  1481. Fb = MIN (1.0, srca / dsta);
  1482. return mult_chan (src, dst, Fa, Fb);
  1483. case PIXMAN_OP_CONJOINT_XOR:
  1484. if (srca == 0.0)
  1485. Fa = 0.0;
  1486. else
  1487. Fa = MAX (0.0, 1.0 - dsta / srca);
  1488. if (dsta == 0.0)
  1489. Fb = 0.0;
  1490. else
  1491. Fb = MAX (0.0, 1.0 - srca / dsta);
  1492. return mult_chan (src, dst, Fa, Fb);
  1493. case PIXMAN_OP_MULTIPLY:
  1494. case PIXMAN_OP_SCREEN:
  1495. case PIXMAN_OP_OVERLAY:
  1496. case PIXMAN_OP_DARKEN:
  1497. case PIXMAN_OP_LIGHTEN:
  1498. case PIXMAN_OP_COLOR_DODGE:
  1499. case PIXMAN_OP_COLOR_BURN:
  1500. case PIXMAN_OP_HARD_LIGHT:
  1501. case PIXMAN_OP_SOFT_LIGHT:
  1502. case PIXMAN_OP_DIFFERENCE:
  1503. case PIXMAN_OP_EXCLUSION:
  1504. case PIXMAN_OP_HSL_HUE:
  1505. case PIXMAN_OP_HSL_SATURATION:
  1506. case PIXMAN_OP_HSL_COLOR:
  1507. case PIXMAN_OP_HSL_LUMINOSITY:
  1508. default:
  1509. abort();
  1510. return 0; /* silence MSVC */
  1511. }
  1512. #undef mult_chan
  1513. }
  1514. void
  1515. do_composite (pixman_op_t op,
  1516. const color_t *src,
  1517. const color_t *mask,
  1518. const color_t *dst,
  1519. color_t *result,
  1520. pixman_bool_t component_alpha)
  1521. {
  1522. color_t srcval, srcalpha;
  1523. static const blend_func_t blend_funcs[] =
  1524. {
  1525. blend_multiply,
  1526. blend_screen,
  1527. blend_overlay,
  1528. blend_darken,
  1529. blend_lighten,
  1530. blend_color_dodge,
  1531. blend_color_burn,
  1532. blend_hard_light,
  1533. blend_soft_light,
  1534. blend_difference,
  1535. blend_exclusion,
  1536. };
  1537. if (mask == NULL)
  1538. {
  1539. srcval = *src;
  1540. srcalpha.r = src->a;
  1541. srcalpha.g = src->a;
  1542. srcalpha.b = src->a;
  1543. srcalpha.a = src->a;
  1544. }
  1545. else if (component_alpha)
  1546. {
  1547. srcval.r = src->r * mask->r;
  1548. srcval.g = src->g * mask->g;
  1549. srcval.b = src->b * mask->b;
  1550. srcval.a = src->a * mask->a;
  1551. srcalpha.r = src->a * mask->r;
  1552. srcalpha.g = src->a * mask->g;
  1553. srcalpha.b = src->a * mask->b;
  1554. srcalpha.a = src->a * mask->a;
  1555. }
  1556. else
  1557. {
  1558. srcval.r = src->r * mask->a;
  1559. srcval.g = src->g * mask->a;
  1560. srcval.b = src->b * mask->a;
  1561. srcval.a = src->a * mask->a;
  1562. srcalpha.r = src->a * mask->a;
  1563. srcalpha.g = src->a * mask->a;
  1564. srcalpha.b = src->a * mask->a;
  1565. srcalpha.a = src->a * mask->a;
  1566. }
  1567. if (op >= PIXMAN_OP_MULTIPLY)
  1568. {
  1569. blend_func_t func = blend_funcs[op - PIXMAN_OP_MULTIPLY];
  1570. result->a = srcalpha.a + dst->a - srcalpha.a * dst->a;
  1571. result->r = blend_channel (srcalpha.r, srcval.r, dst->a, dst->r, func);
  1572. result->g = blend_channel (srcalpha.g, srcval.g, dst->a, dst->g, func);
  1573. result->b = blend_channel (srcalpha.b, srcval.b, dst->a, dst->b, func);
  1574. }
  1575. else
  1576. {
  1577. result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a);
  1578. result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a);
  1579. result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a);
  1580. result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
  1581. }
  1582. }
  1583. static double
  1584. round_channel (double p, int m)
  1585. {
  1586. int t;
  1587. double r;
  1588. t = p * ((1 << m));
  1589. t -= t >> m;
  1590. r = t / (double)((1 << m) - 1);
  1591. return r;
  1592. }
  1593. void
  1594. round_color (pixman_format_code_t format, color_t *color)
  1595. {
  1596. if (PIXMAN_FORMAT_R (format) == 0)
  1597. {
  1598. color->r = 0.0;
  1599. color->g = 0.0;
  1600. color->b = 0.0;
  1601. }
  1602. else
  1603. {
  1604. color->r = round_channel (color->r, PIXMAN_FORMAT_R (format));
  1605. color->g = round_channel (color->g, PIXMAN_FORMAT_G (format));
  1606. color->b = round_channel (color->b, PIXMAN_FORMAT_B (format));
  1607. }
  1608. if (PIXMAN_FORMAT_A (format) == 0)
  1609. color->a = 1;
  1610. else
  1611. color->a = round_channel (color->a, PIXMAN_FORMAT_A (format));
  1612. }
  1613. /* Check whether @pixel is a valid quantization of the a, r, g, b
  1614. * parameters. Some slack is permitted.
  1615. */
  1616. void
  1617. pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format)
  1618. {
  1619. assert (PIXMAN_FORMAT_VIS (format));
  1620. checker->format = format;
  1621. switch (PIXMAN_FORMAT_TYPE (format))
  1622. {
  1623. case PIXMAN_TYPE_A:
  1624. checker->bs = 0;
  1625. checker->gs = 0;
  1626. checker->rs = 0;
  1627. checker->as = 0;
  1628. break;
  1629. case PIXMAN_TYPE_ARGB:
  1630. case PIXMAN_TYPE_ARGB_SRGB:
  1631. checker->bs = 0;
  1632. checker->gs = checker->bs + PIXMAN_FORMAT_B (format);
  1633. checker->rs = checker->gs + PIXMAN_FORMAT_G (format);
  1634. checker->as = checker->rs + PIXMAN_FORMAT_R (format);
  1635. break;
  1636. case PIXMAN_TYPE_ABGR:
  1637. checker->rs = 0;
  1638. checker->gs = checker->rs + PIXMAN_FORMAT_R (format);
  1639. checker->bs = checker->gs + PIXMAN_FORMAT_G (format);
  1640. checker->as = checker->bs + PIXMAN_FORMAT_B (format);
  1641. break;
  1642. case PIXMAN_TYPE_BGRA:
  1643. /* With BGRA formats we start counting at the high end of the pixel */
  1644. checker->bs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_B (format);
  1645. checker->gs = checker->bs - PIXMAN_FORMAT_B (format);
  1646. checker->rs = checker->gs - PIXMAN_FORMAT_G (format);
  1647. checker->as = checker->rs - PIXMAN_FORMAT_R (format);
  1648. break;
  1649. case PIXMAN_TYPE_RGBA:
  1650. /* With BGRA formats we start counting at the high end of the pixel */
  1651. checker->rs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_R (format);
  1652. checker->gs = checker->rs - PIXMAN_FORMAT_R (format);
  1653. checker->bs = checker->gs - PIXMAN_FORMAT_G (format);
  1654. checker->as = checker->bs - PIXMAN_FORMAT_B (format);
  1655. break;
  1656. default:
  1657. assert (0);
  1658. break;
  1659. }
  1660. checker->am = ((1 << PIXMAN_FORMAT_A (format)) - 1) << checker->as;
  1661. checker->rm = ((1 << PIXMAN_FORMAT_R (format)) - 1) << checker->rs;
  1662. checker->gm = ((1 << PIXMAN_FORMAT_G (format)) - 1) << checker->gs;
  1663. checker->bm = ((1 << PIXMAN_FORMAT_B (format)) - 1) << checker->bs;
  1664. checker->aw = PIXMAN_FORMAT_A (format);
  1665. checker->rw = PIXMAN_FORMAT_R (format);
  1666. checker->gw = PIXMAN_FORMAT_G (format);
  1667. checker->bw = PIXMAN_FORMAT_B (format);
  1668. }
  1669. void
  1670. pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
  1671. int *a, int *r, int *g, int *b)
  1672. {
  1673. *a = (pixel & checker->am) >> checker->as;
  1674. *r = (pixel & checker->rm) >> checker->rs;
  1675. *g = (pixel & checker->gm) >> checker->gs;
  1676. *b = (pixel & checker->bm) >> checker->bs;
  1677. }
  1678. void
  1679. pixel_checker_get_masks (const pixel_checker_t *checker,
  1680. uint32_t *am,
  1681. uint32_t *rm,
  1682. uint32_t *gm,
  1683. uint32_t *bm)
  1684. {
  1685. if (am)
  1686. *am = checker->am;
  1687. if (rm)
  1688. *rm = checker->rm;
  1689. if (gm)
  1690. *gm = checker->gm;
  1691. if (bm)
  1692. *bm = checker->bm;
  1693. }
  1694. void
  1695. pixel_checker_convert_pixel_to_color (const pixel_checker_t *checker,
  1696. uint32_t pixel, color_t *color)
  1697. {
  1698. int a, r, g, b;
  1699. pixel_checker_split_pixel (checker, pixel, &a, &r, &g, &b);
  1700. if (checker->am == 0)
  1701. color->a = 1.0;
  1702. else
  1703. color->a = a / (double)(checker->am >> checker->as);
  1704. if (checker->rm == 0)
  1705. color->r = 0.0;
  1706. else
  1707. color->r = r / (double)(checker->rm >> checker->rs);
  1708. if (checker->gm == 0)
  1709. color->g = 0.0;
  1710. else
  1711. color->g = g / (double)(checker->gm >> checker->gs);
  1712. if (checker->bm == 0)
  1713. color->b = 0.0;
  1714. else
  1715. color->b = b / (double)(checker->bm >> checker->bs);
  1716. if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB)
  1717. {
  1718. color->r = convert_srgb_to_linear (color->r);
  1719. color->g = convert_srgb_to_linear (color->g);
  1720. color->b = convert_srgb_to_linear (color->b);
  1721. }
  1722. }
  1723. static int32_t
  1724. convert (double v, uint32_t width, uint32_t mask, uint32_t shift, double def)
  1725. {
  1726. int32_t r;
  1727. if (!mask)
  1728. v = def;
  1729. r = (v * ((mask >> shift) + 1));
  1730. r -= r >> width;
  1731. return r;
  1732. }
  1733. static void
  1734. get_limits (const pixel_checker_t *checker, double limit,
  1735. color_t *color,
  1736. int *ao, int *ro, int *go, int *bo)
  1737. {
  1738. color_t tmp;
  1739. if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB)
  1740. {
  1741. tmp.a = color->a;
  1742. tmp.r = convert_linear_to_srgb (color->r);
  1743. tmp.g = convert_linear_to_srgb (color->g);
  1744. tmp.b = convert_linear_to_srgb (color->b);
  1745. color = &tmp;
  1746. }
  1747. *ao = convert (color->a + limit, checker->aw, checker->am, checker->as, 1.0);
  1748. *ro = convert (color->r + limit, checker->rw, checker->rm, checker->rs, 0.0);
  1749. *go = convert (color->g + limit, checker->gw, checker->gm, checker->gs, 0.0);
  1750. *bo = convert (color->b + limit, checker->bw, checker->bm, checker->bs, 0.0);
  1751. }
  1752. /* The acceptable deviation in units of [0.0, 1.0]
  1753. */
  1754. #define DEVIATION (0.0128)
  1755. void
  1756. pixel_checker_get_max (const pixel_checker_t *checker, color_t *color,
  1757. int *am, int *rm, int *gm, int *bm)
  1758. {
  1759. get_limits (checker, DEVIATION, color, am, rm, gm, bm);
  1760. }
  1761. void
  1762. pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
  1763. int *am, int *rm, int *gm, int *bm)
  1764. {
  1765. get_limits (checker, - DEVIATION, color, am, rm, gm, bm);
  1766. }
  1767. pixman_bool_t
  1768. pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel,
  1769. color_t *color)
  1770. {
  1771. int32_t a_lo, a_hi, r_lo, r_hi, g_lo, g_hi, b_lo, b_hi;
  1772. int32_t ai, ri, gi, bi;
  1773. pixman_bool_t result;
  1774. pixel_checker_get_min (checker, color, &a_lo, &r_lo, &g_lo, &b_lo);
  1775. pixel_checker_get_max (checker, color, &a_hi, &r_hi, &g_hi, &b_hi);
  1776. pixel_checker_split_pixel (checker, pixel, &ai, &ri, &gi, &bi);
  1777. result =
  1778. a_lo <= ai && ai <= a_hi &&
  1779. r_lo <= ri && ri <= r_hi &&
  1780. g_lo <= gi && gi <= g_hi &&
  1781. b_lo <= bi && bi <= b_hi;
  1782. return result;
  1783. }