glamor_trapezoid.c 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819
  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. * Junyan He <junyan.he@linux.intel.com>
  25. *
  26. */
  27. /** @file glamor_trapezoid.c
  28. *
  29. * Trapezoid acceleration implementation
  30. */
  31. #include "glamor_priv.h"
  32. #ifdef RENDER
  33. #include "mipict.h"
  34. #include "fbpict.h"
  35. static xFixed
  36. _glamor_linefixedX(xLineFixed *l, xFixed y, Bool ceil)
  37. {
  38. xFixed dx = l->p2.x - l->p1.x;
  39. xFixed_32_32 ex = (xFixed_32_32) (y - l->p1.y) * dx;
  40. xFixed dy = l->p2.y - l->p1.y;
  41. if (ceil)
  42. ex += (dy - 1);
  43. return l->p1.x + (xFixed) (ex / dy);
  44. }
  45. static xFixed
  46. _glamor_linefixedY(xLineFixed *l, xFixed x, Bool ceil)
  47. {
  48. xFixed dy = l->p2.y - l->p1.y;
  49. xFixed_32_32 ey = (xFixed_32_32) (x - l->p1.x) * dy;
  50. xFixed dx = l->p2.x - l->p1.x;
  51. if (ceil)
  52. ey += (dx - 1);
  53. return l->p1.y + (xFixed) (ey / dx);
  54. }
  55. #ifdef GLAMOR_TRAPEZOID_SHADER
  56. #define GLAMOR_VERTEX_TOP_BOTTOM (GLAMOR_VERTEX_SOURCE + 1)
  57. #define GLAMOR_VERTEX_LEFT_PARAM (GLAMOR_VERTEX_SOURCE + 2)
  58. #define GLAMOR_VERTEX_RIGHT_PARAM (GLAMOR_VERTEX_SOURCE + 3)
  59. #define DEBUG_CLIP_VTX 0
  60. #define POINT_INSIDE_CLIP_RECT(point, rect) \
  61. (point[0] >= IntToxFixed(rect->x1) \
  62. && point[0] <= IntToxFixed(rect->x2) \
  63. && point[1] >= IntToxFixed(rect->y1) \
  64. && point[1] <= IntToxFixed(rect->y2))
  65. static xFixed
  66. _glamor_lines_crossfixedY(xLineFixed *l, xLineFixed *r)
  67. {
  68. xFixed dx1 = l->p2.x - l->p1.x;
  69. xFixed dx2 = r->p2.x - r->p1.x;
  70. xFixed dy1 = l->p2.y - l->p1.y;
  71. xFixed dy2 = r->p2.y - r->p1.y;
  72. xFixed_32_32 tmp = (xFixed_32_32) dy2 * dy1;
  73. xFixed_32_32 dividend1 = (tmp >> 32) * (l->p1.x - r->p1.x);
  74. xFixed_32_32 dividend2;
  75. xFixed_32_32 dividend3;
  76. xFixed_32_32 divisor;
  77. tmp = (xFixed_32_32) dx1 *dy2;
  78. dividend2 = (tmp >> 32) * l->p1.y;
  79. tmp = (xFixed_32_32) dy1 *dx2;
  80. dividend3 = (tmp >> 32) * r->p1.y;
  81. divisor = ((xFixed_32_32) dx1 * (xFixed_32_32) dy2
  82. - (xFixed_32_32) dy1 * (xFixed_32_32) dx2) >> 32;
  83. if (divisor)
  84. return (xFixed) ((dividend2 - dividend1 - dividend3) / divisor);
  85. return 0xFFFFFFFF;
  86. }
  87. static Bool
  88. point_inside_trapezoid(int point[2], xTrapezoid *trap, xFixed cut_y)
  89. {
  90. int ret = TRUE;
  91. int tmp;
  92. if (point[1] > trap->bottom) {
  93. ret = FALSE;
  94. if (DEBUG_CLIP_VTX) {
  95. ErrorF("Out of Trap bottom, point[1] = %d(0x%x)), "
  96. "bottom = %d(0x%x)\n",
  97. (unsigned int) xFixedToInt(point[1]), point[1],
  98. (unsigned int) xFixedToInt(trap->bottom),
  99. (unsigned int) trap->bottom);
  100. }
  101. return ret;
  102. }
  103. if (point[1] < trap->top) {
  104. ret = FALSE;
  105. if (DEBUG_CLIP_VTX) {
  106. ErrorF("Out of Trap top, point[1] = %d(0x%x)), "
  107. "top = %d(0x%x)\n",
  108. (unsigned int) xFixedToInt(point[1]), point[1],
  109. (unsigned int) xFixedToInt(trap->top),
  110. (unsigned int) trap->top);
  111. }
  112. return ret;
  113. }
  114. tmp = _glamor_linefixedX(&trap->left, point[1], FALSE);
  115. if (point[0] < tmp) {
  116. ret = FALSE;
  117. if (abs(cut_y - trap->top) < pixman_fixed_1_minus_e &&
  118. abs(point[1] - trap->top) < pixman_fixed_1_minus_e &&
  119. tmp - point[0] < pixman_fixed_1_minus_e) {
  120. ret = TRUE;
  121. }
  122. else if (abs(cut_y - trap->bottom) < pixman_fixed_1_minus_e &&
  123. point[1] - trap->bottom < pixman_fixed_1_minus_e &&
  124. tmp - point[0] < pixman_fixed_1_minus_e) {
  125. ret = TRUE;
  126. }
  127. if (DEBUG_CLIP_VTX && !ret) {
  128. ErrorF("Out of Trap left, point[0] = %d(0x%x)), "
  129. "left = %d(0x%x)\n",
  130. (unsigned int) xFixedToInt(point[0]), point[0],
  131. (unsigned int) xFixedToInt(tmp), (unsigned int) tmp);
  132. }
  133. if (!ret)
  134. return ret;
  135. }
  136. tmp = _glamor_linefixedX(&trap->right, point[1], TRUE);
  137. if (point[0] > tmp) {
  138. ret = FALSE;
  139. if (abs(cut_y - trap->top) < pixman_fixed_1_minus_e &&
  140. abs(point[1] - trap->top) < pixman_fixed_1_minus_e &&
  141. point[0] - tmp < pixman_fixed_1_minus_e) {
  142. ret = TRUE;
  143. }
  144. else if (abs(cut_y - trap->bottom) < pixman_fixed_1_minus_e &&
  145. abs(point[1] - trap->bottom) < pixman_fixed_1_minus_e &&
  146. point[0] - tmp < pixman_fixed_1_minus_e) {
  147. ret = TRUE;
  148. }
  149. if (DEBUG_CLIP_VTX && !ret) {
  150. ErrorF("Out of Trap right, point[0] = %d(0x%x)), "
  151. "right = %d(0x%x)\n",
  152. (unsigned int) xFixedToInt(point[0]), point[0],
  153. (unsigned int) xFixedToInt(tmp), (unsigned int) tmp);
  154. }
  155. if (!ret)
  156. return ret;
  157. }
  158. return ret;
  159. }
  160. static void
  161. glamor_emit_composite_vert(ScreenPtr screen,
  162. float *vb,
  163. const float *src_coords,
  164. const float *mask_coords,
  165. const float *dst_coords, int i)
  166. {
  167. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  168. int j = 0;
  169. vb += i * glamor_priv->vb_stride / sizeof(float);
  170. vb[j++] = dst_coords[i * 2 + 0];
  171. vb[j++] = dst_coords[i * 2 + 1];
  172. if (glamor_priv->has_source_coords) {
  173. vb[j++] = src_coords[i * 2 + 0];
  174. vb[j++] = src_coords[i * 2 + 1];
  175. }
  176. if (glamor_priv->has_mask_coords) {
  177. vb[j++] = mask_coords[i * 2 + 0];
  178. vb[j++] = mask_coords[i * 2 + 1];
  179. }
  180. glamor_priv->render_nr_verts++;
  181. }
  182. static void
  183. glamor_emit_composite_triangle(ScreenPtr screen,
  184. float *vb,
  185. const float *src_coords,
  186. const float *mask_coords,
  187. const float *dst_coords)
  188. {
  189. glamor_emit_composite_vert(screen, vb,
  190. src_coords, mask_coords, dst_coords, 0);
  191. glamor_emit_composite_vert(screen, vb,
  192. src_coords, mask_coords, dst_coords, 1);
  193. glamor_emit_composite_vert(screen, vb,
  194. src_coords, mask_coords, dst_coords, 2);
  195. }
  196. static void
  197. glamor_flush_composite_triangles(ScreenPtr screen)
  198. {
  199. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  200. glamor_make_current(glamor_priv);
  201. glamor_put_vbo_space(screen);
  202. if (!glamor_priv->render_nr_verts)
  203. return;
  204. glDrawArrays(GL_TRIANGLES, 0, glamor_priv->render_nr_verts);
  205. }
  206. static Bool
  207. _glamor_clip_trapezoid_vertex(xTrapezoid *trap, BoxPtr pbox,
  208. int vertex[6], int *num)
  209. {
  210. xFixed edge_cross_y = 0xFFFFFFFF;
  211. int tl[2];
  212. int bl[2];
  213. int tr[2];
  214. int br[2];
  215. int left_cut_top[2];
  216. int left_cut_left[2];
  217. int left_cut_right[2];
  218. int left_cut_bottom[2];
  219. int right_cut_top[2];
  220. int right_cut_left[2];
  221. int right_cut_right[2];
  222. int right_cut_bottom[2];
  223. int tmp[2];
  224. int tmp_vtx[20 * 2];
  225. float tmp_vtx_slope[20];
  226. BoxRec trap_bound;
  227. int i = 0;
  228. int vertex_num = 0;
  229. if (DEBUG_CLIP_VTX) {
  230. ErrorF
  231. ("The parameter of xTrapezoid is:\ntop: %d 0x%x\tbottom: %d 0x%x\n"
  232. "left: p1 (%d 0x%x, %d 0x%x)\tp2 (%d 0x%x, %d 0x%x)\n"
  233. "right: p1 (%d 0x%x, %d 0x%x)\tp2 (%d 0x%x, %d 0x%x)\n",
  234. xFixedToInt(trap->top), (unsigned int) trap->top,
  235. xFixedToInt(trap->bottom), (unsigned int) trap->bottom,
  236. xFixedToInt(trap->left.p1.x), (unsigned int) trap->left.p1.x,
  237. xFixedToInt(trap->left.p1.y), (unsigned int) trap->left.p1.y,
  238. xFixedToInt(trap->left.p2.x), (unsigned int) trap->left.p2.x,
  239. xFixedToInt(trap->left.p2.y), (unsigned int) trap->left.p2.y,
  240. xFixedToInt(trap->right.p1.x), (unsigned int) trap->right.p1.x,
  241. xFixedToInt(trap->right.p1.y), (unsigned int) trap->right.p1.y,
  242. xFixedToInt(trap->right.p2.x), (unsigned int) trap->right.p2.x,
  243. xFixedToInt(trap->right.p2.y), (unsigned int) trap->right.p2.y);
  244. }
  245. miTrapezoidBounds(1, trap, &trap_bound);
  246. if (DEBUG_CLIP_VTX)
  247. ErrorF("The bounds for this traps is: bounds.x1 = %d, bounds.x2 = %d, "
  248. "bounds.y1 = %d, bounds.y2 = %d\n", trap_bound.x1, trap_bound.x2,
  249. trap_bound.y1, trap_bound.y2);
  250. if (trap_bound.x1 > pbox->x2 || trap_bound.x2 < pbox->x1)
  251. return FALSE;
  252. if (trap_bound.y1 > pbox->y2 || trap_bound.y2 < pbox->y1)
  253. return FALSE;
  254. #define IS_TRAP_EDGE_VERTICAL(edge) \
  255. (edge->p1.x == edge->p2.x)
  256. #define CACULATE_CUT_VERTEX(vtx, cal_x, ceil, vh_edge, edge) \
  257. do { \
  258. if(cal_x) { \
  259. vtx[1] = (vh_edge); \
  260. vtx[0] = (_glamor_linefixedX( \
  261. edge, vh_edge, ceil)); \
  262. if(DEBUG_CLIP_VTX) \
  263. ErrorF("The intersection point of line y=%d and " \
  264. "line of p1:(%d,%d) -- p2 (%d,%d) " \
  265. "is (%d, %d)\n", \
  266. xFixedToInt(vh_edge), \
  267. xFixedToInt(edge->p1.x), \
  268. xFixedToInt(edge->p1.y), \
  269. xFixedToInt(edge->p2.x), \
  270. xFixedToInt(edge->p2.y), \
  271. xFixedToInt(vtx[0]), \
  272. xFixedToInt(vtx[1])); \
  273. } else { \
  274. vtx[0] = (vh_edge); \
  275. vtx[1] = (_glamor_linefixedY( \
  276. edge, vh_edge, ceil)); \
  277. if(DEBUG_CLIP_VTX) \
  278. ErrorF("The intersection point of line x=%d and " \
  279. "line of p1:(%d,%d) -- p2 (%d,%d) " \
  280. "is (%d, %d)\n", \
  281. xFixedToInt(vh_edge), \
  282. xFixedToInt(edge->p1.x), \
  283. xFixedToInt(edge->p1.y), \
  284. xFixedToInt(edge->p2.x), \
  285. xFixedToInt(edge->p2.y), \
  286. xFixedToInt(vtx[0]), \
  287. xFixedToInt(vtx[1])); \
  288. } \
  289. } while(0)
  290. #define ADD_VERTEX_IF_INSIDE(vtx) \
  291. if(POINT_INSIDE_CLIP_RECT(vtx, pbox) \
  292. && point_inside_trapezoid(vtx, trap, edge_cross_y)){ \
  293. tmp_vtx[vertex_num] = xFixedToInt(vtx[0]); \
  294. tmp_vtx[vertex_num + 1] = xFixedToInt(vtx[1]); \
  295. vertex_num += 2; \
  296. if(DEBUG_CLIP_VTX) \
  297. ErrorF("@ Point: (%d, %d) is inside " \
  298. "the Rect and Trapezoid\n", \
  299. xFixedToInt(vtx[0]), \
  300. xFixedToInt(vtx[1])); \
  301. } else if(DEBUG_CLIP_VTX){ \
  302. ErrorF("X Point: (%d, %d) is outside " \
  303. "the Rect and Trapezoid\t", \
  304. xFixedToInt(vtx[0]), \
  305. xFixedToInt(vtx[1])); \
  306. if(POINT_INSIDE_CLIP_RECT(vtx, pbox)) \
  307. ErrorF("The Point is outside " \
  308. "the Trapezoid\n"); \
  309. else \
  310. ErrorF("The Point is outside " \
  311. "the Rect\n"); \
  312. }
  313. /*Trap's right edge cut right edge. */
  314. if ((!IS_TRAP_EDGE_VERTICAL((&trap->left))) ||
  315. (!IS_TRAP_EDGE_VERTICAL((&trap->right)))) {
  316. edge_cross_y = _glamor_lines_crossfixedY((&trap->left), (&trap->right));
  317. if (DEBUG_CLIP_VTX) {
  318. ErrorF("Trap's left edge cut right edge at %d(0x%x), "
  319. "trap_top = %x, trap_bottom = %x\n",
  320. xFixedToInt(edge_cross_y), edge_cross_y,
  321. (unsigned int) trap->top, (unsigned int) trap->bottom);
  322. }
  323. }
  324. /*Trap's TopLeft, BottomLeft, TopRight and BottomRight. */
  325. CACULATE_CUT_VERTEX(tl, 1, FALSE, trap->top, (&trap->left));
  326. CACULATE_CUT_VERTEX(bl, 1, FALSE, trap->bottom, (&trap->left));
  327. CACULATE_CUT_VERTEX(tr, 1, TRUE, trap->top, (&trap->right));
  328. CACULATE_CUT_VERTEX(br, 1, TRUE, trap->bottom, (&trap->right));
  329. if (DEBUG_CLIP_VTX)
  330. ErrorF("Trap's TopLeft, BottomLeft, TopRight and BottomRight\n");
  331. if (DEBUG_CLIP_VTX)
  332. ErrorF("Caculate the vertex of trapezoid:\n"
  333. " (%3d, %3d)-------------------------(%3d, %3d)\n"
  334. " / \\ \n"
  335. " / \\ \n"
  336. " / \\ \n"
  337. " (%3d, %3d)---------------------------------(%3d, %3d)\n"
  338. "Clip with rect:\n"
  339. " (%3d, %3d)------------------------(%3d, %3d) \n"
  340. " | | \n"
  341. " | | \n"
  342. " | | \n"
  343. " (%3d, %3d)------------------------(%3d, %3d) \n",
  344. xFixedToInt(tl[0]), xFixedToInt(tl[1]), xFixedToInt(tr[0]),
  345. xFixedToInt(tr[1]), xFixedToInt(bl[0]), xFixedToInt(bl[1]),
  346. xFixedToInt(br[0]), xFixedToInt(br[1]),
  347. pbox->x1, pbox->y1, pbox->x2, pbox->y1, pbox->x1, pbox->y2,
  348. pbox->x2, pbox->y2);
  349. ADD_VERTEX_IF_INSIDE(tl);
  350. ADD_VERTEX_IF_INSIDE(bl);
  351. ADD_VERTEX_IF_INSIDE(tr);
  352. ADD_VERTEX_IF_INSIDE(br);
  353. /*Trap's left edge cut Rect. */
  354. if (DEBUG_CLIP_VTX)
  355. ErrorF("Trap's left edge cut Rect\n");
  356. CACULATE_CUT_VERTEX(left_cut_top, 1, FALSE, IntToxFixed(pbox->y1),
  357. (&trap->left));
  358. ADD_VERTEX_IF_INSIDE(left_cut_top);
  359. if (!IS_TRAP_EDGE_VERTICAL((&trap->left))) {
  360. CACULATE_CUT_VERTEX(left_cut_left, 0, FALSE, IntToxFixed(pbox->x1),
  361. (&trap->left));
  362. ADD_VERTEX_IF_INSIDE(left_cut_left);
  363. }
  364. CACULATE_CUT_VERTEX(left_cut_bottom, 1, FALSE, IntToxFixed(pbox->y2),
  365. (&trap->left));
  366. ADD_VERTEX_IF_INSIDE(left_cut_bottom);
  367. if (!IS_TRAP_EDGE_VERTICAL((&trap->left))) {
  368. CACULATE_CUT_VERTEX(left_cut_right, 0, FALSE, IntToxFixed(pbox->x2),
  369. (&trap->left));
  370. ADD_VERTEX_IF_INSIDE(left_cut_right);
  371. }
  372. /*Trap's right edge cut Rect. */
  373. if (DEBUG_CLIP_VTX)
  374. ErrorF("Trap's right edge cut Rect\n");
  375. CACULATE_CUT_VERTEX(right_cut_top, 1, TRUE, IntToxFixed(pbox->y1),
  376. (&trap->right));
  377. ADD_VERTEX_IF_INSIDE(right_cut_top);
  378. if (!IS_TRAP_EDGE_VERTICAL((&trap->right))) {
  379. CACULATE_CUT_VERTEX(right_cut_left, 0, TRUE, IntToxFixed(pbox->x1),
  380. (&trap->right));
  381. ADD_VERTEX_IF_INSIDE(right_cut_left);
  382. }
  383. CACULATE_CUT_VERTEX(right_cut_bottom, 1, TRUE, IntToxFixed(pbox->y2),
  384. (&trap->right));
  385. ADD_VERTEX_IF_INSIDE(right_cut_bottom);
  386. if (!IS_TRAP_EDGE_VERTICAL((&trap->right))) {
  387. CACULATE_CUT_VERTEX(right_cut_right, 0, TRUE, IntToxFixed(pbox->x2),
  388. (&trap->right));
  389. ADD_VERTEX_IF_INSIDE(right_cut_right);
  390. }
  391. /* Trap's top cut Left and Right of rect. */
  392. if (DEBUG_CLIP_VTX)
  393. ErrorF("Trap's top cut Left and Right of rect\n");
  394. tmp[0] = IntToxFixed(pbox->x1);
  395. tmp[1] = trap->top;
  396. ADD_VERTEX_IF_INSIDE(tmp);
  397. tmp[0] = IntToxFixed(pbox->x2);
  398. tmp[1] = trap->top;
  399. ADD_VERTEX_IF_INSIDE(tmp);
  400. /* Trap's bottom cut Left and Right of rect. */
  401. if (DEBUG_CLIP_VTX)
  402. ErrorF("Trap's bottom cut Left and Right of rect\n");
  403. tmp[0] = IntToxFixed(pbox->x1);
  404. tmp[1] = trap->bottom;
  405. ADD_VERTEX_IF_INSIDE(tmp);
  406. tmp[0] = IntToxFixed(pbox->x2);
  407. tmp[1] = trap->bottom;
  408. ADD_VERTEX_IF_INSIDE(tmp);
  409. /* The orginal 4 vertex of rect. */
  410. if (DEBUG_CLIP_VTX)
  411. ErrorF("The orginal 4 vertex of rect\n");
  412. tmp[0] = IntToxFixed(pbox->x1);
  413. tmp[1] = IntToxFixed(pbox->y1);
  414. ADD_VERTEX_IF_INSIDE(tmp);
  415. tmp[0] = IntToxFixed(pbox->x1);
  416. tmp[1] = IntToxFixed(pbox->y2);
  417. ADD_VERTEX_IF_INSIDE(tmp);
  418. tmp[0] = IntToxFixed(pbox->x2);
  419. tmp[1] = IntToxFixed(pbox->y2);
  420. ADD_VERTEX_IF_INSIDE(tmp);
  421. tmp[0] = IntToxFixed(pbox->x2);
  422. tmp[1] = IntToxFixed(pbox->y1);
  423. ADD_VERTEX_IF_INSIDE(tmp);
  424. if (DEBUG_CLIP_VTX) {
  425. ErrorF("\nThe candidate vertex number is %d\n", vertex_num / 2);
  426. for (i = 0; i < vertex_num / 2; i++) {
  427. ErrorF("(%d, %d) ", tmp_vtx[2 * i], tmp_vtx[2 * i + 1]);
  428. }
  429. ErrorF("\n");
  430. }
  431. /* Sort the vertex by X and then Y. */
  432. for (i = 0; i < vertex_num / 2; i++) {
  433. int j;
  434. for (j = 0; j < vertex_num / 2 - i - 1; j++) {
  435. if (tmp_vtx[2 * j] > tmp_vtx[2 * (j + 1)]
  436. || (tmp_vtx[2 * j] == tmp_vtx[2 * (j + 1)]
  437. && tmp_vtx[2 * j + 1] > tmp_vtx[2 * (j + 1) + 1])) {
  438. tmp[0] = tmp_vtx[2 * j];
  439. tmp[1] = tmp_vtx[2 * j + 1];
  440. tmp_vtx[2 * j] = tmp_vtx[2 * (j + 1)];
  441. tmp_vtx[2 * j + 1] = tmp_vtx[2 * (j + 1) + 1];
  442. tmp_vtx[2 * (j + 1)] = tmp[0];
  443. tmp_vtx[2 * (j + 1) + 1] = tmp[1];
  444. }
  445. }
  446. }
  447. if (DEBUG_CLIP_VTX) {
  448. ErrorF("\nAfter sort vertex number is:\n");
  449. for (i = 0; i < vertex_num / 2; i++) {
  450. ErrorF("(%d, %d) ", tmp_vtx[2 * i], tmp_vtx[2 * i + 1]);
  451. }
  452. ErrorF("\n");
  453. }
  454. memset(vertex, -1, 2 * 6);
  455. *num = 0;
  456. for (i = 0; i < vertex_num / 2; i++) {
  457. if (*num > 0 && vertex[2 * (*num - 1)] == tmp_vtx[2 * i]
  458. && vertex[2 * (*num - 1) + 1] == tmp_vtx[2 * i + 1]) {
  459. /*same vertex. */
  460. if (DEBUG_CLIP_VTX)
  461. ErrorF("X Point:(%d, %d) discard\n",
  462. tmp_vtx[2 * i], tmp_vtx[2 * i + 1]);
  463. continue;
  464. }
  465. (*num)++;
  466. if (*num > 6) {
  467. if (DEBUG_CLIP_VTX)
  468. FatalError("Trapezoid clip with Rect can never have vtx"
  469. "number bigger than 6\n");
  470. else {
  471. ErrorF("Trapezoid clip with Rect can never have vtx"
  472. "number bigger than 6\n");
  473. *num = 6;
  474. break;
  475. }
  476. }
  477. vertex[2 * (*num - 1)] = tmp_vtx[2 * i];
  478. vertex[2 * (*num - 1) + 1] = tmp_vtx[2 * i + 1];
  479. if (DEBUG_CLIP_VTX)
  480. ErrorF("@ Point:(%d, %d) select, num now is %d\n",
  481. tmp_vtx[2 * i], tmp_vtx[2 * i + 1], *num);
  482. }
  483. /* Now we need to arrange the vtx in the polygon's counter-clockwise
  484. order. We first select the left and top point as the start point and
  485. sort every vtx by the slope from vtx to the start vtx. */
  486. for (i = 1; i < *num; i++) {
  487. tmp_vtx_slope[i] = (vertex[2 * i] != vertex[0] ?
  488. (float) (vertex[2 * i + 1] -
  489. vertex[1]) / (float) (vertex[2 * i] -
  490. vertex[0])
  491. : (float) INT_MAX);
  492. }
  493. if (DEBUG_CLIP_VTX) {
  494. ErrorF("\nvtx number: %d, VTX and slope:\n", *num);
  495. for (i = 0; i < *num; i++) {
  496. ErrorF("(%d, %d):%f ",
  497. vertex[2 * i], vertex[2 * i + 1], tmp_vtx_slope[i]);
  498. }
  499. ErrorF("\n");
  500. }
  501. /* Sort the vertex by slope. */
  502. for (i = 0; i < *num - 1; i++) {
  503. int j;
  504. float tmp_slope;
  505. for (j = 1; j < *num - i - 1; j++) {
  506. if (tmp_vtx_slope[j] < tmp_vtx_slope[j + 1]) {
  507. tmp_slope = tmp_vtx_slope[j];
  508. tmp_vtx_slope[j] = tmp_vtx_slope[j + 1];
  509. tmp_vtx_slope[j + 1] = tmp_slope;
  510. tmp[0] = vertex[2 * j];
  511. tmp[1] = vertex[2 * j + 1];
  512. vertex[2 * j] = vertex[2 * (j + 1)];
  513. vertex[2 * j + 1] = vertex[2 * (j + 1) + 1];
  514. vertex[2 * (j + 1)] = tmp[0];
  515. vertex[2 * (j + 1) + 1] = tmp[1];
  516. }
  517. }
  518. }
  519. if (DEBUG_CLIP_VTX) {
  520. ErrorF("\nBefore return, vtx number: %d, VTX and slope:\n", *num);
  521. for (i = 0; i < *num; i++) {
  522. ErrorF("(%d, %d):%f ",
  523. vertex[2 * i], vertex[2 * i + 1], tmp_vtx_slope[i]);
  524. }
  525. ErrorF("\n");
  526. }
  527. return TRUE;
  528. }
  529. static void *
  530. glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
  531. {
  532. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  533. int stride;
  534. int vert_size;
  535. char *vbo_offset;
  536. void *vb;
  537. glamor_priv->render_nr_verts = 0;
  538. /* For GLAMOR_VERTEX_POS */
  539. glamor_priv->vb_stride = 2 * sizeof(float);
  540. /* For GLAMOR_GLAMOR_VERTEX_SOURCE */
  541. glamor_priv->vb_stride += 2 * sizeof(float);
  542. /* For GLAMOR_VERTEX_TOP_BOTTOM */
  543. glamor_priv->vb_stride += 2 * sizeof(float);
  544. /* For GLAMOR_VERTEX_LEFT_PARAM */
  545. glamor_priv->vb_stride += 4 * sizeof(float);
  546. /* For GLAMOR_VERTEX_RIGHT_PARAM */
  547. glamor_priv->vb_stride += 4 * sizeof(float);
  548. vert_size = n_verts * glamor_priv->vb_stride;
  549. glamor_make_current(glamor_priv);
  550. glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
  551. glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
  552. glDisableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM);
  553. glDisableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
  554. glDisableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
  555. vb = glamor_get_vbo_space(screen, vert_size, &vbo_offset);
  556. /* Set the vertex pointer. */
  557. glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
  558. GL_FALSE, glamor_priv->vb_stride,
  559. vbo_offset);
  560. glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
  561. stride = 2;
  562. glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
  563. GL_FALSE, glamor_priv->vb_stride,
  564. vbo_offset + stride * sizeof(float));
  565. glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
  566. stride += 2;
  567. glVertexAttribPointer(GLAMOR_VERTEX_TOP_BOTTOM, 2, GL_FLOAT,
  568. GL_FALSE, glamor_priv->vb_stride,
  569. vbo_offset + stride * sizeof(float));
  570. glEnableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM);
  571. stride += 2;
  572. glVertexAttribPointer(GLAMOR_VERTEX_LEFT_PARAM, 4, GL_FLOAT,
  573. GL_FALSE, glamor_priv->vb_stride,
  574. vbo_offset + stride * sizeof(float));
  575. glEnableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
  576. stride += 4;
  577. glVertexAttribPointer(GLAMOR_VERTEX_RIGHT_PARAM, 4, GL_FLOAT,
  578. GL_FALSE, glamor_priv->vb_stride,
  579. vbo_offset + stride * sizeof(float));
  580. glEnableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
  581. return vb;
  582. }
  583. static Bool
  584. _glamor_trapezoids_with_shader(CARD8 op,
  585. PicturePtr src, PicturePtr dst,
  586. PictFormatPtr mask_format, INT16 x_src,
  587. INT16 y_src, int ntrap, xTrapezoid * traps)
  588. {
  589. ScreenPtr screen = dst->pDrawable->pScreen;
  590. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  591. struct shader_key key;
  592. glamor_composite_shader *shader = NULL;
  593. struct blendinfo op_info;
  594. PictFormatShort saved_source_format = 0;
  595. PixmapPtr source_pixmap = NULL;
  596. PixmapPtr dest_pixmap = NULL;
  597. glamor_pixmap_private *source_pixmap_priv = NULL;
  598. glamor_pixmap_private *dest_pixmap_priv = NULL;
  599. glamor_pixmap_private *temp_src_priv = NULL;
  600. int x_temp_src, y_temp_src;
  601. int src_width, src_height;
  602. int source_x_off, source_y_off;
  603. GLfloat src_xscale = 1, src_yscale = 1;
  604. int x_dst, y_dst;
  605. int dest_x_off, dest_y_off;
  606. GLfloat dst_xscale, dst_yscale;
  607. BoxRec bounds;
  608. PicturePtr temp_src = src;
  609. int vert_stride = 3;
  610. int ntriangle_per_loop;
  611. int nclip_rect;
  612. int mclip_rect;
  613. int clip_processed;
  614. int clipped_vtx[6 * 2];
  615. RegionRec region;
  616. BoxPtr box = NULL;
  617. BoxPtr pbox = NULL;
  618. int traps_count = 0;
  619. int traps_not_completed = 0;
  620. xTrapezoid *ptrap = NULL;
  621. int nbox;
  622. float src_matrix[9];
  623. Bool ret = FALSE;
  624. /* If a mask format wasn't provided, we get to choose, but behavior should
  625. * be as if there was no temporary mask the traps were accumulated into.
  626. */
  627. if (!mask_format) {
  628. if (dst->polyEdge == PolyEdgeSharp)
  629. mask_format = PictureMatchFormat(screen, 1, PICT_a1);
  630. else
  631. mask_format = PictureMatchFormat(screen, 8, PICT_a8);
  632. for (; ntrap; ntrap--, traps++)
  633. glamor_trapezoids(op, src, dst, mask_format, x_src,
  634. y_src, 1, traps);
  635. return TRUE;
  636. }
  637. miTrapezoidBounds(ntrap, traps, &bounds);
  638. DEBUGF("The bounds for all traps is: bounds.x1 = %d, bounds.x2 = %d, "
  639. "bounds.y1 = %d, bounds.y2 = %d\n", bounds.x1, bounds.x2,
  640. bounds.y1, bounds.y2);
  641. /* No area need to render. */
  642. if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
  643. return TRUE;
  644. dest_pixmap = glamor_get_drawable_pixmap(dst->pDrawable);
  645. dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap);
  646. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)
  647. || dest_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
  648. /* Currently. Always fallback to cpu if destination is in CPU memory. */
  649. ret = FALSE;
  650. DEBUGF("dst pixmap has no FBO.\n");
  651. goto TRAPEZOID_OUT;
  652. }
  653. if (src->pDrawable) {
  654. source_pixmap = glamor_get_drawable_pixmap(src->pDrawable);
  655. source_pixmap_priv = glamor_get_pixmap_private(source_pixmap);
  656. temp_src_priv = source_pixmap_priv;
  657. if (source_pixmap_priv
  658. && (source_pixmap_priv->type == GLAMOR_DRM_ONLY
  659. || source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE)) {
  660. ret = FALSE;
  661. goto TRAPEZOID_OUT;
  662. }
  663. }
  664. x_dst = bounds.x1;
  665. y_dst = bounds.y1;
  666. src_width = bounds.x2 - bounds.x1;
  667. src_height = bounds.y2 - bounds.y1;
  668. x_temp_src = x_src + bounds.x1 - (traps[0].left.p1.x >> 16);
  669. y_temp_src = y_src + bounds.y1 - (traps[0].left.p1.y >> 16);
  670. if ((!src->pDrawable && (src->pSourcePict->type != SourcePictTypeSolidFill)) //1. The Gradient case.
  671. /* 2. Has no fbo but can upload. */
  672. || (src->pDrawable && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv)
  673. && ((src_width * src_height * 4 <
  674. source_pixmap->drawable.width * source_pixmap->drawable.height)
  675. || !glamor_check_fbo_size(glamor_priv,
  676. source_pixmap->drawable.width,
  677. source_pixmap->drawable.height)))) {
  678. if (!glamor_check_fbo_size(glamor_priv, src_width, src_height)) {
  679. ret = FALSE;
  680. goto TRAPEZOID_OUT;
  681. }
  682. temp_src = glamor_convert_gradient_picture(screen, src,
  683. x_src, y_src,
  684. src_width, src_height);
  685. if (!temp_src) {
  686. temp_src = src;
  687. ret = FALSE;
  688. DEBUGF("Convert gradient picture failed\n");
  689. goto TRAPEZOID_OUT;
  690. }
  691. temp_src_priv =
  692. glamor_get_pixmap_private((PixmapPtr) temp_src->pDrawable);
  693. x_temp_src = y_temp_src = 0;
  694. }
  695. x_dst += dst->pDrawable->x;
  696. y_dst += dst->pDrawable->y;
  697. if (temp_src->pDrawable) {
  698. x_temp_src += temp_src->pDrawable->x;
  699. y_temp_src += temp_src->pDrawable->y;
  700. }
  701. if (!miComputeCompositeRegion(&region,
  702. temp_src, NULL, dst,
  703. x_temp_src, y_temp_src,
  704. 0, 0, x_dst, y_dst, src_width, src_height)) {
  705. DEBUGF("All the regions are clipped out, do nothing\n");
  706. goto TRAPEZOID_OUT;
  707. }
  708. glamor_make_current(glamor_priv);
  709. box = REGION_RECTS(&region);
  710. nbox = REGION_NUM_RECTS(&region);
  711. pbox = box;
  712. ret = glamor_composite_choose_shader(op, temp_src, NULL, dst,
  713. temp_src_priv, NULL, dest_pixmap_priv,
  714. &key, &shader, &op_info,
  715. &saved_source_format);
  716. if (ret == FALSE) {
  717. DEBUGF("can not set the shader program for composite\n");
  718. goto TRAPEZOID_RESET_GL;
  719. }
  720. glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv);
  721. glamor_composite_set_shader_blend(dest_pixmap_priv, &key, shader, &op_info);
  722. glamor_priv->has_source_coords = key.source != SHADER_SOURCE_SOLID;
  723. glamor_priv->has_mask_coords = (key.mask != SHADER_MASK_NONE &&
  724. key.mask != SHADER_MASK_SOLID);
  725. glamor_get_drawable_deltas(dst->pDrawable, dest_pixmap,
  726. &dest_x_off, &dest_y_off);
  727. pixmap_priv_get_dest_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale);
  728. if (glamor_priv->has_source_coords) {
  729. source_pixmap = glamor_get_drawable_pixmap(temp_src->pDrawable);
  730. source_pixmap_priv = glamor_get_pixmap_private(source_pixmap);
  731. glamor_get_drawable_deltas(temp_src->pDrawable,
  732. source_pixmap, &source_x_off, &source_y_off);
  733. pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, &src_yscale);
  734. glamor_picture_get_matrixf(temp_src, src_matrix);
  735. vert_stride += 3;
  736. }
  737. if (glamor_priv->has_mask_coords) {
  738. DEBUGF("Should never have mask coords here!\n");
  739. ret = FALSE;
  740. goto TRAPEZOID_RESET_GL;
  741. }
  742. /* A trapezoid clip with a rectangle will at most generate a hexagon,
  743. which can be devided into 4 triangles to render. */
  744. ntriangle_per_loop =
  745. (vert_stride * nbox * ntrap * 4) >
  746. GLAMOR_COMPOSITE_VBO_VERT_CNT ? (GLAMOR_COMPOSITE_VBO_VERT_CNT /
  747. vert_stride) : nbox * ntrap * 4;
  748. ntriangle_per_loop = (ntriangle_per_loop / 4) * 4;
  749. nclip_rect = nbox;
  750. while (nclip_rect) {
  751. float *vb;
  752. mclip_rect = (nclip_rect * ntrap * 4) > ntriangle_per_loop ?
  753. (ntriangle_per_loop / (4 * ntrap)) : nclip_rect;
  754. if (!mclip_rect) { /* Maybe too many traps. */
  755. mclip_rect = 1;
  756. ptrap = traps;
  757. traps_count = ntriangle_per_loop / 4;
  758. traps_not_completed = ntrap - traps_count;
  759. }
  760. else {
  761. traps_count = ntrap;
  762. ptrap = traps;
  763. traps_not_completed = 0;
  764. }
  765. NTRAPS_LOOP_AGAIN:
  766. vb = glamor_setup_composite_vbo(screen,
  767. (mclip_rect * traps_count *
  768. 4 * vert_stride));
  769. clip_processed = mclip_rect;
  770. while (mclip_rect--) {
  771. while (traps_count--) {
  772. int vtx_num;
  773. int i;
  774. float vertices[3 * 2], source_texcoords[3 * 2];
  775. DEBUGF
  776. ("In loop of render trapezoid, nclip_rect = %d, mclip_rect = %d, "
  777. "clip_processed = %d, traps_count = %d, traps_not_completed = %d\n",
  778. nclip_rect, mclip_rect, clip_processed, traps_count,
  779. traps_not_completed);
  780. if (_glamor_clip_trapezoid_vertex
  781. (ptrap, pbox, clipped_vtx, &vtx_num)) {
  782. for (i = 0; i < vtx_num - 2; i++) {
  783. int clipped_vtx_tmp[3 * 2];
  784. clipped_vtx_tmp[0] = clipped_vtx[0];
  785. clipped_vtx_tmp[1] = clipped_vtx[1];
  786. clipped_vtx_tmp[2] = clipped_vtx[(i + 1) * 2];
  787. clipped_vtx_tmp[3] = clipped_vtx[(i + 1) * 2 + 1];
  788. clipped_vtx_tmp[4] = clipped_vtx[(i + 2) * 2];
  789. clipped_vtx_tmp[5] = clipped_vtx[(i + 2) * 2 + 1];
  790. glamor_set_normalize_tri_vcoords(dst_xscale, dst_yscale,
  791. clipped_vtx_tmp,
  792. glamor_priv->yInverted,
  793. vertices);
  794. DEBUGF("vertices of triangle: (%f X %f), (%f X %f), "
  795. "(%f X %f)\n", vertices[0], vertices[1],
  796. vertices[2], vertices[3], vertices[4],
  797. vertices[5]);
  798. if (key.source != SHADER_SOURCE_SOLID) {
  799. if (src->transform) {
  800. glamor_set_transformed_normalize_tri_tcoords
  801. (source_pixmap_priv, src_matrix, src_xscale,
  802. src_yscale, clipped_vtx_tmp,
  803. glamor_priv->yInverted, source_texcoords);
  804. }
  805. else {
  806. glamor_set_normalize_tri_tcoords(src_xscale,
  807. src_yscale,
  808. clipped_vtx_tmp,
  809. glamor_priv->
  810. yInverted,
  811. source_texcoords);
  812. }
  813. DEBUGF("source_texcoords of triangle: (%f X %f), "
  814. "(%f X %f), (%f X %f)\n",
  815. source_texcoords[0], source_texcoords[1],
  816. source_texcoords[2], source_texcoords[3],
  817. source_texcoords[4], source_texcoords[5]);
  818. }
  819. glamor_emit_composite_triangle(screen, vb,
  820. source_texcoords,
  821. NULL, vertices);
  822. vb += 3 * glamor_priv->vb_stride / sizeof(float);
  823. }
  824. }
  825. ptrap++;
  826. }
  827. if (traps_not_completed) { /* one loop of ntraps not completed */
  828. mclip_rect = 1;
  829. traps_count = traps_not_completed > (ntriangle_per_loop / 4) ?
  830. (ntriangle_per_loop / 4) : traps_not_completed;
  831. traps_not_completed -= traps_count;
  832. glamor_flush_composite_triangles(screen);
  833. goto NTRAPS_LOOP_AGAIN;
  834. }
  835. else {
  836. ptrap = traps;
  837. traps_count = ntrap;
  838. }
  839. pbox++;
  840. }
  841. glamor_flush_composite_triangles(screen);
  842. nclip_rect -= clip_processed;
  843. }
  844. ret = TRUE;
  845. TRAPEZOID_RESET_GL:
  846. glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
  847. glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
  848. glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
  849. glDisable(GL_BLEND);
  850. TRAPEZOID_OUT:
  851. if (box) {
  852. REGION_UNINIT(dst->pDrawable->pScreen, &region);
  853. }
  854. if (temp_src != src) {
  855. FreePicture(temp_src, 0);
  856. }
  857. else {
  858. if (saved_source_format) {
  859. src->format = saved_source_format;
  860. }
  861. }
  862. return ret;
  863. }
  864. void
  865. glamor_init_trapezoid_shader(ScreenPtr screen)
  866. {
  867. glamor_screen_private *glamor_priv;
  868. GLint fs_prog, vs_prog;
  869. const char *trapezoid_vs =
  870. GLAMOR_DEFAULT_PRECISION
  871. "attribute vec4 v_position;\n"
  872. "attribute vec2 v_texcoord;\n"
  873. /* v_top_bottom, v_left_param and v_right_param contain the
  874. constant value for all the vertex of one rect. Using uniform
  875. is more suitable but we need to reset the uniform variables
  876. for every rect rendering and can not use the vbo, which causes
  877. performance loss. So we set these attributes to same value
  878. for every vertex of one rect and so it is also a constant in FS */
  879. "attribute vec2 v_top_bottom;\n"
  880. "attribute vec4 v_left_param;\n"
  881. "attribute vec4 v_right_param;\n"
  882. "\n"
  883. "varying vec2 source_texture;\n"
  884. "varying float trap_top;\n"
  885. "varying float trap_bottom;\n"
  886. "varying float trap_left_x;\n"
  887. "varying float trap_left_y;\n"
  888. "varying float trap_left_slope;\n"
  889. "varying float trap_left_vertical_f;\n"
  890. "varying float trap_right_x;\n"
  891. "varying float trap_right_y;\n"
  892. "varying float trap_right_slope;\n"
  893. "varying float trap_right_vertical_f;\n"
  894. "\n"
  895. "void main()\n"
  896. "{\n"
  897. " gl_Position = v_position;\n"
  898. " source_texture = v_texcoord.xy;\n"
  899. " trap_top = v_top_bottom.x;\n"
  900. " trap_bottom = v_top_bottom.y;\n"
  901. " \n"
  902. " trap_left_x = v_left_param.x;\n"
  903. " trap_left_y = v_left_param.y;\n"
  904. " trap_left_slope = v_left_param.z;\n"
  905. " trap_left_vertical_f = v_left_param.w;\n"
  906. " \n"
  907. " trap_right_x = v_right_param.x;\n"
  908. " trap_right_y = v_right_param.y;\n"
  909. " trap_right_slope = v_right_param.z;\n"
  910. " trap_right_vertical_f = v_right_param.w;\n"
  911. "}\n";
  912. /*
  913. * Because some GL fill function do not support the MultSample
  914. * anti-alias, we need to do the MSAA here. This manner like
  915. * pixman, will caculate the value of area in trapezoid dividing
  916. * the totol area for each pixel, as follow:
  917. |
  918. ----+------------------------------------------------------>
  919. |
  920. | -------------
  921. | / \
  922. | / \
  923. | / \
  924. | / +----------------+
  925. | / |.....\ |
  926. | / |......\ |
  927. | / |.......\ |
  928. | / |........\ |
  929. | /-------------------+---------\ |
  930. | | |
  931. | | |
  932. | +----------------+
  933. |
  934. \|/
  935. */
  936. const char *trapezoid_fs =
  937. GLAMOR_DEFAULT_PRECISION
  938. "varying vec2 source_texture; \n"
  939. "varying float trap_top; \n"
  940. "varying float trap_bottom; \n"
  941. "varying float trap_left_x; \n"
  942. "varying float trap_left_y; \n"
  943. "varying float trap_left_slope; \n"
  944. "varying float trap_left_vertical_f; \n"
  945. "varying float trap_right_x; \n"
  946. "varying float trap_right_y; \n"
  947. "varying float trap_right_slope; \n"
  948. "varying float trap_right_vertical_f; \n"
  949. "float x_per_pix = 1.0;"
  950. "float y_per_pix = 1.0;"
  951. "\n"
  952. "float get_alpha_val() \n"
  953. "{ \n"
  954. " float x_up_cut_left; \n"
  955. " float x_bottom_cut_left; \n"
  956. " float x_up_cut_right; \n"
  957. " float x_bottom_cut_right; \n"
  958. " bool trap_left_vertical;\n"
  959. " bool trap_right_vertical;\n"
  960. " if (abs(trap_left_vertical_f - 1.0) <= 0.0001)\n"
  961. " trap_left_vertical = true;\n"
  962. " else\n"
  963. " trap_left_vertical = false;\n"
  964. " if (abs(trap_right_vertical_f - 1.0) <= 0.0001)\n"
  965. " trap_right_vertical = true;\n"
  966. " else\n"
  967. " trap_right_vertical = false;\n"
  968. " \n"
  969. " if(trap_left_vertical == true) { \n"
  970. " x_up_cut_left = trap_left_x; \n"
  971. " x_bottom_cut_left = trap_left_x; \n"
  972. " } else { \n"
  973. " x_up_cut_left = trap_left_x \n"
  974. " + (source_texture.y - y_per_pix/2.0 - trap_left_y) \n"
  975. " / trap_left_slope; \n"
  976. " x_bottom_cut_left = trap_left_x \n"
  977. " + (source_texture.y + y_per_pix/2.0 - trap_left_y) \n"
  978. " / trap_left_slope; \n"
  979. " } \n"
  980. " \n"
  981. " if(trap_right_vertical == true) { \n"
  982. " x_up_cut_right = trap_right_x; \n"
  983. " x_bottom_cut_right = trap_right_x; \n"
  984. " } else { \n"
  985. " x_up_cut_right = trap_right_x \n"
  986. " + (source_texture.y - y_per_pix/2.0 - trap_right_y) \n"
  987. " / trap_right_slope; \n"
  988. " x_bottom_cut_right = trap_right_x \n"
  989. " + (source_texture.y + y_per_pix/2.0 - trap_right_y) \n"
  990. " / trap_right_slope; \n"
  991. " } \n"
  992. " \n"
  993. " if((x_up_cut_left <= source_texture.x - x_per_pix/2.0) && \n"
  994. " (x_bottom_cut_left <= source_texture.x - x_per_pix/2.0) && \n"
  995. " (x_up_cut_right >= source_texture.x + x_per_pix/2.0) && \n"
  996. " (x_bottom_cut_right >= source_texture.x + x_per_pix/2.0) && \n"
  997. " (trap_top <= source_texture.y - y_per_pix/2.0) && \n"
  998. " (trap_bottom >= source_texture.y + y_per_pix/2.0)) { \n"
  999. // The complete inside case.
  1000. " return 1.0; \n"
  1001. " } else if((trap_top > source_texture.y + y_per_pix/2.0) || \n"
  1002. " (trap_bottom < source_texture.y - y_per_pix/2.0)) { \n"
  1003. // The complete outside. Above the top or Below the bottom.
  1004. " return 0.0; \n"
  1005. " } else { \n"
  1006. " if((x_up_cut_right < source_texture.x - x_per_pix/2.0 && \n"
  1007. " x_bottom_cut_right < source_texture.x - x_per_pix/2.0) \n"
  1008. " || (x_up_cut_left > source_texture.x + x_per_pix/2.0 && \n"
  1009. " x_bottom_cut_left > source_texture.x + x_per_pix/2.0)) { \n"
  1010. // The complete outside. At Left or Right of the trapezoide.
  1011. " return 0.0; \n"
  1012. " } \n"
  1013. " } \n"
  1014. // Get here, the pix is partly inside the trapezoid.
  1015. " { \n"
  1016. " float percent = 0.0; \n"
  1017. " float up = (source_texture.y - y_per_pix/2.0) >= trap_top ? \n"
  1018. " (source_texture.y - y_per_pix/2.0) : trap_top; \n"
  1019. " float bottom = (source_texture.y + y_per_pix/2.0) <= trap_bottom ? \n"
  1020. " (source_texture.y + y_per_pix/2.0) : trap_bottom; \n"
  1021. " float left = source_texture.x - x_per_pix/2.0; \n"
  1022. " float right = source_texture.x + x_per_pix/2.0; \n"
  1023. " \n"
  1024. " percent = (bottom - up) / y_per_pix; \n"
  1025. " \n"
  1026. " if(trap_left_vertical == true) { \n"
  1027. " if(trap_left_x > source_texture.x - x_per_pix/2.0 && \n"
  1028. " trap_left_x < source_texture.x + x_per_pix/2.0) \n"
  1029. " left = trap_left_x; \n"
  1030. " } \n"
  1031. " if(trap_right_vertical == true) { \n"
  1032. " if(trap_right_x > source_texture.x - x_per_pix/2.0 && \n"
  1033. " trap_right_x < source_texture.x + x_per_pix/2.0) \n"
  1034. " right = trap_right_x; \n"
  1035. " } \n"
  1036. " if((up >= bottom) || (left >= right)) \n"
  1037. " return 0.0; \n"
  1038. " \n"
  1039. " percent = percent * ((right - left)/x_per_pix); \n"
  1040. " if(trap_left_vertical == true && trap_right_vertical == true) \n"
  1041. " return percent; \n"
  1042. " \n"
  1043. " if(trap_left_vertical != true) { \n"
  1044. " float area; \n"
  1045. // the slope should never be 0.0 here
  1046. " float up_x = trap_left_x + (up - trap_left_y)/trap_left_slope; \n"
  1047. " float bottom_x = trap_left_x + (bottom - trap_left_y)/trap_left_slope; \n"
  1048. " if(trap_left_slope < 0.0 && up_x > left) { \n"
  1049. /* case 1
  1050. |
  1051. ----+------------------------------------->
  1052. | /
  1053. | /
  1054. | +---/--------+
  1055. | | /.........|
  1056. | | /..........|
  1057. | |/...........|
  1058. | /............|
  1059. | /|............|
  1060. | +------------+
  1061. |
  1062. \|/
  1063. */
  1064. " float left_y = trap_left_y + trap_left_slope*(left - trap_left_x); \n"
  1065. " if((up_x > left) && (left_y > up)) { \n"
  1066. " area = 0.5 * (up_x - left) * (left_y - up); \n"
  1067. " if(up_x > right) { \n"
  1068. " float right_y = trap_left_y \n"
  1069. " + trap_left_slope*(right - trap_left_x); \n"
  1070. " area = area - 0.5 * (up_x - right) * (right_y - up); \n"
  1071. " } \n"
  1072. " if(left_y > bottom) { \n"
  1073. " area = area - 0.5 * (bottom_x - left) * (left_y - bottom); \n"
  1074. " } \n"
  1075. " } else { \n"
  1076. " area = 0.0; \n"
  1077. " } \n"
  1078. " percent = percent * (1.0 - (area/((right-left)*(bottom-up)))); \n"
  1079. " } else if(trap_left_slope > 0.0 && bottom_x > left) { \n"
  1080. /* case 2
  1081. |
  1082. ----+------------------------------------->
  1083. | \
  1084. | \
  1085. | +\-----------+
  1086. | | \..........|
  1087. | | \.........|
  1088. | | \........|
  1089. | | \.......|
  1090. | | \......|
  1091. | +------\-----+
  1092. | \
  1093. | \
  1094. \|/
  1095. */
  1096. " float right_y = trap_left_y + trap_left_slope*(right - trap_left_x); \n"
  1097. " if((up_x < right) && (right_y > up)) { \n"
  1098. " area = 0.5 * (right - up_x) * (right_y - up); \n"
  1099. " if(up_x < left) { \n"
  1100. " float left_y = trap_left_y \n"
  1101. " + trap_left_slope*(left - trap_left_x); \n"
  1102. " area = area - 0.5 * (left - up_x) * (left_y - up); \n"
  1103. " } \n"
  1104. " if(right_y > bottom) { \n"
  1105. " area = area - 0.5 * (right - bottom_x) * (right_y - bottom); \n"
  1106. " } \n"
  1107. " } else { \n"
  1108. " area = 0.0; \n"
  1109. " } \n"
  1110. " percent = percent * (area/((right-left)*(bottom-up))); \n"
  1111. " } \n"
  1112. " } \n"
  1113. " \n"
  1114. " if(trap_right_vertical != true) { \n"
  1115. " float area; \n"
  1116. // the slope should never be 0.0 here
  1117. " float up_x = trap_right_x + (up - trap_right_y)/trap_right_slope; \n"
  1118. " float bottom_x = trap_right_x + (bottom - trap_right_y)/trap_right_slope; \n"
  1119. " if(trap_right_slope < 0.0 && bottom_x < right) { \n"
  1120. /* case 3
  1121. |
  1122. ----+------------------------------------->
  1123. | /
  1124. | +--------/---+
  1125. | |......./ |
  1126. | |....../ |
  1127. | |...../ |
  1128. | |..../ |
  1129. | |.../ |
  1130. | +--/---------+
  1131. | /
  1132. |
  1133. \|/
  1134. */
  1135. " float left_y = trap_right_y + trap_right_slope*(left - trap_right_x); \n"
  1136. " if((up_x > left) && (left_y > up)) { \n"
  1137. " area = 0.5 * (up_x - left) * (left_y - up); \n"
  1138. " if(up_x > right) { \n"
  1139. " float right_y = trap_right_y \n"
  1140. " + trap_right_slope*(right - trap_right_x); \n"
  1141. " area = area - 0.5 * (up_x - right) * (right_y - up); \n"
  1142. " } \n"
  1143. " if(left_y > bottom) { \n"
  1144. " area = area - 0.5 * (bottom_x - left) * (left_y - bottom); \n"
  1145. " } \n"
  1146. " } else { \n"
  1147. " area = 0.0; \n"
  1148. " } \n"
  1149. " percent = percent * (area/((right-left)*(bottom-up))); \n"
  1150. " } else if(trap_right_slope > 0.0 && up_x < right) { \n"
  1151. /* case 4
  1152. |
  1153. ----+------------------------------------->
  1154. | \
  1155. | +--------\---+
  1156. | |.........\ |
  1157. | |..........\ |
  1158. | |...........\|
  1159. | |............\
  1160. | |............|\
  1161. | +------------+ \
  1162. | \
  1163. |
  1164. \|/
  1165. */
  1166. " float right_y = trap_right_y + trap_right_slope*(right - trap_right_x); \n"
  1167. " if((up_x < right) && (right_y > up)) { \n"
  1168. " area = 0.5 * (right - up_x) * (right_y - up); \n"
  1169. " if(up_x < left) { \n"
  1170. " float left_y = trap_right_y \n"
  1171. " + trap_right_slope*(left - trap_right_x); \n"
  1172. " area = area - 0.5 * (left - up_x) * (left_y - up); \n"
  1173. " } \n"
  1174. " if(right_y > bottom) { \n"
  1175. " area = area - 0.5 * (right - bottom_x) * (right_y - bottom); \n"
  1176. " } \n"
  1177. " } else { \n"
  1178. " area = 0.0; \n"
  1179. " } \n"
  1180. " percent = percent * (1.0 - (area/((right-left)*(bottom-up)))); \n"
  1181. " } \n"
  1182. " } \n"
  1183. " \n"
  1184. " return percent; \n"
  1185. " } \n"
  1186. "} \n"
  1187. "\n"
  1188. "void main() \n"
  1189. "{ \n"
  1190. " float alpha_val = get_alpha_val(); \n"
  1191. " gl_FragColor = vec4(0.0, 0.0, 0.0, alpha_val); \n"
  1192. "}\n";
  1193. glamor_priv = glamor_get_screen_private(screen);
  1194. glamor_make_current(glamor_priv);
  1195. glamor_priv->trapezoid_prog = glCreateProgram();
  1196. vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, trapezoid_vs);
  1197. fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, trapezoid_fs);
  1198. glAttachShader(glamor_priv->trapezoid_prog, vs_prog);
  1199. glAttachShader(glamor_priv->trapezoid_prog, fs_prog);
  1200. glBindAttribLocation(glamor_priv->trapezoid_prog,
  1201. GLAMOR_VERTEX_POS, "v_positionsition");
  1202. glBindAttribLocation(glamor_priv->trapezoid_prog,
  1203. GLAMOR_VERTEX_SOURCE, "v_texcoord");
  1204. glBindAttribLocation(glamor_priv->trapezoid_prog,
  1205. GLAMOR_VERTEX_TOP_BOTTOM, "v_top_bottom");
  1206. glBindAttribLocation(glamor_priv->trapezoid_prog,
  1207. GLAMOR_VERTEX_LEFT_PARAM, "v_left_param");
  1208. glBindAttribLocation(glamor_priv->trapezoid_prog,
  1209. GLAMOR_VERTEX_RIGHT_PARAM, "v_right_param");
  1210. glamor_link_glsl_prog(screen, glamor_priv->trapezoid_prog, "trapezoid");
  1211. }
  1212. void
  1213. glamor_fini_trapezoid_shader(ScreenPtr screen)
  1214. {
  1215. glamor_screen_private *glamor_priv;
  1216. glamor_priv = glamor_get_screen_private(screen);
  1217. glamor_make_current(glamor_priv);
  1218. glDeleteProgram(glamor_priv->trapezoid_prog);
  1219. }
  1220. static Bool
  1221. _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
  1222. xTrapezoid *traps, int ntrap,
  1223. BoxRec *bounds)
  1224. {
  1225. glamor_screen_private *glamor_priv;
  1226. glamor_pixmap_private *pixmap_priv;
  1227. PixmapPtr pixmap = NULL;
  1228. GLint trapezoid_prog;
  1229. GLfloat xscale, yscale;
  1230. float left_slope, right_slope;
  1231. xTrapezoid *ptrap;
  1232. BoxRec one_trap_bound;
  1233. int nrect_max;
  1234. int i, j;
  1235. float params[4];
  1236. glamor_priv = glamor_get_screen_private(screen);
  1237. trapezoid_prog = glamor_priv->trapezoid_prog;
  1238. pixmap = glamor_get_drawable_pixmap(picture->pDrawable);
  1239. pixmap_priv = glamor_get_pixmap_private(pixmap);
  1240. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)
  1241. || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { /* should always have here. */
  1242. DEBUGF("GLAMOR_PIXMAP_PRIV_HAS_FBO check failed, fallback\n");
  1243. return FALSE;
  1244. }
  1245. /* First, clear all to zero */
  1246. if (!glamor_solid(pixmap, 0, 0, pixmap_priv->base.pixmap->drawable.width,
  1247. pixmap_priv->base.pixmap->drawable.height,
  1248. GXclear, 0xFFFFFFFF, 0)) {
  1249. DEBUGF("glamor_solid failed, fallback\n");
  1250. return FALSE;
  1251. }
  1252. glamor_make_current(glamor_priv);
  1253. glamor_set_destination_pixmap_priv_nc(pixmap_priv);
  1254. pixmap_priv_get_dest_scale(pixmap_priv, (&xscale), (&yscale));
  1255. /* Now draw the Trapezoid mask. */
  1256. glUseProgram(trapezoid_prog);
  1257. glEnable(GL_BLEND);
  1258. glBlendFunc(GL_ONE, GL_ONE);
  1259. nrect_max = GLAMOR_COMPOSITE_VBO_VERT_CNT / (4 * GLAMOR_VERTEX_RIGHT_PARAM);
  1260. for (i = 0; i < ntrap;) {
  1261. float *vertices;
  1262. int mrect;
  1263. int stride;
  1264. mrect = (ntrap - i) > nrect_max ? nrect_max : (ntrap - i);
  1265. vertices = glamor_setup_composite_vbo_for_trapezoid(screen, 4 * mrect);
  1266. stride = glamor_priv->vb_stride / sizeof(float);
  1267. for (j = 0; j < mrect; j++) {
  1268. ptrap = traps + i + j;
  1269. DEBUGF
  1270. ("--- The parameter of xTrapezoid is:\ntop: %d 0x%x\tbottom: %d 0x%x\n"
  1271. "left: p1 (%d 0x%x, %d 0x%x)\tp2 (%d 0x%x, %d 0x%x)\n"
  1272. "right: p1 (%d 0x%x, %d 0x%x)\tp2 (%d 0x%x, %d 0x%x)\n",
  1273. xFixedToInt(ptrap->top), ptrap->top,
  1274. xFixedToInt(ptrap->bottom), ptrap->bottom,
  1275. xFixedToInt(ptrap->left.p1.x), ptrap->left.p1.x,
  1276. xFixedToInt(ptrap->left.p1.y), ptrap->left.p1.y,
  1277. xFixedToInt(ptrap->left.p2.x), ptrap->left.p2.x,
  1278. xFixedToInt(ptrap->left.p2.y), ptrap->left.p2.y,
  1279. xFixedToInt(ptrap->right.p1.x), ptrap->right.p1.x,
  1280. xFixedToInt(ptrap->right.p1.y), ptrap->right.p1.y,
  1281. xFixedToInt(ptrap->right.p2.x), ptrap->right.p2.x,
  1282. xFixedToInt(ptrap->right.p2.y), ptrap->right.p2.y);
  1283. miTrapezoidBounds(1, ptrap, &one_trap_bound);
  1284. vertices += 2;
  1285. glamor_set_tcoords_ext((pixmap_priv->base.pixmap->drawable.width),
  1286. (pixmap_priv->base.pixmap->drawable.height),
  1287. (one_trap_bound.x1), (one_trap_bound.y1),
  1288. (one_trap_bound.x2), (one_trap_bound.y2),
  1289. glamor_priv->yInverted, vertices, stride);
  1290. DEBUGF("tex_vertices --> leftup : %f X %f, rightup: %f X %f,"
  1291. "rightbottom: %f X %f, leftbottom : %f X %f\n", vertices[0],
  1292. vertices[1], vertices[1 * stride], vertices[1 * stride + 1],
  1293. vertices[2 * stride], vertices[2 * stride + 1],
  1294. vertices[3 * stride], vertices[3 * stride + 1]);
  1295. /* Need to rebase. */
  1296. one_trap_bound.x1 -= bounds->x1;
  1297. one_trap_bound.x2 -= bounds->x1;
  1298. one_trap_bound.y1 -= bounds->y1;
  1299. one_trap_bound.y2 -= bounds->y1;
  1300. vertices -= 2;
  1301. glamor_set_normalize_vcoords_ext(pixmap_priv, xscale, yscale,
  1302. one_trap_bound.x1,
  1303. one_trap_bound.y1,
  1304. one_trap_bound.x2,
  1305. one_trap_bound.y2,
  1306. glamor_priv->yInverted, vertices,
  1307. stride);
  1308. DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f,"
  1309. "rightbottom: %f X %f, leftbottom : %f X %f\n", vertices[0],
  1310. vertices[1], vertices[1 * stride], vertices[1 * stride + 1],
  1311. vertices[2 * stride], vertices[2 * stride + 1],
  1312. vertices[3 * stride], vertices[3 * stride + 1]);
  1313. vertices += 4;
  1314. /* Set the top and bottom. */
  1315. params[0] = ((float) ptrap->top) / 65536;
  1316. params[1] = ((float) ptrap->bottom) / 65536;
  1317. glamor_set_const_ext(params, 2, vertices, 4, stride);
  1318. vertices += 2;
  1319. /* Set the left params. */
  1320. params[0] = ((float) ptrap->left.p1.x) / 65536;
  1321. params[1] = ((float) ptrap->left.p1.y) / 65536;
  1322. if (ptrap->left.p1.x == ptrap->left.p2.x) {
  1323. left_slope = 0.0;
  1324. params[3] = 1.0;
  1325. }
  1326. else {
  1327. left_slope = ((float) (ptrap->left.p1.y - ptrap->left.p2.y))
  1328. / ((float) (ptrap->left.p1.x - ptrap->left.p2.x));
  1329. params[3] = 0.0;
  1330. }
  1331. params[2] = left_slope;
  1332. glamor_set_const_ext(params, 4, vertices, 4, stride);
  1333. vertices += 4;
  1334. /* Set the left params. */
  1335. params[0] = ((float) ptrap->right.p1.x) / 65536;
  1336. params[1] = ((float) ptrap->right.p1.y) / 65536;
  1337. if (ptrap->right.p1.x == ptrap->right.p2.x) {
  1338. right_slope = 0.0;
  1339. params[3] = 1.0;
  1340. }
  1341. else {
  1342. right_slope = ((float) (ptrap->right.p1.y - ptrap->right.p2.y))
  1343. / ((float) (ptrap->right.p1.x - ptrap->right.p2.x));
  1344. params[3] = 0.0;
  1345. }
  1346. params[2] = right_slope;
  1347. glamor_set_const_ext(params, 4, vertices, 4, stride);
  1348. vertices += 4;
  1349. DEBUGF("trap_top = %f, trap_bottom = %f, "
  1350. "trap_left_x = %f, trap_left_y = %f, left_slope = %f, "
  1351. "trap_right_x = %f, trap_right_y = %f, right_slope = %f\n",
  1352. ((float) ptrap->top) / 65536,
  1353. ((float) ptrap->bottom) / 65536,
  1354. ((float) ptrap->left.p1.x) / 65536,
  1355. ((float) ptrap->left.p1.y) / 65536, left_slope,
  1356. ((float) ptrap->right.p1.x) / 65536,
  1357. ((float) ptrap->right.p1.y) / 65536, right_slope);
  1358. glamor_priv->render_nr_verts += 4;
  1359. vertices += 3 * stride;
  1360. }
  1361. i += mrect;
  1362. glamor_put_vbo_space(screen);
  1363. /* Now rendering. */
  1364. if (!glamor_priv->render_nr_verts)
  1365. continue;
  1366. if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
  1367. glDrawRangeElements(GL_TRIANGLES, 0,
  1368. glamor_priv->render_nr_verts,
  1369. (glamor_priv->render_nr_verts * 3) / 2,
  1370. GL_UNSIGNED_SHORT, NULL);
  1371. } else {
  1372. glDrawElements(GL_TRIANGLES,
  1373. (glamor_priv->render_nr_verts * 3) / 2,
  1374. GL_UNSIGNED_SHORT, NULL);
  1375. }
  1376. }
  1377. glBlendFunc(GL_ONE, GL_ZERO);
  1378. glDisable(GL_BLEND);
  1379. glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
  1380. glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
  1381. glDisableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM);
  1382. glDisableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
  1383. glDisableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
  1384. return TRUE;
  1385. }
  1386. #endif /*GLAMOR_TRAPEZOID_SHADER */
  1387. /**
  1388. * Creates an appropriate picture for temp mask use.
  1389. */
  1390. static PicturePtr
  1391. glamor_create_mask_picture(ScreenPtr screen,
  1392. PicturePtr dst,
  1393. PictFormatPtr pict_format,
  1394. CARD16 width, CARD16 height, int gpu)
  1395. {
  1396. PixmapPtr pixmap;
  1397. PicturePtr picture;
  1398. int error;
  1399. if (!pict_format) {
  1400. if (dst->polyEdge == PolyEdgeSharp)
  1401. pict_format = PictureMatchFormat(screen, 1, PICT_a1);
  1402. else
  1403. pict_format = PictureMatchFormat(screen, 8, PICT_a8);
  1404. if (!pict_format)
  1405. return 0;
  1406. }
  1407. if (gpu) {
  1408. pixmap = glamor_create_pixmap(screen, width, height,
  1409. pict_format->depth, 0);
  1410. }
  1411. else {
  1412. pixmap = glamor_create_pixmap(screen, 0, 0,
  1413. pict_format->depth,
  1414. GLAMOR_CREATE_PIXMAP_CPU);
  1415. }
  1416. if (!pixmap)
  1417. return 0;
  1418. picture = CreatePicture(0, &pixmap->drawable, pict_format,
  1419. 0, 0, serverClient, &error);
  1420. glamor_destroy_pixmap(pixmap);
  1421. return picture;
  1422. }
  1423. static int
  1424. _glamor_trapezoid_bounds(int ntrap, xTrapezoid *traps, BoxPtr box)
  1425. {
  1426. int has_large_trapezoid = 0;
  1427. box->y1 = MAXSHORT;
  1428. box->y2 = MINSHORT;
  1429. box->x1 = MAXSHORT;
  1430. box->x2 = MINSHORT;
  1431. for (; ntrap; ntrap--, traps++) {
  1432. INT16 x1, y1, x2, y2;
  1433. if (!xTrapezoidValid(traps))
  1434. continue;
  1435. y1 = xFixedToInt(traps->top);
  1436. if (y1 < box->y1)
  1437. box->y1 = y1;
  1438. y2 = xFixedToInt(xFixedCeil(traps->bottom));
  1439. if (y2 > box->y2)
  1440. box->y2 = y2;
  1441. x1 = xFixedToInt(min
  1442. (_glamor_linefixedX(&traps->left, traps->top, FALSE),
  1443. _glamor_linefixedX(&traps->left, traps->bottom,
  1444. FALSE)));
  1445. if (x1 < box->x1)
  1446. box->x1 = x1;
  1447. x2 = xFixedToInt(xFixedCeil
  1448. (max
  1449. (_glamor_linefixedX(&traps->right, traps->top, TRUE),
  1450. _glamor_linefixedX(&traps->right, traps->bottom,
  1451. TRUE))));
  1452. if (x2 > box->x2)
  1453. box->x2 = x2;
  1454. if (!has_large_trapezoid && (x2 - x1) > 256 && (y2 - y1) > 32)
  1455. has_large_trapezoid = 1;
  1456. }
  1457. return has_large_trapezoid;
  1458. }
  1459. /**
  1460. * glamor_trapezoids will first try to create a trapezoid mask using shader,
  1461. * if failed, miTrapezoids will generate trapezoid mask accumulating in
  1462. * system memory.
  1463. */
  1464. static Bool
  1465. _glamor_trapezoids(CARD8 op,
  1466. PicturePtr src, PicturePtr dst,
  1467. PictFormatPtr mask_format, INT16 x_src, INT16 y_src,
  1468. int ntrap, xTrapezoid *traps, Bool fallback)
  1469. {
  1470. ScreenPtr screen = dst->pDrawable->pScreen;
  1471. BoxRec bounds;
  1472. PicturePtr picture;
  1473. INT16 x_dst, y_dst;
  1474. INT16 x_rel, y_rel;
  1475. int width, height, stride;
  1476. PixmapPtr pixmap;
  1477. pixman_image_t *image = NULL;
  1478. int ret = 0;
  1479. int has_large_trapezoid;
  1480. /* If a mask format wasn't provided, we get to choose, but behavior should
  1481. * be as if there was no temporary mask the traps were accumulated into.
  1482. */
  1483. if (!mask_format) {
  1484. if (dst->polyEdge == PolyEdgeSharp)
  1485. mask_format = PictureMatchFormat(screen, 1, PICT_a1);
  1486. else
  1487. mask_format = PictureMatchFormat(screen, 8, PICT_a8);
  1488. for (; ntrap; ntrap--, traps++)
  1489. glamor_trapezoids(op, src, dst, mask_format, x_src,
  1490. y_src, 1, traps);
  1491. return TRUE;
  1492. }
  1493. has_large_trapezoid = _glamor_trapezoid_bounds(ntrap, traps, &bounds);
  1494. DEBUGF("The bounds for all traps is: bounds.x1 = %d, bounds.x2 = %d, "
  1495. "bounds.y1 = %d, bounds.y2 = %d, ---- ntrap = %d\n", bounds.x1,
  1496. bounds.x2, bounds.y1, bounds.y2, ntrap);
  1497. if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
  1498. return TRUE;
  1499. x_dst = traps[0].left.p1.x >> 16;
  1500. y_dst = traps[0].left.p1.y >> 16;
  1501. width = bounds.x2 - bounds.x1;
  1502. height = bounds.y2 - bounds.y1;
  1503. stride = PixmapBytePad(width, mask_format->depth);
  1504. #ifdef GLAMOR_TRAPEZOID_SHADER
  1505. /* We seperate the render to two paths.
  1506. Some GL implemetation do not implement the Anti-Alias for triangles
  1507. and polygen's filling. So when the edge is not vertical or horizontal,
  1508. sawtooth will be obvious. The trapezoid is widely used to render wide
  1509. lines and circles. In these case, the line or circle will be divided
  1510. into a large number of small trapezoids to approximate it, so the sawtooth
  1511. at the edge will cause the result not be acceptable.
  1512. When the depth of the mask is 1, there is no Anti-Alias needed, so we
  1513. use the clip logic to generate the result directly(fast path).
  1514. When the depth is not 1, AA is needed and we use a shader to generate
  1515. a temp mask pixmap.
  1516. */
  1517. if (mask_format->depth == 1) {
  1518. ret = _glamor_trapezoids_with_shader(op, src, dst, mask_format,
  1519. x_src, y_src, ntrap, traps);
  1520. if (ret)
  1521. return TRUE;
  1522. }
  1523. else {
  1524. if (has_large_trapezoid || ntrap > 256) {
  1525. /* The shader speed is relative slower than pixman when generating big chunk
  1526. trapezoid mask. We fallback to pixman to improve the performance. */
  1527. ;
  1528. }
  1529. else if (dst->polyMode == PolyModeImprecise) {
  1530. /* The precise mode is that we sample the trapezoid on the centre points of
  1531. an (2*n+1)x(2*n-1) subpixel grid. It is computationally expensive in shader
  1532. and we use inside area ratio to replace it if the polymode == Imprecise. */
  1533. picture = glamor_create_mask_picture(screen, dst, mask_format,
  1534. width, height, 1);
  1535. if (!picture)
  1536. return TRUE;
  1537. ret =
  1538. _glamor_generate_trapezoid_with_shader(screen, picture, traps,
  1539. ntrap, &bounds);
  1540. if (!ret)
  1541. FreePicture(picture, 0);
  1542. }
  1543. }
  1544. #endif
  1545. if (!ret) {
  1546. DEBUGF("Fallback to sw rasterize of trapezoid\n");
  1547. picture = glamor_create_mask_picture(screen, dst, mask_format,
  1548. width, height, 0);
  1549. if (!picture)
  1550. return TRUE;
  1551. image = pixman_image_create_bits(picture->format,
  1552. width, height, NULL, stride);
  1553. if (!image) {
  1554. FreePicture(picture, 0);
  1555. return TRUE;
  1556. }
  1557. for (; ntrap; ntrap--, traps++)
  1558. pixman_rasterize_trapezoid(image,
  1559. (pixman_trapezoid_t *) traps,
  1560. -bounds.x1, -bounds.y1);
  1561. pixmap = glamor_get_drawable_pixmap(picture->pDrawable);
  1562. screen->ModifyPixmapHeader(pixmap, width, height,
  1563. mask_format->depth,
  1564. BitsPerPixel(mask_format->depth),
  1565. PixmapBytePad(width,
  1566. mask_format->depth),
  1567. pixman_image_get_data(image));
  1568. }
  1569. x_rel = bounds.x1 + x_src - x_dst;
  1570. y_rel = bounds.y1 + y_src - y_dst;
  1571. DEBUGF("x_src = %d, y_src = %d, x_dst = %d, y_dst = %d, "
  1572. "x_rel = %d, y_rel = %d\n", x_src, y_src, x_dst,
  1573. y_dst, x_rel, y_rel);
  1574. CompositePicture(op, src, picture, dst,
  1575. x_rel, y_rel,
  1576. 0, 0,
  1577. bounds.x1, bounds.y1,
  1578. bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
  1579. if (image)
  1580. pixman_image_unref(image);
  1581. FreePicture(picture, 0);
  1582. return TRUE;
  1583. }
  1584. void
  1585. glamor_trapezoids(CARD8 op,
  1586. PicturePtr src, PicturePtr dst,
  1587. PictFormatPtr mask_format, INT16 x_src, INT16 y_src,
  1588. int ntrap, xTrapezoid *traps)
  1589. {
  1590. DEBUGF("x_src = %d, y_src = %d, ntrap = %d\n", x_src, y_src, ntrap);
  1591. _glamor_trapezoids(op, src, dst, mask_format, x_src,
  1592. y_src, ntrap, traps, TRUE);
  1593. }
  1594. Bool
  1595. glamor_trapezoids_nf(CARD8 op,
  1596. PicturePtr src, PicturePtr dst,
  1597. PictFormatPtr mask_format, INT16 x_src, INT16 y_src,
  1598. int ntrap, xTrapezoid *traps)
  1599. {
  1600. DEBUGF("x_src = %d, y_src = %d, ntrap = %d\n", x_src, y_src, ntrap);
  1601. return _glamor_trapezoids(op, src, dst, mask_format, x_src,
  1602. y_src, ntrap, traps, FALSE);
  1603. }
  1604. #endif /* RENDER */