glamor_utils.h 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511
  1. /*
  2. * Copyright © 2009 Intel Corporation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the next
  12. * paragraph) shall be included in all copies or substantial portions of the
  13. * Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. * IN THE SOFTWARE.
  22. *
  23. * Authors:
  24. * Zhigang Gong <zhigang.gong@linux.intel.com>
  25. *
  26. */
  27. #ifndef GLAMOR_PRIV_H
  28. #error This file can only be included by glamor_priv.h
  29. #endif
  30. #ifndef __GLAMOR_UTILS_H__
  31. #define __GLAMOR_UTILS_H__
  32. #define v_from_x_coord_x(_xscale_, _x_) ( 2 * (_x_) * (_xscale_) - 1.0)
  33. #define v_from_x_coord_y(_yscale_, _y_) (-2 * (_y_) * (_yscale_) + 1.0)
  34. #define v_from_x_coord_y_inverted(_yscale_, _y_) (2 * (_y_) * (_yscale_) - 1.0)
  35. #define t_from_x_coord_x(_xscale_, _x_) ((_x_) * (_xscale_))
  36. #define t_from_x_coord_y(_yscale_, _y_) (1.0 - (_y_) * (_yscale_))
  37. #define t_from_x_coord_y_inverted(_yscale_, _y_) ((_y_) * (_yscale_))
  38. #define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_) \
  39. do { \
  40. int _w_,_h_; \
  41. PIXMAP_PRIV_GET_ACTUAL_SIZE(_pixmap_priv_, _w_, _h_); \
  42. *(_pxscale_) = 1.0 / _w_; \
  43. *(_pyscale_) = 1.0 / _h_; \
  44. } while(0)
  45. #define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \
  46. do { \
  47. *(_pxscale_) = 1.0 / (_pixmap_priv_)->base.fbo->width; \
  48. *(_pyscale_) = 1.0 / (_pixmap_priv_)->base.fbo->height; \
  49. } while(0)
  50. #define GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(priv) \
  51. (priv->base.fbo->width != priv->base.pixmap->drawable.width \
  52. || priv->base.fbo->height != priv->base.pixmap->drawable.height) \
  53. #define PIXMAP_PRIV_GET_ACTUAL_SIZE(priv, w, h) \
  54. do { \
  55. if (_X_UNLIKELY(priv->type == GLAMOR_TEXTURE_LARGE)) { \
  56. w = priv->large.box.x2 - priv->large.box.x1; \
  57. h = priv->large.box.y2 - priv->large.box.y1; \
  58. } else { \
  59. w = priv->base.pixmap->drawable.width; \
  60. h = priv->base.pixmap->drawable.height; \
  61. } \
  62. } while(0)
  63. #define glamor_pixmap_fbo_fix_wh_ratio(wh, priv) \
  64. do { \
  65. int actual_w, actual_h; \
  66. PIXMAP_PRIV_GET_ACTUAL_SIZE(priv, actual_w, actual_h); \
  67. wh[0] = (float)priv->base.fbo->width / actual_w; \
  68. wh[1] = (float)priv->base.fbo->height / actual_h; \
  69. wh[2] = 1.0 / priv->base.fbo->width; \
  70. wh[3] = 1.0 / priv->base.fbo->height; \
  71. } while(0)
  72. #define pixmap_priv_get_fbo_off(_priv_, _xoff_, _yoff_) \
  73. do { \
  74. if (_X_UNLIKELY(_priv_ && (_priv_)->type == GLAMOR_TEXTURE_LARGE)) { \
  75. *(_xoff_) = - (_priv_)->large.box.x1; \
  76. *(_yoff_) = - (_priv_)->large.box.y1; \
  77. } else { \
  78. *(_xoff_) = 0; \
  79. *(_yoff_) = 0; \
  80. } \
  81. } while(0)
  82. #define xFixedToFloat(_val_) ((float)xFixedToInt(_val_) \
  83. + ((float)xFixedFrac(_val_) / 65536.0))
  84. #define glamor_picture_get_matrixf(_picture_, _matrix_) \
  85. do { \
  86. int _i_; \
  87. if ((_picture_)->transform) \
  88. { \
  89. for(_i_ = 0; _i_ < 3; _i_++) \
  90. { \
  91. (_matrix_)[_i_ * 3 + 0] = \
  92. xFixedToFloat((_picture_)->transform->matrix[_i_][0]); \
  93. (_matrix_)[_i_ * 3 + 1] = \
  94. xFixedToFloat((_picture_)->transform->matrix[_i_][1]); \
  95. (_matrix_)[_i_ * 3 + 2] = \
  96. xFixedToFloat((_picture_)->transform->matrix[_i_][2]); \
  97. } \
  98. } \
  99. } while(0)
  100. #define fmod(x, w) (x - w * floor((float)x/w))
  101. #define fmodulus(x, w, c) do {c = fmod(x, w); \
  102. c = c >= 0 ? c : c + w;} \
  103. while(0)
  104. /* @x: is current coord
  105. * @x2: is the right/bottom edge
  106. * @w: is current width or height
  107. * @odd: is output value, 0 means we are in an even region, 1 means we are in a
  108. * odd region.
  109. * @c: is output value, equal to x mod w. */
  110. #define fodd_repeat_mod(x, x2, w, odd, c) \
  111. do { \
  112. float shift; \
  113. fmodulus((x), w, c); \
  114. shift = fabs((x) - (c)); \
  115. shift = floor(fabs(round(shift)) / w); \
  116. odd = (int)shift & 1; \
  117. if (odd && (((x2 % w) == 0) && \
  118. round(fabs(x)) == x2)) \
  119. odd = 0; \
  120. } while(0)
  121. /* @txy: output value, is the corrected coords.
  122. * @xy: input coords to be fixed up.
  123. * @cd: xy mod wh, is a input value.
  124. * @wh: current width or height.
  125. * @bxy1,bxy2: current box edge's x1/x2 or y1/y2
  126. *
  127. * case 1:
  128. * ----------
  129. * | * |
  130. * | |
  131. * ----------
  132. * tx = (c - x1) mod w
  133. *
  134. * case 2:
  135. * ---------
  136. * * | |
  137. * | |
  138. * ---------
  139. * tx = - (c - (x1 mod w))
  140. *
  141. * case 3:
  142. *
  143. * ----------
  144. * | | *
  145. * | |
  146. * ----------
  147. * tx = ((x2 mod x) - c) + (x2 - x1)
  148. **/
  149. #define __glamor_repeat_reflect_fixup(txy, xy, \
  150. cd, wh, bxy1, bxy2) \
  151. do { \
  152. cd = wh - cd; \
  153. if ( xy >= bxy1 && xy < bxy2) { \
  154. cd = cd - bxy1; \
  155. fmodulus(cd, wh, txy); \
  156. } else if (xy < bxy1) { \
  157. float bxy1_mod; \
  158. fmodulus(bxy1, wh, bxy1_mod); \
  159. txy = -(cd - bxy1_mod); \
  160. } \
  161. else if (xy >= bxy2) { \
  162. float bxy2_mod; \
  163. fmodulus(bxy2, wh, bxy2_mod); \
  164. if (bxy2_mod == 0) \
  165. bxy2_mod = wh; \
  166. txy = (bxy2_mod - cd) + bxy2 - bxy1; \
  167. } else {assert(0); txy = 0;} \
  168. } while(0)
  169. #define _glamor_repeat_reflect_fixup(txy, xy, cd, odd, \
  170. wh, bxy1, bxy2) \
  171. do { \
  172. if (odd) { \
  173. __glamor_repeat_reflect_fixup(txy, xy, \
  174. cd, wh, bxy1, bxy2); \
  175. } else \
  176. txy = xy - bxy1; \
  177. } while(0)
  178. #define _glamor_get_reflect_transform_coords(priv, repeat_type, \
  179. tx1, ty1, \
  180. _x1_, _y1_) \
  181. do { \
  182. int odd_x, odd_y; \
  183. float c, d; \
  184. fodd_repeat_mod(_x1_,priv->box.x2, \
  185. priv->base.pixmap->drawable.width, \
  186. odd_x, c); \
  187. fodd_repeat_mod(_y1_, priv->box.y2, \
  188. priv->base.pixmap->drawable.height, \
  189. odd_y, d); \
  190. DEBUGF("c %f d %f oddx %d oddy %d \n", \
  191. c, d, odd_x, odd_y); \
  192. DEBUGF("x2 %d x1 %d fbo->width %d \n", priv->box.x2, \
  193. priv->box.x1, priv->base.fbo->width); \
  194. DEBUGF("y2 %d y1 %d fbo->height %d \n", priv->box.y2, \
  195. priv->box.y1, priv->base.fbo->height); \
  196. _glamor_repeat_reflect_fixup(tx1, _x1_, c, odd_x, \
  197. priv->base.pixmap->drawable.width, \
  198. priv->box.x1, priv->box.x2); \
  199. _glamor_repeat_reflect_fixup(ty1, _y1_, d, odd_y, \
  200. priv->base.pixmap->drawable.height, \
  201. priv->box.y1, priv->box.y2); \
  202. } while(0)
  203. #define _glamor_get_repeat_coords(priv, repeat_type, tx1, \
  204. ty1, tx2, ty2, \
  205. _x1_, _y1_, _x2_, \
  206. _y2_, c, d, odd_x, odd_y) \
  207. do { \
  208. if (repeat_type == RepeatReflect) { \
  209. DEBUGF("x1 y1 %d %d\n", \
  210. _x1_, _y1_ ); \
  211. DEBUGF("width %d box.x1 %d \n", \
  212. (priv)->base.pixmap->drawable.width, \
  213. priv->box.x1); \
  214. if (odd_x) { \
  215. c = (priv)->base.pixmap->drawable.width \
  216. - c; \
  217. tx1 = c - priv->box.x1; \
  218. tx2 = tx1 - ((_x2_) - (_x1_)); \
  219. } else { \
  220. tx1 = c - priv->box.x1; \
  221. tx2 = tx1 + ((_x2_) - (_x1_)); \
  222. } \
  223. if (odd_y){ \
  224. d = (priv)->base.pixmap->drawable.height\
  225. - d; \
  226. ty1 = d - priv->box.y1; \
  227. ty2 = ty1 - ((_y2_) - (_y1_)); \
  228. } else { \
  229. ty1 = d - priv->box.y1; \
  230. ty2 = ty1 + ((_y2_) - (_y1_)); \
  231. } \
  232. } else { /* RepeatNormal*/ \
  233. tx1 = (c - priv->box.x1); \
  234. ty1 = (d - priv->box.y1); \
  235. tx2 = tx1 + ((_x2_) - (_x1_)); \
  236. ty2 = ty1 + ((_y2_) - (_y1_)); \
  237. } \
  238. } while(0)
  239. /* _x1_ ... _y2_ may has fractional. */
  240. #define glamor_get_repeat_transform_coords(priv, repeat_type, tx1, \
  241. ty1, _x1_, _y1_) \
  242. do { \
  243. DEBUGF("width %d box.x1 %d x2 %d y1 %d y2 %d\n", \
  244. (priv)->base.pixmap->drawable.width, \
  245. priv->box.x1, priv->box.x2, priv->box.y1, \
  246. priv->box.y2); \
  247. DEBUGF("x1 %f y1 %f \n", _x1_, _y1_); \
  248. if (repeat_type != RepeatReflect) { \
  249. tx1 = _x1_ - priv->box.x1; \
  250. ty1 = _y1_ - priv->box.y1; \
  251. } else \
  252. _glamor_get_reflect_transform_coords(priv, repeat_type, \
  253. tx1, ty1, \
  254. _x1_, _y1_); \
  255. DEBUGF("tx1 %f ty1 %f \n", tx1, ty1); \
  256. } while(0)
  257. /* _x1_ ... _y2_ must be integer. */
  258. #define glamor_get_repeat_coords(priv, repeat_type, tx1, \
  259. ty1, tx2, ty2, _x1_, _y1_, _x2_, \
  260. _y2_) \
  261. do { \
  262. int c, d; \
  263. int odd_x = 0, odd_y = 0; \
  264. DEBUGF("width %d box.x1 %d x2 %d y1 %d y2 %d\n", \
  265. (priv)->base.pixmap->drawable.width, \
  266. priv->box.x1, priv->box.x2, \
  267. priv->box.y1, priv->box.y2); \
  268. modulus((_x1_), (priv)->base.pixmap->drawable.width, c); \
  269. modulus((_y1_), (priv)->base.pixmap->drawable.height, d); \
  270. DEBUGF("c %d d %d \n", c, d); \
  271. if (repeat_type == RepeatReflect) { \
  272. odd_x = abs((_x1_ - c) \
  273. / (priv->base.pixmap->drawable.width)) & 1; \
  274. odd_y = abs((_y1_ - d) \
  275. / (priv->base.pixmap->drawable.height)) & 1; \
  276. } \
  277. _glamor_get_repeat_coords(priv, repeat_type, tx1, ty1, tx2, ty2,\
  278. _x1_, _y1_, _x2_, _y2_, c, d, \
  279. odd_x, odd_y); \
  280. } while(0)
  281. #define glamor_transform_point(matrix, tx, ty, x, y) \
  282. do { \
  283. int _i_; \
  284. float _result_[4]; \
  285. for (_i_ = 0; _i_ < 3; _i_++) { \
  286. _result_[_i_] = (matrix)[_i_ * 3] * (x) + (matrix)[_i_ * 3 + 1] * (y) \
  287. + (matrix)[_i_ * 3 + 2]; \
  288. } \
  289. tx = _result_[0] / _result_[2]; \
  290. ty = _result_[1] / _result_[2]; \
  291. } while(0)
  292. #define _glamor_set_normalize_tpoint(xscale, yscale, _tx_, _ty_, \
  293. texcoord, yInverted) \
  294. do { \
  295. (texcoord)[0] = t_from_x_coord_x(xscale, _tx_); \
  296. if (_X_LIKELY(yInverted)) \
  297. (texcoord)[1] = t_from_x_coord_y_inverted(yscale, _ty_);\
  298. else \
  299. (texcoord)[1] = t_from_x_coord_y(yscale, _ty_); \
  300. DEBUGF("normalized point tx %f ty %f \n", (texcoord)[0], \
  301. (texcoord)[1]); \
  302. } while(0)
  303. #define glamor_set_transformed_point(priv, matrix, xscale, \
  304. yscale, texcoord, \
  305. x, y, \
  306. yInverted) \
  307. do { \
  308. float tx, ty; \
  309. int fbo_x_off, fbo_y_off; \
  310. pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \
  311. glamor_transform_point(matrix, tx, ty, x, y); \
  312. DEBUGF("tx %f ty %f fbooff %d %d \n", \
  313. tx, ty, fbo_x_off, fbo_y_off); \
  314. \
  315. tx += fbo_x_off; \
  316. ty += fbo_y_off; \
  317. (texcoord)[0] = t_from_x_coord_x(xscale, tx); \
  318. if (_X_LIKELY(yInverted)) \
  319. (texcoord)[1] = t_from_x_coord_y_inverted(yscale, ty); \
  320. else \
  321. (texcoord)[1] = t_from_x_coord_y(yscale, ty); \
  322. DEBUGF("normalized tx %f ty %f \n", (texcoord)[0], (texcoord)[1]); \
  323. } while(0)
  324. #define glamor_set_transformed_normalize_tri_tcoords(priv, \
  325. matrix, \
  326. xscale, \
  327. yscale, \
  328. vtx, \
  329. yInverted, \
  330. texcoords) \
  331. do { \
  332. glamor_set_transformed_point(priv, matrix, xscale, yscale, \
  333. texcoords, (vtx)[0], (vtx)[1], \
  334. yInverted); \
  335. glamor_set_transformed_point(priv, matrix, xscale, yscale, \
  336. texcoords+2, (vtx)[2], (vtx)[3], \
  337. yInverted); \
  338. glamor_set_transformed_point(priv, matrix, xscale, yscale, \
  339. texcoords+4, (vtx)[4], (vtx)[5], \
  340. yInverted); \
  341. } while (0)
  342. #define glamor_set_transformed_normalize_tcoords_ext( priv, \
  343. matrix, \
  344. xscale, \
  345. yscale, \
  346. tx1, ty1, tx2, ty2, \
  347. yInverted, texcoords, \
  348. stride) \
  349. do { \
  350. glamor_set_transformed_point(priv, matrix, xscale, yscale, \
  351. texcoords, tx1, ty1, \
  352. yInverted); \
  353. glamor_set_transformed_point(priv, matrix, xscale, yscale, \
  354. texcoords + 1 * stride, tx2, ty1, \
  355. yInverted); \
  356. glamor_set_transformed_point(priv, matrix, xscale, yscale, \
  357. texcoords + 2 * stride, tx2, ty2, \
  358. yInverted); \
  359. glamor_set_transformed_point(priv, matrix, xscale, yscale, \
  360. texcoords + 3 * stride, tx1, ty2, \
  361. yInverted); \
  362. } while (0)
  363. #define glamor_set_transformed_normalize_tcoords( priv, \
  364. matrix, \
  365. xscale, \
  366. yscale, \
  367. tx1, ty1, tx2, ty2, \
  368. yInverted, texcoords) \
  369. do { \
  370. glamor_set_transformed_normalize_tcoords_ext( priv, \
  371. matrix, \
  372. xscale, \
  373. yscale, \
  374. tx1, ty1, tx2, ty2, \
  375. yInverted, texcoords, \
  376. 2); \
  377. } while (0)
  378. #define glamor_set_normalize_tri_tcoords(xscale, \
  379. yscale, \
  380. vtx, \
  381. yInverted, \
  382. texcoords) \
  383. do { \
  384. _glamor_set_normalize_tpoint(xscale, yscale, \
  385. (vtx)[0], (vtx)[1], \
  386. texcoords, \
  387. yInverted); \
  388. _glamor_set_normalize_tpoint(xscale, yscale, \
  389. (vtx)[2], (vtx)[3], \
  390. texcoords+2, \
  391. yInverted); \
  392. _glamor_set_normalize_tpoint(xscale, yscale, \
  393. (vtx)[4], (vtx)[5], \
  394. texcoords+4, \
  395. yInverted); \
  396. } while (0)
  397. #define glamor_set_repeat_transformed_normalize_tcoords_ext( priv, \
  398. repeat_type, \
  399. matrix, \
  400. xscale, \
  401. yscale, \
  402. _x1_, _y1_, \
  403. _x2_, _y2_, \
  404. yInverted, \
  405. texcoords, \
  406. stride) \
  407. do { \
  408. if (_X_LIKELY(priv->type != GLAMOR_TEXTURE_LARGE)) { \
  409. glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale, \
  410. yscale, _x1_, _y1_, \
  411. _x2_, _y2_, yInverted, \
  412. texcoords, stride); \
  413. } else { \
  414. float tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4; \
  415. float ttx1, tty1, ttx2, tty2, ttx3, tty3, ttx4, tty4; \
  416. DEBUGF("original coords %d %d %d %d\n", _x1_, _y1_, _x2_, _y2_); \
  417. glamor_transform_point(matrix, tx1, ty1, _x1_, _y1_); \
  418. glamor_transform_point(matrix, tx2, ty2, _x2_, _y1_); \
  419. glamor_transform_point(matrix, tx3, ty3, _x2_, _y2_); \
  420. glamor_transform_point(matrix, tx4, ty4, _x1_, _y2_); \
  421. DEBUGF("transformed %f %f %f %f %f %f %f %f\n", \
  422. tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4); \
  423. glamor_get_repeat_transform_coords((&priv->large), repeat_type, \
  424. ttx1, tty1, \
  425. tx1, ty1); \
  426. glamor_get_repeat_transform_coords((&priv->large), repeat_type, \
  427. ttx2, tty2, \
  428. tx2, ty2); \
  429. glamor_get_repeat_transform_coords((&priv->large), repeat_type, \
  430. ttx3, tty3, \
  431. tx3, ty3); \
  432. glamor_get_repeat_transform_coords((&priv->large), repeat_type, \
  433. ttx4, tty4, \
  434. tx4, ty4); \
  435. DEBUGF("repeat transformed %f %f %f %f %f %f %f %f\n", ttx1, tty1, \
  436. ttx2, tty2, ttx3, tty3, ttx4, tty4); \
  437. _glamor_set_normalize_tpoint(xscale, yscale, ttx1, tty1, \
  438. texcoords, yInverted); \
  439. _glamor_set_normalize_tpoint(xscale, yscale, ttx2, tty2, \
  440. texcoords + 1 * stride, yInverted); \
  441. _glamor_set_normalize_tpoint(xscale, yscale, ttx3, tty3, \
  442. texcoords + 2 * stride, yInverted); \
  443. _glamor_set_normalize_tpoint(xscale, yscale, ttx4, tty4, \
  444. texcoords + 3 * stride, yInverted); \
  445. } \
  446. } while (0)
  447. #define glamor_set_repeat_transformed_normalize_tcoords( priv, \
  448. repeat_type, \
  449. matrix, \
  450. xscale, \
  451. yscale, \
  452. _x1_, _y1_, \
  453. _x2_, _y2_, \
  454. yInverted, \
  455. texcoords) \
  456. do { \
  457. glamor_set_repeat_transformed_normalize_tcoords_ext( priv, \
  458. repeat_type, \
  459. matrix, \
  460. xscale, \
  461. yscale, \
  462. _x1_, _y1_, \
  463. _x2_, _y2_, \
  464. yInverted, \
  465. texcoords, \
  466. 2); \
  467. } while (0)
  468. #define _glamor_set_normalize_tcoords(xscale, yscale, tx1, \
  469. ty1, tx2, ty2, \
  470. yInverted, vertices, stride) \
  471. do { \
  472. /* vertices may be write-only, so we use following \
  473. * temporary variable. */ \
  474. float _t0_, _t1_, _t2_, _t5_; \
  475. (vertices)[0] = _t0_ = t_from_x_coord_x(xscale, tx1); \
  476. (vertices)[1 * stride] = _t2_ = t_from_x_coord_x(xscale, tx2); \
  477. (vertices)[2 * stride] = _t2_; \
  478. (vertices)[3 * stride] = _t0_; \
  479. if (_X_LIKELY(yInverted)) { \
  480. (vertices)[1] = _t1_ = t_from_x_coord_y_inverted(yscale, ty1); \
  481. (vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y_inverted(yscale, ty2);\
  482. } \
  483. else { \
  484. (vertices)[1] = _t1_ = t_from_x_coord_y(yscale, ty1); \
  485. (vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y(yscale, ty2);\
  486. } \
  487. (vertices)[1 * stride + 1] = _t1_; \
  488. (vertices)[3 * stride + 1] = _t5_; \
  489. } while(0)
  490. #define glamor_set_normalize_tcoords_ext(priv, xscale, yscale, \
  491. x1, y1, x2, y2, \
  492. yInverted, vertices, stride) \
  493. do { \
  494. if (_X_UNLIKELY(priv->type == GLAMOR_TEXTURE_LARGE)) { \
  495. float tx1, tx2, ty1, ty2; \
  496. int fbo_x_off, fbo_y_off; \
  497. pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \
  498. tx1 = x1 + fbo_x_off; \
  499. tx2 = x2 + fbo_x_off; \
  500. ty1 = y1 + fbo_y_off; \
  501. ty2 = y2 + fbo_y_off; \
  502. _glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \
  503. tx2, ty2, yInverted, vertices, \
  504. stride); \
  505. } else \
  506. _glamor_set_normalize_tcoords(xscale, yscale, x1, y1, \
  507. x2, y2, yInverted, vertices, stride);\
  508. } while(0)
  509. #define glamor_set_normalize_tcoords(priv, xscale, yscale, \
  510. x1, y1, x2, y2, \
  511. yInverted, vertices) \
  512. do { \
  513. glamor_set_normalize_tcoords_ext(priv, xscale, yscale, \
  514. x1, y1, x2, y2, \
  515. yInverted, vertices, 2); \
  516. } while(0)
  517. #define glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type, \
  518. xscale, yscale, \
  519. _x1_, _y1_, _x2_, _y2_, \
  520. yInverted, vertices, stride)\
  521. do { \
  522. if (_X_UNLIKELY(priv->type == GLAMOR_TEXTURE_LARGE)) { \
  523. float tx1, tx2, ty1, ty2; \
  524. if (repeat_type == RepeatPad) { \
  525. tx1 = _x1_ - priv->large.box.x1; \
  526. ty1 = _y1_ - priv->large.box.y1; \
  527. tx2 = tx1 + ((_x2_) - (_x1_)); \
  528. ty2 = ty1 + ((_y2_) - (_y1_)); \
  529. } else { \
  530. glamor_get_repeat_coords((&priv->large), repeat_type, \
  531. tx1, ty1, tx2, ty2, \
  532. _x1_, _y1_, _x2_, _y2_); \
  533. } \
  534. _glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \
  535. tx2, ty2, yInverted, vertices, \
  536. stride); \
  537. } else \
  538. _glamor_set_normalize_tcoords(xscale, yscale, _x1_, _y1_, \
  539. _x2_, _y2_, yInverted, vertices, \
  540. stride); \
  541. } while(0)
  542. #define glamor_set_repeat_normalize_tcoords(priv, repeat_type, \
  543. xscale, yscale, \
  544. _x1_, _y1_, _x2_, _y2_, \
  545. yInverted, vertices) \
  546. do { \
  547. glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type, \
  548. xscale, yscale, \
  549. _x1_, _y1_, _x2_, _y2_, \
  550. yInverted, vertices, 2); \
  551. } while(0)
  552. #define glamor_set_normalize_tcoords_tri_stripe(xscale, yscale, \
  553. x1, y1, x2, y2, \
  554. yInverted, vertices) \
  555. do { \
  556. (vertices)[0] = t_from_x_coord_x(xscale, x1); \
  557. (vertices)[2] = t_from_x_coord_x(xscale, x2); \
  558. (vertices)[6] = (vertices)[2]; \
  559. (vertices)[4] = (vertices)[0]; \
  560. if (_X_LIKELY(yInverted)) { \
  561. (vertices)[1] = t_from_x_coord_y_inverted(yscale, y1); \
  562. (vertices)[7] = t_from_x_coord_y_inverted(yscale, y2); \
  563. } \
  564. else { \
  565. (vertices)[1] = t_from_x_coord_y(yscale, y1); \
  566. (vertices)[7] = t_from_x_coord_y(yscale, y2); \
  567. } \
  568. (vertices)[3] = (vertices)[1]; \
  569. (vertices)[5] = (vertices)[7]; \
  570. } while(0)
  571. #define glamor_set_tcoords(width, height, x1, y1, x2, y2, \
  572. yInverted, vertices) \
  573. do { \
  574. (vertices)[0] = (x1); \
  575. (vertices)[2] = (x2); \
  576. (vertices)[4] = (vertices)[2]; \
  577. (vertices)[6] = (vertices)[0]; \
  578. if (_X_LIKELY(yInverted)) { \
  579. (vertices)[1] = (y1); \
  580. (vertices)[5] = (y2); \
  581. } \
  582. else { \
  583. (vertices)[1] = height - (y2); \
  584. (vertices)[5] = height - (y1); \
  585. } \
  586. (vertices)[3] = (vertices)[1]; \
  587. (vertices)[7] = (vertices)[5]; \
  588. } while(0)
  589. #define glamor_set_tcoords_ext(width, height, x1, y1, x2, y2, \
  590. yInverted, vertices, stride) \
  591. do { \
  592. (vertices)[0] = (x1); \
  593. (vertices)[1*stride] = (x2); \
  594. (vertices)[2*stride] = (vertices)[1*stride]; \
  595. (vertices)[3*stride] = (vertices)[0]; \
  596. if (_X_LIKELY(yInverted)) { \
  597. (vertices)[1] = (y1); \
  598. (vertices)[2*stride + 1] = (y2); \
  599. } \
  600. else { \
  601. (vertices)[1] = height - (y2); \
  602. (vertices)[2*stride + 1] = height - (y1); \
  603. } \
  604. (vertices)[1*stride + 1] = (vertices)[1]; \
  605. (vertices)[3*stride + 1] = (vertices)[2*stride + 1]; \
  606. } while(0)
  607. #define glamor_set_normalize_one_vcoord(xscale, yscale, x, y, \
  608. yInverted, vertices) \
  609. do { \
  610. (vertices)[0] = v_from_x_coord_x(xscale, x); \
  611. if (_X_LIKELY(yInverted)) { \
  612. (vertices)[1] = v_from_x_coord_y_inverted(yscale, y); \
  613. } else { \
  614. (vertices)[1] = v_from_x_coord_y(yscale, y); \
  615. } \
  616. } while(0)
  617. #define glamor_set_normalize_tri_vcoords(xscale, yscale, vtx, \
  618. yInverted, vertices) \
  619. do { \
  620. glamor_set_normalize_one_vcoord(xscale, yscale, \
  621. (vtx)[0], (vtx)[1], \
  622. yInverted, vertices); \
  623. glamor_set_normalize_one_vcoord(xscale, yscale, \
  624. (vtx)[2], (vtx)[3], \
  625. yInverted, vertices+2); \
  626. glamor_set_normalize_one_vcoord(xscale, yscale, \
  627. (vtx)[4], (vtx)[5], \
  628. yInverted, vertices+4); \
  629. } while(0)
  630. #define glamor_set_tcoords_tri_strip(width, height, x1, y1, x2, y2, \
  631. yInverted, vertices) \
  632. do { \
  633. (vertices)[0] = (x1); \
  634. (vertices)[2] = (x2); \
  635. (vertices)[6] = (vertices)[2]; \
  636. (vertices)[4] = (vertices)[0]; \
  637. if (_X_LIKELY(yInverted)) { \
  638. (vertices)[1] = (y1); \
  639. (vertices)[7] = (y2); \
  640. } \
  641. else { \
  642. (vertices)[1] = height - (y2); \
  643. (vertices)[7] = height - (y1); \
  644. } \
  645. (vertices)[3] = (vertices)[1]; \
  646. (vertices)[5] = (vertices)[7]; \
  647. } while(0)
  648. #define glamor_set_normalize_vcoords_ext(priv, xscale, yscale, \
  649. x1, y1, x2, y2, \
  650. yInverted, vertices, stride) \
  651. do { \
  652. int fbo_x_off, fbo_y_off; \
  653. /* vertices may be write-only, so we use following \
  654. * temporary variable. */ \
  655. float _t0_, _t1_, _t2_, _t5_; \
  656. pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \
  657. (vertices)[0] = _t0_ = v_from_x_coord_x(xscale, x1 + fbo_x_off); \
  658. (vertices)[1 * stride] = _t2_ = v_from_x_coord_x(xscale, \
  659. x2 + fbo_x_off); \
  660. (vertices)[2 * stride] = _t2_; \
  661. (vertices)[3 * stride] = _t0_; \
  662. if (_X_LIKELY(yInverted)) { \
  663. (vertices)[1] = _t1_ = v_from_x_coord_y_inverted(yscale, \
  664. y1 + fbo_y_off); \
  665. (vertices)[2 * stride + 1] = _t5_ = \
  666. v_from_x_coord_y_inverted(yscale, \
  667. y2 + fbo_y_off); \
  668. } \
  669. else { \
  670. (vertices)[1] = _t1_ = v_from_x_coord_y(yscale, y1 + fbo_y_off); \
  671. (vertices)[2 * stride + 1] = _t5_ = v_from_x_coord_y(yscale, \
  672. y2 + fbo_y_off); \
  673. } \
  674. (vertices)[1 * stride + 1] = _t1_; \
  675. (vertices)[3 * stride + 1] = _t5_; \
  676. } while(0)
  677. #define glamor_set_normalize_vcoords(priv, xscale, yscale, \
  678. x1, y1, x2, y2, \
  679. yInverted, vertices) \
  680. do { \
  681. glamor_set_normalize_vcoords_ext(priv, xscale, yscale, \
  682. x1, y1, x2, y2, \
  683. yInverted, vertices, 2); \
  684. } while(0)
  685. #define glamor_set_const_ext(params, nparam, vertices, nverts, stride) \
  686. do { \
  687. int _i_ = 0, _j_ = 0; \
  688. for(; _i_ < nverts; _i_++) { \
  689. for(_j_ = 0; _j_ < nparam; _j_++) { \
  690. vertices[stride*_i_ + _j_] = params[_j_]; \
  691. } \
  692. } \
  693. } while(0)
  694. #define glamor_set_normalize_vcoords_tri_strip(xscale, yscale, \
  695. x1, y1, x2, y2, \
  696. yInverted, vertices) \
  697. do { \
  698. (vertices)[0] = v_from_x_coord_x(xscale, x1); \
  699. (vertices)[2] = v_from_x_coord_x(xscale, x2); \
  700. (vertices)[6] = (vertices)[2]; \
  701. (vertices)[4] = (vertices)[0]; \
  702. if (_X_LIKELY(yInverted)) { \
  703. (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1); \
  704. (vertices)[7] = v_from_x_coord_y_inverted(yscale, y2); \
  705. } \
  706. else { \
  707. (vertices)[1] = v_from_x_coord_y(yscale, y1); \
  708. (vertices)[7] = v_from_x_coord_y(yscale, y2); \
  709. } \
  710. (vertices)[3] = (vertices)[1]; \
  711. (vertices)[5] = (vertices)[7]; \
  712. } while(0)
  713. #define glamor_set_normalize_pt(xscale, yscale, x, y, \
  714. yInverted, pt) \
  715. do { \
  716. (pt)[0] = t_from_x_coord_x(xscale, x); \
  717. if (_X_LIKELY(yInverted)) { \
  718. (pt)[1] = t_from_x_coord_y_inverted(yscale, y); \
  719. } else { \
  720. (pt)[1] = t_from_x_coord_y(yscale, y); \
  721. } \
  722. } while(0)
  723. #define glamor_set_circle_centre(width, height, x, y, \
  724. yInverted, c) \
  725. do { \
  726. (c)[0] = (float)x; \
  727. if (_X_LIKELY(yInverted)) { \
  728. (c)[1] = (float)y; \
  729. } else { \
  730. (c)[1] = (float)height - (float)y; \
  731. } \
  732. } while(0)
  733. inline static void
  734. glamor_calculate_boxes_bound(BoxPtr bound, BoxPtr boxes, int nbox)
  735. {
  736. int x_min, y_min;
  737. int x_max, y_max;
  738. int i;
  739. x_min = y_min = MAXSHORT;
  740. x_max = y_max = MINSHORT;
  741. for (i = 0; i < nbox; i++) {
  742. if (x_min > boxes[i].x1)
  743. x_min = boxes[i].x1;
  744. if (y_min > boxes[i].y1)
  745. y_min = boxes[i].y1;
  746. if (x_max < boxes[i].x2)
  747. x_max = boxes[i].x2;
  748. if (y_max < boxes[i].y2)
  749. y_max = boxes[i].y2;
  750. }
  751. bound->x1 = x_min;
  752. bound->y1 = y_min;
  753. bound->x2 = x_max;
  754. bound->y2 = y_max;
  755. }
  756. inline static void
  757. glamor_translate_boxes(BoxPtr boxes, int nbox, int dx, int dy)
  758. {
  759. int i;
  760. for (i = 0; i < nbox; i++) {
  761. boxes[i].x1 += dx;
  762. boxes[i].y1 += dy;
  763. boxes[i].x2 += dx;
  764. boxes[i].y2 += dy;
  765. }
  766. }
  767. #ifndef ARRAY_SIZE
  768. #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
  769. #endif
  770. #define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1))
  771. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  772. #define MAX(a,b) ((a) > (b) ? (a) : (b))
  773. #define glamor_check_fbo_size(_glamor_,_w_, _h_) ((_w_) > 0 && (_h_) > 0 \
  774. && (_w_) <= _glamor_->max_fbo_size \
  775. && (_h_) <= _glamor_->max_fbo_size)
  776. /* For 1bpp pixmap, we don't store it as texture. */
  777. #define glamor_check_pixmap_fbo_depth(_depth_) ( \
  778. _depth_ == 8 \
  779. || _depth_ == 15 \
  780. || _depth_ == 16 \
  781. || _depth_ == 24 \
  782. || _depth_ == 30 \
  783. || _depth_ == 32)
  784. #define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv && pixmap_priv->base.is_picture == 1)
  785. #define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv && pixmap_priv->base.gl_fbo == GLAMOR_FBO_NORMAL)
  786. #define GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv) (pixmap_priv && (pixmap_priv->base.gl_fbo == GLAMOR_FBO_DOWNLOADED))
  787. /**
  788. * Borrow from uxa.
  789. */
  790. static inline CARD32
  791. format_for_depth(int depth)
  792. {
  793. switch (depth) {
  794. case 1:
  795. return PICT_a1;
  796. case 4:
  797. return PICT_a4;
  798. case 8:
  799. return PICT_a8;
  800. case 15:
  801. return PICT_x1r5g5b5;
  802. case 16:
  803. return PICT_r5g6b5;
  804. default:
  805. case 24:
  806. return PICT_x8r8g8b8;
  807. #if XORG_VERSION_CURRENT >= 10699900
  808. case 30:
  809. return PICT_x2r10g10b10;
  810. #endif
  811. case 32:
  812. return PICT_a8r8g8b8;
  813. }
  814. }
  815. static inline GLenum
  816. gl_iformat_for_pixmap(PixmapPtr pixmap)
  817. {
  818. glamor_screen_private *glamor_priv =
  819. glamor_get_screen_private(pixmap->drawable.pScreen);
  820. if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP &&
  821. (pixmap->drawable.depth == 1 || pixmap->drawable.depth == 8)) {
  822. return GL_ALPHA;
  823. } else {
  824. return GL_RGBA;
  825. }
  826. }
  827. static inline CARD32
  828. format_for_pixmap(PixmapPtr pixmap)
  829. {
  830. glamor_pixmap_private *pixmap_priv;
  831. PictFormatShort pict_format;
  832. pixmap_priv = glamor_get_pixmap_private(pixmap);
  833. if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv))
  834. pict_format = pixmap_priv->base.picture->format;
  835. else
  836. pict_format = format_for_depth(pixmap->drawable.depth);
  837. return pict_format;
  838. }
  839. #define REVERT_NONE 0
  840. #define REVERT_NORMAL 1
  841. #define REVERT_DOWNLOADING_A1 2
  842. #define REVERT_UPLOADING_A1 3
  843. #define REVERT_DOWNLOADING_2_10_10_10 4
  844. #define REVERT_UPLOADING_2_10_10_10 5
  845. #define REVERT_DOWNLOADING_1_5_5_5 7
  846. #define REVERT_UPLOADING_1_5_5_5 8
  847. #define REVERT_DOWNLOADING_10_10_10_2 9
  848. #define REVERT_UPLOADING_10_10_10_2 10
  849. #define SWAP_NONE_DOWNLOADING 0
  850. #define SWAP_DOWNLOADING 1
  851. #define SWAP_UPLOADING 2
  852. #define SWAP_NONE_UPLOADING 3
  853. inline static int
  854. cache_format(GLenum format)
  855. {
  856. switch (format) {
  857. case GL_ALPHA:
  858. return 2;
  859. case GL_RGB:
  860. return 1;
  861. case GL_RGBA:
  862. return 0;
  863. default:
  864. return -1;
  865. }
  866. }
  867. /* borrowed from uxa */
  868. static inline Bool
  869. glamor_get_rgba_from_pixel(CARD32 pixel,
  870. float *red,
  871. float *green,
  872. float *blue, float *alpha, CARD32 format)
  873. {
  874. int rbits, bbits, gbits, abits;
  875. int rshift, bshift, gshift, ashift;
  876. rbits = PICT_FORMAT_R(format);
  877. gbits = PICT_FORMAT_G(format);
  878. bbits = PICT_FORMAT_B(format);
  879. abits = PICT_FORMAT_A(format);
  880. if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) {
  881. rshift = gshift = bshift = ashift = 0;
  882. }
  883. else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
  884. bshift = 0;
  885. gshift = bbits;
  886. rshift = gshift + gbits;
  887. ashift = rshift + rbits;
  888. }
  889. else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
  890. rshift = 0;
  891. gshift = rbits;
  892. bshift = gshift + gbits;
  893. ashift = bshift + bbits;
  894. #if XORG_VERSION_CURRENT >= 10699900
  895. }
  896. else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
  897. ashift = 0;
  898. rshift = abits;
  899. if (abits == 0)
  900. rshift = PICT_FORMAT_BPP(format) - (rbits + gbits + bbits);
  901. gshift = rshift + rbits;
  902. bshift = gshift + gbits;
  903. #endif
  904. }
  905. else {
  906. return FALSE;
  907. }
  908. #define COLOR_INT_TO_FLOAT(_fc_, _p_, _s_, _bits_) \
  909. *_fc_ = (((_p_) >> (_s_)) & (( 1 << (_bits_)) - 1)) \
  910. / (float)((1<<(_bits_)) - 1)
  911. if (rbits)
  912. COLOR_INT_TO_FLOAT(red, pixel, rshift, rbits);
  913. else
  914. *red = 0;
  915. if (gbits)
  916. COLOR_INT_TO_FLOAT(green, pixel, gshift, gbits);
  917. else
  918. *green = 0;
  919. if (bbits)
  920. COLOR_INT_TO_FLOAT(blue, pixel, bshift, bbits);
  921. else
  922. *blue = 0;
  923. if (abits)
  924. COLOR_INT_TO_FLOAT(alpha, pixel, ashift, abits);
  925. else
  926. *alpha = 1;
  927. return TRUE;
  928. }
  929. inline static Bool
  930. glamor_pict_format_is_compatible(PicturePtr picture)
  931. {
  932. GLenum iformat;
  933. PixmapPtr pixmap = glamor_get_drawable_pixmap(picture->pDrawable);
  934. iformat = gl_iformat_for_pixmap(pixmap);
  935. switch (iformat) {
  936. case GL_RGBA:
  937. return (picture->format == PICT_a8r8g8b8 ||
  938. picture->format == PICT_x8r8g8b8);
  939. case GL_ALPHA:
  940. return (picture->format == PICT_a8);
  941. default:
  942. return FALSE;
  943. }
  944. }
  945. /* return TRUE if we can access this pixmap at DDX driver. */
  946. inline static Bool
  947. glamor_ddx_fallback_check_pixmap(DrawablePtr drawable)
  948. {
  949. PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
  950. glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
  951. return (!pixmap_priv
  952. || (pixmap_priv->type == GLAMOR_TEXTURE_DRM
  953. || pixmap_priv->type == GLAMOR_MEMORY
  954. || pixmap_priv->type == GLAMOR_DRM_ONLY));
  955. }
  956. inline static Bool
  957. glamor_ddx_fallback_check_gc(GCPtr gc)
  958. {
  959. PixmapPtr pixmap;
  960. if (!gc)
  961. return TRUE;
  962. switch (gc->fillStyle) {
  963. case FillStippled:
  964. case FillOpaqueStippled:
  965. pixmap = gc->stipple;
  966. break;
  967. case FillTiled:
  968. pixmap = gc->tile.pixmap;
  969. break;
  970. default:
  971. pixmap = NULL;
  972. }
  973. return (!pixmap || glamor_ddx_fallback_check_pixmap(&pixmap->drawable));
  974. }
  975. inline static Bool
  976. glamor_is_large_pixmap(PixmapPtr pixmap)
  977. {
  978. glamor_pixmap_private *priv;
  979. priv = glamor_get_pixmap_private(pixmap);
  980. return (priv->type == GLAMOR_TEXTURE_LARGE);
  981. }
  982. inline static Bool
  983. glamor_is_large_picture(PicturePtr picture)
  984. {
  985. PixmapPtr pixmap;
  986. if (picture->pDrawable) {
  987. pixmap = glamor_get_drawable_pixmap(picture->pDrawable);
  988. return glamor_is_large_pixmap(pixmap);
  989. }
  990. return FALSE;
  991. }
  992. inline static Bool
  993. glamor_tex_format_is_readable(GLenum format)
  994. {
  995. return ((format == GL_RGBA || format == GL_RGB || format == GL_ALPHA));
  996. }
  997. static inline void
  998. _glamor_dump_pixmap_bits(PixmapPtr pixmap, int x, int y, int w, int h)
  999. {
  1000. int i, j;
  1001. unsigned char *p = pixmap->devPrivate.ptr;
  1002. int stride = pixmap->devKind;
  1003. p = p + y * stride + x;
  1004. for (i = 0; i < h; i++) {
  1005. ErrorF("line %3d: ", i);
  1006. for (j = 0; j < w; j++)
  1007. ErrorF("%2d ", (p[j / 8] & (1 << (j % 8))) >> (j % 8));
  1008. p += stride;
  1009. ErrorF("\n");
  1010. }
  1011. }
  1012. static inline void
  1013. _glamor_dump_pixmap_byte(PixmapPtr pixmap, int x, int y, int w, int h)
  1014. {
  1015. int i, j;
  1016. unsigned char *p = pixmap->devPrivate.ptr;
  1017. int stride = pixmap->devKind;
  1018. p = p + y * stride + x;
  1019. for (i = 0; i < h; i++) {
  1020. ErrorF("line %3d: ", i);
  1021. for (j = 0; j < w; j++)
  1022. ErrorF("%2x ", p[j]);
  1023. p += stride;
  1024. ErrorF("\n");
  1025. }
  1026. }
  1027. static inline void
  1028. _glamor_dump_pixmap_sword(PixmapPtr pixmap, int x, int y, int w, int h)
  1029. {
  1030. int i, j;
  1031. unsigned short *p = pixmap->devPrivate.ptr;
  1032. int stride = pixmap->devKind / 2;
  1033. p = p + y * stride + x;
  1034. for (i = 0; i < h; i++) {
  1035. ErrorF("line %3d: ", i);
  1036. for (j = 0; j < w; j++)
  1037. ErrorF("%2x ", p[j]);
  1038. p += stride;
  1039. ErrorF("\n");
  1040. }
  1041. }
  1042. static inline void
  1043. _glamor_dump_pixmap_word(PixmapPtr pixmap, int x, int y, int w, int h)
  1044. {
  1045. int i, j;
  1046. unsigned int *p = pixmap->devPrivate.ptr;
  1047. int stride = pixmap->devKind / 4;
  1048. p = p + y * stride + x;
  1049. for (i = 0; i < h; i++) {
  1050. ErrorF("line %3d: ", i);
  1051. for (j = 0; j < w; j++)
  1052. ErrorF("%2x ", p[j]);
  1053. p += stride;
  1054. ErrorF("\n");
  1055. }
  1056. }
  1057. static inline void
  1058. glamor_dump_pixmap(PixmapPtr pixmap, int x, int y, int w, int h)
  1059. {
  1060. w = ((x + w) > pixmap->drawable.width) ? (pixmap->drawable.width - x) : w;
  1061. h = ((y + h) > pixmap->drawable.height) ? (pixmap->drawable.height - y) : h;
  1062. glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO);
  1063. switch (pixmap->drawable.depth) {
  1064. case 8:
  1065. _glamor_dump_pixmap_byte(pixmap, x, y, w, h);
  1066. break;
  1067. case 15:
  1068. case 16:
  1069. _glamor_dump_pixmap_sword(pixmap, x, y, w, h);
  1070. break;
  1071. case 24:
  1072. case 32:
  1073. _glamor_dump_pixmap_word(pixmap, x, y, w, h);
  1074. break;
  1075. case 1:
  1076. _glamor_dump_pixmap_bits(pixmap, x, y, w, h);
  1077. break;
  1078. default:
  1079. ErrorF("dump depth %d, not implemented.\n", pixmap->drawable.depth);
  1080. }
  1081. glamor_finish_access(&pixmap->drawable);
  1082. }
  1083. static inline void
  1084. _glamor_compare_pixmaps(PixmapPtr pixmap1, PixmapPtr pixmap2,
  1085. int x, int y, int w, int h,
  1086. PictFormatShort short_format, int all, int diffs)
  1087. {
  1088. int i, j;
  1089. unsigned char *p1 = pixmap1->devPrivate.ptr;
  1090. unsigned char *p2 = pixmap2->devPrivate.ptr;
  1091. int line_need_printed = 0;
  1092. int test_code = 0xAABBCCDD;
  1093. int little_endian = 0;
  1094. unsigned char *p_test;
  1095. int bpp = pixmap1->drawable.depth == 8 ? 1 : 4;
  1096. int stride = pixmap1->devKind;
  1097. assert(pixmap1->devKind == pixmap2->devKind);
  1098. ErrorF("stride:%d, width:%d, height:%d\n", stride, w, h);
  1099. p1 = p1 + y * stride + x;
  1100. p2 = p2 + y * stride + x;
  1101. if (all) {
  1102. for (i = 0; i < h; i++) {
  1103. ErrorF("line %3d: ", i);
  1104. for (j = 0; j < stride; j++) {
  1105. if (j % bpp == 0)
  1106. ErrorF("[%d]%2x:%2x ", j / bpp, p1[j], p2[j]);
  1107. else
  1108. ErrorF("%2x:%2x ", p1[j], p2[j]);
  1109. }
  1110. p1 += stride;
  1111. p2 += stride;
  1112. ErrorF("\n");
  1113. }
  1114. }
  1115. else {
  1116. if (short_format == PICT_a8r8g8b8) {
  1117. p_test = (unsigned char *) &test_code;
  1118. little_endian = (*p_test == 0xDD);
  1119. bpp = 4;
  1120. for (i = 0; i < h; i++) {
  1121. line_need_printed = 0;
  1122. for (j = 0; j < stride; j++) {
  1123. if (p1[j] != p2[j] &&
  1124. (p1[j] - p2[j] > diffs || p2[j] - p1[j] > diffs)) {
  1125. if (line_need_printed) {
  1126. if (little_endian) {
  1127. switch (j % 4) {
  1128. case 2:
  1129. ErrorF("[%d]RED:%2x:%2x ", j / bpp, p1[j],
  1130. p2[j]);
  1131. break;
  1132. case 1:
  1133. ErrorF("[%d]GREEN:%2x:%2x ", j / bpp, p1[j],
  1134. p2[j]);
  1135. break;
  1136. case 0:
  1137. ErrorF("[%d]BLUE:%2x:%2x ", j / bpp, p1[j],
  1138. p2[j]);
  1139. break;
  1140. case 3:
  1141. ErrorF("[%d]Alpha:%2x:%2x ", j / bpp, p1[j],
  1142. p2[j]);
  1143. break;
  1144. }
  1145. }
  1146. else {
  1147. switch (j % 4) {
  1148. case 1:
  1149. ErrorF("[%d]RED:%2x:%2x ", j / bpp, p1[j],
  1150. p2[j]);
  1151. break;
  1152. case 2:
  1153. ErrorF("[%d]GREEN:%2x:%2x ", j / bpp, p1[j],
  1154. p2[j]);
  1155. break;
  1156. case 3:
  1157. ErrorF("[%d]BLUE:%2x:%2x ", j / bpp, p1[j],
  1158. p2[j]);
  1159. break;
  1160. case 0:
  1161. ErrorF("[%d]Alpha:%2x:%2x ", j / bpp, p1[j],
  1162. p2[j]);
  1163. break;
  1164. }
  1165. }
  1166. }
  1167. else {
  1168. line_need_printed = 1;
  1169. j = -1;
  1170. ErrorF("line %3d: ", i);
  1171. continue;
  1172. }
  1173. }
  1174. }
  1175. p1 += stride;
  1176. p2 += stride;
  1177. ErrorF("\n");
  1178. }
  1179. } //more format can be added here.
  1180. else { // the default format, just print.
  1181. for (i = 0; i < h; i++) {
  1182. line_need_printed = 0;
  1183. for (j = 0; j < stride; j++) {
  1184. if (p1[j] != p2[j]) {
  1185. if (line_need_printed) {
  1186. ErrorF("[%d]%2x:%2x ", j / bpp, p1[j], p2[j]);
  1187. }
  1188. else {
  1189. line_need_printed = 1;
  1190. j = -1;
  1191. ErrorF("line %3d: ", i);
  1192. continue;
  1193. }
  1194. }
  1195. }
  1196. p1 += stride;
  1197. p2 += stride;
  1198. ErrorF("\n");
  1199. }
  1200. }
  1201. }
  1202. }
  1203. static inline void
  1204. glamor_compare_pixmaps(PixmapPtr pixmap1, PixmapPtr pixmap2,
  1205. int x, int y, int w, int h, int all, int diffs)
  1206. {
  1207. assert(pixmap1->drawable.depth == pixmap2->drawable.depth);
  1208. if (glamor_prepare_access(&pixmap1->drawable, GLAMOR_ACCESS_RO) &&
  1209. glamor_prepare_access(&pixmap2->drawable, GLAMOR_ACCESS_RO)) {
  1210. _glamor_compare_pixmaps(pixmap1, pixmap2, x, y, w, h, -1, all, diffs);
  1211. }
  1212. glamor_finish_access(&pixmap1->drawable);
  1213. glamor_finish_access(&pixmap2->drawable);
  1214. }
  1215. /* This function is used to compare two pictures.
  1216. If the picture has no drawable, we use fb functions to generate it. */
  1217. static inline void
  1218. glamor_compare_pictures(ScreenPtr screen,
  1219. PicturePtr fst_picture,
  1220. PicturePtr snd_picture,
  1221. int x_source, int y_source,
  1222. int width, int height, int all, int diffs)
  1223. {
  1224. PixmapPtr fst_pixmap;
  1225. PixmapPtr snd_pixmap;
  1226. int fst_generated, snd_generated;
  1227. int error;
  1228. int fst_type = -1;
  1229. int snd_type = -1; // -1 represent has drawable.
  1230. if (fst_picture->format != snd_picture->format) {
  1231. ErrorF("Different picture format can not compare!\n");
  1232. return;
  1233. }
  1234. if (!fst_picture->pDrawable) {
  1235. fst_type = fst_picture->pSourcePict->type;
  1236. }
  1237. if (!snd_picture->pDrawable) {
  1238. snd_type = snd_picture->pSourcePict->type;
  1239. }
  1240. if ((fst_type != -1) && (snd_type != -1) && (fst_type != snd_type)) {
  1241. ErrorF("Different picture type will never be same!\n");
  1242. return;
  1243. }
  1244. fst_generated = snd_generated = 0;
  1245. if (!fst_picture->pDrawable) {
  1246. PicturePtr pixman_pic;
  1247. PixmapPtr pixmap = NULL;
  1248. PictFormatShort format;
  1249. format = fst_picture->format;
  1250. pixmap = glamor_create_pixmap(screen,
  1251. width, height,
  1252. PIXMAN_FORMAT_DEPTH(format),
  1253. GLAMOR_CREATE_PIXMAP_CPU);
  1254. pixman_pic = CreatePicture(0,
  1255. &pixmap->drawable,
  1256. PictureMatchFormat(screen,
  1257. PIXMAN_FORMAT_DEPTH
  1258. (format), format), 0, 0,
  1259. serverClient, &error);
  1260. fbComposite(PictOpSrc, fst_picture, NULL, pixman_pic,
  1261. x_source, y_source, 0, 0, 0, 0, width, height);
  1262. glamor_destroy_pixmap(pixmap);
  1263. fst_picture = pixman_pic;
  1264. fst_generated = 1;
  1265. }
  1266. if (!snd_picture->pDrawable) {
  1267. PicturePtr pixman_pic;
  1268. PixmapPtr pixmap = NULL;
  1269. PictFormatShort format;
  1270. format = snd_picture->format;
  1271. pixmap = glamor_create_pixmap(screen,
  1272. width, height,
  1273. PIXMAN_FORMAT_DEPTH(format),
  1274. GLAMOR_CREATE_PIXMAP_CPU);
  1275. pixman_pic = CreatePicture(0,
  1276. &pixmap->drawable,
  1277. PictureMatchFormat(screen,
  1278. PIXMAN_FORMAT_DEPTH
  1279. (format), format), 0, 0,
  1280. serverClient, &error);
  1281. fbComposite(PictOpSrc, snd_picture, NULL, pixman_pic,
  1282. x_source, y_source, 0, 0, 0, 0, width, height);
  1283. glamor_destroy_pixmap(pixmap);
  1284. snd_picture = pixman_pic;
  1285. snd_generated = 1;
  1286. }
  1287. fst_pixmap = glamor_get_drawable_pixmap(fst_picture->pDrawable);
  1288. snd_pixmap = glamor_get_drawable_pixmap(snd_picture->pDrawable);
  1289. if (fst_pixmap->drawable.depth != snd_pixmap->drawable.depth) {
  1290. if (fst_generated)
  1291. glamor_destroy_picture(fst_picture);
  1292. if (snd_generated)
  1293. glamor_destroy_picture(snd_picture);
  1294. ErrorF("Different pixmap depth can not compare!\n");
  1295. return;
  1296. }
  1297. if ((fst_type == SourcePictTypeLinear) ||
  1298. (fst_type == SourcePictTypeRadial) ||
  1299. (fst_type == SourcePictTypeConical) ||
  1300. (snd_type == SourcePictTypeLinear) ||
  1301. (snd_type == SourcePictTypeRadial) ||
  1302. (snd_type == SourcePictTypeConical)) {
  1303. x_source = y_source = 0;
  1304. }
  1305. if (glamor_prepare_access(&fst_pixmap->drawable, GLAMOR_ACCESS_RO) &&
  1306. glamor_prepare_access(&snd_pixmap->drawable, GLAMOR_ACCESS_RO)) {
  1307. _glamor_compare_pixmaps(fst_pixmap, snd_pixmap,
  1308. x_source, y_source,
  1309. width, height, fst_picture->format,
  1310. all, diffs);
  1311. }
  1312. glamor_finish_access(&fst_pixmap->drawable);
  1313. glamor_finish_access(&snd_pixmap->drawable);
  1314. if (fst_generated)
  1315. glamor_destroy_picture(fst_picture);
  1316. if (snd_generated)
  1317. glamor_destroy_picture(snd_picture);
  1318. return;
  1319. }
  1320. #ifdef __i386__
  1321. static inline unsigned long
  1322. __fls(unsigned long x)
  1323. {
  1324. asm("bsr %1,%0":"=r"(x)
  1325. : "rm"(x));
  1326. return x;
  1327. }
  1328. #else
  1329. static inline unsigned long
  1330. __fls(unsigned long x)
  1331. {
  1332. int n;
  1333. if (x == 0)
  1334. return (0);
  1335. n = 0;
  1336. if (x <= 0x0000FFFF) {
  1337. n = n + 16;
  1338. x = x << 16;
  1339. }
  1340. if (x <= 0x00FFFFFF) {
  1341. n = n + 8;
  1342. x = x << 8;
  1343. }
  1344. if (x <= 0x0FFFFFFF) {
  1345. n = n + 4;
  1346. x = x << 4;
  1347. }
  1348. if (x <= 0x3FFFFFFF) {
  1349. n = n + 2;
  1350. x = x << 2;
  1351. }
  1352. if (x <= 0x7FFFFFFF) {
  1353. n = n + 1;
  1354. }
  1355. return 31 - n;
  1356. }
  1357. #endif
  1358. static inline void
  1359. glamor_make_current(glamor_screen_private *glamor_priv)
  1360. {
  1361. if (lastGLContext != &glamor_priv->ctx) {
  1362. lastGLContext = &glamor_priv->ctx;
  1363. glamor_priv->ctx.make_current(&glamor_priv->ctx);
  1364. }
  1365. }
  1366. #endif