glamor_pixmap.c 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690
  1. /*
  2. * Copyright © 2001 Keith Packard
  3. * Copyright © 2008 Intel Corporation
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the "Software"),
  7. * to deal in the Software without restriction, including without limitation
  8. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. * and/or sell copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice (including the next
  13. * paragraph) shall be included in all copies or substantial portions of the
  14. * Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. *
  24. * Authors:
  25. * Eric Anholt <eric@anholt.net>
  26. * Zhigang Gong <zhigang.gong@linux.intel.com>
  27. *
  28. */
  29. #include <stdlib.h>
  30. #include "glamor_priv.h"
  31. /**
  32. * Sets the offsets to add to coordinates to make them address the same bits in
  33. * the backing drawable. These coordinates are nonzero only for redirected
  34. * windows.
  35. */
  36. void
  37. glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap,
  38. int *x, int *y)
  39. {
  40. #ifdef COMPOSITE
  41. if (drawable->type == DRAWABLE_WINDOW) {
  42. *x = -pixmap->screen_x;
  43. *y = -pixmap->screen_y;
  44. return;
  45. }
  46. #endif
  47. *x = 0;
  48. *y = 0;
  49. }
  50. void
  51. glamor_pixmap_init(ScreenPtr screen)
  52. {
  53. }
  54. void
  55. glamor_pixmap_fini(ScreenPtr screen)
  56. {
  57. }
  58. void
  59. glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *fbo, int x0, int y0,
  60. int width, int height)
  61. {
  62. glamor_make_current(fbo->glamor_priv);
  63. glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
  64. glViewport(x0, y0, width, height);
  65. }
  66. void
  67. glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv)
  68. {
  69. int w, h;
  70. PIXMAP_PRIV_GET_ACTUAL_SIZE(pixmap_priv, w, h);
  71. glamor_set_destination_pixmap_fbo(pixmap_priv->base.fbo, 0, 0, w, h);
  72. }
  73. int
  74. glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv)
  75. {
  76. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
  77. return -1;
  78. glamor_set_destination_pixmap_priv_nc(pixmap_priv);
  79. return 0;
  80. }
  81. int
  82. glamor_set_destination_pixmap(PixmapPtr pixmap)
  83. {
  84. int err;
  85. glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
  86. err = glamor_set_destination_pixmap_priv(pixmap_priv);
  87. return err;
  88. }
  89. Bool
  90. glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask)
  91. {
  92. if (glamor_pm_is_solid(&pixmap->drawable, planemask)) {
  93. return GL_TRUE;
  94. }
  95. glamor_fallback("unsupported planemask %lx\n", planemask);
  96. return GL_FALSE;
  97. }
  98. Bool
  99. glamor_set_alu(ScreenPtr screen, unsigned char alu)
  100. {
  101. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  102. if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) {
  103. if (alu != GXcopy)
  104. return FALSE;
  105. else
  106. return TRUE;
  107. }
  108. if (alu == GXcopy) {
  109. glDisable(GL_COLOR_LOGIC_OP);
  110. return TRUE;
  111. }
  112. glEnable(GL_COLOR_LOGIC_OP);
  113. switch (alu) {
  114. case GXclear:
  115. glLogicOp(GL_CLEAR);
  116. break;
  117. case GXand:
  118. glLogicOp(GL_AND);
  119. break;
  120. case GXandReverse:
  121. glLogicOp(GL_AND_REVERSE);
  122. break;
  123. case GXandInverted:
  124. glLogicOp(GL_AND_INVERTED);
  125. break;
  126. case GXnoop:
  127. glLogicOp(GL_NOOP);
  128. break;
  129. case GXxor:
  130. glLogicOp(GL_XOR);
  131. break;
  132. case GXor:
  133. glLogicOp(GL_OR);
  134. break;
  135. case GXnor:
  136. glLogicOp(GL_NOR);
  137. break;
  138. case GXequiv:
  139. glLogicOp(GL_EQUIV);
  140. break;
  141. case GXinvert:
  142. glLogicOp(GL_INVERT);
  143. break;
  144. case GXorReverse:
  145. glLogicOp(GL_OR_REVERSE);
  146. break;
  147. case GXcopyInverted:
  148. glLogicOp(GL_COPY_INVERTED);
  149. break;
  150. case GXorInverted:
  151. glLogicOp(GL_OR_INVERTED);
  152. break;
  153. case GXnand:
  154. glLogicOp(GL_NAND);
  155. break;
  156. case GXset:
  157. glLogicOp(GL_SET);
  158. break;
  159. default:
  160. glamor_fallback("unsupported alu %x\n", alu);
  161. return FALSE;
  162. }
  163. return TRUE;
  164. }
  165. /*
  166. * Map picture's format to the correct gl texture format and type.
  167. * no_alpha is used to indicate whehter we need to wire alpha to 1.
  168. *
  169. * Although opengl support A1/GL_BITMAP, we still don't use it
  170. * here, it seems that mesa has bugs when uploading a A1 bitmap.
  171. *
  172. * Return 0 if find a matched texture type. Otherwise return -1.
  173. **/
  174. static int
  175. glamor_get_tex_format_type_from_pictformat_gl(PictFormatShort format,
  176. GLenum *tex_format,
  177. GLenum *tex_type,
  178. int *no_alpha,
  179. int *revert,
  180. int *swap_rb, int is_upload)
  181. {
  182. *no_alpha = 0;
  183. *revert = REVERT_NONE;
  184. *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING;
  185. switch (format) {
  186. case PICT_a1:
  187. *tex_format = GL_ALPHA;
  188. *tex_type = GL_UNSIGNED_BYTE;
  189. *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1;
  190. break;
  191. case PICT_b8g8r8x8:
  192. *no_alpha = 1;
  193. case PICT_b8g8r8a8:
  194. *tex_format = GL_BGRA;
  195. *tex_type = GL_UNSIGNED_INT_8_8_8_8;
  196. break;
  197. case PICT_x8r8g8b8:
  198. *no_alpha = 1;
  199. case PICT_a8r8g8b8:
  200. *tex_format = GL_BGRA;
  201. *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
  202. break;
  203. case PICT_x8b8g8r8:
  204. *no_alpha = 1;
  205. case PICT_a8b8g8r8:
  206. *tex_format = GL_RGBA;
  207. *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
  208. break;
  209. case PICT_x2r10g10b10:
  210. *no_alpha = 1;
  211. case PICT_a2r10g10b10:
  212. *tex_format = GL_BGRA;
  213. *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV;
  214. break;
  215. case PICT_x2b10g10r10:
  216. *no_alpha = 1;
  217. case PICT_a2b10g10r10:
  218. *tex_format = GL_RGBA;
  219. *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV;
  220. break;
  221. case PICT_r5g6b5:
  222. *tex_format = GL_RGB;
  223. *tex_type = GL_UNSIGNED_SHORT_5_6_5;
  224. break;
  225. case PICT_b5g6r5:
  226. *tex_format = GL_RGB;
  227. *tex_type = GL_UNSIGNED_SHORT_5_6_5_REV;
  228. break;
  229. case PICT_x1b5g5r5:
  230. *no_alpha = 1;
  231. case PICT_a1b5g5r5:
  232. *tex_format = GL_RGBA;
  233. *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
  234. break;
  235. case PICT_x1r5g5b5:
  236. *no_alpha = 1;
  237. case PICT_a1r5g5b5:
  238. *tex_format = GL_BGRA;
  239. *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
  240. break;
  241. case PICT_a8:
  242. *tex_format = GL_ALPHA;
  243. *tex_type = GL_UNSIGNED_BYTE;
  244. break;
  245. case PICT_x4r4g4b4:
  246. *no_alpha = 1;
  247. case PICT_a4r4g4b4:
  248. *tex_format = GL_BGRA;
  249. *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
  250. break;
  251. case PICT_x4b4g4r4:
  252. *no_alpha = 1;
  253. case PICT_a4b4g4r4:
  254. *tex_format = GL_RGBA;
  255. *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
  256. break;
  257. default:
  258. return -1;
  259. }
  260. return 0;
  261. }
  262. #define IS_LITTLE_ENDIAN (IMAGE_BYTE_ORDER == LSBFirst)
  263. static int
  264. glamor_get_tex_format_type_from_pictformat_gles2(PictFormatShort format,
  265. GLenum *tex_format,
  266. GLenum *tex_type,
  267. int *no_alpha,
  268. int *revert,
  269. int *swap_rb, int is_upload)
  270. {
  271. int need_swap_rb = 0;
  272. *no_alpha = 0;
  273. *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL;
  274. switch (format) {
  275. case PICT_b8g8r8x8:
  276. *no_alpha = 1;
  277. case PICT_b8g8r8a8:
  278. *tex_format = GL_RGBA;
  279. *tex_type = GL_UNSIGNED_BYTE;
  280. need_swap_rb = 1;
  281. *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
  282. break;
  283. case PICT_x8r8g8b8:
  284. *no_alpha = 1;
  285. case PICT_a8r8g8b8:
  286. *tex_format = GL_RGBA;
  287. *tex_type = GL_UNSIGNED_BYTE;
  288. need_swap_rb = 1;
  289. break;
  290. case PICT_x8b8g8r8:
  291. *no_alpha = 1;
  292. case PICT_a8b8g8r8:
  293. *tex_format = GL_RGBA;
  294. *tex_type = GL_UNSIGNED_BYTE;
  295. break;
  296. case PICT_x2r10g10b10:
  297. *no_alpha = 1;
  298. case PICT_a2r10g10b10:
  299. *tex_format = GL_RGBA;
  300. /* glReadPixmap doesn't support GL_UNSIGNED_INT_10_10_10_2.
  301. * we have to use GL_UNSIGNED_BYTE and do the conversion in
  302. * shader latter.*/
  303. *tex_type = GL_UNSIGNED_BYTE;
  304. if (is_upload == 1) {
  305. if (!IS_LITTLE_ENDIAN)
  306. *revert = REVERT_UPLOADING_10_10_10_2;
  307. else
  308. *revert = REVERT_UPLOADING_2_10_10_10;
  309. }
  310. else {
  311. if (!IS_LITTLE_ENDIAN) {
  312. *revert = REVERT_DOWNLOADING_10_10_10_2;
  313. }
  314. else {
  315. *revert = REVERT_DOWNLOADING_2_10_10_10;
  316. }
  317. }
  318. need_swap_rb = 1;
  319. break;
  320. case PICT_x2b10g10r10:
  321. *no_alpha = 1;
  322. case PICT_a2b10g10r10:
  323. *tex_format = GL_RGBA;
  324. *tex_type = GL_UNSIGNED_BYTE;
  325. if (is_upload == 1) {
  326. if (!IS_LITTLE_ENDIAN)
  327. *revert = REVERT_UPLOADING_10_10_10_2;
  328. else
  329. *revert = REVERT_UPLOADING_2_10_10_10;
  330. }
  331. else {
  332. if (!IS_LITTLE_ENDIAN) {
  333. *revert = REVERT_DOWNLOADING_10_10_10_2;
  334. }
  335. else {
  336. *revert = REVERT_DOWNLOADING_2_10_10_10;
  337. }
  338. }
  339. break;
  340. case PICT_r5g6b5:
  341. *tex_format = GL_RGB;
  342. *tex_type = GL_UNSIGNED_SHORT_5_6_5;
  343. *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL;
  344. break;
  345. case PICT_b5g6r5:
  346. *tex_format = GL_RGB;
  347. *tex_type = GL_UNSIGNED_SHORT_5_6_5;
  348. need_swap_rb = IS_LITTLE_ENDIAN ? 1 : 0;;
  349. break;
  350. case PICT_x1b5g5r5:
  351. *no_alpha = 1;
  352. case PICT_a1b5g5r5:
  353. *tex_format = GL_RGBA;
  354. *tex_type = GL_UNSIGNED_SHORT_5_5_5_1;
  355. if (IS_LITTLE_ENDIAN) {
  356. *revert =
  357. is_upload ? REVERT_UPLOADING_1_5_5_5 :
  358. REVERT_DOWNLOADING_1_5_5_5;
  359. }
  360. else
  361. *revert = REVERT_NONE;
  362. break;
  363. case PICT_x1r5g5b5:
  364. *no_alpha = 1;
  365. case PICT_a1r5g5b5:
  366. *tex_format = GL_RGBA;
  367. *tex_type = GL_UNSIGNED_SHORT_5_5_5_1;
  368. if (IS_LITTLE_ENDIAN) {
  369. *revert =
  370. is_upload ? REVERT_UPLOADING_1_5_5_5 :
  371. REVERT_DOWNLOADING_1_5_5_5;
  372. }
  373. else
  374. *revert = REVERT_NONE;
  375. need_swap_rb = 1;
  376. break;
  377. case PICT_a1:
  378. *tex_format = GL_ALPHA;
  379. *tex_type = GL_UNSIGNED_BYTE;
  380. *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1;
  381. break;
  382. case PICT_a8:
  383. *tex_format = GL_ALPHA;
  384. *tex_type = GL_UNSIGNED_BYTE;
  385. *revert = REVERT_NONE;
  386. break;
  387. case PICT_x4r4g4b4:
  388. *no_alpha = 1;
  389. case PICT_a4r4g4b4:
  390. *tex_format = GL_RGBA;
  391. *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
  392. *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
  393. need_swap_rb = 1;
  394. break;
  395. case PICT_x4b4g4r4:
  396. *no_alpha = 1;
  397. case PICT_a4b4g4r4:
  398. *tex_format = GL_RGBA;
  399. *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
  400. *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
  401. break;
  402. default:
  403. LogMessageVerb(X_INFO, 0,
  404. "fail to get matched format for %x \n", format);
  405. return -1;
  406. }
  407. if (need_swap_rb)
  408. *swap_rb = is_upload ? SWAP_UPLOADING : SWAP_DOWNLOADING;
  409. else
  410. *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING;
  411. return 0;
  412. }
  413. static int
  414. glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
  415. GLenum *format,
  416. GLenum *type,
  417. int *no_alpha,
  418. int *revert, int *swap_rb, int is_upload)
  419. {
  420. glamor_pixmap_private *pixmap_priv;
  421. PictFormatShort pict_format;
  422. glamor_screen_private *glamor_priv =
  423. glamor_get_screen_private(pixmap->drawable.pScreen);
  424. pixmap_priv = glamor_get_pixmap_private(pixmap);
  425. if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv))
  426. pict_format = pixmap_priv->base.picture->format;
  427. else
  428. pict_format = format_for_depth(pixmap->drawable.depth);
  429. if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
  430. return glamor_get_tex_format_type_from_pictformat_gl(pict_format,
  431. format, type,
  432. no_alpha,
  433. revert,
  434. swap_rb,
  435. is_upload);
  436. } else {
  437. return glamor_get_tex_format_type_from_pictformat_gles2(pict_format,
  438. format, type,
  439. no_alpha,
  440. revert,
  441. swap_rb,
  442. is_upload);
  443. }
  444. }
  445. static void *
  446. _glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h,
  447. int stride, int revert)
  448. {
  449. PictFormatShort dst_format, src_format;
  450. pixman_image_t *dst_image;
  451. pixman_image_t *src_image;
  452. int src_stride;
  453. if (revert == REVERT_UPLOADING_A1) {
  454. src_format = PICT_a1;
  455. dst_format = PICT_a8;
  456. src_stride = PixmapBytePad(w, 1);
  457. }
  458. else {
  459. dst_format = PICT_a1;
  460. src_format = PICT_a8;
  461. src_stride = (((w * 8 + 7) / 8) + 3) & ~3;
  462. }
  463. dst_image = pixman_image_create_bits(dst_format, w, h, dst_bits, stride);
  464. if (dst_image == NULL) {
  465. return NULL;
  466. }
  467. src_image = pixman_image_create_bits(src_format,
  468. w, h, src_bits, src_stride);
  469. if (src_image == NULL) {
  470. pixman_image_unref(dst_image);
  471. return NULL;
  472. }
  473. pixman_image_composite(PictOpSrc, src_image, NULL, dst_image,
  474. 0, 0, 0, 0, 0, 0, w, h);
  475. pixman_image_unref(src_image);
  476. pixman_image_unref(dst_image);
  477. return dst_bits;
  478. }
  479. #define ADJUST_BITS(d, src_bits, dst_bits) (((dst_bits) == (src_bits)) ? (d) : \
  480. (((dst_bits) > (src_bits)) ? \
  481. (((d) << ((dst_bits) - (src_bits))) \
  482. + (( 1 << ((dst_bits) - (src_bits))) >> 1)) \
  483. : ((d) >> ((src_bits) - (dst_bits)))))
  484. #define GLAMOR_DO_CONVERT(src, dst, no_alpha, swap, \
  485. a_shift_src, a_bits_src, \
  486. b_shift_src, b_bits_src, \
  487. g_shift_src, g_bits_src, \
  488. r_shift_src, r_bits_src, \
  489. a_shift, a_bits, \
  490. b_shift, b_bits, \
  491. g_shift, g_bits, \
  492. r_shift, r_bits) \
  493. do { \
  494. typeof(src) a,b,g,r; \
  495. typeof(src) a_mask_src, b_mask_src, g_mask_src, r_mask_src;\
  496. a_mask_src = (((1 << (a_bits_src)) - 1) << a_shift_src);\
  497. b_mask_src = (((1 << (b_bits_src)) - 1) << b_shift_src);\
  498. g_mask_src = (((1 << (g_bits_src)) - 1) << g_shift_src);\
  499. r_mask_src = (((1 << (r_bits_src)) - 1) << r_shift_src);\
  500. if (no_alpha) \
  501. a = (a_mask_src) >> (a_shift_src); \
  502. else \
  503. a = ((src) & (a_mask_src)) >> (a_shift_src); \
  504. b = ((src) & (b_mask_src)) >> (b_shift_src); \
  505. g = ((src) & (g_mask_src)) >> (g_shift_src); \
  506. r = ((src) & (r_mask_src)) >> (r_shift_src); \
  507. a = ADJUST_BITS(a, a_bits_src, a_bits); \
  508. b = ADJUST_BITS(b, b_bits_src, b_bits); \
  509. g = ADJUST_BITS(g, g_bits_src, g_bits); \
  510. r = ADJUST_BITS(r, r_bits_src, r_bits); \
  511. if (swap == 0) \
  512. (*dst) = ((a) << (a_shift)) | ((b) << (b_shift)) | ((g) << (g_shift)) | ((r) << (r_shift)); \
  513. else \
  514. (*dst) = ((a) << (a_shift)) | ((r) << (b_shift)) | ((g) << (g_shift)) | ((b) << (r_shift)); \
  515. } while (0)
  516. static void *
  517. _glamor_color_revert_x2b10g10r10(void *src_bits, void *dst_bits, int w, int h,
  518. int stride, int no_alpha, int revert,
  519. int swap_rb)
  520. {
  521. int x, y;
  522. unsigned int *words, *saved_words, *source_words;
  523. int swap = !(swap_rb == SWAP_NONE_DOWNLOADING ||
  524. swap_rb == SWAP_NONE_UPLOADING);
  525. source_words = src_bits;
  526. words = dst_bits;
  527. saved_words = words;
  528. for (y = 0; y < h; y++) {
  529. DEBUGF("Line %d : ", y);
  530. for (x = 0; x < w; x++) {
  531. unsigned int pixel = source_words[x];
  532. if (revert == REVERT_DOWNLOADING_2_10_10_10)
  533. GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap,
  534. 24, 8, 16, 8, 8, 8, 0, 8,
  535. 30, 2, 20, 10, 10, 10, 0, 10);
  536. else
  537. GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap,
  538. 30, 2, 20, 10, 10, 10, 0, 10,
  539. 24, 8, 16, 8, 8, 8, 0, 8);
  540. DEBUGF("%x:%x ", pixel, words[x]);
  541. }
  542. DEBUGF("\n");
  543. words += stride / sizeof(*words);
  544. source_words += stride / sizeof(*words);
  545. }
  546. DEBUGF("\n");
  547. return saved_words;
  548. }
  549. static void *
  550. _glamor_color_revert_x1b5g5r5(void *src_bits, void *dst_bits, int w, int h,
  551. int stride, int no_alpha, int revert, int swap_rb)
  552. {
  553. int x, y;
  554. unsigned short *words, *saved_words, *source_words;
  555. int swap = !(swap_rb == SWAP_NONE_DOWNLOADING ||
  556. swap_rb == SWAP_NONE_UPLOADING);
  557. words = dst_bits;
  558. source_words = src_bits;
  559. saved_words = words;
  560. for (y = 0; y < h; y++) {
  561. DEBUGF("Line %d : ", y);
  562. for (x = 0; x < w; x++) {
  563. unsigned short pixel = source_words[x];
  564. if (revert == REVERT_DOWNLOADING_1_5_5_5)
  565. GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap,
  566. 0, 1, 1, 5, 6, 5, 11, 5,
  567. 15, 1, 10, 5, 5, 5, 0, 5);
  568. else
  569. GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap,
  570. 15, 1, 10, 5, 5, 5, 0, 5,
  571. 0, 1, 1, 5, 6, 5, 11, 5);
  572. DEBUGF("%04x:%04x ", pixel, words[x]);
  573. }
  574. DEBUGF("\n");
  575. words += stride / sizeof(*words);
  576. source_words += stride / sizeof(*words);
  577. }
  578. DEBUGF("\n");
  579. return saved_words;
  580. }
  581. /*
  582. * This function is to convert an unsupported color format to/from a
  583. * supported GL format.
  584. * Here are the current scenarios:
  585. *
  586. * @no_alpha:
  587. * If it is set, then we need to wire the alpha value to 1.
  588. * @revert:
  589. REVERT_DOWNLOADING_A1 : convert an Alpha8 buffer to a A1 buffer.
  590. REVERT_UPLOADING_A1 : convert an A1 buffer to an Alpha8 buffer
  591. REVERT_DOWNLOADING_2_10_10_10 : convert r10G10b10X2 to X2B10G10R10
  592. REVERT_UPLOADING_2_10_10_10 : convert X2B10G10R10 to R10G10B10X2
  593. REVERT_DOWNLOADING_1_5_5_5 : convert B5G5R5X1 to X1R5G5B5
  594. REVERT_UPLOADING_1_5_5_5 : convert X1R5G5B5 to B5G5R5X1
  595. @swap_rb: if we have the swap_rb set, then we need to swap the R and B's position.
  596. *
  597. */
  598. static void *
  599. glamor_color_convert_to_bits(void *src_bits, void *dst_bits, int w, int h,
  600. int stride, int no_alpha, int revert, int swap_rb)
  601. {
  602. if (revert == REVERT_DOWNLOADING_A1 || revert == REVERT_UPLOADING_A1) {
  603. return _glamor_color_convert_a1_a8(src_bits, dst_bits, w, h, stride,
  604. revert);
  605. }
  606. else if (revert == REVERT_DOWNLOADING_2_10_10_10 ||
  607. revert == REVERT_UPLOADING_2_10_10_10) {
  608. return _glamor_color_revert_x2b10g10r10(src_bits, dst_bits, w, h,
  609. stride, no_alpha, revert,
  610. swap_rb);
  611. }
  612. else if (revert == REVERT_DOWNLOADING_1_5_5_5 ||
  613. revert == REVERT_UPLOADING_1_5_5_5) {
  614. return _glamor_color_revert_x1b5g5r5(src_bits, dst_bits, w, h, stride,
  615. no_alpha, revert, swap_rb);
  616. }
  617. else
  618. ErrorF("convert a non-supported mode %x.\n", revert);
  619. return NULL;
  620. }
  621. /**
  622. * Upload pixmap to a specified texture.
  623. * This texture may not be the one attached to it.
  624. **/
  625. static void
  626. __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
  627. GLenum format,
  628. GLenum type,
  629. int x, int y, int w, int h,
  630. void *bits, int pbo)
  631. {
  632. glamor_screen_private *glamor_priv =
  633. glamor_get_screen_private(pixmap->drawable.pScreen);
  634. int non_sub = 0;
  635. unsigned int iformat = 0;
  636. glamor_make_current(glamor_priv);
  637. if (*tex == 0) {
  638. glGenTextures(1, tex);
  639. if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
  640. iformat = gl_iformat_for_pixmap(pixmap);
  641. else
  642. iformat = format;
  643. non_sub = 1;
  644. assert(x == 0 && y == 0);
  645. }
  646. glBindTexture(GL_TEXTURE_2D, *tex);
  647. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
  648. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  649. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  650. glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  651. assert(pbo || bits != 0);
  652. if (bits == NULL) {
  653. glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
  654. glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
  655. }
  656. if (non_sub)
  657. glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, bits);
  658. else
  659. glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, format, type, bits);
  660. if (bits == NULL)
  661. glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
  662. }
  663. static Bool
  664. _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
  665. GLenum type, int no_alpha, int revert,
  666. int swap_rb, int x, int y, int w, int h,
  667. int stride, void *bits, int pbo)
  668. {
  669. glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
  670. glamor_screen_private *glamor_priv =
  671. glamor_get_screen_private(pixmap->drawable.pScreen);
  672. static float vertices[8];
  673. static float texcoords[8] = { 0, 1,
  674. 1, 1,
  675. 1, 0,
  676. 0, 0
  677. };
  678. static float texcoords_inv[8] = { 0, 0,
  679. 1, 0,
  680. 1, 1,
  681. 0, 1
  682. };
  683. float *ptexcoords;
  684. float dst_xscale, dst_yscale;
  685. GLuint tex = 0;
  686. int need_flip;
  687. int need_free_bits = 0;
  688. need_flip = !glamor_priv->yInverted;
  689. if (bits == NULL)
  690. goto ready_to_upload;
  691. if (revert > REVERT_NORMAL) {
  692. /* XXX if we are restoring the pixmap, then we may not need to allocate
  693. * new buffer */
  694. void *converted_bits;
  695. if (pixmap->drawable.depth == 1)
  696. stride = (((w * 8 + 7) / 8) + 3) & ~3;
  697. converted_bits = malloc(h * stride);
  698. if (converted_bits == NULL)
  699. return FALSE;
  700. bits = glamor_color_convert_to_bits(bits, converted_bits, w, h,
  701. stride, no_alpha, revert, swap_rb);
  702. if (bits == NULL) {
  703. ErrorF("Failed to convert pixmap no_alpha %d,"
  704. "revert mode %d, swap mode %d\n", no_alpha, revert, swap_rb);
  705. return FALSE;
  706. }
  707. no_alpha = 0;
  708. revert = REVERT_NONE;
  709. swap_rb = SWAP_NONE_UPLOADING;
  710. need_free_bits = TRUE;
  711. }
  712. ready_to_upload:
  713. /* Try fast path firstly, upload the pixmap to the texture attached
  714. * to the fbo directly. */
  715. if (no_alpha == 0
  716. && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING && !need_flip
  717. #ifdef WALKAROUND_LARGE_TEXTURE_MAP
  718. && pixmap_priv->type != GLAMOR_TEXTURE_LARGE
  719. #endif
  720. ) {
  721. int fbo_x_off, fbo_y_off;
  722. assert(pixmap_priv->base.fbo->tex);
  723. pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off);
  724. assert(x + fbo_x_off >= 0 && y + fbo_y_off >= 0);
  725. assert(x + fbo_x_off + w <= pixmap_priv->base.fbo->width);
  726. assert(y + fbo_y_off + h <= pixmap_priv->base.fbo->height);
  727. __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->base.fbo->tex,
  728. format, type,
  729. x + fbo_x_off, y + fbo_y_off, w, h,
  730. bits, pbo);
  731. return TRUE;
  732. }
  733. if (need_flip)
  734. ptexcoords = texcoords;
  735. else
  736. ptexcoords = texcoords_inv;
  737. pixmap_priv_get_dest_scale(pixmap_priv, &dst_xscale, &dst_yscale);
  738. glamor_set_normalize_vcoords(pixmap_priv, dst_xscale,
  739. dst_yscale,
  740. x, y,
  741. x + w, y + h,
  742. glamor_priv->yInverted, vertices);
  743. /* Slow path, we need to flip y or wire alpha to 1. */
  744. glamor_make_current(glamor_priv);
  745. glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
  746. GL_FALSE, 2 * sizeof(float), vertices);
  747. glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
  748. glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
  749. GL_FALSE, 2 * sizeof(float), ptexcoords);
  750. glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
  751. glamor_set_destination_pixmap_priv_nc(pixmap_priv);
  752. __glamor_upload_pixmap_to_texture(pixmap, &tex,
  753. format, type, 0, 0, w, h, bits, pbo);
  754. glActiveTexture(GL_TEXTURE0);
  755. glBindTexture(GL_TEXTURE_2D, tex);
  756. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  757. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  758. glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
  759. glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert);
  760. glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb);
  761. glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  762. glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
  763. glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
  764. glDeleteTextures(1, &tex);
  765. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  766. if (need_free_bits)
  767. free(bits);
  768. return TRUE;
  769. }
  770. /*
  771. * Prepare to upload a pixmap to texture memory.
  772. * no_alpha equals 1 means the format needs to wire alpha to 1.
  773. * Two condtion need to setup a fbo for a pixmap
  774. * 1. !yInverted, we need to do flip if we are not yInverted.
  775. * 2. no_alpha != 0, we need to wire the alpha.
  776. * */
  777. static int
  778. glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha,
  779. int revert, int swap_rb)
  780. {
  781. int flag = 0;
  782. glamor_pixmap_private *pixmap_priv;
  783. glamor_screen_private *glamor_priv;
  784. glamor_pixmap_fbo *fbo;
  785. GLenum iformat;
  786. pixmap_priv = glamor_get_pixmap_private(pixmap);
  787. glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
  788. if (pixmap_priv->base.gl_fbo != GLAMOR_FBO_UNATTACHED)
  789. return 0;
  790. if (pixmap_priv->base.fbo
  791. && (pixmap_priv->base.fbo->width < pixmap->drawable.width
  792. || pixmap_priv->base.fbo->height < pixmap->drawable.height)) {
  793. fbo = glamor_pixmap_detach_fbo(pixmap_priv);
  794. glamor_destroy_fbo(fbo);
  795. }
  796. if (pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb)
  797. return 0;
  798. if (!(no_alpha || (revert == REVERT_NORMAL)
  799. || (swap_rb != SWAP_NONE_UPLOADING)
  800. || !glamor_priv->yInverted)) {
  801. /* We don't need a fbo, a simple texture uploading should work. */
  802. flag = GLAMOR_CREATE_FBO_NO_FBO;
  803. }
  804. if ((flag == GLAMOR_CREATE_FBO_NO_FBO
  805. && pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex)
  806. || (flag == 0 && pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb))
  807. return 0;
  808. if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
  809. iformat = gl_iformat_for_pixmap(pixmap);
  810. else
  811. iformat = format;
  812. if (!glamor_pixmap_ensure_fbo(pixmap, iformat, flag))
  813. return -1;
  814. return 0;
  815. }
  816. /*
  817. * upload sub region to a large region.
  818. * */
  819. static void
  820. glamor_put_bits(char *dst_bits, int dst_stride, char *src_bits,
  821. int src_stride, int bpp, int x, int y, int w, int h)
  822. {
  823. int j;
  824. int byte_per_pixel;
  825. byte_per_pixel = bpp / 8;
  826. src_bits += y * src_stride + (x * byte_per_pixel);
  827. for (j = y; j < y + h; j++) {
  828. memcpy(dst_bits, src_bits, w * byte_per_pixel);
  829. src_bits += src_stride;
  830. dst_bits += dst_stride;
  831. }
  832. }
  833. /*
  834. * download sub region from a large region.
  835. */
  836. static void
  837. glamor_get_bits(char *dst_bits, int dst_stride, char *src_bits,
  838. int src_stride, int bpp, int x, int y, int w, int h)
  839. {
  840. int j;
  841. int byte_per_pixel;
  842. byte_per_pixel = bpp / 8;
  843. dst_bits += y * dst_stride + x * byte_per_pixel;
  844. for (j = y; j < y + h; j++) {
  845. memcpy(dst_bits, src_bits, w * byte_per_pixel);
  846. src_bits += src_stride;
  847. dst_bits += dst_stride;
  848. }
  849. }
  850. Bool
  851. glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w,
  852. int h, int stride, void *bits, int pbo)
  853. {
  854. GLenum format, type;
  855. int no_alpha, revert, swap_rb;
  856. glamor_pixmap_private *pixmap_priv;
  857. Bool force_clip;
  858. if (glamor_get_tex_format_type_from_pixmap(pixmap,
  859. &format,
  860. &type,
  861. &no_alpha,
  862. &revert, &swap_rb, 1)) {
  863. glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
  864. return FALSE;
  865. }
  866. if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb))
  867. return FALSE;
  868. pixmap_priv = glamor_get_pixmap_private(pixmap);
  869. force_clip = pixmap_priv->base.glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP
  870. && !glamor_check_fbo_size(pixmap_priv->base.glamor_priv, w, h);
  871. if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE || force_clip) {
  872. RegionRec region;
  873. BoxRec box;
  874. int n_region;
  875. glamor_pixmap_clipped_regions *clipped_regions;
  876. void *sub_bits;
  877. int i, j;
  878. sub_bits = malloc(h * stride);
  879. if (sub_bits == NULL)
  880. return FALSE;
  881. box.x1 = x;
  882. box.y1 = y;
  883. box.x2 = x + w;
  884. box.y2 = y + h;
  885. RegionInitBoxes(&region, &box, 1);
  886. if (!force_clip)
  887. clipped_regions =
  888. glamor_compute_clipped_regions(pixmap_priv, &region, &n_region,
  889. 0, 0, 0);
  890. else
  891. clipped_regions =
  892. glamor_compute_clipped_regions_ext(pixmap_priv, &region,
  893. &n_region,
  894. pixmap_priv->large.block_w,
  895. pixmap_priv->large.block_h,
  896. 0,
  897. 0);
  898. DEBUGF("prepare upload %dx%d to a large pixmap %p\n", w, h, pixmap);
  899. for (i = 0; i < n_region; i++) {
  900. BoxPtr boxes;
  901. int nbox;
  902. int temp_stride;
  903. void *temp_bits;
  904. assert(pbo == 0);
  905. SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx);
  906. boxes = RegionRects(clipped_regions[i].region);
  907. nbox = RegionNumRects(clipped_regions[i].region);
  908. DEBUGF("split to %d boxes\n", nbox);
  909. for (j = 0; j < nbox; j++) {
  910. temp_stride = PixmapBytePad(boxes[j].x2 - boxes[j].x1,
  911. pixmap->drawable.depth);
  912. if (boxes[j].x1 == x && temp_stride == stride) {
  913. temp_bits = (char *) bits + (boxes[j].y1 - y) * stride;
  914. }
  915. else {
  916. temp_bits = sub_bits;
  917. glamor_put_bits(temp_bits, temp_stride, bits, stride,
  918. pixmap->drawable.bitsPerPixel,
  919. boxes[j].x1 - x, boxes[j].y1 - y,
  920. boxes[j].x2 - boxes[j].x1,
  921. boxes[j].y2 - boxes[j].y1);
  922. }
  923. DEBUGF("upload x %d y %d w %d h %d temp stride %d \n",
  924. boxes[j].x1 - x, boxes[j].y1 - y,
  925. boxes[j].x2 - boxes[j].x1,
  926. boxes[j].y2 - boxes[j].y1, temp_stride);
  927. if (_glamor_upload_bits_to_pixmap_texture
  928. (pixmap, format, type, no_alpha, revert, swap_rb,
  929. boxes[j].x1, boxes[j].y1, boxes[j].x2 - boxes[j].x1,
  930. boxes[j].y2 - boxes[j].y1, temp_stride, temp_bits,
  931. pbo) == FALSE) {
  932. RegionUninit(&region);
  933. free(sub_bits);
  934. assert(0);
  935. return FALSE;
  936. }
  937. }
  938. RegionDestroy(clipped_regions[i].region);
  939. }
  940. free(sub_bits);
  941. free(clipped_regions);
  942. RegionUninit(&region);
  943. return TRUE;
  944. }
  945. else
  946. return _glamor_upload_bits_to_pixmap_texture(pixmap, format, type,
  947. no_alpha, revert, swap_rb,
  948. x, y, w, h, stride, bits,
  949. pbo);
  950. }
  951. enum glamor_pixmap_status
  952. glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
  953. {
  954. glamor_pixmap_private *pixmap_priv;
  955. void *data;
  956. int pbo;
  957. int ret;
  958. pixmap_priv = glamor_get_pixmap_private(pixmap);
  959. if ((pixmap_priv->base.fbo)
  960. && (pixmap_priv->base.fbo->pbo_valid)) {
  961. data = NULL;
  962. pbo = pixmap_priv->base.fbo->pbo;
  963. }
  964. else {
  965. data = pixmap->devPrivate.ptr;
  966. pbo = 0;
  967. }
  968. if (glamor_upload_sub_pixmap_to_texture(pixmap, 0, 0,
  969. pixmap->drawable.width,
  970. pixmap->drawable.height,
  971. pixmap->devKind, data, pbo))
  972. ret = GLAMOR_UPLOAD_DONE;
  973. else
  974. ret = GLAMOR_UPLOAD_FAILED;
  975. return ret;
  976. }
  977. void
  978. glamor_restore_pixmap_to_texture(PixmapPtr pixmap)
  979. {
  980. if (glamor_upload_pixmap_to_texture(pixmap) != GLAMOR_UPLOAD_DONE)
  981. LogMessage(X_WARNING, "Failed to restore pixmap to texture.\n");
  982. }
  983. /*
  984. * as gles2 only support a very small set of color format and
  985. * type when do glReadPixel,
  986. * Before we use glReadPixels to get back a textured pixmap,
  987. * Use shader to convert it to a supported format and thus
  988. * get a new temporary pixmap returned.
  989. * */
  990. glamor_pixmap_fbo *
  991. glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
  992. GLenum format, GLenum type, int no_alpha,
  993. int revert, int swap_rb)
  994. {
  995. glamor_pixmap_private *source_priv;
  996. glamor_screen_private *glamor_priv;
  997. ScreenPtr screen;
  998. glamor_pixmap_fbo *temp_fbo;
  999. float temp_xscale, temp_yscale, source_xscale, source_yscale;
  1000. static float vertices[8];
  1001. static float texcoords[8];
  1002. screen = source->drawable.pScreen;
  1003. glamor_priv = glamor_get_screen_private(screen);
  1004. source_priv = glamor_get_pixmap_private(source);
  1005. temp_fbo = glamor_create_fbo(glamor_priv, w, h, format, 0);
  1006. if (temp_fbo == NULL)
  1007. return NULL;
  1008. glamor_make_current(glamor_priv);
  1009. temp_xscale = 1.0 / w;
  1010. temp_yscale = 1.0 / h;
  1011. glamor_set_normalize_vcoords((struct glamor_pixmap_private *) NULL,
  1012. temp_xscale, temp_yscale, 0, 0, w, h,
  1013. glamor_priv->yInverted, vertices);
  1014. glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
  1015. 2 * sizeof(float), vertices);
  1016. glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
  1017. pixmap_priv_get_scale(source_priv, &source_xscale, &source_yscale);
  1018. glamor_set_normalize_tcoords(source_priv, source_xscale,
  1019. source_yscale,
  1020. x, y,
  1021. x + w, y + h,
  1022. glamor_priv->yInverted, texcoords);
  1023. glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE,
  1024. 2 * sizeof(float), texcoords);
  1025. glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
  1026. glActiveTexture(GL_TEXTURE0);
  1027. glBindTexture(GL_TEXTURE_2D, source_priv->base.fbo->tex);
  1028. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  1029. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  1030. glamor_set_destination_pixmap_fbo(temp_fbo, 0, 0, w, h);
  1031. glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
  1032. glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert);
  1033. glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb);
  1034. glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  1035. glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
  1036. glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
  1037. return temp_fbo;
  1038. }
  1039. /*
  1040. * Download a sub region of pixmap to a specified memory region.
  1041. * The pixmap must have a valid FBO, otherwise return a NULL.
  1042. * */
  1043. static void *
  1044. _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
  1045. GLenum type, int no_alpha,
  1046. int revert, int swap_rb,
  1047. int x, int y, int w, int h,
  1048. int stride, void *bits, int pbo,
  1049. glamor_access_t access)
  1050. {
  1051. glamor_pixmap_private *pixmap_priv;
  1052. GLenum gl_access = 0, gl_usage = 0;
  1053. void *data, *read;
  1054. glamor_screen_private *glamor_priv =
  1055. glamor_get_screen_private(pixmap->drawable.pScreen);
  1056. glamor_pixmap_fbo *temp_fbo = NULL;
  1057. int need_post_conversion = 0;
  1058. int need_free_data = 0;
  1059. int fbo_x_off, fbo_y_off;
  1060. data = bits;
  1061. pixmap_priv = glamor_get_pixmap_private(pixmap);
  1062. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
  1063. return NULL;
  1064. switch (access) {
  1065. case GLAMOR_ACCESS_RO:
  1066. gl_access = GL_READ_ONLY;
  1067. gl_usage = GL_STREAM_READ;
  1068. break;
  1069. case GLAMOR_ACCESS_RW:
  1070. gl_access = GL_READ_WRITE;
  1071. gl_usage = GL_DYNAMIC_DRAW;
  1072. break;
  1073. default:
  1074. ErrorF("Glamor: Invalid access code. %d\n", access);
  1075. assert(0);
  1076. }
  1077. glamor_make_current(glamor_priv);
  1078. glamor_set_destination_pixmap_priv_nc(pixmap_priv);
  1079. need_post_conversion = (revert > REVERT_NORMAL);
  1080. if (need_post_conversion) {
  1081. if (pixmap->drawable.depth == 1) {
  1082. int temp_stride;
  1083. temp_stride = (((w * 8 + 7) / 8) + 3) & ~3;
  1084. data = malloc(temp_stride * h);
  1085. if (data == NULL)
  1086. return NULL;
  1087. need_free_data = 1;
  1088. }
  1089. }
  1090. pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off);
  1091. if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
  1092. && !need_post_conversion
  1093. && (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) {
  1094. if (!(temp_fbo = glamor_es2_pixmap_read_prepare(pixmap, x, y, w, h,
  1095. format, type, no_alpha,
  1096. revert, swap_rb))) {
  1097. free(data);
  1098. return NULL;
  1099. }
  1100. x = 0;
  1101. y = 0;
  1102. fbo_x_off = 0;
  1103. fbo_y_off = 0;
  1104. }
  1105. glPixelStorei(GL_PACK_ALIGNMENT, 4);
  1106. if (glamor_priv->has_pack_invert || glamor_priv->yInverted) {
  1107. if (!glamor_priv->yInverted) {
  1108. assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
  1109. glPixelStorei(GL_PACK_INVERT_MESA, 1);
  1110. }
  1111. if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && data == NULL) {
  1112. assert(pbo > 0);
  1113. glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
  1114. glBufferData(GL_PIXEL_PACK_BUFFER, stride * h, NULL, gl_usage);
  1115. }
  1116. glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, data);
  1117. if (!glamor_priv->yInverted) {
  1118. assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
  1119. glPixelStorei(GL_PACK_INVERT_MESA, 0);
  1120. }
  1121. if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && bits == NULL) {
  1122. bits = glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access);
  1123. glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
  1124. }
  1125. }
  1126. else {
  1127. unsigned int temp_pbo;
  1128. int yy;
  1129. glamor_make_current(glamor_priv);
  1130. glGenBuffers(1, &temp_pbo);
  1131. glBindBuffer(GL_PIXEL_PACK_BUFFER, temp_pbo);
  1132. glBufferData(GL_PIXEL_PACK_BUFFER, stride * h, NULL, GL_STREAM_READ);
  1133. glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, 0);
  1134. read = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
  1135. for (yy = 0; yy < pixmap->drawable.height; yy++)
  1136. memcpy((char *) data + yy * stride,
  1137. (char *) read + (h - yy - 1) * stride, stride);
  1138. glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
  1139. glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
  1140. glDeleteBuffers(1, &temp_pbo);
  1141. }
  1142. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  1143. if (need_post_conversion) {
  1144. /* As OpenGL desktop version never enters here.
  1145. * Don't need to consider if the pbo is valid.*/
  1146. bits = glamor_color_convert_to_bits(data, bits,
  1147. w, h,
  1148. stride, no_alpha, revert, swap_rb);
  1149. }
  1150. if (temp_fbo != NULL)
  1151. glamor_destroy_fbo(temp_fbo);
  1152. if (need_free_data)
  1153. free(data);
  1154. return bits;
  1155. }
  1156. void *
  1157. glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
  1158. int stride, void *bits, int pbo,
  1159. glamor_access_t access)
  1160. {
  1161. GLenum format, type;
  1162. int no_alpha, revert, swap_rb;
  1163. glamor_pixmap_private *pixmap_priv;
  1164. Bool force_clip;
  1165. if (glamor_get_tex_format_type_from_pixmap(pixmap,
  1166. &format,
  1167. &type,
  1168. &no_alpha,
  1169. &revert, &swap_rb, 0)) {
  1170. glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
  1171. return NULL;
  1172. }
  1173. pixmap_priv = glamor_get_pixmap_private(pixmap);
  1174. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
  1175. return NULL;
  1176. force_clip = pixmap_priv->base.glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP
  1177. && !glamor_check_fbo_size(pixmap_priv->base.glamor_priv, w, h);
  1178. if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE || force_clip) {
  1179. RegionRec region;
  1180. BoxRec box;
  1181. int n_region;
  1182. glamor_pixmap_clipped_regions *clipped_regions;
  1183. void *sub_bits;
  1184. int i, j;
  1185. sub_bits = malloc(h * stride);
  1186. if (sub_bits == NULL)
  1187. return FALSE;
  1188. box.x1 = x;
  1189. box.y1 = y;
  1190. box.x2 = x + w;
  1191. box.y2 = y + h;
  1192. RegionInitBoxes(&region, &box, 1);
  1193. if (!force_clip)
  1194. clipped_regions =
  1195. glamor_compute_clipped_regions(pixmap_priv, &region, &n_region,
  1196. 0, 0, 0);
  1197. else
  1198. clipped_regions =
  1199. glamor_compute_clipped_regions_ext(pixmap_priv, &region,
  1200. &n_region,
  1201. pixmap_priv->large.block_w,
  1202. pixmap_priv->large.block_h,
  1203. 0,
  1204. 0);
  1205. DEBUGF("start download large pixmap %p %dx%d \n", pixmap, w, h);
  1206. for (i = 0; i < n_region; i++) {
  1207. BoxPtr boxes;
  1208. int nbox;
  1209. int temp_stride;
  1210. void *temp_bits;
  1211. assert(pbo == 0);
  1212. SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx);
  1213. boxes = RegionRects(clipped_regions[i].region);
  1214. nbox = RegionNumRects(clipped_regions[i].region);
  1215. for (j = 0; j < nbox; j++) {
  1216. temp_stride = PixmapBytePad(boxes[j].x2 - boxes[j].x1,
  1217. pixmap->drawable.depth);
  1218. if (boxes[j].x1 == x && temp_stride == stride) {
  1219. temp_bits = (char *) bits + (boxes[j].y1 - y) * stride;
  1220. }
  1221. else {
  1222. temp_bits = sub_bits;
  1223. }
  1224. DEBUGF("download x %d y %d w %d h %d temp stride %d \n",
  1225. boxes[j].x1, boxes[j].y1,
  1226. boxes[j].x2 - boxes[j].x1,
  1227. boxes[j].y2 - boxes[j].y1, temp_stride);
  1228. /* For large pixmap, we don't support pbo currently. */
  1229. assert(pbo == 0);
  1230. if (_glamor_download_sub_pixmap_to_cpu
  1231. (pixmap, format, type, no_alpha, revert, swap_rb,
  1232. boxes[j].x1, boxes[j].y1, boxes[j].x2 - boxes[j].x1,
  1233. boxes[j].y2 - boxes[j].y1, temp_stride, temp_bits, pbo,
  1234. access) == FALSE) {
  1235. RegionUninit(&region);
  1236. free(sub_bits);
  1237. assert(0);
  1238. return NULL;
  1239. }
  1240. if (boxes[j].x1 != x || temp_stride != stride)
  1241. glamor_get_bits(bits, stride, temp_bits, temp_stride,
  1242. pixmap->drawable.bitsPerPixel,
  1243. boxes[j].x1 - x, boxes[j].y1 - y,
  1244. boxes[j].x2 - boxes[j].x1,
  1245. boxes[j].y2 - boxes[j].y1);
  1246. }
  1247. RegionDestroy(clipped_regions[i].region);
  1248. }
  1249. free(sub_bits);
  1250. free(clipped_regions);
  1251. RegionUninit(&region);
  1252. return bits;
  1253. }
  1254. else
  1255. return _glamor_download_sub_pixmap_to_cpu(pixmap, format, type,
  1256. no_alpha, revert, swap_rb, x,
  1257. y, w, h, stride, bits, pbo,
  1258. access);
  1259. }
  1260. /**
  1261. * Move a pixmap to CPU memory.
  1262. * The input data is the pixmap's fbo.
  1263. * The output data is at pixmap->devPrivate.ptr. We always use pbo
  1264. * to read the fbo and then map it to va. If possible, we will use
  1265. * it directly as devPrivate.ptr.
  1266. * If successfully download a fbo to cpu then return TRUE.
  1267. * Otherwise return FALSE.
  1268. **/
  1269. Bool
  1270. glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
  1271. {
  1272. glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
  1273. unsigned int stride;
  1274. void *data = NULL, *dst;
  1275. glamor_screen_private *glamor_priv =
  1276. glamor_get_screen_private(pixmap->drawable.pScreen);
  1277. int pbo = 0;
  1278. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
  1279. return TRUE;
  1280. glamor_debug_output(GLAMOR_DEBUG_TEXTURE_DOWNLOAD,
  1281. "Downloading pixmap %p %dx%d depth%d\n",
  1282. pixmap,
  1283. pixmap->drawable.width,
  1284. pixmap->drawable.height, pixmap->drawable.depth);
  1285. stride = pixmap->devKind;
  1286. if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
  1287. || (!glamor_priv->has_pack_invert && !glamor_priv->yInverted)
  1288. || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
  1289. data = malloc(stride * pixmap->drawable.height);
  1290. }
  1291. else {
  1292. glamor_make_current(glamor_priv);
  1293. if (pixmap_priv->base.fbo->pbo == 0)
  1294. glGenBuffers(1, &pixmap_priv->base.fbo->pbo);
  1295. pbo = pixmap_priv->base.fbo->pbo;
  1296. }
  1297. if (pixmap_priv->type == GLAMOR_TEXTURE_DRM) {
  1298. stride = PixmapBytePad(pixmap->drawable.width, pixmap->drawable.depth);
  1299. pixmap_priv->base.drm_stride = pixmap->devKind;
  1300. pixmap->devKind = stride;
  1301. }
  1302. dst = glamor_download_sub_pixmap_to_cpu(pixmap, 0, 0,
  1303. pixmap->drawable.width,
  1304. pixmap->drawable.height,
  1305. pixmap->devKind, data, pbo, access);
  1306. if (!dst) {
  1307. if (data)
  1308. free(data);
  1309. return FALSE;
  1310. }
  1311. if (pbo != 0)
  1312. pixmap_priv->base.fbo->pbo_valid = 1;
  1313. pixmap_priv->base.gl_fbo = GLAMOR_FBO_DOWNLOADED;
  1314. pixmap->devPrivate.ptr = dst;
  1315. return TRUE;
  1316. }
  1317. /* fixup a fbo to the exact size as the pixmap. */
  1318. /* XXX LARGE pixmap? */
  1319. Bool
  1320. glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv)
  1321. {
  1322. glamor_pixmap_fbo *old_fbo;
  1323. glamor_pixmap_fbo *new_fbo = NULL;
  1324. PixmapPtr scratch = NULL;
  1325. glamor_pixmap_private *scratch_priv;
  1326. DrawablePtr drawable;
  1327. GCPtr gc = NULL;
  1328. int ret = FALSE;
  1329. drawable = &pixmap_priv->base.pixmap->drawable;
  1330. if (!GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(pixmap_priv))
  1331. return TRUE;
  1332. old_fbo = pixmap_priv->base.fbo;
  1333. if (!old_fbo)
  1334. return FALSE;
  1335. gc = GetScratchGC(drawable->depth, screen);
  1336. if (!gc)
  1337. goto fail;
  1338. scratch = glamor_create_pixmap(screen, drawable->width, drawable->height,
  1339. drawable->depth, GLAMOR_CREATE_PIXMAP_FIXUP);
  1340. scratch_priv = glamor_get_pixmap_private(scratch);
  1341. if (!scratch_priv->base.fbo)
  1342. goto fail;
  1343. ValidateGC(&scratch->drawable, gc);
  1344. glamor_copy_area(drawable,
  1345. &scratch->drawable,
  1346. gc, 0, 0, drawable->width, drawable->height, 0, 0);
  1347. old_fbo = glamor_pixmap_detach_fbo(pixmap_priv);
  1348. new_fbo = glamor_pixmap_detach_fbo(scratch_priv);
  1349. glamor_pixmap_attach_fbo(pixmap_priv->base.pixmap, new_fbo);
  1350. glamor_pixmap_attach_fbo(scratch, old_fbo);
  1351. DEBUGF("old %dx%d type %d\n",
  1352. drawable->width, drawable->height, pixmap_priv->type);
  1353. DEBUGF("copy tex %d %dx%d to tex %d %dx%d \n",
  1354. old_fbo->tex, old_fbo->width, old_fbo->height, new_fbo->tex,
  1355. new_fbo->width, new_fbo->height);
  1356. ret = TRUE;
  1357. fail:
  1358. if (gc)
  1359. FreeScratchGC(gc);
  1360. if (scratch)
  1361. glamor_destroy_pixmap(scratch);
  1362. return ret;
  1363. }
  1364. /*
  1365. * We may use this function to reduce a large pixmap to a small sub
  1366. * pixmap. Two scenarios currently:
  1367. * 1. When fallback a large textured pixmap to CPU but we do need to
  1368. * do rendering within a small sub region, then we can just get a
  1369. * sub region.
  1370. *
  1371. * 2. When uploading a large pixmap to texture but we only need to
  1372. * use part of the source/mask picture. As glTexImage2D will be more
  1373. * efficient to upload a contingent region rather than a sub block
  1374. * in a large buffer. We use this function to gather the sub region
  1375. * to a contingent sub pixmap.
  1376. *
  1377. * The sub-pixmap must have the same format as the source pixmap.
  1378. *
  1379. * */
  1380. PixmapPtr
  1381. glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h,
  1382. glamor_access_t access)
  1383. {
  1384. glamor_screen_private *glamor_priv;
  1385. PixmapPtr sub_pixmap;
  1386. glamor_pixmap_private *sub_pixmap_priv, *pixmap_priv;
  1387. void *data;
  1388. int pbo;
  1389. int flag;
  1390. if (x < 0 || y < 0)
  1391. return NULL;
  1392. w = (x + w) > pixmap->drawable.width ? (pixmap->drawable.width - x) : w;
  1393. h = (y + h) > pixmap->drawable.height ? (pixmap->drawable.height - y) : h;
  1394. glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
  1395. pixmap_priv = glamor_get_pixmap_private(pixmap);
  1396. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
  1397. return NULL;
  1398. if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 ||
  1399. pixmap_priv->type == GLAMOR_TEXTURE_LARGE)
  1400. flag = GLAMOR_CREATE_PIXMAP_CPU;
  1401. else
  1402. flag = GLAMOR_CREATE_PIXMAP_MAP;
  1403. sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
  1404. pixmap->drawable.depth, flag);
  1405. if (sub_pixmap == NULL)
  1406. return NULL;
  1407. sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
  1408. pbo =
  1409. sub_pixmap_priv ? (sub_pixmap_priv->base.fbo ? sub_pixmap_priv->base.
  1410. fbo->pbo : 0) : 0;
  1411. if (pixmap_priv->base.is_picture) {
  1412. sub_pixmap_priv->base.picture = pixmap_priv->base.picture;
  1413. sub_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture;
  1414. }
  1415. if (pbo)
  1416. data = NULL;
  1417. else
  1418. data = sub_pixmap->devPrivate.ptr;
  1419. data =
  1420. glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h,
  1421. sub_pixmap->devKind, data, pbo,
  1422. access);
  1423. if (data == NULL) {
  1424. fbDestroyPixmap(sub_pixmap);
  1425. return NULL;
  1426. }
  1427. if (pbo) {
  1428. assert(sub_pixmap->devPrivate.ptr == NULL);
  1429. sub_pixmap->devPrivate.ptr = data;
  1430. sub_pixmap_priv->base.fbo->pbo_valid = 1;
  1431. }
  1432. #if 0
  1433. struct pixman_box16 box;
  1434. PixmapPtr new_sub_pixmap;
  1435. int dx, dy;
  1436. box.x1 = 0;
  1437. box.y1 = 0;
  1438. box.x2 = w;
  1439. box.y2 = h;
  1440. dx = x;
  1441. dy = y;
  1442. new_sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
  1443. pixmap->drawable.depth,
  1444. GLAMOR_CREATE_PIXMAP_CPU);
  1445. glamor_copy_n_to_n(&pixmap->drawable, &new_sub_pixmap->drawable, NULL, &box,
  1446. 1, dx, dy, 0, 0, 0, NULL);
  1447. glamor_compare_pixmaps(new_sub_pixmap, sub_pixmap, 0, 0, w, h, 1, 1);
  1448. #endif
  1449. return sub_pixmap;
  1450. }
  1451. void
  1452. glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y,
  1453. int w, int h, glamor_access_t access)
  1454. {
  1455. void *bits;
  1456. int pbo;
  1457. glamor_pixmap_private *sub_pixmap_priv;
  1458. if (access != GLAMOR_ACCESS_RO) {
  1459. sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
  1460. if (sub_pixmap_priv->base.fbo && sub_pixmap_priv->base.fbo->pbo_valid) {
  1461. bits = NULL;
  1462. pbo = sub_pixmap_priv->base.fbo->pbo;
  1463. }
  1464. else {
  1465. bits = sub_pixmap->devPrivate.ptr;
  1466. pbo = 0;
  1467. }
  1468. assert(x >= 0 && y >= 0);
  1469. w = (w > sub_pixmap->drawable.width) ? sub_pixmap->drawable.width : w;
  1470. h = (h > sub_pixmap->drawable.height) ? sub_pixmap->drawable.height : h;
  1471. glamor_upload_sub_pixmap_to_texture(pixmap, x, y, w, h,
  1472. sub_pixmap->devKind, bits, pbo);
  1473. }
  1474. glamor_destroy_pixmap(sub_pixmap);
  1475. }