Clone of mesa.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

u_gen_mipmap.c 54KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558
  1. /**************************************************************************
  2. *
  3. * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
  4. * All Rights Reserved.
  5. * Copyright 2008 VMware, Inc. All rights reserved.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the
  9. * "Software"), to deal in the Software without restriction, including
  10. * without limitation the rights to use, copy, modify, merge, publish,
  11. * distribute, sub license, and/or sell copies of the Software, and to
  12. * permit persons to whom the Software is furnished to do so, subject to
  13. * the following conditions:
  14. *
  15. * The above copyright notice and this permission notice (including the
  16. * next paragraph) shall be included in all copies or substantial portions
  17. * of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  21. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  22. * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  23. * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  24. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  25. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26. *
  27. **************************************************************************/
  28. /**
  29. * @file
  30. * Mipmap generation utility
  31. *
  32. * @author Brian Paul
  33. */
  34. #include "pipe/p_context.h"
  35. #include "util/u_debug.h"
  36. #include "pipe/p_defines.h"
  37. #include "pipe/p_inlines.h"
  38. #include "pipe/p_shader_tokens.h"
  39. #include "util/u_memory.h"
  40. #include "util/u_draw_quad.h"
  41. #include "util/u_gen_mipmap.h"
  42. #include "util/u_simple_shaders.h"
  43. #include "tgsi/tgsi_build.h"
  44. #include "tgsi/tgsi_dump.h"
  45. #include "tgsi/tgsi_parse.h"
  46. #include "cso_cache/cso_context.h"
  47. struct gen_mipmap_state
  48. {
  49. struct pipe_context *pipe;
  50. struct cso_context *cso;
  51. struct pipe_blend_state blend;
  52. struct pipe_depth_stencil_alpha_state depthstencil;
  53. struct pipe_rasterizer_state rasterizer;
  54. struct pipe_sampler_state sampler;
  55. struct pipe_viewport_state viewport;
  56. struct pipe_shader_state vert_shader;
  57. struct pipe_shader_state frag_shader;
  58. void *vs;
  59. void *fs;
  60. struct pipe_buffer *vbuf; /**< quad vertices */
  61. unsigned vbuf_slot;
  62. float vertices[4][2][4]; /**< vertex/texcoords for quad */
  63. };
  64. enum dtype
  65. {
  66. UBYTE,
  67. UBYTE_3_3_2,
  68. USHORT,
  69. USHORT_4_4_4_4,
  70. USHORT_5_6_5,
  71. USHORT_1_5_5_5_REV,
  72. UINT,
  73. FLOAT,
  74. HALF_FLOAT
  75. };
  76. typedef ushort half_float;
  77. static half_float
  78. float_to_half(float f)
  79. {
  80. /* XXX fix this */
  81. return 0;
  82. }
  83. static float
  84. half_to_float(half_float h)
  85. {
  86. /* XXX fix this */
  87. return 0.0f;
  88. }
  89. /**
  90. * \name Support macros for do_row and do_row_3d
  91. *
  92. * The macro madness is here for two reasons. First, it compacts the code
  93. * slightly. Second, it makes it much easier to adjust the specifics of the
  94. * filter to tune the rounding characteristics.
  95. */
  96. /*@{*/
  97. #define DECLARE_ROW_POINTERS(t, e) \
  98. const t(*rowA)[e] = (const t(*)[e]) srcRowA; \
  99. const t(*rowB)[e] = (const t(*)[e]) srcRowB; \
  100. const t(*rowC)[e] = (const t(*)[e]) srcRowC; \
  101. const t(*rowD)[e] = (const t(*)[e]) srcRowD; \
  102. t(*dst)[e] = (t(*)[e]) dstRow
  103. #define DECLARE_ROW_POINTERS0(t) \
  104. const t *rowA = (const t *) srcRowA; \
  105. const t *rowB = (const t *) srcRowB; \
  106. const t *rowC = (const t *) srcRowC; \
  107. const t *rowD = (const t *) srcRowD; \
  108. t *dst = (t *) dstRow
  109. #define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
  110. ((unsigned) Aj + (unsigned) Ak \
  111. + (unsigned) Bj + (unsigned) Bk \
  112. + (unsigned) Cj + (unsigned) Ck \
  113. + (unsigned) Dj + (unsigned) Dk \
  114. + 4) >> 3
  115. #define FILTER_3D(e) \
  116. do { \
  117. dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \
  118. rowB[j][e], rowB[k][e], \
  119. rowC[j][e], rowC[k][e], \
  120. rowD[j][e], rowD[k][e]); \
  121. } while(0)
  122. #define FILTER_F_3D(e) \
  123. do { \
  124. dst[i][e] = (rowA[j][e] + rowA[k][e] \
  125. + rowB[j][e] + rowB[k][e] \
  126. + rowC[j][e] + rowC[k][e] \
  127. + rowD[j][e] + rowD[k][e]) * 0.125F; \
  128. } while(0)
  129. #define FILTER_HF_3D(e) \
  130. do { \
  131. const float aj = half_to_float(rowA[j][e]); \
  132. const float ak = half_to_float(rowA[k][e]); \
  133. const float bj = half_to_float(rowB[j][e]); \
  134. const float bk = half_to_float(rowB[k][e]); \
  135. const float cj = half_to_float(rowC[j][e]); \
  136. const float ck = half_to_float(rowC[k][e]); \
  137. const float dj = half_to_float(rowD[j][e]); \
  138. const float dk = half_to_float(rowD[k][e]); \
  139. dst[i][e] = float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
  140. * 0.125F); \
  141. } while(0)
  142. /*@}*/
  143. /**
  144. * Average together two rows of a source image to produce a single new
  145. * row in the dest image. It's legal for the two source rows to point
  146. * to the same data. The source width must be equal to either the
  147. * dest width or two times the dest width.
  148. * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
  149. * \param comps number of components per pixel (1..4)
  150. */
  151. static void
  152. do_row(enum dtype datatype, uint comps, int srcWidth,
  153. const void *srcRowA, const void *srcRowB,
  154. int dstWidth, void *dstRow)
  155. {
  156. const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
  157. const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
  158. assert(comps >= 1);
  159. assert(comps <= 4);
  160. /* This assertion is no longer valid with non-power-of-2 textures
  161. assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
  162. */
  163. if (datatype == UBYTE && comps == 4) {
  164. uint i, j, k;
  165. const ubyte(*rowA)[4] = (const ubyte(*)[4]) srcRowA;
  166. const ubyte(*rowB)[4] = (const ubyte(*)[4]) srcRowB;
  167. ubyte(*dst)[4] = (ubyte(*)[4]) dstRow;
  168. for (i = j = 0, k = k0; i < (uint) dstWidth;
  169. i++, j += colStride, k += colStride) {
  170. dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  171. dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  172. dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
  173. dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
  174. }
  175. }
  176. else if (datatype == UBYTE && comps == 3) {
  177. uint i, j, k;
  178. const ubyte(*rowA)[3] = (const ubyte(*)[3]) srcRowA;
  179. const ubyte(*rowB)[3] = (const ubyte(*)[3]) srcRowB;
  180. ubyte(*dst)[3] = (ubyte(*)[3]) dstRow;
  181. for (i = j = 0, k = k0; i < (uint) dstWidth;
  182. i++, j += colStride, k += colStride) {
  183. dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  184. dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  185. dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
  186. }
  187. }
  188. else if (datatype == UBYTE && comps == 2) {
  189. uint i, j, k;
  190. const ubyte(*rowA)[2] = (const ubyte(*)[2]) srcRowA;
  191. const ubyte(*rowB)[2] = (const ubyte(*)[2]) srcRowB;
  192. ubyte(*dst)[2] = (ubyte(*)[2]) dstRow;
  193. for (i = j = 0, k = k0; i < (uint) dstWidth;
  194. i++, j += colStride, k += colStride) {
  195. dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
  196. dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
  197. }
  198. }
  199. else if (datatype == UBYTE && comps == 1) {
  200. uint i, j, k;
  201. const ubyte *rowA = (const ubyte *) srcRowA;
  202. const ubyte *rowB = (const ubyte *) srcRowB;
  203. ubyte *dst = (ubyte *) dstRow;
  204. for (i = j = 0, k = k0; i < (uint) dstWidth;
  205. i++, j += colStride, k += colStride) {
  206. dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
  207. }
  208. }
  209. else if (datatype == USHORT && comps == 4) {
  210. uint i, j, k;
  211. const ushort(*rowA)[4] = (const ushort(*)[4]) srcRowA;
  212. const ushort(*rowB)[4] = (const ushort(*)[4]) srcRowB;
  213. ushort(*dst)[4] = (ushort(*)[4]) dstRow;
  214. for (i = j = 0, k = k0; i < (uint) dstWidth;
  215. i++, j += colStride, k += colStride) {
  216. dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  217. dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  218. dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
  219. dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
  220. }
  221. }
  222. else if (datatype == USHORT && comps == 3) {
  223. uint i, j, k;
  224. const ushort(*rowA)[3] = (const ushort(*)[3]) srcRowA;
  225. const ushort(*rowB)[3] = (const ushort(*)[3]) srcRowB;
  226. ushort(*dst)[3] = (ushort(*)[3]) dstRow;
  227. for (i = j = 0, k = k0; i < (uint) dstWidth;
  228. i++, j += colStride, k += colStride) {
  229. dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  230. dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  231. dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
  232. }
  233. }
  234. else if (datatype == USHORT && comps == 2) {
  235. uint i, j, k;
  236. const ushort(*rowA)[2] = (const ushort(*)[2]) srcRowA;
  237. const ushort(*rowB)[2] = (const ushort(*)[2]) srcRowB;
  238. ushort(*dst)[2] = (ushort(*)[2]) dstRow;
  239. for (i = j = 0, k = k0; i < (uint) dstWidth;
  240. i++, j += colStride, k += colStride) {
  241. dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  242. dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  243. }
  244. }
  245. else if (datatype == USHORT && comps == 1) {
  246. uint i, j, k;
  247. const ushort *rowA = (const ushort *) srcRowA;
  248. const ushort *rowB = (const ushort *) srcRowB;
  249. ushort *dst = (ushort *) dstRow;
  250. for (i = j = 0, k = k0; i < (uint) dstWidth;
  251. i++, j += colStride, k += colStride) {
  252. dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
  253. }
  254. }
  255. else if (datatype == FLOAT && comps == 4) {
  256. uint i, j, k;
  257. const float(*rowA)[4] = (const float(*)[4]) srcRowA;
  258. const float(*rowB)[4] = (const float(*)[4]) srcRowB;
  259. float(*dst)[4] = (float(*)[4]) dstRow;
  260. for (i = j = 0, k = k0; i < (uint) dstWidth;
  261. i++, j += colStride, k += colStride) {
  262. dst[i][0] = (rowA[j][0] + rowA[k][0] +
  263. rowB[j][0] + rowB[k][0]) * 0.25F;
  264. dst[i][1] = (rowA[j][1] + rowA[k][1] +
  265. rowB[j][1] + rowB[k][1]) * 0.25F;
  266. dst[i][2] = (rowA[j][2] + rowA[k][2] +
  267. rowB[j][2] + rowB[k][2]) * 0.25F;
  268. dst[i][3] = (rowA[j][3] + rowA[k][3] +
  269. rowB[j][3] + rowB[k][3]) * 0.25F;
  270. }
  271. }
  272. else if (datatype == FLOAT && comps == 3) {
  273. uint i, j, k;
  274. const float(*rowA)[3] = (const float(*)[3]) srcRowA;
  275. const float(*rowB)[3] = (const float(*)[3]) srcRowB;
  276. float(*dst)[3] = (float(*)[3]) dstRow;
  277. for (i = j = 0, k = k0; i < (uint) dstWidth;
  278. i++, j += colStride, k += colStride) {
  279. dst[i][0] = (rowA[j][0] + rowA[k][0] +
  280. rowB[j][0] + rowB[k][0]) * 0.25F;
  281. dst[i][1] = (rowA[j][1] + rowA[k][1] +
  282. rowB[j][1] + rowB[k][1]) * 0.25F;
  283. dst[i][2] = (rowA[j][2] + rowA[k][2] +
  284. rowB[j][2] + rowB[k][2]) * 0.25F;
  285. }
  286. }
  287. else if (datatype == FLOAT && comps == 2) {
  288. uint i, j, k;
  289. const float(*rowA)[2] = (const float(*)[2]) srcRowA;
  290. const float(*rowB)[2] = (const float(*)[2]) srcRowB;
  291. float(*dst)[2] = (float(*)[2]) dstRow;
  292. for (i = j = 0, k = k0; i < (uint) dstWidth;
  293. i++, j += colStride, k += colStride) {
  294. dst[i][0] = (rowA[j][0] + rowA[k][0] +
  295. rowB[j][0] + rowB[k][0]) * 0.25F;
  296. dst[i][1] = (rowA[j][1] + rowA[k][1] +
  297. rowB[j][1] + rowB[k][1]) * 0.25F;
  298. }
  299. }
  300. else if (datatype == FLOAT && comps == 1) {
  301. uint i, j, k;
  302. const float *rowA = (const float *) srcRowA;
  303. const float *rowB = (const float *) srcRowB;
  304. float *dst = (float *) dstRow;
  305. for (i = j = 0, k = k0; i < (uint) dstWidth;
  306. i++, j += colStride, k += colStride) {
  307. dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
  308. }
  309. }
  310. #if 0
  311. else if (datatype == HALF_FLOAT && comps == 4) {
  312. uint i, j, k, comp;
  313. const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA;
  314. const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB;
  315. half_float(*dst)[4] = (half_float(*)[4]) dstRow;
  316. for (i = j = 0, k = k0; i < (uint) dstWidth;
  317. i++, j += colStride, k += colStride) {
  318. for (comp = 0; comp < 4; comp++) {
  319. float aj, ak, bj, bk;
  320. aj = half_to_float(rowA[j][comp]);
  321. ak = half_to_float(rowA[k][comp]);
  322. bj = half_to_float(rowB[j][comp]);
  323. bk = half_to_float(rowB[k][comp]);
  324. dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
  325. }
  326. }
  327. }
  328. else if (datatype == HALF_FLOAT && comps == 3) {
  329. uint i, j, k, comp;
  330. const half_float(*rowA)[3] = (const half_float(*)[3]) srcRowA;
  331. const half_float(*rowB)[3] = (const half_float(*)[3]) srcRowB;
  332. half_float(*dst)[3] = (half_float(*)[3]) dstRow;
  333. for (i = j = 0, k = k0; i < (uint) dstWidth;
  334. i++, j += colStride, k += colStride) {
  335. for (comp = 0; comp < 3; comp++) {
  336. float aj, ak, bj, bk;
  337. aj = half_to_float(rowA[j][comp]);
  338. ak = half_to_float(rowA[k][comp]);
  339. bj = half_to_float(rowB[j][comp]);
  340. bk = half_to_float(rowB[k][comp]);
  341. dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
  342. }
  343. }
  344. }
  345. else if (datatype == HALF_FLOAT && comps == 2) {
  346. uint i, j, k, comp;
  347. const half_float(*rowA)[2] = (const half_float(*)[2]) srcRowA;
  348. const half_float(*rowB)[2] = (const half_float(*)[2]) srcRowB;
  349. half_float(*dst)[2] = (half_float(*)[2]) dstRow;
  350. for (i = j = 0, k = k0; i < (uint) dstWidth;
  351. i++, j += colStride, k += colStride) {
  352. for (comp = 0; comp < 2; comp++) {
  353. float aj, ak, bj, bk;
  354. aj = half_to_float(rowA[j][comp]);
  355. ak = half_to_float(rowA[k][comp]);
  356. bj = half_to_float(rowB[j][comp]);
  357. bk = half_to_float(rowB[k][comp]);
  358. dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
  359. }
  360. }
  361. }
  362. else if (datatype == HALF_FLOAT && comps == 1) {
  363. uint i, j, k;
  364. const half_float *rowA = (const half_float *) srcRowA;
  365. const half_float *rowB = (const half_float *) srcRowB;
  366. half_float *dst = (half_float *) dstRow;
  367. for (i = j = 0, k = k0; i < (uint) dstWidth;
  368. i++, j += colStride, k += colStride) {
  369. float aj, ak, bj, bk;
  370. aj = half_to_float(rowA[j]);
  371. ak = half_to_float(rowA[k]);
  372. bj = half_to_float(rowB[j]);
  373. bk = half_to_float(rowB[k]);
  374. dst[i] = float_to_half((aj + ak + bj + bk) * 0.25F);
  375. }
  376. }
  377. #endif
  378. else if (datatype == UINT && comps == 1) {
  379. uint i, j, k;
  380. const uint *rowA = (const uint *) srcRowA;
  381. const uint *rowB = (const uint *) srcRowB;
  382. uint *dst = (uint *) dstRow;
  383. for (i = j = 0, k = k0; i < (uint) dstWidth;
  384. i++, j += colStride, k += colStride) {
  385. dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4;
  386. }
  387. }
  388. else if (datatype == USHORT_5_6_5 && comps == 3) {
  389. uint i, j, k;
  390. const ushort *rowA = (const ushort *) srcRowA;
  391. const ushort *rowB = (const ushort *) srcRowB;
  392. ushort *dst = (ushort *) dstRow;
  393. for (i = j = 0, k = k0; i < (uint) dstWidth;
  394. i++, j += colStride, k += colStride) {
  395. const int rowAr0 = rowA[j] & 0x1f;
  396. const int rowAr1 = rowA[k] & 0x1f;
  397. const int rowBr0 = rowB[j] & 0x1f;
  398. const int rowBr1 = rowB[k] & 0x1f;
  399. const int rowAg0 = (rowA[j] >> 5) & 0x3f;
  400. const int rowAg1 = (rowA[k] >> 5) & 0x3f;
  401. const int rowBg0 = (rowB[j] >> 5) & 0x3f;
  402. const int rowBg1 = (rowB[k] >> 5) & 0x3f;
  403. const int rowAb0 = (rowA[j] >> 11) & 0x1f;
  404. const int rowAb1 = (rowA[k] >> 11) & 0x1f;
  405. const int rowBb0 = (rowB[j] >> 11) & 0x1f;
  406. const int rowBb1 = (rowB[k] >> 11) & 0x1f;
  407. const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
  408. const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
  409. const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
  410. dst[i] = (blue << 11) | (green << 5) | red;
  411. }
  412. }
  413. else if (datatype == USHORT_4_4_4_4 && comps == 4) {
  414. uint i, j, k;
  415. const ushort *rowA = (const ushort *) srcRowA;
  416. const ushort *rowB = (const ushort *) srcRowB;
  417. ushort *dst = (ushort *) dstRow;
  418. for (i = j = 0, k = k0; i < (uint) dstWidth;
  419. i++, j += colStride, k += colStride) {
  420. const int rowAr0 = rowA[j] & 0xf;
  421. const int rowAr1 = rowA[k] & 0xf;
  422. const int rowBr0 = rowB[j] & 0xf;
  423. const int rowBr1 = rowB[k] & 0xf;
  424. const int rowAg0 = (rowA[j] >> 4) & 0xf;
  425. const int rowAg1 = (rowA[k] >> 4) & 0xf;
  426. const int rowBg0 = (rowB[j] >> 4) & 0xf;
  427. const int rowBg1 = (rowB[k] >> 4) & 0xf;
  428. const int rowAb0 = (rowA[j] >> 8) & 0xf;
  429. const int rowAb1 = (rowA[k] >> 8) & 0xf;
  430. const int rowBb0 = (rowB[j] >> 8) & 0xf;
  431. const int rowBb1 = (rowB[k] >> 8) & 0xf;
  432. const int rowAa0 = (rowA[j] >> 12) & 0xf;
  433. const int rowAa1 = (rowA[k] >> 12) & 0xf;
  434. const int rowBa0 = (rowB[j] >> 12) & 0xf;
  435. const int rowBa1 = (rowB[k] >> 12) & 0xf;
  436. const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
  437. const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
  438. const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
  439. const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
  440. dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
  441. }
  442. }
  443. else if (datatype == USHORT_1_5_5_5_REV && comps == 4) {
  444. uint i, j, k;
  445. const ushort *rowA = (const ushort *) srcRowA;
  446. const ushort *rowB = (const ushort *) srcRowB;
  447. ushort *dst = (ushort *) dstRow;
  448. for (i = j = 0, k = k0; i < (uint) dstWidth;
  449. i++, j += colStride, k += colStride) {
  450. const int rowAr0 = rowA[j] & 0x1f;
  451. const int rowAr1 = rowA[k] & 0x1f;
  452. const int rowBr0 = rowB[j] & 0x1f;
  453. const int rowBr1 = rowB[k] & 0x1f;
  454. const int rowAg0 = (rowA[j] >> 5) & 0x1f;
  455. const int rowAg1 = (rowA[k] >> 5) & 0x1f;
  456. const int rowBg0 = (rowB[j] >> 5) & 0x1f;
  457. const int rowBg1 = (rowB[k] >> 5) & 0x1f;
  458. const int rowAb0 = (rowA[j] >> 10) & 0x1f;
  459. const int rowAb1 = (rowA[k] >> 10) & 0x1f;
  460. const int rowBb0 = (rowB[j] >> 10) & 0x1f;
  461. const int rowBb1 = (rowB[k] >> 10) & 0x1f;
  462. const int rowAa0 = (rowA[j] >> 15) & 0x1;
  463. const int rowAa1 = (rowA[k] >> 15) & 0x1;
  464. const int rowBa0 = (rowB[j] >> 15) & 0x1;
  465. const int rowBa1 = (rowB[k] >> 15) & 0x1;
  466. const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
  467. const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
  468. const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
  469. const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
  470. dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
  471. }
  472. }
  473. else if (datatype == UBYTE_3_3_2 && comps == 3) {
  474. uint i, j, k;
  475. const ubyte *rowA = (const ubyte *) srcRowA;
  476. const ubyte *rowB = (const ubyte *) srcRowB;
  477. ubyte *dst = (ubyte *) dstRow;
  478. for (i = j = 0, k = k0; i < (uint) dstWidth;
  479. i++, j += colStride, k += colStride) {
  480. const int rowAr0 = rowA[j] & 0x3;
  481. const int rowAr1 = rowA[k] & 0x3;
  482. const int rowBr0 = rowB[j] & 0x3;
  483. const int rowBr1 = rowB[k] & 0x3;
  484. const int rowAg0 = (rowA[j] >> 2) & 0x7;
  485. const int rowAg1 = (rowA[k] >> 2) & 0x7;
  486. const int rowBg0 = (rowB[j] >> 2) & 0x7;
  487. const int rowBg1 = (rowB[k] >> 2) & 0x7;
  488. const int rowAb0 = (rowA[j] >> 5) & 0x7;
  489. const int rowAb1 = (rowA[k] >> 5) & 0x7;
  490. const int rowBb0 = (rowB[j] >> 5) & 0x7;
  491. const int rowBb1 = (rowB[k] >> 5) & 0x7;
  492. const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
  493. const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
  494. const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
  495. dst[i] = (blue << 5) | (green << 2) | red;
  496. }
  497. }
  498. else {
  499. debug_printf("bad format in do_row()");
  500. }
  501. }
  502. /**
  503. * Average together four rows of a source image to produce a single new
  504. * row in the dest image. It's legal for the two source rows to point
  505. * to the same data. The source width must be equal to either the
  506. * dest width or two times the dest width.
  507. *
  508. * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT,
  509. * \c GL_FLOAT, etc.
  510. * \param comps number of components per pixel (1..4)
  511. * \param srcWidth Width of a row in the source data
  512. * \param srcRowA Pointer to one of the rows of source data
  513. * \param srcRowB Pointer to one of the rows of source data
  514. * \param srcRowC Pointer to one of the rows of source data
  515. * \param srcRowD Pointer to one of the rows of source data
  516. * \param dstWidth Width of a row in the destination data
  517. * \param srcRowA Pointer to the row of destination data
  518. */
  519. static void
  520. do_row_3D(enum dtype datatype, uint comps, int srcWidth,
  521. const void *srcRowA, const void *srcRowB,
  522. const void *srcRowC, const void *srcRowD,
  523. int dstWidth, void *dstRow)
  524. {
  525. const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
  526. const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
  527. uint i, j, k;
  528. assert(comps >= 1);
  529. assert(comps <= 4);
  530. if ((datatype == UBYTE) && (comps == 4)) {
  531. DECLARE_ROW_POINTERS(ubyte, 4);
  532. for (i = j = 0, k = k0; i < (uint) dstWidth;
  533. i++, j += colStride, k += colStride) {
  534. FILTER_3D(0);
  535. FILTER_3D(1);
  536. FILTER_3D(2);
  537. FILTER_3D(3);
  538. }
  539. }
  540. else if ((datatype == UBYTE) && (comps == 3)) {
  541. DECLARE_ROW_POINTERS(ubyte, 3);
  542. for (i = j = 0, k = k0; i < (uint) dstWidth;
  543. i++, j += colStride, k += colStride) {
  544. FILTER_3D(0);
  545. FILTER_3D(1);
  546. FILTER_3D(2);
  547. }
  548. }
  549. else if ((datatype == UBYTE) && (comps == 2)) {
  550. DECLARE_ROW_POINTERS(ubyte, 2);
  551. for (i = j = 0, k = k0; i < (uint) dstWidth;
  552. i++, j += colStride, k += colStride) {
  553. FILTER_3D(0);
  554. FILTER_3D(1);
  555. }
  556. }
  557. else if ((datatype == UBYTE) && (comps == 1)) {
  558. DECLARE_ROW_POINTERS(ubyte, 1);
  559. for (i = j = 0, k = k0; i < (uint) dstWidth;
  560. i++, j += colStride, k += colStride) {
  561. FILTER_3D(0);
  562. }
  563. }
  564. else if ((datatype == USHORT) && (comps == 4)) {
  565. DECLARE_ROW_POINTERS(ushort, 4);
  566. for (i = j = 0, k = k0; i < (uint) dstWidth;
  567. i++, j += colStride, k += colStride) {
  568. FILTER_3D(0);
  569. FILTER_3D(1);
  570. FILTER_3D(2);
  571. FILTER_3D(3);
  572. }
  573. }
  574. else if ((datatype == USHORT) && (comps == 3)) {
  575. DECLARE_ROW_POINTERS(ushort, 3);
  576. for (i = j = 0, k = k0; i < (uint) dstWidth;
  577. i++, j += colStride, k += colStride) {
  578. FILTER_3D(0);
  579. FILTER_3D(1);
  580. FILTER_3D(2);
  581. }
  582. }
  583. else if ((datatype == USHORT) && (comps == 2)) {
  584. DECLARE_ROW_POINTERS(ushort, 2);
  585. for (i = j = 0, k = k0; i < (uint) dstWidth;
  586. i++, j += colStride, k += colStride) {
  587. FILTER_3D(0);
  588. FILTER_3D(1);
  589. }
  590. }
  591. else if ((datatype == USHORT) && (comps == 1)) {
  592. DECLARE_ROW_POINTERS(ushort, 1);
  593. for (i = j = 0, k = k0; i < (uint) dstWidth;
  594. i++, j += colStride, k += colStride) {
  595. FILTER_3D(0);
  596. }
  597. }
  598. else if ((datatype == FLOAT) && (comps == 4)) {
  599. DECLARE_ROW_POINTERS(float, 4);
  600. for (i = j = 0, k = k0; i < (uint) dstWidth;
  601. i++, j += colStride, k += colStride) {
  602. FILTER_F_3D(0);
  603. FILTER_F_3D(1);
  604. FILTER_F_3D(2);
  605. FILTER_F_3D(3);
  606. }
  607. }
  608. else if ((datatype == FLOAT) && (comps == 3)) {
  609. DECLARE_ROW_POINTERS(float, 3);
  610. for (i = j = 0, k = k0; i < (uint) dstWidth;
  611. i++, j += colStride, k += colStride) {
  612. FILTER_F_3D(0);
  613. FILTER_F_3D(1);
  614. FILTER_F_3D(2);
  615. }
  616. }
  617. else if ((datatype == FLOAT) && (comps == 2)) {
  618. DECLARE_ROW_POINTERS(float, 2);
  619. for (i = j = 0, k = k0; i < (uint) dstWidth;
  620. i++, j += colStride, k += colStride) {
  621. FILTER_F_3D(0);
  622. FILTER_F_3D(1);
  623. }
  624. }
  625. else if ((datatype == FLOAT) && (comps == 1)) {
  626. DECLARE_ROW_POINTERS(float, 1);
  627. for (i = j = 0, k = k0; i < (uint) dstWidth;
  628. i++, j += colStride, k += colStride) {
  629. FILTER_F_3D(0);
  630. }
  631. }
  632. else if ((datatype == HALF_FLOAT) && (comps == 4)) {
  633. DECLARE_ROW_POINTERS(half_float, 4);
  634. for (i = j = 0, k = k0; i < (uint) dstWidth;
  635. i++, j += colStride, k += colStride) {
  636. FILTER_HF_3D(0);
  637. FILTER_HF_3D(1);
  638. FILTER_HF_3D(2);
  639. FILTER_HF_3D(3);
  640. }
  641. }
  642. else if ((datatype == HALF_FLOAT) && (comps == 3)) {
  643. DECLARE_ROW_POINTERS(half_float, 4);
  644. for (i = j = 0, k = k0; i < (uint) dstWidth;
  645. i++, j += colStride, k += colStride) {
  646. FILTER_HF_3D(0);
  647. FILTER_HF_3D(1);
  648. FILTER_HF_3D(2);
  649. }
  650. }
  651. else if ((datatype == HALF_FLOAT) && (comps == 2)) {
  652. DECLARE_ROW_POINTERS(half_float, 4);
  653. for (i = j = 0, k = k0; i < (uint) dstWidth;
  654. i++, j += colStride, k += colStride) {
  655. FILTER_HF_3D(0);
  656. FILTER_HF_3D(1);
  657. }
  658. }
  659. else if ((datatype == HALF_FLOAT) && (comps == 1)) {
  660. DECLARE_ROW_POINTERS(half_float, 4);
  661. for (i = j = 0, k = k0; i < (uint) dstWidth;
  662. i++, j += colStride, k += colStride) {
  663. FILTER_HF_3D(0);
  664. }
  665. }
  666. else if ((datatype == UINT) && (comps == 1)) {
  667. const uint *rowA = (const uint *) srcRowA;
  668. const uint *rowB = (const uint *) srcRowB;
  669. const uint *rowC = (const uint *) srcRowC;
  670. const uint *rowD = (const uint *) srcRowD;
  671. float *dst = (float *) dstRow;
  672. for (i = j = 0, k = k0; i < (uint) dstWidth;
  673. i++, j += colStride, k += colStride) {
  674. const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k])
  675. + ((uint64_t) rowB[j] + (uint64_t) rowB[k])
  676. + ((uint64_t) rowC[j] + (uint64_t) rowC[k])
  677. + ((uint64_t) rowD[j] + (uint64_t) rowD[k]));
  678. dst[i] = (float)((double) tmp * 0.125);
  679. }
  680. }
  681. else if ((datatype == USHORT_5_6_5) && (comps == 3)) {
  682. DECLARE_ROW_POINTERS0(ushort);
  683. for (i = j = 0, k = k0; i < (uint) dstWidth;
  684. i++, j += colStride, k += colStride) {
  685. const int rowAr0 = rowA[j] & 0x1f;
  686. const int rowAr1 = rowA[k] & 0x1f;
  687. const int rowBr0 = rowB[j] & 0x1f;
  688. const int rowBr1 = rowB[k] & 0x1f;
  689. const int rowCr0 = rowC[j] & 0x1f;
  690. const int rowCr1 = rowC[k] & 0x1f;
  691. const int rowDr0 = rowD[j] & 0x1f;
  692. const int rowDr1 = rowD[k] & 0x1f;
  693. const int rowAg0 = (rowA[j] >> 5) & 0x3f;
  694. const int rowAg1 = (rowA[k] >> 5) & 0x3f;
  695. const int rowBg0 = (rowB[j] >> 5) & 0x3f;
  696. const int rowBg1 = (rowB[k] >> 5) & 0x3f;
  697. const int rowCg0 = (rowC[j] >> 5) & 0x3f;
  698. const int rowCg1 = (rowC[k] >> 5) & 0x3f;
  699. const int rowDg0 = (rowD[j] >> 5) & 0x3f;
  700. const int rowDg1 = (rowD[k] >> 5) & 0x3f;
  701. const int rowAb0 = (rowA[j] >> 11) & 0x1f;
  702. const int rowAb1 = (rowA[k] >> 11) & 0x1f;
  703. const int rowBb0 = (rowB[j] >> 11) & 0x1f;
  704. const int rowBb1 = (rowB[k] >> 11) & 0x1f;
  705. const int rowCb0 = (rowC[j] >> 11) & 0x1f;
  706. const int rowCb1 = (rowC[k] >> 11) & 0x1f;
  707. const int rowDb0 = (rowD[j] >> 11) & 0x1f;
  708. const int rowDb1 = (rowD[k] >> 11) & 0x1f;
  709. const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
  710. rowCr0, rowCr1, rowDr0, rowDr1);
  711. const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
  712. rowCg0, rowCg1, rowDg0, rowDg1);
  713. const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
  714. rowCb0, rowCb1, rowDb0, rowDb1);
  715. dst[i] = (b << 11) | (g << 5) | r;
  716. }
  717. }
  718. else if ((datatype == USHORT_4_4_4_4) && (comps == 4)) {
  719. DECLARE_ROW_POINTERS0(ushort);
  720. for (i = j = 0, k = k0; i < (uint) dstWidth;
  721. i++, j += colStride, k += colStride) {
  722. const int rowAr0 = rowA[j] & 0xf;
  723. const int rowAr1 = rowA[k] & 0xf;
  724. const int rowBr0 = rowB[j] & 0xf;
  725. const int rowBr1 = rowB[k] & 0xf;
  726. const int rowCr0 = rowC[j] & 0xf;
  727. const int rowCr1 = rowC[k] & 0xf;
  728. const int rowDr0 = rowD[j] & 0xf;
  729. const int rowDr1 = rowD[k] & 0xf;
  730. const int rowAg0 = (rowA[j] >> 4) & 0xf;
  731. const int rowAg1 = (rowA[k] >> 4) & 0xf;
  732. const int rowBg0 = (rowB[j] >> 4) & 0xf;
  733. const int rowBg1 = (rowB[k] >> 4) & 0xf;
  734. const int rowCg0 = (rowC[j] >> 4) & 0xf;
  735. const int rowCg1 = (rowC[k] >> 4) & 0xf;
  736. const int rowDg0 = (rowD[j] >> 4) & 0xf;
  737. const int rowDg1 = (rowD[k] >> 4) & 0xf;
  738. const int rowAb0 = (rowA[j] >> 8) & 0xf;
  739. const int rowAb1 = (rowA[k] >> 8) & 0xf;
  740. const int rowBb0 = (rowB[j] >> 8) & 0xf;
  741. const int rowBb1 = (rowB[k] >> 8) & 0xf;
  742. const int rowCb0 = (rowC[j] >> 8) & 0xf;
  743. const int rowCb1 = (rowC[k] >> 8) & 0xf;
  744. const int rowDb0 = (rowD[j] >> 8) & 0xf;
  745. const int rowDb1 = (rowD[k] >> 8) & 0xf;
  746. const int rowAa0 = (rowA[j] >> 12) & 0xf;
  747. const int rowAa1 = (rowA[k] >> 12) & 0xf;
  748. const int rowBa0 = (rowB[j] >> 12) & 0xf;
  749. const int rowBa1 = (rowB[k] >> 12) & 0xf;
  750. const int rowCa0 = (rowC[j] >> 12) & 0xf;
  751. const int rowCa1 = (rowC[k] >> 12) & 0xf;
  752. const int rowDa0 = (rowD[j] >> 12) & 0xf;
  753. const int rowDa1 = (rowD[k] >> 12) & 0xf;
  754. const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
  755. rowCr0, rowCr1, rowDr0, rowDr1);
  756. const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
  757. rowCg0, rowCg1, rowDg0, rowDg1);
  758. const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
  759. rowCb0, rowCb1, rowDb0, rowDb1);
  760. const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
  761. rowCa0, rowCa1, rowDa0, rowDa1);
  762. dst[i] = (a << 12) | (b << 8) | (g << 4) | r;
  763. }
  764. }
  765. else if ((datatype == USHORT_1_5_5_5_REV) && (comps == 4)) {
  766. DECLARE_ROW_POINTERS0(ushort);
  767. for (i = j = 0, k = k0; i < (uint) dstWidth;
  768. i++, j += colStride, k += colStride) {
  769. const int rowAr0 = rowA[j] & 0x1f;
  770. const int rowAr1 = rowA[k] & 0x1f;
  771. const int rowBr0 = rowB[j] & 0x1f;
  772. const int rowBr1 = rowB[k] & 0x1f;
  773. const int rowCr0 = rowC[j] & 0x1f;
  774. const int rowCr1 = rowC[k] & 0x1f;
  775. const int rowDr0 = rowD[j] & 0x1f;
  776. const int rowDr1 = rowD[k] & 0x1f;
  777. const int rowAg0 = (rowA[j] >> 5) & 0x1f;
  778. const int rowAg1 = (rowA[k] >> 5) & 0x1f;
  779. const int rowBg0 = (rowB[j] >> 5) & 0x1f;
  780. const int rowBg1 = (rowB[k] >> 5) & 0x1f;
  781. const int rowCg0 = (rowC[j] >> 5) & 0x1f;
  782. const int rowCg1 = (rowC[k] >> 5) & 0x1f;
  783. const int rowDg0 = (rowD[j] >> 5) & 0x1f;
  784. const int rowDg1 = (rowD[k] >> 5) & 0x1f;
  785. const int rowAb0 = (rowA[j] >> 10) & 0x1f;
  786. const int rowAb1 = (rowA[k] >> 10) & 0x1f;
  787. const int rowBb0 = (rowB[j] >> 10) & 0x1f;
  788. const int rowBb1 = (rowB[k] >> 10) & 0x1f;
  789. const int rowCb0 = (rowC[j] >> 10) & 0x1f;
  790. const int rowCb1 = (rowC[k] >> 10) & 0x1f;
  791. const int rowDb0 = (rowD[j] >> 10) & 0x1f;
  792. const int rowDb1 = (rowD[k] >> 10) & 0x1f;
  793. const int rowAa0 = (rowA[j] >> 15) & 0x1;
  794. const int rowAa1 = (rowA[k] >> 15) & 0x1;
  795. const int rowBa0 = (rowB[j] >> 15) & 0x1;
  796. const int rowBa1 = (rowB[k] >> 15) & 0x1;
  797. const int rowCa0 = (rowC[j] >> 15) & 0x1;
  798. const int rowCa1 = (rowC[k] >> 15) & 0x1;
  799. const int rowDa0 = (rowD[j] >> 15) & 0x1;
  800. const int rowDa1 = (rowD[k] >> 15) & 0x1;
  801. const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
  802. rowCr0, rowCr1, rowDr0, rowDr1);
  803. const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
  804. rowCg0, rowCg1, rowDg0, rowDg1);
  805. const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
  806. rowCb0, rowCb1, rowDb0, rowDb1);
  807. const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
  808. rowCa0, rowCa1, rowDa0, rowDa1);
  809. dst[i] = (a << 15) | (b << 10) | (g << 5) | r;
  810. }
  811. }
  812. else if ((datatype == UBYTE_3_3_2) && (comps == 3)) {
  813. DECLARE_ROW_POINTERS0(ushort);
  814. for (i = j = 0, k = k0; i < (uint) dstWidth;
  815. i++, j += colStride, k += colStride) {
  816. const int rowAr0 = rowA[j] & 0x3;
  817. const int rowAr1 = rowA[k] & 0x3;
  818. const int rowBr0 = rowB[j] & 0x3;
  819. const int rowBr1 = rowB[k] & 0x3;
  820. const int rowCr0 = rowC[j] & 0x3;
  821. const int rowCr1 = rowC[k] & 0x3;
  822. const int rowDr0 = rowD[j] & 0x3;
  823. const int rowDr1 = rowD[k] & 0x3;
  824. const int rowAg0 = (rowA[j] >> 2) & 0x7;
  825. const int rowAg1 = (rowA[k] >> 2) & 0x7;
  826. const int rowBg0 = (rowB[j] >> 2) & 0x7;
  827. const int rowBg1 = (rowB[k] >> 2) & 0x7;
  828. const int rowCg0 = (rowC[j] >> 2) & 0x7;
  829. const int rowCg1 = (rowC[k] >> 2) & 0x7;
  830. const int rowDg0 = (rowD[j] >> 2) & 0x7;
  831. const int rowDg1 = (rowD[k] >> 2) & 0x7;
  832. const int rowAb0 = (rowA[j] >> 5) & 0x7;
  833. const int rowAb1 = (rowA[k] >> 5) & 0x7;
  834. const int rowBb0 = (rowB[j] >> 5) & 0x7;
  835. const int rowBb1 = (rowB[k] >> 5) & 0x7;
  836. const int rowCb0 = (rowC[j] >> 5) & 0x7;
  837. const int rowCb1 = (rowC[k] >> 5) & 0x7;
  838. const int rowDb0 = (rowD[j] >> 5) & 0x7;
  839. const int rowDb1 = (rowD[k] >> 5) & 0x7;
  840. const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
  841. rowCr0, rowCr1, rowDr0, rowDr1);
  842. const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
  843. rowCg0, rowCg1, rowDg0, rowDg1);
  844. const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
  845. rowCb0, rowCb1, rowDb0, rowDb1);
  846. dst[i] = (b << 5) | (g << 2) | r;
  847. }
  848. }
  849. else {
  850. debug_printf("bad format in do_row_3D()");
  851. }
  852. }
  853. static void
  854. format_to_type_comps(enum pipe_format pformat,
  855. enum dtype *datatype, uint *comps)
  856. {
  857. switch (pformat) {
  858. case PIPE_FORMAT_A8R8G8B8_UNORM:
  859. case PIPE_FORMAT_X8R8G8B8_UNORM:
  860. case PIPE_FORMAT_B8G8R8A8_UNORM:
  861. case PIPE_FORMAT_B8G8R8X8_UNORM:
  862. *datatype = UBYTE;
  863. *comps = 4;
  864. return;
  865. case PIPE_FORMAT_A1R5G5B5_UNORM:
  866. *datatype = USHORT_1_5_5_5_REV;
  867. *comps = 4;
  868. return;
  869. case PIPE_FORMAT_A4R4G4B4_UNORM:
  870. *datatype = USHORT_4_4_4_4;
  871. *comps = 4;
  872. return;
  873. case PIPE_FORMAT_R5G6B5_UNORM:
  874. *datatype = USHORT_5_6_5;
  875. *comps = 3;
  876. return;
  877. case PIPE_FORMAT_L8_UNORM:
  878. case PIPE_FORMAT_A8_UNORM:
  879. case PIPE_FORMAT_I8_UNORM:
  880. *datatype = UBYTE;
  881. *comps = 1;
  882. return;
  883. case PIPE_FORMAT_A8L8_UNORM:
  884. *datatype = UBYTE;
  885. *comps = 2;
  886. return;
  887. default:
  888. assert(0);
  889. *datatype = UBYTE;
  890. *comps = 0;
  891. break;
  892. }
  893. }
  894. static void
  895. reduce_1d(enum pipe_format pformat,
  896. int srcWidth, const ubyte *srcPtr,
  897. int dstWidth, ubyte *dstPtr)
  898. {
  899. enum dtype datatype;
  900. uint comps;
  901. format_to_type_comps(pformat, &datatype, &comps);
  902. /* we just duplicate the input row, kind of hack, saves code */
  903. do_row(datatype, comps,
  904. srcWidth, srcPtr, srcPtr,
  905. dstWidth, dstPtr);
  906. }
  907. /**
  908. * Strides are in bytes. If zero, it'll be computed as width * bpp.
  909. */
  910. static void
  911. reduce_2d(enum pipe_format pformat,
  912. int srcWidth, int srcHeight,
  913. int srcRowStride, const ubyte *srcPtr,
  914. int dstWidth, int dstHeight,
  915. int dstRowStride, ubyte *dstPtr)
  916. {
  917. enum dtype datatype;
  918. uint comps;
  919. const int bpt = pf_get_size(pformat);
  920. const ubyte *srcA, *srcB;
  921. ubyte *dst;
  922. int row;
  923. format_to_type_comps(pformat, &datatype, &comps);
  924. if (!srcRowStride)
  925. srcRowStride = bpt * srcWidth;
  926. if (!dstRowStride)
  927. dstRowStride = bpt * dstWidth;
  928. /* Compute src and dst pointers */
  929. srcA = srcPtr;
  930. if (srcHeight > 1)
  931. srcB = srcA + srcRowStride;
  932. else
  933. srcB = srcA;
  934. dst = dstPtr;
  935. for (row = 0; row < dstHeight; row++) {
  936. do_row(datatype, comps,
  937. srcWidth, srcA, srcB,
  938. dstWidth, dst);
  939. srcA += 2 * srcRowStride;
  940. srcB += 2 * srcRowStride;
  941. dst += dstRowStride;
  942. }
  943. }
  944. static void
  945. reduce_3d(enum pipe_format pformat,
  946. int srcWidth, int srcHeight, int srcDepth,
  947. int srcRowStride, const ubyte *srcPtr,
  948. int dstWidth, int dstHeight, int dstDepth,
  949. int dstRowStride, ubyte *dstPtr)
  950. {
  951. const int bpt = pf_get_size(pformat);
  952. const int border = 0;
  953. int img, row;
  954. int bytesPerSrcImage, bytesPerDstImage;
  955. int bytesPerSrcRow, bytesPerDstRow;
  956. int srcImageOffset, srcRowOffset;
  957. enum dtype datatype;
  958. uint comps;
  959. format_to_type_comps(pformat, &datatype, &comps);
  960. bytesPerSrcImage = srcWidth * srcHeight * bpt;
  961. bytesPerDstImage = dstWidth * dstHeight * bpt;
  962. bytesPerSrcRow = srcWidth * bpt;
  963. bytesPerDstRow = dstWidth * bpt;
  964. /* Offset between adjacent src images to be averaged together */
  965. srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
  966. /* Offset between adjacent src rows to be averaged together */
  967. srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
  968. /*
  969. * Need to average together up to 8 src pixels for each dest pixel.
  970. * Break that down into 3 operations:
  971. * 1. take two rows from source image and average them together.
  972. * 2. take two rows from next source image and average them together.
  973. * 3. take the two averaged rows and average them for the final dst row.
  974. */
  975. /*
  976. _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
  977. srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
  978. */
  979. for (img = 0; img < dstDepth; img++) {
  980. /* first source image pointer, skipping border */
  981. const ubyte *imgSrcA = srcPtr
  982. + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
  983. + img * (bytesPerSrcImage + srcImageOffset);
  984. /* second source image pointer, skipping border */
  985. const ubyte *imgSrcB = imgSrcA + srcImageOffset;
  986. /* address of the dest image, skipping border */
  987. ubyte *imgDst = dstPtr
  988. + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
  989. + img * bytesPerDstImage;
  990. /* setup the four source row pointers and the dest row pointer */
  991. const ubyte *srcImgARowA = imgSrcA;
  992. const ubyte *srcImgARowB = imgSrcA + srcRowOffset;
  993. const ubyte *srcImgBRowA = imgSrcB;
  994. const ubyte *srcImgBRowB = imgSrcB + srcRowOffset;
  995. ubyte *dstImgRow = imgDst;
  996. for (row = 0; row < dstHeight; row++) {
  997. do_row_3D(datatype, comps, srcWidth,
  998. srcImgARowA, srcImgARowB,
  999. srcImgBRowA, srcImgBRowB,
  1000. dstWidth, dstImgRow);
  1001. /* advance to next rows */
  1002. srcImgARowA += bytesPerSrcRow + srcRowOffset;
  1003. srcImgARowB += bytesPerSrcRow + srcRowOffset;
  1004. srcImgBRowA += bytesPerSrcRow + srcRowOffset;
  1005. srcImgBRowB += bytesPerSrcRow + srcRowOffset;
  1006. dstImgRow += bytesPerDstRow;
  1007. }
  1008. }
  1009. }
  1010. static void
  1011. make_1d_mipmap(struct gen_mipmap_state *ctx,
  1012. struct pipe_texture *pt,
  1013. uint face, uint baseLevel, uint lastLevel)
  1014. {
  1015. struct pipe_context *pipe = ctx->pipe;
  1016. struct pipe_screen *screen = pipe->screen;
  1017. const uint zslice = 0;
  1018. uint dstLevel;
  1019. for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
  1020. const uint srcLevel = dstLevel - 1;
  1021. struct pipe_transfer *srcTrans, *dstTrans;
  1022. void *srcMap, *dstMap;
  1023. srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice,
  1024. PIPE_TRANSFER_READ, 0, 0,
  1025. pt->width[srcLevel],
  1026. pt->height[srcLevel]);
  1027. dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice,
  1028. PIPE_TRANSFER_WRITE, 0, 0,
  1029. pt->width[dstLevel],
  1030. pt->height[dstLevel]);
  1031. srcMap = (ubyte *) screen->transfer_map(screen, srcTrans);
  1032. dstMap = (ubyte *) screen->transfer_map(screen, dstTrans);
  1033. reduce_1d(pt->format,
  1034. srcTrans->width, srcMap,
  1035. dstTrans->width, dstMap);
  1036. screen->transfer_unmap(screen, srcTrans);
  1037. screen->transfer_unmap(screen, dstTrans);
  1038. screen->tex_transfer_release(screen, &srcTrans);
  1039. screen->tex_transfer_release(screen, &dstTrans);
  1040. }
  1041. }
  1042. static void
  1043. make_2d_mipmap(struct gen_mipmap_state *ctx,
  1044. struct pipe_texture *pt,
  1045. uint face, uint baseLevel, uint lastLevel)
  1046. {
  1047. struct pipe_context *pipe = ctx->pipe;
  1048. struct pipe_screen *screen = pipe->screen;
  1049. const uint zslice = 0;
  1050. uint dstLevel;
  1051. assert(pt->block.width == 1);
  1052. assert(pt->block.height == 1);
  1053. for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
  1054. const uint srcLevel = dstLevel - 1;
  1055. struct pipe_transfer *srcTrans, *dstTrans;
  1056. ubyte *srcMap, *dstMap;
  1057. srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice,
  1058. PIPE_TRANSFER_READ, 0, 0,
  1059. pt->width[srcLevel],
  1060. pt->height[srcLevel]);
  1061. dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice,
  1062. PIPE_TRANSFER_WRITE, 0, 0,
  1063. pt->width[dstLevel],
  1064. pt->height[dstLevel]);
  1065. srcMap = (ubyte *) screen->transfer_map(screen, srcTrans);
  1066. dstMap = (ubyte *) screen->transfer_map(screen, dstTrans);
  1067. reduce_2d(pt->format,
  1068. srcTrans->width, srcTrans->height,
  1069. srcTrans->stride, srcMap,
  1070. dstTrans->width, dstTrans->height,
  1071. dstTrans->stride, dstMap);
  1072. screen->transfer_unmap(screen, srcTrans);
  1073. screen->transfer_unmap(screen, dstTrans);
  1074. screen->tex_transfer_release(screen, &srcTrans);
  1075. screen->tex_transfer_release(screen, &dstTrans);
  1076. }
  1077. }
  1078. static void
  1079. make_3d_mipmap(struct gen_mipmap_state *ctx,
  1080. struct pipe_texture *pt,
  1081. uint face, uint baseLevel, uint lastLevel)
  1082. {
  1083. #if 0
  1084. struct pipe_context *pipe = ctx->pipe;
  1085. struct pipe_screen *screen = pipe->screen;
  1086. uint dstLevel, zslice = 0;
  1087. assert(pt->block.width == 1);
  1088. assert(pt->block.height == 1);
  1089. for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
  1090. const uint srcLevel = dstLevel - 1;
  1091. struct pipe_transfer *srcTrans, *dstTrans;
  1092. ubyte *srcMap, *dstMap;
  1093. srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice,
  1094. PIPE_TRANSFER_READ, 0, 0,
  1095. pt->width[srcLevel],
  1096. pt->height[srcLevel]);
  1097. dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice,
  1098. PIPE_TRANSFER_WRITE, 0, 0,
  1099. pt->width[dstLevel],
  1100. pt->height[dstLevel]);
  1101. srcMap = (ubyte *) screen->transfer_map(screen, srcTrans);
  1102. dstMap = (ubyte *) screen->transfer_map(screen, dstTrans);
  1103. reduce_3d(pt->format,
  1104. srcTrans->width, srcTrans->height,
  1105. srcTrans->stride, srcMap,
  1106. dstTrans->width, dstTrans->height,
  1107. dstTrans->stride, dstMap);
  1108. screen->transfer_unmap(screen, srcTrans);
  1109. screen->transfer_unmap(screen, dstTrans);
  1110. screen->tex_transfer_release(screen, &srcTrans);
  1111. screen->tex_transfer_release(screen, &dstTrans);
  1112. }
  1113. #else
  1114. (void) reduce_3d;
  1115. #endif
  1116. }
  1117. static void
  1118. fallback_gen_mipmap(struct gen_mipmap_state *ctx,
  1119. struct pipe_texture *pt,
  1120. uint face, uint baseLevel, uint lastLevel)
  1121. {
  1122. switch (pt->target) {
  1123. case PIPE_TEXTURE_1D:
  1124. make_1d_mipmap(ctx, pt, face, baseLevel, lastLevel);
  1125. break;
  1126. case PIPE_TEXTURE_2D:
  1127. case PIPE_TEXTURE_CUBE:
  1128. make_2d_mipmap(ctx, pt, face, baseLevel, lastLevel);
  1129. break;
  1130. case PIPE_TEXTURE_3D:
  1131. make_3d_mipmap(ctx, pt, face, baseLevel, lastLevel);
  1132. break;
  1133. default:
  1134. assert(0);
  1135. }
  1136. }
  1137. /**
  1138. * Create a mipmap generation context.
  1139. * The idea is to create one of these and re-use it each time we need to
  1140. * generate a mipmap.
  1141. */
  1142. struct gen_mipmap_state *
  1143. util_create_gen_mipmap(struct pipe_context *pipe,
  1144. struct cso_context *cso)
  1145. {
  1146. struct gen_mipmap_state *ctx;
  1147. uint i;
  1148. ctx = CALLOC_STRUCT(gen_mipmap_state);
  1149. if (!ctx)
  1150. return NULL;
  1151. ctx->pipe = pipe;
  1152. ctx->cso = cso;
  1153. /* disabled blending/masking */
  1154. memset(&ctx->blend, 0, sizeof(ctx->blend));
  1155. ctx->blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
  1156. ctx->blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
  1157. ctx->blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
  1158. ctx->blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
  1159. ctx->blend.colormask = PIPE_MASK_RGBA;
  1160. /* no-op depth/stencil/alpha */
  1161. memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
  1162. /* rasterizer */
  1163. memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
  1164. ctx->rasterizer.front_winding = PIPE_WINDING_CW;
  1165. ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
  1166. ctx->rasterizer.bypass_clipping = 1;
  1167. /*ctx->rasterizer.bypass_vs = 1;*/
  1168. ctx->rasterizer.gl_rasterization_rules = 1;
  1169. /* sampler state */
  1170. memset(&ctx->sampler, 0, sizeof(ctx->sampler));
  1171. ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  1172. ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  1173. ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  1174. ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
  1175. ctx->sampler.normalized_coords = 1;
  1176. /* viewport state (identity, verts are in wincoords) */
  1177. ctx->viewport.scale[0] = 1.0;
  1178. ctx->viewport.scale[1] = 1.0;
  1179. ctx->viewport.scale[2] = 1.0;
  1180. ctx->viewport.scale[3] = 1.0;
  1181. ctx->viewport.translate[0] = 0.0;
  1182. ctx->viewport.translate[1] = 0.0;
  1183. ctx->viewport.translate[2] = 0.0;
  1184. ctx->viewport.translate[3] = 0.0;
  1185. /* vertex shader */
  1186. {
  1187. const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
  1188. TGSI_SEMANTIC_GENERIC };
  1189. const uint semantic_indexes[] = { 0, 0 };
  1190. ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
  1191. semantic_indexes,
  1192. &ctx->vert_shader);
  1193. }
  1194. /* fragment shader */
  1195. ctx->fs = util_make_fragment_tex_shader(pipe, &ctx->frag_shader);
  1196. /* vertex data that doesn't change */
  1197. for (i = 0; i < 4; i++) {
  1198. ctx->vertices[i][0][2] = 0.0f; /* z */
  1199. ctx->vertices[i][0][3] = 1.0f; /* w */
  1200. ctx->vertices[i][1][2] = 0.0f; /* r */
  1201. ctx->vertices[i][1][3] = 1.0f; /* q */
  1202. }
  1203. /* Note: the actual vertex buffer is allocated as needed below */
  1204. return ctx;
  1205. }
  1206. /**
  1207. * Get next "slot" of vertex space in the vertex buffer.
  1208. * We're allocating one large vertex buffer and using it piece by piece.
  1209. */
  1210. static unsigned
  1211. get_next_slot(struct gen_mipmap_state *ctx)
  1212. {
  1213. const unsigned max_slots = 4096 / sizeof ctx->vertices;
  1214. if (ctx->vbuf_slot >= max_slots)
  1215. util_gen_mipmap_flush( ctx );
  1216. if (!ctx->vbuf) {
  1217. ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
  1218. 32,
  1219. PIPE_BUFFER_USAGE_VERTEX,
  1220. max_slots * sizeof ctx->vertices);
  1221. }
  1222. return ctx->vbuf_slot++ * sizeof ctx->vertices;
  1223. }
  1224. static unsigned
  1225. set_vertex_data(struct gen_mipmap_state *ctx, float width, float height)
  1226. {
  1227. void *buf;
  1228. unsigned offset;
  1229. ctx->vertices[0][0][0] = 0.0f; /*x*/
  1230. ctx->vertices[0][0][1] = 0.0f; /*y*/
  1231. ctx->vertices[0][1][0] = 0.0f; /*s*/
  1232. ctx->vertices[0][1][1] = 0.0f; /*t*/
  1233. ctx->vertices[1][0][0] = width;
  1234. ctx->vertices[1][0][1] = 0.0f;
  1235. ctx->vertices[1][1][0] = 1.0f;
  1236. ctx->vertices[1][1][1] = 0.0f;
  1237. ctx->vertices[2][0][0] = width;
  1238. ctx->vertices[2][0][1] = height;
  1239. ctx->vertices[2][1][0] = 1.0f;
  1240. ctx->vertices[2][1][1] = 1.0f;
  1241. ctx->vertices[3][0][0] = 0.0f;
  1242. ctx->vertices[3][0][1] = height;
  1243. ctx->vertices[3][1][0] = 0.0f;
  1244. ctx->vertices[3][1][1] = 1.0f;
  1245. offset = get_next_slot( ctx );
  1246. buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
  1247. PIPE_BUFFER_USAGE_CPU_WRITE);
  1248. memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices));
  1249. pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
  1250. return offset;
  1251. }
  1252. /**
  1253. * Destroy a mipmap generation context
  1254. */
  1255. void
  1256. util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
  1257. {
  1258. struct pipe_context *pipe = ctx->pipe;
  1259. pipe->delete_vs_state(pipe, ctx->vs);
  1260. pipe->delete_fs_state(pipe, ctx->fs);
  1261. FREE((void*) ctx->vert_shader.tokens);
  1262. FREE((void*) ctx->frag_shader.tokens);
  1263. pipe_buffer_reference(pipe->screen, &ctx->vbuf, NULL);
  1264. FREE(ctx);
  1265. }
  1266. /* Release vertex buffer at end of frame to avoid synchronous
  1267. * rendering.
  1268. */
  1269. void util_gen_mipmap_flush( struct gen_mipmap_state *ctx )
  1270. {
  1271. pipe_buffer_reference(ctx->pipe->screen, &ctx->vbuf, NULL);
  1272. ctx->vbuf_slot = 0;
  1273. }
  1274. /**
  1275. * Generate mipmap images. It's assumed all needed texture memory is
  1276. * already allocated.
  1277. *
  1278. * \param pt the texture to generate mipmap levels for
  1279. * \param face which cube face to generate mipmaps for (0 for non-cube maps)
  1280. * \param baseLevel the first mipmap level to use as a src
  1281. * \param lastLevel the last mipmap level to generate
  1282. * \param filter the minification filter used to generate mipmap levels with
  1283. * \param filter one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST
  1284. */
  1285. void
  1286. util_gen_mipmap(struct gen_mipmap_state *ctx,
  1287. struct pipe_texture *pt,
  1288. uint face, uint baseLevel, uint lastLevel, uint filter)
  1289. {
  1290. struct pipe_context *pipe = ctx->pipe;
  1291. struct pipe_screen *screen = pipe->screen;
  1292. struct pipe_framebuffer_state fb;
  1293. uint dstLevel;
  1294. uint zslice = 0;
  1295. uint offset;
  1296. /* check if we can render in the texture's format */
  1297. if (!screen->is_format_supported(screen, pt->format, PIPE_TEXTURE_2D,
  1298. PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
  1299. fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
  1300. return;
  1301. }
  1302. /* save state (restored below) */
  1303. cso_save_blend(ctx->cso);
  1304. cso_save_depth_stencil_alpha(ctx->cso);
  1305. cso_save_rasterizer(ctx->cso);
  1306. cso_save_samplers(ctx->cso);
  1307. cso_save_sampler_textures(ctx->cso);
  1308. cso_save_framebuffer(ctx->cso);
  1309. cso_save_fragment_shader(ctx->cso);
  1310. cso_save_vertex_shader(ctx->cso);
  1311. cso_save_viewport(ctx->cso);
  1312. /* bind our state */
  1313. cso_set_blend(ctx->cso, &ctx->blend);
  1314. cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
  1315. cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
  1316. cso_set_viewport(ctx->cso, &ctx->viewport);
  1317. cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
  1318. cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
  1319. /* init framebuffer state */
  1320. memset(&fb, 0, sizeof(fb));
  1321. fb.nr_cbufs = 1;
  1322. /* set min/mag to same filter for faster sw speed */
  1323. ctx->sampler.mag_img_filter = filter;
  1324. ctx->sampler.min_img_filter = filter;
  1325. /*
  1326. * XXX for small mipmap levels, it may be faster to use the software
  1327. * fallback path...
  1328. */
  1329. for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
  1330. const uint srcLevel = dstLevel - 1;
  1331. struct pipe_surface *surf =
  1332. screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
  1333. PIPE_BUFFER_USAGE_GPU_WRITE);
  1334. /*
  1335. * Setup framebuffer / dest surface
  1336. */
  1337. fb.cbufs[0] = surf;
  1338. fb.width = pt->width[dstLevel];
  1339. fb.height = pt->height[dstLevel];
  1340. cso_set_framebuffer(ctx->cso, &fb);
  1341. /*
  1342. * Setup sampler state
  1343. * Note: we should only have to set the min/max LOD clamps to ensure
  1344. * we grab texels from the right mipmap level. But some hardware
  1345. * has trouble with min clamping so we also set the lod_bias to
  1346. * try to work around that.
  1347. */
  1348. ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
  1349. ctx->sampler.lod_bias = (float) srcLevel;
  1350. cso_single_sampler(ctx->cso, 0, &ctx->sampler);
  1351. cso_single_sampler_done(ctx->cso);
  1352. cso_set_sampler_textures(ctx->cso, 1, &pt);
  1353. /* quad coords in window coords (bypassing clipping, viewport mapping) */
  1354. offset = set_vertex_data(ctx,
  1355. (float) pt->width[dstLevel],
  1356. (float) pt->height[dstLevel]);
  1357. util_draw_vertex_buffer(ctx->pipe,
  1358. ctx->vbuf,
  1359. offset,
  1360. PIPE_PRIM_TRIANGLE_FAN,
  1361. 4, /* verts */
  1362. 2); /* attribs/vert */
  1363. pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
  1364. /* need to signal that the texture has changed _after_ rendering to it */
  1365. pipe_surface_reference( &surf, NULL );
  1366. }
  1367. /* restore state we changed */
  1368. cso_restore_blend(ctx->cso);
  1369. cso_restore_depth_stencil_alpha(ctx->cso);
  1370. cso_restore_rasterizer(ctx->cso);
  1371. cso_restore_samplers(ctx->cso);
  1372. cso_restore_sampler_textures(ctx->cso);
  1373. cso_restore_framebuffer(ctx->cso);
  1374. cso_restore_fragment_shader(ctx->cso);
  1375. cso_restore_vertex_shader(ctx->cso);
  1376. cso_restore_viewport(ctx->cso);
  1377. }