glamor_render.c 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984
  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. * Eric Anholt <eric@anholt.net>
  25. * Zhigang Gong <zhigang.gong@linux.intel.com>
  26. * Junyan He <junyan.he@linux.intel.com>
  27. *
  28. */
  29. /** @file glamor_render.c
  30. *
  31. * Render acceleration implementation
  32. */
  33. #include "glamor_priv.h"
  34. #ifdef RENDER
  35. #include "mipict.h"
  36. #include "fbpict.h"
  37. #if 0
  38. //#define DEBUGF(str, ...) do {} while(0)
  39. #define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__)
  40. //#define DEBUGRegionPrint(x) do {} while (0)
  41. #define DEBUGRegionPrint RegionPrint
  42. #endif
  43. static struct blendinfo composite_op_info[] = {
  44. [PictOpClear] = {0, 0, GL_ZERO, GL_ZERO},
  45. [PictOpSrc] = {0, 0, GL_ONE, GL_ZERO},
  46. [PictOpDst] = {0, 0, GL_ZERO, GL_ONE},
  47. [PictOpOver] = {0, 1, GL_ONE, GL_ONE_MINUS_SRC_ALPHA},
  48. [PictOpOverReverse] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ONE},
  49. [PictOpIn] = {1, 0, GL_DST_ALPHA, GL_ZERO},
  50. [PictOpInReverse] = {0, 1, GL_ZERO, GL_SRC_ALPHA},
  51. [PictOpOut] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ZERO},
  52. [PictOpOutReverse] = {0, 1, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA},
  53. [PictOpAtop] = {1, 1, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
  54. [PictOpAtopReverse] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA},
  55. [PictOpXor] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
  56. [PictOpAdd] = {0, 0, GL_ONE, GL_ONE},
  57. };
  58. #define RepeatFix 10
  59. static GLuint
  60. glamor_create_composite_fs(struct shader_key *key)
  61. {
  62. const char *repeat_define =
  63. "#define RepeatNone 0\n"
  64. "#define RepeatNormal 1\n"
  65. "#define RepeatPad 2\n"
  66. "#define RepeatReflect 3\n"
  67. "#define RepeatFix 10\n"
  68. "uniform int source_repeat_mode;\n"
  69. "uniform int mask_repeat_mode;\n";
  70. const char *relocate_texture =
  71. GLAMOR_DEFAULT_PRECISION
  72. "vec2 rel_tex_coord(vec2 texture, vec4 wh, int repeat) \n"
  73. "{\n"
  74. " vec2 rel_tex; \n"
  75. " rel_tex = texture * wh.xy; \n"
  76. " if (repeat == RepeatNone)\n"
  77. " return rel_tex; \n"
  78. " else if (repeat == RepeatNormal) \n"
  79. " rel_tex = floor(rel_tex) + (fract(rel_tex) / wh.xy); \n"
  80. " else if(repeat == RepeatPad) { \n"
  81. " if (rel_tex.x >= 1.0) rel_tex.x = 1.0 - wh.z * wh.x / 2.; \n"
  82. " else if(rel_tex.x < 0.0) rel_tex.x = 0.0; \n"
  83. " if (rel_tex.y >= 1.0) rel_tex.y = 1.0 - wh.w * wh.y / 2.; \n"
  84. " else if(rel_tex.y < 0.0) rel_tex.y = 0.0; \n"
  85. " rel_tex = rel_tex / wh.xy; \n"
  86. " } \n"
  87. " else if(repeat == RepeatReflect) {\n"
  88. " if ((1.0 - mod(abs(floor(rel_tex.x)), 2.0)) < 0.001)\n"
  89. " rel_tex.x = 2.0 - (1.0 - fract(rel_tex.x))/wh.x;\n"
  90. " else \n"
  91. " rel_tex.x = fract(rel_tex.x)/wh.x;\n"
  92. " if ((1.0 - mod(abs(floor(rel_tex.y)), 2.0)) < 0.001)\n"
  93. " rel_tex.y = 2.0 - (1.0 - fract(rel_tex.y))/wh.y;\n"
  94. " else \n"
  95. " rel_tex.y = fract(rel_tex.y)/wh.y;\n"
  96. " } \n"
  97. " return rel_tex; \n"
  98. "}\n";
  99. /* The texture and the pixmap size is not match eaxctly, so can't sample it directly.
  100. * rel_sampler will recalculate the texture coords.*/
  101. const char *rel_sampler =
  102. " vec4 rel_sampler(sampler2D tex_image, vec2 tex, vec4 wh, int repeat, int set_alpha)\n"
  103. "{\n"
  104. " tex = rel_tex_coord(tex, wh, repeat - RepeatFix);\n"
  105. " if (repeat == RepeatFix) {\n"
  106. " if (!(tex.x >= 0.0 && tex.x < 1.0 \n"
  107. " && tex.y >= 0.0 && tex.y < 1.0))\n"
  108. " return vec4(0.0, 0.0, 0.0, set_alpha);\n"
  109. " tex = (fract(tex) / wh.xy);\n"
  110. " }\n"
  111. " if (set_alpha != 1)\n"
  112. " return texture2D(tex_image, tex);\n"
  113. " else\n"
  114. " return vec4(texture2D(tex_image, tex).rgb, 1.0);\n"
  115. "}\n";
  116. const char *source_solid_fetch =
  117. GLAMOR_DEFAULT_PRECISION
  118. "uniform vec4 source;\n"
  119. "vec4 get_source()\n"
  120. "{\n"
  121. " return source;\n"
  122. "}\n";
  123. const char *source_alpha_pixmap_fetch =
  124. GLAMOR_DEFAULT_PRECISION
  125. "varying vec2 source_texture;\n"
  126. "uniform sampler2D source_sampler;\n"
  127. "uniform vec4 source_wh;"
  128. "vec4 get_source()\n"
  129. "{\n"
  130. " if (source_repeat_mode < RepeatFix)\n"
  131. " return texture2D(source_sampler, source_texture);\n"
  132. " else \n"
  133. " return rel_sampler(source_sampler, source_texture,\n"
  134. " source_wh, source_repeat_mode, 0);\n"
  135. "}\n";
  136. const char *source_pixmap_fetch =
  137. GLAMOR_DEFAULT_PRECISION
  138. "varying vec2 source_texture;\n"
  139. "uniform sampler2D source_sampler;\n"
  140. "uniform vec4 source_wh;\n"
  141. "vec4 get_source()\n"
  142. "{\n"
  143. " if (source_repeat_mode < RepeatFix) \n"
  144. " return vec4(texture2D(source_sampler, source_texture).rgb, 1);\n"
  145. " else \n"
  146. " return rel_sampler(source_sampler, source_texture,\n"
  147. " source_wh, source_repeat_mode, 1);\n"
  148. "}\n";
  149. const char *mask_solid_fetch =
  150. GLAMOR_DEFAULT_PRECISION
  151. "uniform vec4 mask;\n"
  152. "vec4 get_mask()\n"
  153. "{\n"
  154. " return mask;\n"
  155. "}\n";
  156. const char *mask_alpha_pixmap_fetch =
  157. GLAMOR_DEFAULT_PRECISION
  158. "varying vec2 mask_texture;\n"
  159. "uniform sampler2D mask_sampler;\n"
  160. "uniform vec4 mask_wh;\n"
  161. "vec4 get_mask()\n"
  162. "{\n"
  163. " if (mask_repeat_mode < RepeatFix) \n"
  164. " return texture2D(mask_sampler, mask_texture);\n"
  165. " else \n"
  166. " return rel_sampler(mask_sampler, mask_texture,\n"
  167. " mask_wh, mask_repeat_mode, 0);\n"
  168. "}\n";
  169. const char *mask_pixmap_fetch =
  170. GLAMOR_DEFAULT_PRECISION
  171. "varying vec2 mask_texture;\n"
  172. "uniform sampler2D mask_sampler;\n"
  173. "uniform vec4 mask_wh;\n"
  174. "vec4 get_mask()\n"
  175. "{\n"
  176. " if (mask_repeat_mode < RepeatFix) \n"
  177. " return vec4(texture2D(mask_sampler, mask_texture).rgb, 1);\n"
  178. " else \n"
  179. " return rel_sampler(mask_sampler, mask_texture,\n"
  180. " mask_wh, mask_repeat_mode, 1);\n"
  181. "}\n";
  182. const char *in_source_only =
  183. GLAMOR_DEFAULT_PRECISION
  184. "void main()\n"
  185. "{\n"
  186. " gl_FragColor = get_source();\n"
  187. "}\n";
  188. const char *in_normal =
  189. GLAMOR_DEFAULT_PRECISION
  190. "void main()\n"
  191. "{\n"
  192. " gl_FragColor = get_source() * get_mask().a;\n"
  193. "}\n";
  194. const char *in_ca_source =
  195. GLAMOR_DEFAULT_PRECISION
  196. "void main()\n"
  197. "{\n"
  198. " gl_FragColor = get_source() * get_mask();\n"
  199. "}\n";
  200. const char *in_ca_alpha =
  201. GLAMOR_DEFAULT_PRECISION
  202. "void main()\n"
  203. "{\n"
  204. " gl_FragColor = get_source().a * get_mask();\n"
  205. "}\n";
  206. char *source;
  207. const char *source_fetch;
  208. const char *mask_fetch = "";
  209. const char *in;
  210. GLuint prog;
  211. switch (key->source) {
  212. case SHADER_SOURCE_SOLID:
  213. source_fetch = source_solid_fetch;
  214. break;
  215. case SHADER_SOURCE_TEXTURE_ALPHA:
  216. source_fetch = source_alpha_pixmap_fetch;
  217. break;
  218. case SHADER_SOURCE_TEXTURE:
  219. source_fetch = source_pixmap_fetch;
  220. break;
  221. default:
  222. FatalError("Bad composite shader source");
  223. }
  224. switch (key->mask) {
  225. case SHADER_MASK_NONE:
  226. break;
  227. case SHADER_MASK_SOLID:
  228. mask_fetch = mask_solid_fetch;
  229. break;
  230. case SHADER_MASK_TEXTURE_ALPHA:
  231. mask_fetch = mask_alpha_pixmap_fetch;
  232. break;
  233. case SHADER_MASK_TEXTURE:
  234. mask_fetch = mask_pixmap_fetch;
  235. break;
  236. default:
  237. FatalError("Bad composite shader mask");
  238. }
  239. switch (key->in) {
  240. case SHADER_IN_SOURCE_ONLY:
  241. in = in_source_only;
  242. break;
  243. case SHADER_IN_NORMAL:
  244. in = in_normal;
  245. break;
  246. case SHADER_IN_CA_SOURCE:
  247. in = in_ca_source;
  248. break;
  249. case SHADER_IN_CA_ALPHA:
  250. in = in_ca_alpha;
  251. break;
  252. default:
  253. FatalError("Bad composite IN type");
  254. }
  255. XNFasprintf(&source, "%s%s%s%s%s%s", repeat_define, relocate_texture,
  256. rel_sampler, source_fetch, mask_fetch, in);
  257. prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, source);
  258. free(source);
  259. return prog;
  260. }
  261. static GLuint
  262. glamor_create_composite_vs(struct shader_key *key)
  263. {
  264. const char *main_opening =
  265. "attribute vec4 v_position;\n"
  266. "attribute vec4 v_texcoord0;\n"
  267. "attribute vec4 v_texcoord1;\n"
  268. "varying vec2 source_texture;\n"
  269. "varying vec2 mask_texture;\n"
  270. "void main()\n"
  271. "{\n"
  272. " gl_Position = v_position;\n";
  273. const char *source_coords = " source_texture = v_texcoord0.xy;\n";
  274. const char *mask_coords = " mask_texture = v_texcoord1.xy;\n";
  275. const char *main_closing = "}\n";
  276. const char *source_coords_setup = "";
  277. const char *mask_coords_setup = "";
  278. char *source;
  279. GLuint prog;
  280. if (key->source != SHADER_SOURCE_SOLID)
  281. source_coords_setup = source_coords;
  282. if (key->mask != SHADER_MASK_NONE && key->mask != SHADER_MASK_SOLID)
  283. mask_coords_setup = mask_coords;
  284. XNFasprintf(&source,
  285. "%s%s%s%s",
  286. main_opening,
  287. source_coords_setup, mask_coords_setup, main_closing);
  288. prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, source);
  289. free(source);
  290. return prog;
  291. }
  292. static void
  293. glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key,
  294. glamor_composite_shader *shader)
  295. {
  296. GLuint vs, fs, prog;
  297. GLint source_sampler_uniform_location, mask_sampler_uniform_location;
  298. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  299. glamor_make_current(glamor_priv);
  300. vs = glamor_create_composite_vs(key);
  301. if (vs == 0)
  302. return;
  303. fs = glamor_create_composite_fs(key);
  304. if (fs == 0)
  305. return;
  306. prog = glCreateProgram();
  307. glAttachShader(prog, vs);
  308. glAttachShader(prog, fs);
  309. glBindAttribLocation(prog, GLAMOR_VERTEX_POS, "v_position");
  310. glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0");
  311. glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, "v_texcoord1");
  312. glamor_link_glsl_prog(screen, prog, "composite");
  313. shader->prog = prog;
  314. glUseProgram(prog);
  315. if (key->source == SHADER_SOURCE_SOLID) {
  316. shader->source_uniform_location = glGetUniformLocation(prog, "source");
  317. }
  318. else {
  319. source_sampler_uniform_location =
  320. glGetUniformLocation(prog, "source_sampler");
  321. glUniform1i(source_sampler_uniform_location, 0);
  322. shader->source_wh = glGetUniformLocation(prog, "source_wh");
  323. shader->source_repeat_mode =
  324. glGetUniformLocation(prog, "source_repeat_mode");
  325. }
  326. if (key->mask != SHADER_MASK_NONE) {
  327. if (key->mask == SHADER_MASK_SOLID) {
  328. shader->mask_uniform_location = glGetUniformLocation(prog, "mask");
  329. }
  330. else {
  331. mask_sampler_uniform_location =
  332. glGetUniformLocation(prog, "mask_sampler");
  333. glUniform1i(mask_sampler_uniform_location, 1);
  334. shader->mask_wh = glGetUniformLocation(prog, "mask_wh");
  335. shader->mask_repeat_mode =
  336. glGetUniformLocation(prog, "mask_repeat_mode");
  337. }
  338. }
  339. }
  340. static glamor_composite_shader *
  341. glamor_lookup_composite_shader(ScreenPtr screen, struct
  342. shader_key
  343. *key)
  344. {
  345. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  346. glamor_composite_shader *shader;
  347. shader = &glamor_priv->composite_shader[key->source][key->mask][key->in];
  348. if (shader->prog == 0)
  349. glamor_create_composite_shader(screen, key, shader);
  350. return shader;
  351. }
  352. static void
  353. glamor_init_eb(unsigned short *eb, int vert_cnt)
  354. {
  355. int i, j;
  356. for (i = 0, j = 0; j < vert_cnt; i += 6, j += 4) {
  357. eb[i] = j;
  358. eb[i + 1] = j + 1;
  359. eb[i + 2] = j + 2;
  360. eb[i + 3] = j;
  361. eb[i + 4] = j + 2;
  362. eb[i + 5] = j + 3;
  363. }
  364. }
  365. void
  366. glamor_init_composite_shaders(ScreenPtr screen)
  367. {
  368. glamor_screen_private *glamor_priv;
  369. unsigned short *eb;
  370. int eb_size;
  371. glamor_priv = glamor_get_screen_private(screen);
  372. glamor_make_current(glamor_priv);
  373. glGenBuffers(1, &glamor_priv->ebo);
  374. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
  375. eb_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(short) * 2;
  376. eb = XNFalloc(eb_size);
  377. glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT);
  378. glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, eb, GL_STATIC_DRAW);
  379. free(eb);
  380. }
  381. void
  382. glamor_fini_composite_shaders(ScreenPtr screen)
  383. {
  384. glamor_screen_private *glamor_priv;
  385. glamor_composite_shader *shader;
  386. int i, j, k;
  387. glamor_priv = glamor_get_screen_private(screen);
  388. glamor_make_current(glamor_priv);
  389. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  390. glDeleteBuffers(1, &glamor_priv->ebo);
  391. for (i = 0; i < SHADER_SOURCE_COUNT; i++)
  392. for (j = 0; j < SHADER_MASK_COUNT; j++)
  393. for (k = 0; k < SHADER_IN_COUNT; k++) {
  394. shader = &glamor_priv->composite_shader[i][j][k];
  395. if (shader->prog)
  396. glDeleteProgram(shader->prog);
  397. }
  398. }
  399. static Bool
  400. glamor_set_composite_op(ScreenPtr screen,
  401. CARD8 op, struct blendinfo *op_info_result,
  402. PicturePtr dest, PicturePtr mask)
  403. {
  404. GLenum source_blend, dest_blend;
  405. struct blendinfo *op_info;
  406. if (op >= ARRAY_SIZE(composite_op_info)) {
  407. glamor_fallback("unsupported render op %d \n", op);
  408. return GL_FALSE;
  409. }
  410. op_info = &composite_op_info[op];
  411. source_blend = op_info->source_blend;
  412. dest_blend = op_info->dest_blend;
  413. /* If there's no dst alpha channel, adjust the blend op so that we'll treat
  414. * it as always 1.
  415. */
  416. if (PICT_FORMAT_A(dest->format) == 0 && op_info->dest_alpha) {
  417. if (source_blend == GL_DST_ALPHA)
  418. source_blend = GL_ONE;
  419. else if (source_blend == GL_ONE_MINUS_DST_ALPHA)
  420. source_blend = GL_ZERO;
  421. }
  422. /* Set up the source alpha value for blending in component alpha mode. */
  423. if (mask && mask->componentAlpha
  424. && PICT_FORMAT_RGB(mask->format) != 0 && op_info->source_alpha) {
  425. if (dest_blend == GL_SRC_ALPHA)
  426. dest_blend = GL_SRC_COLOR;
  427. else if (dest_blend == GL_ONE_MINUS_SRC_ALPHA)
  428. dest_blend = GL_ONE_MINUS_SRC_COLOR;
  429. }
  430. op_info_result->source_blend = source_blend;
  431. op_info_result->dest_blend = dest_blend;
  432. op_info_result->source_alpha = op_info->source_alpha;
  433. op_info_result->dest_alpha = op_info->dest_alpha;
  434. return TRUE;
  435. }
  436. static void
  437. glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit,
  438. PicturePtr picture,
  439. glamor_pixmap_private *pixmap_priv,
  440. GLuint wh_location, GLuint repeat_location)
  441. {
  442. float wh[4];
  443. int repeat_type;
  444. glamor_make_current(glamor_priv);
  445. glActiveTexture(GL_TEXTURE0 + unit);
  446. glBindTexture(GL_TEXTURE_2D, pixmap_priv->base.fbo->tex);
  447. repeat_type = picture->repeatType;
  448. switch (picture->repeatType) {
  449. case RepeatNone:
  450. if (glamor_priv->gl_flavor != GLAMOR_GL_ES2) {
  451. /* XXX GLES2 doesn't support GL_CLAMP_TO_BORDER. */
  452. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
  453. GL_CLAMP_TO_BORDER);
  454. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
  455. GL_CLAMP_TO_BORDER);
  456. } else {
  457. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  458. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  459. }
  460. break;
  461. case RepeatNormal:
  462. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  463. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  464. break;
  465. case RepeatPad:
  466. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  467. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  468. break;
  469. case RepeatReflect:
  470. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
  471. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
  472. break;
  473. }
  474. switch (picture->filter) {
  475. default:
  476. case PictFilterFast:
  477. case PictFilterNearest:
  478. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  479. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  480. break;
  481. case PictFilterGood:
  482. case PictFilterBest:
  483. case PictFilterBilinear:
  484. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  485. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  486. break;
  487. }
  488. /*
  489. * GLES2 doesn't support RepeatNone. We need to fix it anyway.
  490. *
  491. **/
  492. if (repeat_type != RepeatNone)
  493. repeat_type += RepeatFix;
  494. else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
  495. || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
  496. if (picture->transform
  497. || (GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(pixmap_priv)))
  498. repeat_type += RepeatFix;
  499. }
  500. if (repeat_type >= RepeatFix) {
  501. glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv);
  502. if ((wh[0] != 1.0 || wh[1] != 1.0)
  503. || (glamor_priv->gl_flavor == GLAMOR_GL_ES2
  504. && repeat_type == RepeatFix))
  505. glUniform4fv(wh_location, 1, wh);
  506. else
  507. repeat_type -= RepeatFix;
  508. }
  509. glUniform1i(repeat_location, repeat_type);
  510. }
  511. static void
  512. glamor_set_composite_solid(float *color, GLint uniform_location)
  513. {
  514. glUniform4fv(uniform_location, 1, color);
  515. }
  516. static int
  517. compatible_formats(CARD8 op, PicturePtr dst, PicturePtr src)
  518. {
  519. if (op == PictOpSrc) {
  520. if (src->format == dst->format)
  521. return 1;
  522. if (src->format == PICT_a8r8g8b8 && dst->format == PICT_x8r8g8b8)
  523. return 1;
  524. if (src->format == PICT_a8b8g8r8 && dst->format == PICT_x8b8g8r8)
  525. return 1;
  526. }
  527. else if (op == PictOpOver) {
  528. if (src->alphaMap || dst->alphaMap)
  529. return 0;
  530. if (src->format != dst->format)
  531. return 0;
  532. if (src->format == PICT_x8r8g8b8 || src->format == PICT_x8b8g8r8)
  533. return 1;
  534. }
  535. return 0;
  536. }
  537. static char
  538. glamor_get_picture_location(PicturePtr picture)
  539. {
  540. if (picture == NULL)
  541. return ' ';
  542. if (picture->pDrawable == NULL) {
  543. switch (picture->pSourcePict->type) {
  544. case SourcePictTypeSolidFill:
  545. return 'c';
  546. case SourcePictTypeLinear:
  547. return 'l';
  548. case SourcePictTypeRadial:
  549. return 'r';
  550. default:
  551. return '?';
  552. }
  553. }
  554. return glamor_get_drawable_location(picture->pDrawable);
  555. }
  556. static Bool
  557. glamor_composite_with_copy(CARD8 op,
  558. PicturePtr source,
  559. PicturePtr dest,
  560. INT16 x_source,
  561. INT16 y_source,
  562. INT16 x_dest, INT16 y_dest, RegionPtr region)
  563. {
  564. int ret = FALSE;
  565. if (!source->pDrawable)
  566. return FALSE;
  567. if (!compatible_formats(op, dest, source))
  568. return FALSE;
  569. if (source->repeat || source->transform) {
  570. return FALSE;
  571. }
  572. x_dest += dest->pDrawable->x;
  573. y_dest += dest->pDrawable->y;
  574. x_source += source->pDrawable->x;
  575. y_source += source->pDrawable->y;
  576. if (PICT_FORMAT_A(source->format) == 0) {
  577. /* Fallback if we sample outside the source so that we
  578. * swizzle the correct clear color for out-of-bounds texels.
  579. */
  580. if (region->extents.x1 + x_source - x_dest < 0)
  581. goto cleanup_region;
  582. if (region->extents.x2 + x_source - x_dest > source->pDrawable->width)
  583. goto cleanup_region;
  584. if (region->extents.y1 + y_source - y_dest < 0)
  585. goto cleanup_region;
  586. if (region->extents.y2 + y_source - y_dest > source->pDrawable->height)
  587. goto cleanup_region;
  588. }
  589. ret = glamor_copy_n_to_n_nf(source->pDrawable,
  590. dest->pDrawable, NULL,
  591. RegionRects(region), RegionNumRects(region),
  592. x_source - x_dest, y_source - y_dest,
  593. FALSE, FALSE, 0, NULL);
  594. cleanup_region:
  595. return ret;
  596. }
  597. void *
  598. glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
  599. {
  600. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  601. int vert_size;
  602. char *vbo_offset;
  603. float *vb;
  604. glamor_priv->render_nr_verts = 0;
  605. glamor_priv->vb_stride = 2 * sizeof(float);
  606. if (glamor_priv->has_source_coords)
  607. glamor_priv->vb_stride += 2 * sizeof(float);
  608. if (glamor_priv->has_mask_coords)
  609. glamor_priv->vb_stride += 2 * sizeof(float);
  610. vert_size = n_verts * glamor_priv->vb_stride;
  611. glamor_make_current(glamor_priv);
  612. vb = glamor_get_vbo_space(screen, vert_size, &vbo_offset);
  613. glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
  614. glamor_priv->vb_stride, vbo_offset);
  615. glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
  616. if (glamor_priv->has_source_coords) {
  617. glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
  618. GL_FLOAT, GL_FALSE,
  619. glamor_priv->vb_stride,
  620. vbo_offset + 2 * sizeof(float));
  621. glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
  622. }
  623. if (glamor_priv->has_mask_coords) {
  624. glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, GL_FLOAT, GL_FALSE,
  625. glamor_priv->vb_stride,
  626. vbo_offset + (glamor_priv->has_source_coords ?
  627. 4 : 2) * sizeof(float));
  628. glEnableVertexAttribArray(GLAMOR_VERTEX_MASK);
  629. }
  630. return vb;
  631. }
  632. static void
  633. glamor_flush_composite_rects(ScreenPtr screen)
  634. {
  635. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  636. glamor_make_current(glamor_priv);
  637. if (!glamor_priv->render_nr_verts)
  638. return;
  639. if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
  640. glDrawRangeElements(GL_TRIANGLES, 0, glamor_priv->render_nr_verts,
  641. (glamor_priv->render_nr_verts * 3) / 2,
  642. GL_UNSIGNED_SHORT, NULL);
  643. } else {
  644. glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2,
  645. GL_UNSIGNED_SHORT, NULL);
  646. }
  647. }
  648. int pict_format_combine_tab[][3] = {
  649. {PICT_TYPE_ARGB, PICT_TYPE_A, PICT_TYPE_ARGB},
  650. {PICT_TYPE_ABGR, PICT_TYPE_A, PICT_TYPE_ABGR},
  651. };
  652. static Bool
  653. combine_pict_format(PictFormatShort * des, const PictFormatShort src,
  654. const PictFormatShort mask, enum shader_in in_ca)
  655. {
  656. PictFormatShort new_vis;
  657. int src_type, mask_type, src_bpp;
  658. int i;
  659. if (src == mask) {
  660. *des = src;
  661. return TRUE;
  662. }
  663. src_bpp = PICT_FORMAT_BPP(src);
  664. assert(src_bpp == PICT_FORMAT_BPP(mask));
  665. new_vis = PICT_FORMAT_VIS(src) | PICT_FORMAT_VIS(mask);
  666. switch (in_ca) {
  667. case SHADER_IN_SOURCE_ONLY:
  668. return TRUE;
  669. case SHADER_IN_NORMAL:
  670. src_type = PICT_FORMAT_TYPE(src);
  671. mask_type = PICT_TYPE_A;
  672. break;
  673. case SHADER_IN_CA_SOURCE:
  674. src_type = PICT_FORMAT_TYPE(src);
  675. mask_type = PICT_FORMAT_TYPE(mask);
  676. break;
  677. case SHADER_IN_CA_ALPHA:
  678. src_type = PICT_TYPE_A;
  679. mask_type = PICT_FORMAT_TYPE(mask);
  680. break;
  681. default:
  682. return FALSE;
  683. }
  684. if (src_type == mask_type) {
  685. *des = PICT_VISFORMAT(src_bpp, src_type, new_vis);
  686. return TRUE;
  687. }
  688. for (i = 0;
  689. i <
  690. sizeof(pict_format_combine_tab) /
  691. sizeof(pict_format_combine_tab[0]); i++) {
  692. if ((src_type == pict_format_combine_tab[i][0]
  693. && mask_type == pict_format_combine_tab[i][1])
  694. || (src_type == pict_format_combine_tab[i][1]
  695. && mask_type == pict_format_combine_tab[i][0])) {
  696. *des = PICT_VISFORMAT(src_bpp, pict_format_combine_tab[i]
  697. [2], new_vis);
  698. return TRUE;
  699. }
  700. }
  701. return FALSE;
  702. }
  703. static void
  704. glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv,
  705. int repeat_type,
  706. float *matrix,
  707. float xscale, float yscale,
  708. int x1, int y1, int x2, int y2,
  709. int yInverted, float *texcoords,
  710. int stride)
  711. {
  712. if (!matrix && repeat_type == RepeatNone)
  713. glamor_set_normalize_tcoords_ext(priv, xscale, yscale,
  714. x1, y1,
  715. x2, y2, yInverted, texcoords, stride);
  716. else if (matrix && repeat_type == RepeatNone)
  717. glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale,
  718. yscale, x1, y1,
  719. x2, y2,
  720. yInverted,
  721. texcoords, stride);
  722. else if (!matrix && repeat_type != RepeatNone)
  723. glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type,
  724. xscale, yscale,
  725. x1, y1,
  726. x2, y2,
  727. yInverted, texcoords, stride);
  728. else if (matrix && repeat_type != RepeatNone)
  729. glamor_set_repeat_transformed_normalize_tcoords_ext(priv, repeat_type,
  730. matrix, xscale,
  731. yscale, x1, y1, x2,
  732. y2, yInverted,
  733. texcoords, stride);
  734. }
  735. Bool
  736. glamor_composite_choose_shader(CARD8 op,
  737. PicturePtr source,
  738. PicturePtr mask,
  739. PicturePtr dest,
  740. glamor_pixmap_private *source_pixmap_priv,
  741. glamor_pixmap_private *mask_pixmap_priv,
  742. glamor_pixmap_private *dest_pixmap_priv,
  743. struct shader_key *s_key,
  744. glamor_composite_shader ** shader,
  745. struct blendinfo *op_info,
  746. PictFormatShort *psaved_source_format)
  747. {
  748. ScreenPtr screen = dest->pDrawable->pScreen;
  749. PixmapPtr dest_pixmap = dest_pixmap_priv->base.pixmap;
  750. PixmapPtr source_pixmap = NULL;
  751. PixmapPtr mask_pixmap = NULL;
  752. enum glamor_pixmap_status source_status = GLAMOR_NONE;
  753. enum glamor_pixmap_status mask_status = GLAMOR_NONE;
  754. PictFormatShort saved_source_format = 0;
  755. struct shader_key key;
  756. GLfloat source_solid_color[4];
  757. GLfloat mask_solid_color[4];
  758. Bool ret = FALSE;
  759. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) {
  760. glamor_fallback("dest has no fbo.\n");
  761. goto fail;
  762. }
  763. memset(&key, 0, sizeof(key));
  764. if (!source) {
  765. key.source = SHADER_SOURCE_SOLID;
  766. source_solid_color[0] = 0.0;
  767. source_solid_color[1] = 0.0;
  768. source_solid_color[2] = 0.0;
  769. source_solid_color[3] = 0.0;
  770. }
  771. else if (!source->pDrawable) {
  772. if (source->pSourcePict->type == SourcePictTypeSolidFill) {
  773. key.source = SHADER_SOURCE_SOLID;
  774. glamor_get_rgba_from_pixel(source->pSourcePict->solidFill.color,
  775. &source_solid_color[0],
  776. &source_solid_color[1],
  777. &source_solid_color[2],
  778. &source_solid_color[3], PICT_a8r8g8b8);
  779. }
  780. else
  781. goto fail;
  782. }
  783. else {
  784. if (PICT_FORMAT_A(source->format))
  785. key.source = SHADER_SOURCE_TEXTURE_ALPHA;
  786. else
  787. key.source = SHADER_SOURCE_TEXTURE;
  788. }
  789. if (mask) {
  790. if (!mask->pDrawable) {
  791. if (mask->pSourcePict->type == SourcePictTypeSolidFill) {
  792. key.mask = SHADER_MASK_SOLID;
  793. glamor_get_rgba_from_pixel
  794. (mask->pSourcePict->solidFill.color,
  795. &mask_solid_color[0],
  796. &mask_solid_color[1],
  797. &mask_solid_color[2], &mask_solid_color[3], PICT_a8r8g8b8);
  798. }
  799. else
  800. goto fail;
  801. }
  802. else {
  803. key.mask = SHADER_MASK_TEXTURE_ALPHA;
  804. }
  805. if (!mask->componentAlpha) {
  806. key.in = SHADER_IN_NORMAL;
  807. }
  808. else {
  809. if (op == PictOpClear)
  810. key.mask = SHADER_MASK_NONE;
  811. else if (op == PictOpSrc || op == PictOpAdd
  812. || op == PictOpIn || op == PictOpOut
  813. || op == PictOpOverReverse)
  814. key.in = SHADER_IN_CA_SOURCE;
  815. else if (op == PictOpOutReverse || op == PictOpInReverse) {
  816. key.in = SHADER_IN_CA_ALPHA;
  817. }
  818. else {
  819. glamor_fallback("Unsupported component alpha op: %d\n", op);
  820. goto fail;
  821. }
  822. }
  823. }
  824. else {
  825. key.mask = SHADER_MASK_NONE;
  826. key.in = SHADER_IN_SOURCE_ONLY;
  827. }
  828. if (source && source->alphaMap) {
  829. glamor_fallback("source alphaMap\n");
  830. goto fail;
  831. }
  832. if (mask && mask->alphaMap) {
  833. glamor_fallback("mask alphaMap\n");
  834. goto fail;
  835. }
  836. if (key.source == SHADER_SOURCE_TEXTURE ||
  837. key.source == SHADER_SOURCE_TEXTURE_ALPHA) {
  838. source_pixmap = source_pixmap_priv->base.pixmap;
  839. if (source_pixmap == dest_pixmap) {
  840. /* XXX source and the dest share the same texture.
  841. * Does it need special handle? */
  842. glamor_fallback("source == dest\n");
  843. }
  844. if (source_pixmap_priv->base.gl_fbo == GLAMOR_FBO_UNATTACHED) {
  845. #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
  846. source_status = GLAMOR_UPLOAD_PENDING;
  847. #else
  848. glamor_fallback("no texture in source\n");
  849. goto fail;
  850. #endif
  851. }
  852. }
  853. if (key.mask == SHADER_MASK_TEXTURE ||
  854. key.mask == SHADER_MASK_TEXTURE_ALPHA) {
  855. mask_pixmap = mask_pixmap_priv->base.pixmap;
  856. if (mask_pixmap == dest_pixmap) {
  857. glamor_fallback("mask == dest\n");
  858. goto fail;
  859. }
  860. if (mask_pixmap_priv->base.gl_fbo == GLAMOR_FBO_UNATTACHED) {
  861. #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
  862. mask_status = GLAMOR_UPLOAD_PENDING;
  863. #else
  864. glamor_fallback("no texture in mask\n");
  865. goto fail;
  866. #endif
  867. }
  868. }
  869. #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
  870. if (source_status == GLAMOR_UPLOAD_PENDING
  871. && mask_status == GLAMOR_UPLOAD_PENDING
  872. && source_pixmap == mask_pixmap) {
  873. if (source->format != mask->format) {
  874. saved_source_format = source->format;
  875. if (!combine_pict_format(&source->format, source->format,
  876. mask->format, key.in)) {
  877. glamor_fallback("combine source %x mask %x failed.\n",
  878. source->format, mask->format);
  879. goto fail;
  880. }
  881. if (source->format != saved_source_format) {
  882. glamor_picture_format_fixup(source, source_pixmap_priv);
  883. }
  884. /* XXX
  885. * By default, glamor_upload_picture_to_texture will wire alpha to 1
  886. * if one picture doesn't have alpha. So we don't do that again in
  887. * rendering function. But here is a special case, as source and
  888. * mask share the same texture but may have different formats. For
  889. * example, source doesn't have alpha, but mask has alpha. Then the
  890. * texture will have the alpha value for the mask. And will not wire
  891. * to 1 for the source. In this case, we have to use different shader
  892. * to wire the source's alpha to 1.
  893. *
  894. * But this may cause a potential problem if the source's repeat mode
  895. * is REPEAT_NONE, and if the source is smaller than the dest, then
  896. * for the region not covered by the source may be painted incorrectly.
  897. * because we wire the alpha to 1.
  898. *
  899. **/
  900. if (!PICT_FORMAT_A(saved_source_format)
  901. && PICT_FORMAT_A(mask->format))
  902. key.source = SHADER_SOURCE_TEXTURE;
  903. if (!PICT_FORMAT_A(mask->format)
  904. && PICT_FORMAT_A(saved_source_format))
  905. key.mask = SHADER_MASK_TEXTURE;
  906. mask_status = GLAMOR_NONE;
  907. }
  908. source_status = glamor_upload_picture_to_texture(source);
  909. if (source_status != GLAMOR_UPLOAD_DONE) {
  910. glamor_fallback("Failed to upload source texture.\n");
  911. goto fail;
  912. }
  913. }
  914. else {
  915. if (source_status == GLAMOR_UPLOAD_PENDING) {
  916. source_status = glamor_upload_picture_to_texture(source);
  917. if (source_status != GLAMOR_UPLOAD_DONE) {
  918. glamor_fallback("Failed to upload source texture.\n");
  919. goto fail;
  920. }
  921. }
  922. if (mask_status == GLAMOR_UPLOAD_PENDING) {
  923. mask_status = glamor_upload_picture_to_texture(mask);
  924. if (mask_status != GLAMOR_UPLOAD_DONE) {
  925. glamor_fallback("Failed to upload mask texture.\n");
  926. goto fail;
  927. }
  928. }
  929. }
  930. #endif
  931. /* If the source and mask are two differently-formatted views of
  932. * the same pixmap bits, and the pixmap was already uploaded (so
  933. * the dynamic code above doesn't apply), then fall back to
  934. * software. We should use texture views to fix this properly.
  935. */
  936. if (source_pixmap && source_pixmap == mask_pixmap &&
  937. source->format != mask->format) {
  938. goto fail;
  939. }
  940. /*Before enter the rendering stage, we need to fixup
  941. * transformed source and mask, if the transform is not int translate. */
  942. if (key.source != SHADER_SOURCE_SOLID
  943. && source->transform
  944. && !pixman_transform_is_int_translate(source->transform)
  945. && source_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) {
  946. if (!glamor_fixup_pixmap_priv(screen, source_pixmap_priv))
  947. goto fail;
  948. }
  949. if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID
  950. && mask->transform
  951. && !pixman_transform_is_int_translate(mask->transform)
  952. && mask_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) {
  953. if (!glamor_fixup_pixmap_priv(screen, mask_pixmap_priv))
  954. goto fail;
  955. }
  956. if (!glamor_set_composite_op(screen, op, op_info, dest, mask))
  957. goto fail;
  958. *shader = glamor_lookup_composite_shader(screen, &key);
  959. if ((*shader)->prog == 0) {
  960. glamor_fallback("no shader program for this render acccel mode\n");
  961. goto fail;
  962. }
  963. if (key.source == SHADER_SOURCE_SOLID)
  964. memcpy(&(*shader)->source_solid_color[0],
  965. source_solid_color, 4 * sizeof(float));
  966. else {
  967. (*shader)->source_priv = source_pixmap_priv;
  968. (*shader)->source = source;
  969. }
  970. if (key.mask == SHADER_MASK_SOLID)
  971. memcpy(&(*shader)->mask_solid_color[0],
  972. mask_solid_color, 4 * sizeof(float));
  973. else {
  974. (*shader)->mask_priv = mask_pixmap_priv;
  975. (*shader)->mask = mask;
  976. }
  977. ret = TRUE;
  978. memcpy(s_key, &key, sizeof(key));
  979. *psaved_source_format = saved_source_format;
  980. goto done;
  981. fail:
  982. if (saved_source_format)
  983. source->format = saved_source_format;
  984. done:
  985. return ret;
  986. }
  987. void
  988. glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv,
  989. struct shader_key *key,
  990. glamor_composite_shader *shader,
  991. struct blendinfo *op_info)
  992. {
  993. glamor_screen_private *glamor_priv;
  994. glamor_priv = dest_priv->base.glamor_priv;
  995. glamor_make_current(glamor_priv);
  996. glUseProgram(shader->prog);
  997. if (key->source == SHADER_SOURCE_SOLID) {
  998. glamor_set_composite_solid(shader->source_solid_color,
  999. shader->source_uniform_location);
  1000. }
  1001. else {
  1002. glamor_set_composite_texture(glamor_priv, 0,
  1003. shader->source,
  1004. shader->source_priv, shader->source_wh,
  1005. shader->source_repeat_mode);
  1006. }
  1007. if (key->mask != SHADER_MASK_NONE) {
  1008. if (key->mask == SHADER_MASK_SOLID) {
  1009. glamor_set_composite_solid(shader->mask_solid_color,
  1010. shader->mask_uniform_location);
  1011. }
  1012. else {
  1013. glamor_set_composite_texture(glamor_priv, 1,
  1014. shader->mask,
  1015. shader->mask_priv, shader->mask_wh,
  1016. shader->mask_repeat_mode);
  1017. }
  1018. }
  1019. if (op_info->source_blend == GL_ONE && op_info->dest_blend == GL_ZERO) {
  1020. glDisable(GL_BLEND);
  1021. }
  1022. else {
  1023. glEnable(GL_BLEND);
  1024. glBlendFunc(op_info->source_blend, op_info->dest_blend);
  1025. }
  1026. }
  1027. static Bool
  1028. glamor_composite_with_shader(CARD8 op,
  1029. PicturePtr source,
  1030. PicturePtr mask,
  1031. PicturePtr dest,
  1032. glamor_pixmap_private *source_pixmap_priv,
  1033. glamor_pixmap_private *mask_pixmap_priv,
  1034. glamor_pixmap_private *dest_pixmap_priv,
  1035. int nrect, glamor_composite_rect_t *rects,
  1036. Bool two_pass_ca)
  1037. {
  1038. ScreenPtr screen = dest->pDrawable->pScreen;
  1039. glamor_screen_private *glamor_priv = dest_pixmap_priv->base.glamor_priv;
  1040. PixmapPtr dest_pixmap = dest_pixmap_priv->base.pixmap;
  1041. PixmapPtr source_pixmap = NULL;
  1042. PixmapPtr mask_pixmap = NULL;
  1043. GLfloat dst_xscale, dst_yscale;
  1044. GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1;
  1045. struct shader_key key, key_ca;
  1046. int dest_x_off, dest_y_off;
  1047. int source_x_off, source_y_off;
  1048. int mask_x_off, mask_y_off;
  1049. PictFormatShort saved_source_format = 0;
  1050. float src_matrix[9], mask_matrix[9];
  1051. float *psrc_matrix = NULL, *pmask_matrix = NULL;
  1052. int nrect_max;
  1053. Bool ret = FALSE;
  1054. glamor_composite_shader *shader = NULL, *shader_ca = NULL;
  1055. struct blendinfo op_info, op_info_ca;
  1056. if (!glamor_composite_choose_shader(op, source, mask, dest,
  1057. source_pixmap_priv, mask_pixmap_priv,
  1058. dest_pixmap_priv,
  1059. &key, &shader, &op_info,
  1060. &saved_source_format)) {
  1061. glamor_fallback("glamor_composite_choose_shader failed\n");
  1062. return ret;
  1063. }
  1064. if (two_pass_ca) {
  1065. if (!glamor_composite_choose_shader(PictOpAdd, source, mask, dest,
  1066. source_pixmap_priv,
  1067. mask_pixmap_priv, dest_pixmap_priv,
  1068. &key_ca, &shader_ca, &op_info_ca,
  1069. &saved_source_format)) {
  1070. glamor_fallback("glamor_composite_choose_shader failed\n");
  1071. return ret;
  1072. }
  1073. }
  1074. glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv);
  1075. glamor_composite_set_shader_blend(dest_pixmap_priv, &key, shader, &op_info);
  1076. glamor_make_current(glamor_priv);
  1077. glamor_priv->has_source_coords = key.source != SHADER_SOURCE_SOLID;
  1078. glamor_priv->has_mask_coords = (key.mask != SHADER_MASK_NONE &&
  1079. key.mask != SHADER_MASK_SOLID);
  1080. dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable);
  1081. dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap);
  1082. glamor_get_drawable_deltas(dest->pDrawable, dest_pixmap,
  1083. &dest_x_off, &dest_y_off);
  1084. pixmap_priv_get_dest_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale);
  1085. if (glamor_priv->has_source_coords) {
  1086. source_pixmap = source_pixmap_priv->base.pixmap;
  1087. glamor_get_drawable_deltas(source->pDrawable,
  1088. source_pixmap, &source_x_off, &source_y_off);
  1089. pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, &src_yscale);
  1090. if (source->transform) {
  1091. psrc_matrix = src_matrix;
  1092. glamor_picture_get_matrixf(source, psrc_matrix);
  1093. }
  1094. }
  1095. if (glamor_priv->has_mask_coords) {
  1096. mask_pixmap = mask_pixmap_priv->base.pixmap;
  1097. glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap,
  1098. &mask_x_off, &mask_y_off);
  1099. pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, &mask_yscale);
  1100. if (mask->transform) {
  1101. pmask_matrix = mask_matrix;
  1102. glamor_picture_get_matrixf(mask, pmask_matrix);
  1103. }
  1104. }
  1105. nrect_max = MIN(nrect, GLAMOR_COMPOSITE_VBO_VERT_CNT / 4);
  1106. while (nrect) {
  1107. int mrect, rect_processed;
  1108. int vb_stride;
  1109. float *vertices;
  1110. mrect = nrect > nrect_max ? nrect_max : nrect;
  1111. vertices = glamor_setup_composite_vbo(screen, mrect * 4);
  1112. rect_processed = mrect;
  1113. vb_stride = glamor_priv->vb_stride / sizeof(float);
  1114. while (mrect--) {
  1115. INT16 x_source;
  1116. INT16 y_source;
  1117. INT16 x_mask;
  1118. INT16 y_mask;
  1119. INT16 x_dest;
  1120. INT16 y_dest;
  1121. CARD16 width;
  1122. CARD16 height;
  1123. x_dest = rects->x_dst + dest_x_off;
  1124. y_dest = rects->y_dst + dest_y_off;
  1125. x_source = rects->x_src + source_x_off;
  1126. y_source = rects->y_src + source_y_off;
  1127. x_mask = rects->x_mask + mask_x_off;
  1128. y_mask = rects->y_mask + mask_y_off;
  1129. width = rects->width;
  1130. height = rects->height;
  1131. DEBUGF
  1132. ("dest(%d,%d) source(%d %d) mask (%d %d), width %d height %d \n",
  1133. x_dest, y_dest, x_source, y_source, x_mask, y_mask, width,
  1134. height);
  1135. glamor_set_normalize_vcoords_ext(dest_pixmap_priv, dst_xscale,
  1136. dst_yscale, x_dest, y_dest,
  1137. x_dest + width, y_dest + height,
  1138. glamor_priv->yInverted, vertices,
  1139. vb_stride);
  1140. vertices += 2;
  1141. if (key.source != SHADER_SOURCE_SOLID) {
  1142. glamor_set_normalize_tcoords_generic(source_pixmap_priv,
  1143. source->repeatType,
  1144. psrc_matrix, src_xscale,
  1145. src_yscale, x_source,
  1146. y_source, x_source + width,
  1147. y_source + height,
  1148. glamor_priv->yInverted,
  1149. vertices, vb_stride);
  1150. vertices += 2;
  1151. }
  1152. if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) {
  1153. glamor_set_normalize_tcoords_generic(mask_pixmap_priv,
  1154. mask->repeatType,
  1155. pmask_matrix, mask_xscale,
  1156. mask_yscale, x_mask,
  1157. y_mask, x_mask + width,
  1158. y_mask + height,
  1159. glamor_priv->yInverted,
  1160. vertices, vb_stride);
  1161. vertices += 2;
  1162. }
  1163. glamor_priv->render_nr_verts += 4;
  1164. rects++;
  1165. /* We've incremented by one of our 4 verts, now do the other 3. */
  1166. vertices += 3 * vb_stride;
  1167. }
  1168. glamor_put_vbo_space(screen);
  1169. glamor_flush_composite_rects(screen);
  1170. nrect -= rect_processed;
  1171. if (two_pass_ca) {
  1172. glamor_composite_set_shader_blend(dest_pixmap_priv,
  1173. &key_ca, shader_ca, &op_info_ca);
  1174. glamor_flush_composite_rects(screen);
  1175. if (nrect)
  1176. glamor_composite_set_shader_blend(dest_pixmap_priv,
  1177. &key, shader, &op_info);
  1178. }
  1179. }
  1180. glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
  1181. glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
  1182. glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
  1183. glDisable(GL_BLEND);
  1184. DEBUGF("finish rendering.\n");
  1185. glamor_priv->state = RENDER_STATE;
  1186. glamor_priv->render_idle_cnt = 0;
  1187. if (saved_source_format)
  1188. source->format = saved_source_format;
  1189. ret = TRUE;
  1190. return ret;
  1191. }
  1192. PicturePtr
  1193. glamor_convert_gradient_picture(ScreenPtr screen,
  1194. PicturePtr source,
  1195. int x_source,
  1196. int y_source, int width, int height)
  1197. {
  1198. PixmapPtr pixmap;
  1199. PicturePtr dst = NULL;
  1200. int error;
  1201. PictFormatShort format;
  1202. if (!source->pDrawable)
  1203. format = PICT_a8r8g8b8;
  1204. else
  1205. format = source->format;
  1206. #ifdef GLAMOR_GRADIENT_SHADER
  1207. if (!source->pDrawable) {
  1208. if (source->pSourcePict->type == SourcePictTypeLinear) {
  1209. dst = glamor_generate_linear_gradient_picture(screen,
  1210. source, x_source,
  1211. y_source, width,
  1212. height, format);
  1213. }
  1214. else if (source->pSourcePict->type == SourcePictTypeRadial) {
  1215. dst = glamor_generate_radial_gradient_picture(screen,
  1216. source, x_source,
  1217. y_source, width,
  1218. height, format);
  1219. }
  1220. if (dst) {
  1221. #if 0 /* Debug to compare it to pixman, Enable it if needed. */
  1222. glamor_compare_pictures(screen, source,
  1223. dst, x_source, y_source, width, height,
  1224. 0, 3);
  1225. #endif
  1226. return dst;
  1227. }
  1228. }
  1229. #endif
  1230. pixmap = glamor_create_pixmap(screen,
  1231. width,
  1232. height,
  1233. PIXMAN_FORMAT_DEPTH(format),
  1234. GLAMOR_CREATE_PIXMAP_CPU);
  1235. if (!pixmap)
  1236. return NULL;
  1237. dst = CreatePicture(0,
  1238. &pixmap->drawable,
  1239. PictureMatchFormat(screen,
  1240. PIXMAN_FORMAT_DEPTH(format),
  1241. format), 0, 0, serverClient, &error);
  1242. glamor_destroy_pixmap(pixmap);
  1243. if (!dst)
  1244. return NULL;
  1245. ValidatePicture(dst);
  1246. fbComposite(PictOpSrc, source, NULL, dst, x_source, y_source,
  1247. 0, 0, 0, 0, width, height);
  1248. return dst;
  1249. }
  1250. Bool
  1251. glamor_composite_clipped_region(CARD8 op,
  1252. PicturePtr source,
  1253. PicturePtr mask,
  1254. PicturePtr dest,
  1255. glamor_pixmap_private *source_pixmap_priv,
  1256. glamor_pixmap_private *mask_pixmap_priv,
  1257. glamor_pixmap_private *dest_pixmap_priv,
  1258. RegionPtr region,
  1259. int x_source,
  1260. int y_source,
  1261. int x_mask, int y_mask, int x_dest, int y_dest)
  1262. {
  1263. ScreenPtr screen = dest->pDrawable->pScreen;
  1264. PixmapPtr source_pixmap = NULL, mask_pixmap = NULL;
  1265. PicturePtr temp_src = source, temp_mask = mask;
  1266. glamor_pixmap_private *temp_src_priv = source_pixmap_priv;
  1267. glamor_pixmap_private *temp_mask_priv = mask_pixmap_priv;
  1268. int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask;
  1269. BoxPtr extent;
  1270. glamor_composite_rect_t rect[10];
  1271. glamor_composite_rect_t *prect = rect;
  1272. int prect_size = ARRAY_SIZE(rect);
  1273. int ok = FALSE;
  1274. int i;
  1275. int width;
  1276. int height;
  1277. BoxPtr box;
  1278. int nbox;
  1279. Bool two_pass_ca = FALSE;
  1280. extent = RegionExtents(region);
  1281. box = RegionRects(region);
  1282. nbox = RegionNumRects(region);
  1283. width = extent->x2 - extent->x1;
  1284. height = extent->y2 - extent->y1;
  1285. x_temp_src = x_source;
  1286. y_temp_src = y_source;
  1287. x_temp_mask = x_mask;
  1288. y_temp_mask = y_mask;
  1289. DEBUGF("clipped (%d %d) (%d %d) (%d %d) width %d height %d \n",
  1290. x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height);
  1291. if (source_pixmap_priv)
  1292. source_pixmap = source_pixmap_priv->base.pixmap;
  1293. if (mask_pixmap_priv)
  1294. mask_pixmap = mask_pixmap_priv->base.pixmap;
  1295. /* XXX is it possible source mask have non-zero drawable.x/y? */
  1296. if (source
  1297. && ((!source->pDrawable
  1298. && (source->pSourcePict->type != SourcePictTypeSolidFill))
  1299. || (source->pDrawable
  1300. && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv)
  1301. && (source_pixmap->drawable.width != width
  1302. || source_pixmap->drawable.height != height)))) {
  1303. temp_src =
  1304. glamor_convert_gradient_picture(screen, source,
  1305. extent->x1 + x_source - x_dest - dest->pDrawable->x,
  1306. extent->y1 + y_source - y_dest - dest->pDrawable->y,
  1307. width, height);
  1308. if (!temp_src) {
  1309. temp_src = source;
  1310. goto out;
  1311. }
  1312. temp_src_priv =
  1313. glamor_get_pixmap_private((PixmapPtr) (temp_src->pDrawable));
  1314. x_temp_src = -extent->x1 + x_dest + dest->pDrawable->x;
  1315. y_temp_src = -extent->y1 + y_dest + dest->pDrawable->y;
  1316. }
  1317. if (mask
  1318. &&
  1319. ((!mask->pDrawable
  1320. && (mask->pSourcePict->type != SourcePictTypeSolidFill))
  1321. || (mask->pDrawable && !GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv)
  1322. && (mask_pixmap->drawable.width != width
  1323. || mask_pixmap->drawable.height != height)))) {
  1324. /* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity
  1325. * to do reduce one convertion. */
  1326. temp_mask =
  1327. glamor_convert_gradient_picture(screen, mask,
  1328. extent->x1 + x_mask - x_dest - dest->pDrawable->x,
  1329. extent->y1 + y_mask - y_dest - dest->pDrawable->y,
  1330. width, height);
  1331. if (!temp_mask) {
  1332. temp_mask = mask;
  1333. goto out;
  1334. }
  1335. temp_mask_priv =
  1336. glamor_get_pixmap_private((PixmapPtr) (temp_mask->pDrawable));
  1337. x_temp_mask = -extent->x1 + x_dest + dest->pDrawable->x;
  1338. y_temp_mask = -extent->y1 + y_dest + dest->pDrawable->y;
  1339. }
  1340. /* Do two-pass PictOpOver componentAlpha, until we enable
  1341. * dual source color blending.
  1342. */
  1343. if (mask && mask->componentAlpha) {
  1344. if (op == PictOpOver) {
  1345. two_pass_ca = TRUE;
  1346. op = PictOpOutReverse;
  1347. }
  1348. }
  1349. if (!mask && temp_src) {
  1350. if (glamor_composite_with_copy(op, temp_src, dest,
  1351. x_temp_src, y_temp_src,
  1352. x_dest, y_dest, region)) {
  1353. ok = TRUE;
  1354. goto out;
  1355. }
  1356. }
  1357. /*XXXXX, self copy? */
  1358. x_dest += dest->pDrawable->x;
  1359. y_dest += dest->pDrawable->y;
  1360. if (temp_src && temp_src->pDrawable) {
  1361. x_temp_src += temp_src->pDrawable->x;
  1362. y_temp_src += temp_src->pDrawable->y;
  1363. }
  1364. if (temp_mask && temp_mask->pDrawable) {
  1365. x_temp_mask += temp_mask->pDrawable->x;
  1366. y_temp_mask += temp_mask->pDrawable->y;
  1367. }
  1368. if (nbox > ARRAY_SIZE(rect)) {
  1369. prect = calloc(nbox, sizeof(*prect));
  1370. if (prect)
  1371. prect_size = nbox;
  1372. else {
  1373. prect = rect;
  1374. prect_size = ARRAY_SIZE(rect);
  1375. }
  1376. }
  1377. while (nbox) {
  1378. int box_cnt;
  1379. box_cnt = nbox > prect_size ? prect_size : nbox;
  1380. for (i = 0; i < box_cnt; i++) {
  1381. prect[i].x_src = box[i].x1 + x_temp_src - x_dest;
  1382. prect[i].y_src = box[i].y1 + y_temp_src - y_dest;
  1383. prect[i].x_mask = box[i].x1 + x_temp_mask - x_dest;
  1384. prect[i].y_mask = box[i].y1 + y_temp_mask - y_dest;
  1385. prect[i].x_dst = box[i].x1;
  1386. prect[i].y_dst = box[i].y1;
  1387. prect[i].width = box[i].x2 - box[i].x1;
  1388. prect[i].height = box[i].y2 - box[i].y1;
  1389. DEBUGF("dest %d %d \n", prect[i].x_dst, prect[i].y_dst);
  1390. }
  1391. ok = glamor_composite_with_shader(op, temp_src, temp_mask, dest,
  1392. temp_src_priv, temp_mask_priv,
  1393. dest_pixmap_priv,
  1394. box_cnt, prect, two_pass_ca);
  1395. if (!ok)
  1396. break;
  1397. nbox -= box_cnt;
  1398. box += box_cnt;
  1399. }
  1400. if (prect != rect)
  1401. free(prect);
  1402. out:
  1403. if (temp_src != source)
  1404. FreePicture(temp_src, 0);
  1405. if (temp_mask != mask)
  1406. FreePicture(temp_mask, 0);
  1407. return ok;
  1408. }
  1409. static Bool
  1410. _glamor_composite(CARD8 op,
  1411. PicturePtr source,
  1412. PicturePtr mask,
  1413. PicturePtr dest,
  1414. INT16 x_source,
  1415. INT16 y_source,
  1416. INT16 x_mask,
  1417. INT16 y_mask,
  1418. INT16 x_dest, INT16 y_dest,
  1419. CARD16 width, CARD16 height, Bool fallback)
  1420. {
  1421. ScreenPtr screen = dest->pDrawable->pScreen;
  1422. glamor_pixmap_private *dest_pixmap_priv;
  1423. glamor_pixmap_private *source_pixmap_priv = NULL, *mask_pixmap_priv = NULL;
  1424. PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable);
  1425. PixmapPtr source_pixmap = NULL, mask_pixmap = NULL;
  1426. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  1427. Bool ret = TRUE;
  1428. RegionRec region;
  1429. BoxPtr extent;
  1430. int nbox, ok = FALSE;
  1431. PixmapPtr sub_dest_pixmap = NULL;
  1432. PixmapPtr sub_source_pixmap = NULL;
  1433. PixmapPtr sub_mask_pixmap = NULL;
  1434. int dest_x_off, dest_y_off, saved_dest_x, saved_dest_y;
  1435. int source_x_off, source_y_off, saved_source_x, saved_source_y;
  1436. int mask_x_off, mask_y_off, saved_mask_x, saved_mask_y;
  1437. DrawablePtr saved_dest_drawable;
  1438. DrawablePtr saved_source_drawable;
  1439. DrawablePtr saved_mask_drawable;
  1440. int force_clip = 0;
  1441. dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap);
  1442. if (source->pDrawable) {
  1443. source_pixmap = glamor_get_drawable_pixmap(source->pDrawable);
  1444. source_pixmap_priv = glamor_get_pixmap_private(source_pixmap);
  1445. if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY)
  1446. goto fail;
  1447. }
  1448. if (mask && mask->pDrawable) {
  1449. mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable);
  1450. mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap);
  1451. if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY)
  1452. goto fail;
  1453. }
  1454. DEBUGF
  1455. ("source pixmap %p (%d %d) mask(%d %d) dest(%d %d) width %d height %d \n",
  1456. source_pixmap, x_source, y_source, x_mask, y_mask, x_dest, y_dest,
  1457. width, height);
  1458. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) {
  1459. goto fail;
  1460. }
  1461. if (op >= ARRAY_SIZE(composite_op_info))
  1462. goto fail;
  1463. if (mask && mask->componentAlpha) {
  1464. if (op == PictOpAtop
  1465. || op == PictOpAtopReverse
  1466. || op == PictOpXor || op >= PictOpSaturate) {
  1467. glamor_fallback("glamor_composite(): component alpha op %x\n", op);
  1468. goto fail;
  1469. }
  1470. }
  1471. if ((source && source->filter >= PictFilterConvolution)
  1472. || (mask && mask->filter >= PictFilterConvolution)) {
  1473. glamor_fallback("glamor_composite(): unsupported filter\n");
  1474. goto fail;
  1475. }
  1476. if (!miComputeCompositeRegion(&region,
  1477. source, mask, dest,
  1478. x_source +
  1479. (source_pixmap ? source->pDrawable->x : 0),
  1480. y_source +
  1481. (source_pixmap ? source->pDrawable->y : 0),
  1482. x_mask +
  1483. (mask_pixmap ? mask->pDrawable->x : 0),
  1484. y_mask +
  1485. (mask_pixmap ? mask->pDrawable->y : 0),
  1486. x_dest + dest->pDrawable->x,
  1487. y_dest + dest->pDrawable->y, width, height)) {
  1488. ret = TRUE;
  1489. goto done;
  1490. }
  1491. nbox = REGION_NUM_RECTS(&region);
  1492. DEBUGF("first clipped when compositing.\n");
  1493. DEBUGRegionPrint(&region);
  1494. extent = RegionExtents(&region);
  1495. if (nbox == 0) {
  1496. ret = TRUE;
  1497. goto done;
  1498. }
  1499. /* If destination is not a large pixmap, but the region is larger
  1500. * than texture size limitation, and source or mask is memory pixmap,
  1501. * then there may be need to load a large memory pixmap to a
  1502. * texture, and this is not permitted. Then we force to clip the
  1503. * destination and make sure latter will not upload a large memory
  1504. * pixmap. */
  1505. if (!glamor_check_fbo_size(glamor_priv,
  1506. extent->x2 - extent->x1, extent->y2 - extent->y1)
  1507. && (dest_pixmap_priv->type != GLAMOR_TEXTURE_LARGE)
  1508. && ((source_pixmap_priv
  1509. && (source_pixmap_priv->type == GLAMOR_MEMORY ||
  1510. source->repeatType == RepeatPad))
  1511. || (mask_pixmap_priv &&
  1512. (mask_pixmap_priv->type == GLAMOR_MEMORY ||
  1513. mask->repeatType == RepeatPad))
  1514. || (!source_pixmap_priv &&
  1515. (source->pSourcePict->type != SourcePictTypeSolidFill))
  1516. || (!mask_pixmap_priv && mask &&
  1517. mask->pSourcePict->type != SourcePictTypeSolidFill)))
  1518. force_clip = 1;
  1519. if (force_clip || dest_pixmap_priv->type == GLAMOR_TEXTURE_LARGE
  1520. || (source_pixmap_priv
  1521. && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE)
  1522. || (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE))
  1523. ok = glamor_composite_largepixmap_region(op,
  1524. source, mask, dest,
  1525. source_pixmap_priv,
  1526. mask_pixmap_priv,
  1527. dest_pixmap_priv,
  1528. &region, force_clip,
  1529. x_source, y_source,
  1530. x_mask, y_mask,
  1531. x_dest, y_dest, width, height);
  1532. else
  1533. ok = glamor_composite_clipped_region(op, source,
  1534. mask, dest,
  1535. source_pixmap_priv,
  1536. mask_pixmap_priv,
  1537. dest_pixmap_priv,
  1538. &region,
  1539. x_source, y_source,
  1540. x_mask, y_mask, x_dest, y_dest);
  1541. REGION_UNINIT(dest->pDrawable->pScreen, &region);
  1542. if (ok)
  1543. goto done;
  1544. fail:
  1545. if (!fallback && glamor_ddx_fallback_check_pixmap(&dest_pixmap->drawable)
  1546. && (!source_pixmap
  1547. || glamor_ddx_fallback_check_pixmap(&source_pixmap->drawable))
  1548. && (!mask_pixmap
  1549. || glamor_ddx_fallback_check_pixmap(&mask_pixmap->drawable))) {
  1550. ret = FALSE;
  1551. goto done;
  1552. }
  1553. glamor_fallback
  1554. ("from picts %p:%p %dx%d / %p:%p %d x %d (%c,%c) to pict %p:%p %dx%d (%c)\n",
  1555. source, source->pDrawable,
  1556. source->pDrawable ? source->pDrawable->width : 0,
  1557. source->pDrawable ? source->pDrawable->height : 0, mask,
  1558. (!mask) ? NULL : mask->pDrawable, (!mask
  1559. || !mask->pDrawable) ? 0 :
  1560. mask->pDrawable->width, (!mask
  1561. || !mask->pDrawable) ? 0 : mask->
  1562. pDrawable->height, glamor_get_picture_location(source),
  1563. glamor_get_picture_location(mask), dest, dest->pDrawable,
  1564. dest->pDrawable->width, dest->pDrawable->height,
  1565. glamor_get_picture_location(dest));
  1566. #define GET_SUB_PICTURE(p, access) do { \
  1567. glamor_get_drawable_deltas(p->pDrawable, p ##_pixmap, \
  1568. & p ##_x_off, & p ##_y_off); \
  1569. sub_ ##p ##_pixmap = glamor_get_sub_pixmap(p ##_pixmap, \
  1570. x_ ##p + p ##_x_off + p->pDrawable->x, \
  1571. y_ ##p + p ##_y_off + p->pDrawable->y, \
  1572. width, height, access); \
  1573. if (sub_ ##p ##_pixmap != NULL) { \
  1574. saved_ ##p ##_drawable = p->pDrawable; \
  1575. saved_ ##p ##_x = x_ ##p; \
  1576. saved_ ##p ##_y = y_ ##p; \
  1577. if (p->pCompositeClip) \
  1578. pixman_region_translate (p->pCompositeClip, \
  1579. -p->pDrawable->x - x_ ##p, \
  1580. -p->pDrawable->y - y_ ##p); \
  1581. p->pDrawable = &sub_ ##p ##_pixmap->drawable; \
  1582. x_ ##p = 0; \
  1583. y_ ##p = 0; \
  1584. } } while(0)
  1585. GET_SUB_PICTURE(dest, GLAMOR_ACCESS_RW);
  1586. if (source->pDrawable && !source->transform)
  1587. GET_SUB_PICTURE(source, GLAMOR_ACCESS_RO);
  1588. if (mask && mask->pDrawable && !mask->transform)
  1589. GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO);
  1590. if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW) &&
  1591. glamor_prepare_access_picture(source, GLAMOR_ACCESS_RO) &&
  1592. glamor_prepare_access_picture(mask, GLAMOR_ACCESS_RO)) {
  1593. fbComposite(op,
  1594. source, mask, dest,
  1595. x_source, y_source,
  1596. x_mask, y_mask, x_dest, y_dest, width, height);
  1597. }
  1598. glamor_finish_access_picture(mask);
  1599. glamor_finish_access_picture(source);
  1600. glamor_finish_access_picture(dest);
  1601. #define PUT_SUB_PICTURE(p, access) do { \
  1602. if (sub_ ##p ##_pixmap != NULL) { \
  1603. x_ ##p = saved_ ##p ##_x; \
  1604. y_ ##p = saved_ ##p ##_y; \
  1605. p->pDrawable = saved_ ##p ##_drawable; \
  1606. if (p->pCompositeClip) \
  1607. pixman_region_translate (p->pCompositeClip, \
  1608. p->pDrawable->x + x_ ##p, \
  1609. p->pDrawable->y + y_ ##p); \
  1610. glamor_put_sub_pixmap(sub_ ##p ##_pixmap, p ##_pixmap, \
  1611. x_ ##p + p ##_x_off + p->pDrawable->x, \
  1612. y_ ##p + p ##_y_off + p->pDrawable->y, \
  1613. width, height, access); \
  1614. }} while(0)
  1615. if (mask && mask->pDrawable)
  1616. PUT_SUB_PICTURE(mask, GLAMOR_ACCESS_RO);
  1617. if (source->pDrawable)
  1618. PUT_SUB_PICTURE(source, GLAMOR_ACCESS_RO);
  1619. PUT_SUB_PICTURE(dest, GLAMOR_ACCESS_RW);
  1620. done:
  1621. return ret;
  1622. }
  1623. void
  1624. glamor_composite(CARD8 op,
  1625. PicturePtr source,
  1626. PicturePtr mask,
  1627. PicturePtr dest,
  1628. INT16 x_source,
  1629. INT16 y_source,
  1630. INT16 x_mask,
  1631. INT16 y_mask,
  1632. INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height)
  1633. {
  1634. _glamor_composite(op, source, mask, dest, x_source, y_source,
  1635. x_mask, y_mask, x_dest, y_dest, width, height, TRUE);
  1636. }
  1637. Bool
  1638. glamor_composite_nf(CARD8 op,
  1639. PicturePtr source,
  1640. PicturePtr mask,
  1641. PicturePtr dest,
  1642. INT16 x_source,
  1643. INT16 y_source,
  1644. INT16 x_mask,
  1645. INT16 y_mask,
  1646. INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height)
  1647. {
  1648. return _glamor_composite(op, source, mask, dest, x_source, y_source,
  1649. x_mask, y_mask, x_dest, y_dest, width, height,
  1650. FALSE);
  1651. }
  1652. static void
  1653. glamor_get_src_rect_extent(int nrect,
  1654. glamor_composite_rect_t *rects, BoxPtr extent)
  1655. {
  1656. extent->x1 = MAXSHORT;
  1657. extent->y1 = MAXSHORT;
  1658. extent->x2 = MINSHORT;
  1659. extent->y2 = MINSHORT;
  1660. while (nrect--) {
  1661. if (extent->x1 > rects->x_src)
  1662. extent->x1 = rects->x_src;
  1663. if (extent->y1 > rects->y_src)
  1664. extent->y1 = rects->y_src;
  1665. if (extent->x2 < rects->x_src + rects->width)
  1666. extent->x2 = rects->x_src + rects->width;
  1667. if (extent->y2 < rects->y_src + rects->height)
  1668. extent->y2 = rects->y_src + rects->height;
  1669. rects++;
  1670. }
  1671. }
  1672. static void
  1673. glamor_composite_src_rect_translate(int nrect,
  1674. glamor_composite_rect_t *rects,
  1675. int x, int y)
  1676. {
  1677. while (nrect--) {
  1678. rects->x_src += x;
  1679. rects->y_src += y;
  1680. rects++;
  1681. }
  1682. }
  1683. void
  1684. glamor_composite_glyph_rects(CARD8 op,
  1685. PicturePtr src, PicturePtr mask, PicturePtr dst,
  1686. int nrect, glamor_composite_rect_t *rects)
  1687. {
  1688. int n;
  1689. PicturePtr temp_src = NULL;
  1690. glamor_composite_rect_t *r;
  1691. ValidatePicture(src);
  1692. ValidatePicture(dst);
  1693. if (!(glamor_is_large_picture(src)
  1694. || (mask && glamor_is_large_picture(mask))
  1695. || glamor_is_large_picture(dst))) {
  1696. glamor_pixmap_private *src_pixmap_priv = NULL;
  1697. glamor_pixmap_private *mask_pixmap_priv = NULL;
  1698. glamor_pixmap_private *dst_pixmap_priv;
  1699. glamor_pixmap_private *temp_src_priv = NULL;
  1700. BoxRec src_extent;
  1701. dst_pixmap_priv = glamor_get_pixmap_private
  1702. (glamor_get_drawable_pixmap(dst->pDrawable));
  1703. if (mask && mask->pDrawable)
  1704. mask_pixmap_priv = glamor_get_pixmap_private
  1705. (glamor_get_drawable_pixmap(mask->pDrawable));
  1706. if (src->pDrawable)
  1707. src_pixmap_priv = glamor_get_pixmap_private
  1708. (glamor_get_drawable_pixmap(src->pDrawable));
  1709. if (!src->pDrawable
  1710. && (src->pSourcePict->type != SourcePictTypeSolidFill)) {
  1711. glamor_get_src_rect_extent(nrect, rects, &src_extent);
  1712. temp_src = glamor_convert_gradient_picture(dst->pDrawable->pScreen,
  1713. src,
  1714. src_extent.x1,
  1715. src_extent.y1,
  1716. src_extent.x2 -
  1717. src_extent.x1,
  1718. src_extent.y2 -
  1719. src_extent.y1);
  1720. if (!temp_src)
  1721. goto fallback;
  1722. temp_src_priv = glamor_get_pixmap_private
  1723. ((PixmapPtr) (temp_src->pDrawable));
  1724. glamor_composite_src_rect_translate(nrect, rects,
  1725. -src_extent.x1, -src_extent.y1);
  1726. }
  1727. else {
  1728. temp_src = src;
  1729. temp_src_priv = src_pixmap_priv;
  1730. }
  1731. if (mask && mask->componentAlpha) {
  1732. if (op == PictOpOver) {
  1733. if (glamor_composite_with_shader(PictOpOutReverse,
  1734. temp_src, mask, dst,
  1735. temp_src_priv,
  1736. mask_pixmap_priv,
  1737. dst_pixmap_priv, nrect, rects,
  1738. TRUE))
  1739. goto done;
  1740. }
  1741. }
  1742. else {
  1743. if (glamor_composite_with_shader
  1744. (op, temp_src, mask, dst, temp_src_priv, mask_pixmap_priv,
  1745. dst_pixmap_priv, nrect, rects, FALSE))
  1746. goto done;
  1747. }
  1748. }
  1749. fallback:
  1750. n = nrect;
  1751. r = rects;
  1752. while (n--) {
  1753. CompositePicture(op,
  1754. temp_src ? temp_src : src,
  1755. mask,
  1756. dst,
  1757. r->x_src, r->y_src,
  1758. r->x_mask, r->y_mask,
  1759. r->x_dst, r->y_dst, r->width, r->height);
  1760. r++;
  1761. }
  1762. done:
  1763. if (temp_src && temp_src != src)
  1764. FreePicture(temp_src, 0);
  1765. }
  1766. static Bool
  1767. _glamor_composite_rects(CARD8 op,
  1768. PicturePtr pDst,
  1769. xRenderColor *color,
  1770. int nRect, xRectangle *rects, Bool fallback)
  1771. {
  1772. miCompositeRects(op, pDst, color, nRect, rects);
  1773. return TRUE;
  1774. }
  1775. void
  1776. glamor_composite_rects(CARD8 op,
  1777. PicturePtr pDst,
  1778. xRenderColor *color, int nRect, xRectangle *rects)
  1779. {
  1780. _glamor_composite_rects(op, pDst, color, nRect, rects, TRUE);
  1781. }
  1782. Bool
  1783. glamor_composite_rects_nf(CARD8 op,
  1784. PicturePtr pDst,
  1785. xRenderColor *color, int nRect, xRectangle *rects)
  1786. {
  1787. return _glamor_composite_rects(op, pDst, color, nRect, rects, FALSE);
  1788. }
  1789. #endif /* RENDER */