Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmipmap.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 7.1 00004 * 00005 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 00030 #include "imports.h" 00031 #include "mipmap.h" 00032 #include "texcompress.h" 00033 #include "texformat.h" 00034 #include "teximage.h" 00035 #include "image.h" 00036 00037 00038 00039 static GLint 00040 bytes_per_pixel(GLenum datatype, GLuint comps) 00041 { 00042 GLint b = _mesa_sizeof_packed_type(datatype); 00043 assert(b >= 0); 00044 00045 if (_mesa_type_is_packed(datatype)) 00046 return b; 00047 else 00048 return b * comps; 00049 } 00050 00051 00060 #define DECLARE_ROW_POINTERS(t, e) \ 00061 const t(*rowA)[e] = (const t(*)[e]) srcRowA; \ 00062 const t(*rowB)[e] = (const t(*)[e]) srcRowB; \ 00063 const t(*rowC)[e] = (const t(*)[e]) srcRowC; \ 00064 const t(*rowD)[e] = (const t(*)[e]) srcRowD; \ 00065 t(*dst)[e] = (t(*)[e]) dstRow 00066 00067 #define DECLARE_ROW_POINTERS0(t) \ 00068 const t *rowA = (const t *) srcRowA; \ 00069 const t *rowB = (const t *) srcRowB; \ 00070 const t *rowC = (const t *) srcRowC; \ 00071 const t *rowD = (const t *) srcRowD; \ 00072 t *dst = (t *) dstRow 00073 00074 #define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \ 00075 ((unsigned) Aj + (unsigned) Ak \ 00076 + (unsigned) Bj + (unsigned) Bk \ 00077 + (unsigned) Cj + (unsigned) Ck \ 00078 + (unsigned) Dj + (unsigned) Dk \ 00079 + 4) >> 3 00080 00081 #define FILTER_3D(e) \ 00082 do { \ 00083 dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \ 00084 rowB[j][e], rowB[k][e], \ 00085 rowC[j][e], rowC[k][e], \ 00086 rowD[j][e], rowD[k][e]); \ 00087 } while(0) 00088 00089 #define FILTER_F_3D(e) \ 00090 do { \ 00091 dst[i][e] = (rowA[j][e] + rowA[k][e] \ 00092 + rowB[j][e] + rowB[k][e] \ 00093 + rowC[j][e] + rowC[k][e] \ 00094 + rowD[j][e] + rowD[k][e]) * 0.125F; \ 00095 } while(0) 00096 00097 #define FILTER_HF_3D(e) \ 00098 do { \ 00099 const GLfloat aj = _mesa_half_to_float(rowA[j][e]); \ 00100 const GLfloat ak = _mesa_half_to_float(rowA[k][e]); \ 00101 const GLfloat bj = _mesa_half_to_float(rowB[j][e]); \ 00102 const GLfloat bk = _mesa_half_to_float(rowB[k][e]); \ 00103 const GLfloat cj = _mesa_half_to_float(rowC[j][e]); \ 00104 const GLfloat ck = _mesa_half_to_float(rowC[k][e]); \ 00105 const GLfloat dj = _mesa_half_to_float(rowD[j][e]); \ 00106 const GLfloat dk = _mesa_half_to_float(rowD[k][e]); \ 00107 dst[i][e] = _mesa_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \ 00108 * 0.125F); \ 00109 } while(0) 00110 00121 static void 00122 do_row(GLenum datatype, GLuint comps, GLint srcWidth, 00123 const GLvoid *srcRowA, const GLvoid *srcRowB, 00124 GLint dstWidth, GLvoid *dstRow) 00125 { 00126 const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1; 00127 const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2; 00128 00129 ASSERT(comps >= 1); 00130 ASSERT(comps <= 4); 00131 00132 /* This assertion is no longer valid with non-power-of-2 textures 00133 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth); 00134 */ 00135 00136 if (datatype == GL_UNSIGNED_BYTE && comps == 4) { 00137 GLuint i, j, k; 00138 const GLubyte(*rowA)[4] = (const GLubyte(*)[4]) srcRowA; 00139 const GLubyte(*rowB)[4] = (const GLubyte(*)[4]) srcRowB; 00140 GLubyte(*dst)[4] = (GLubyte(*)[4]) dstRow; 00141 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00142 i++, j += colStride, k += colStride) { 00143 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 00144 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 00145 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 00146 dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; 00147 } 00148 } 00149 else if (datatype == GL_UNSIGNED_BYTE && comps == 3) { 00150 GLuint i, j, k; 00151 const GLubyte(*rowA)[3] = (const GLubyte(*)[3]) srcRowA; 00152 const GLubyte(*rowB)[3] = (const GLubyte(*)[3]) srcRowB; 00153 GLubyte(*dst)[3] = (GLubyte(*)[3]) dstRow; 00154 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00155 i++, j += colStride, k += colStride) { 00156 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 00157 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 00158 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 00159 } 00160 } 00161 else if (datatype == GL_UNSIGNED_BYTE && comps == 2) { 00162 GLuint i, j, k; 00163 const GLubyte(*rowA)[2] = (const GLubyte(*)[2]) srcRowA; 00164 const GLubyte(*rowB)[2] = (const GLubyte(*)[2]) srcRowB; 00165 GLubyte(*dst)[2] = (GLubyte(*)[2]) dstRow; 00166 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00167 i++, j += colStride, k += colStride) { 00168 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2; 00169 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2; 00170 } 00171 } 00172 else if (datatype == GL_UNSIGNED_BYTE && comps == 1) { 00173 GLuint i, j, k; 00174 const GLubyte *rowA = (const GLubyte *) srcRowA; 00175 const GLubyte *rowB = (const GLubyte *) srcRowB; 00176 GLubyte *dst = (GLubyte *) dstRow; 00177 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00178 i++, j += colStride, k += colStride) { 00179 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2; 00180 } 00181 } 00182 00183 else if (datatype == GL_UNSIGNED_SHORT && comps == 4) { 00184 GLuint i, j, k; 00185 const GLushort(*rowA)[4] = (const GLushort(*)[4]) srcRowA; 00186 const GLushort(*rowB)[4] = (const GLushort(*)[4]) srcRowB; 00187 GLushort(*dst)[4] = (GLushort(*)[4]) dstRow; 00188 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00189 i++, j += colStride, k += colStride) { 00190 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 00191 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 00192 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 00193 dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; 00194 } 00195 } 00196 else if (datatype == GL_UNSIGNED_SHORT && comps == 3) { 00197 GLuint i, j, k; 00198 const GLushort(*rowA)[3] = (const GLushort(*)[3]) srcRowA; 00199 const GLushort(*rowB)[3] = (const GLushort(*)[3]) srcRowB; 00200 GLushort(*dst)[3] = (GLushort(*)[3]) dstRow; 00201 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00202 i++, j += colStride, k += colStride) { 00203 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 00204 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 00205 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; 00206 } 00207 } 00208 else if (datatype == GL_UNSIGNED_SHORT && comps == 2) { 00209 GLuint i, j, k; 00210 const GLushort(*rowA)[2] = (const GLushort(*)[2]) srcRowA; 00211 const GLushort(*rowB)[2] = (const GLushort(*)[2]) srcRowB; 00212 GLushort(*dst)[2] = (GLushort(*)[2]) dstRow; 00213 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00214 i++, j += colStride, k += colStride) { 00215 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; 00216 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; 00217 } 00218 } 00219 else if (datatype == GL_UNSIGNED_SHORT && comps == 1) { 00220 GLuint i, j, k; 00221 const GLushort *rowA = (const GLushort *) srcRowA; 00222 const GLushort *rowB = (const GLushort *) srcRowB; 00223 GLushort *dst = (GLushort *) dstRow; 00224 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00225 i++, j += colStride, k += colStride) { 00226 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; 00227 } 00228 } 00229 00230 else if (datatype == GL_FLOAT && comps == 4) { 00231 GLuint i, j, k; 00232 const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA; 00233 const GLfloat(*rowB)[4] = (const GLfloat(*)[4]) srcRowB; 00234 GLfloat(*dst)[4] = (GLfloat(*)[4]) dstRow; 00235 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00236 i++, j += colStride, k += colStride) { 00237 dst[i][0] = (rowA[j][0] + rowA[k][0] + 00238 rowB[j][0] + rowB[k][0]) * 0.25F; 00239 dst[i][1] = (rowA[j][1] + rowA[k][1] + 00240 rowB[j][1] + rowB[k][1]) * 0.25F; 00241 dst[i][2] = (rowA[j][2] + rowA[k][2] + 00242 rowB[j][2] + rowB[k][2]) * 0.25F; 00243 dst[i][3] = (rowA[j][3] + rowA[k][3] + 00244 rowB[j][3] + rowB[k][3]) * 0.25F; 00245 } 00246 } 00247 else if (datatype == GL_FLOAT && comps == 3) { 00248 GLuint i, j, k; 00249 const GLfloat(*rowA)[3] = (const GLfloat(*)[3]) srcRowA; 00250 const GLfloat(*rowB)[3] = (const GLfloat(*)[3]) srcRowB; 00251 GLfloat(*dst)[3] = (GLfloat(*)[3]) dstRow; 00252 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00253 i++, j += colStride, k += colStride) { 00254 dst[i][0] = (rowA[j][0] + rowA[k][0] + 00255 rowB[j][0] + rowB[k][0]) * 0.25F; 00256 dst[i][1] = (rowA[j][1] + rowA[k][1] + 00257 rowB[j][1] + rowB[k][1]) * 0.25F; 00258 dst[i][2] = (rowA[j][2] + rowA[k][2] + 00259 rowB[j][2] + rowB[k][2]) * 0.25F; 00260 } 00261 } 00262 else if (datatype == GL_FLOAT && comps == 2) { 00263 GLuint i, j, k; 00264 const GLfloat(*rowA)[2] = (const GLfloat(*)[2]) srcRowA; 00265 const GLfloat(*rowB)[2] = (const GLfloat(*)[2]) srcRowB; 00266 GLfloat(*dst)[2] = (GLfloat(*)[2]) dstRow; 00267 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00268 i++, j += colStride, k += colStride) { 00269 dst[i][0] = (rowA[j][0] + rowA[k][0] + 00270 rowB[j][0] + rowB[k][0]) * 0.25F; 00271 dst[i][1] = (rowA[j][1] + rowA[k][1] + 00272 rowB[j][1] + rowB[k][1]) * 0.25F; 00273 } 00274 } 00275 else if (datatype == GL_FLOAT && comps == 1) { 00276 GLuint i, j, k; 00277 const GLfloat *rowA = (const GLfloat *) srcRowA; 00278 const GLfloat *rowB = (const GLfloat *) srcRowB; 00279 GLfloat *dst = (GLfloat *) dstRow; 00280 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00281 i++, j += colStride, k += colStride) { 00282 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F; 00283 } 00284 } 00285 00286 else if (datatype == GL_HALF_FLOAT_ARB && comps == 4) { 00287 GLuint i, j, k, comp; 00288 const GLhalfARB(*rowA)[4] = (const GLhalfARB(*)[4]) srcRowA; 00289 const GLhalfARB(*rowB)[4] = (const GLhalfARB(*)[4]) srcRowB; 00290 GLhalfARB(*dst)[4] = (GLhalfARB(*)[4]) dstRow; 00291 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00292 i++, j += colStride, k += colStride) { 00293 for (comp = 0; comp < 4; comp++) { 00294 GLfloat aj, ak, bj, bk; 00295 aj = _mesa_half_to_float(rowA[j][comp]); 00296 ak = _mesa_half_to_float(rowA[k][comp]); 00297 bj = _mesa_half_to_float(rowB[j][comp]); 00298 bk = _mesa_half_to_float(rowB[k][comp]); 00299 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); 00300 } 00301 } 00302 } 00303 else if (datatype == GL_HALF_FLOAT_ARB && comps == 3) { 00304 GLuint i, j, k, comp; 00305 const GLhalfARB(*rowA)[3] = (const GLhalfARB(*)[3]) srcRowA; 00306 const GLhalfARB(*rowB)[3] = (const GLhalfARB(*)[3]) srcRowB; 00307 GLhalfARB(*dst)[3] = (GLhalfARB(*)[3]) dstRow; 00308 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00309 i++, j += colStride, k += colStride) { 00310 for (comp = 0; comp < 3; comp++) { 00311 GLfloat aj, ak, bj, bk; 00312 aj = _mesa_half_to_float(rowA[j][comp]); 00313 ak = _mesa_half_to_float(rowA[k][comp]); 00314 bj = _mesa_half_to_float(rowB[j][comp]); 00315 bk = _mesa_half_to_float(rowB[k][comp]); 00316 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); 00317 } 00318 } 00319 } 00320 else if (datatype == GL_HALF_FLOAT_ARB && comps == 2) { 00321 GLuint i, j, k, comp; 00322 const GLhalfARB(*rowA)[2] = (const GLhalfARB(*)[2]) srcRowA; 00323 const GLhalfARB(*rowB)[2] = (const GLhalfARB(*)[2]) srcRowB; 00324 GLhalfARB(*dst)[2] = (GLhalfARB(*)[2]) dstRow; 00325 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00326 i++, j += colStride, k += colStride) { 00327 for (comp = 0; comp < 2; comp++) { 00328 GLfloat aj, ak, bj, bk; 00329 aj = _mesa_half_to_float(rowA[j][comp]); 00330 ak = _mesa_half_to_float(rowA[k][comp]); 00331 bj = _mesa_half_to_float(rowB[j][comp]); 00332 bk = _mesa_half_to_float(rowB[k][comp]); 00333 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); 00334 } 00335 } 00336 } 00337 else if (datatype == GL_HALF_FLOAT_ARB && comps == 1) { 00338 GLuint i, j, k; 00339 const GLhalfARB *rowA = (const GLhalfARB *) srcRowA; 00340 const GLhalfARB *rowB = (const GLhalfARB *) srcRowB; 00341 GLhalfARB *dst = (GLhalfARB *) dstRow; 00342 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00343 i++, j += colStride, k += colStride) { 00344 GLfloat aj, ak, bj, bk; 00345 aj = _mesa_half_to_float(rowA[j]); 00346 ak = _mesa_half_to_float(rowA[k]); 00347 bj = _mesa_half_to_float(rowB[j]); 00348 bk = _mesa_half_to_float(rowB[k]); 00349 dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); 00350 } 00351 } 00352 00353 else if (datatype == GL_UNSIGNED_INT && comps == 1) { 00354 GLuint i, j, k; 00355 const GLuint *rowA = (const GLuint *) srcRowA; 00356 const GLuint *rowB = (const GLuint *) srcRowB; 00357 GLfloat *dst = (GLfloat *) dstRow; 00358 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00359 i++, j += colStride, k += colStride) { 00360 dst[i] = (GLfloat)(rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4); 00361 } 00362 } 00363 00364 else if (datatype == GL_UNSIGNED_SHORT_5_6_5 && comps == 3) { 00365 GLuint i, j, k; 00366 const GLushort *rowA = (const GLushort *) srcRowA; 00367 const GLushort *rowB = (const GLushort *) srcRowB; 00368 GLushort *dst = (GLushort *) dstRow; 00369 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00370 i++, j += colStride, k += colStride) { 00371 const GLint rowAr0 = rowA[j] & 0x1f; 00372 const GLint rowAr1 = rowA[k] & 0x1f; 00373 const GLint rowBr0 = rowB[j] & 0x1f; 00374 const GLint rowBr1 = rowB[k] & 0x1f; 00375 const GLint rowAg0 = (rowA[j] >> 5) & 0x3f; 00376 const GLint rowAg1 = (rowA[k] >> 5) & 0x3f; 00377 const GLint rowBg0 = (rowB[j] >> 5) & 0x3f; 00378 const GLint rowBg1 = (rowB[k] >> 5) & 0x3f; 00379 const GLint rowAb0 = (rowA[j] >> 11) & 0x1f; 00380 const GLint rowAb1 = (rowA[k] >> 11) & 0x1f; 00381 const GLint rowBb0 = (rowB[j] >> 11) & 0x1f; 00382 const GLint rowBb1 = (rowB[k] >> 11) & 0x1f; 00383 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 00384 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 00385 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 00386 dst[i] = (blue << 11) | (green << 5) | red; 00387 } 00388 } 00389 else if (datatype == GL_UNSIGNED_SHORT_4_4_4_4 && comps == 4) { 00390 GLuint i, j, k; 00391 const GLushort *rowA = (const GLushort *) srcRowA; 00392 const GLushort *rowB = (const GLushort *) srcRowB; 00393 GLushort *dst = (GLushort *) dstRow; 00394 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00395 i++, j += colStride, k += colStride) { 00396 const GLint rowAr0 = rowA[j] & 0xf; 00397 const GLint rowAr1 = rowA[k] & 0xf; 00398 const GLint rowBr0 = rowB[j] & 0xf; 00399 const GLint rowBr1 = rowB[k] & 0xf; 00400 const GLint rowAg0 = (rowA[j] >> 4) & 0xf; 00401 const GLint rowAg1 = (rowA[k] >> 4) & 0xf; 00402 const GLint rowBg0 = (rowB[j] >> 4) & 0xf; 00403 const GLint rowBg1 = (rowB[k] >> 4) & 0xf; 00404 const GLint rowAb0 = (rowA[j] >> 8) & 0xf; 00405 const GLint rowAb1 = (rowA[k] >> 8) & 0xf; 00406 const GLint rowBb0 = (rowB[j] >> 8) & 0xf; 00407 const GLint rowBb1 = (rowB[k] >> 8) & 0xf; 00408 const GLint rowAa0 = (rowA[j] >> 12) & 0xf; 00409 const GLint rowAa1 = (rowA[k] >> 12) & 0xf; 00410 const GLint rowBa0 = (rowB[j] >> 12) & 0xf; 00411 const GLint rowBa1 = (rowB[k] >> 12) & 0xf; 00412 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 00413 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 00414 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 00415 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; 00416 dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red; 00417 } 00418 } 00419 else if (datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV && comps == 4) { 00420 GLuint i, j, k; 00421 const GLushort *rowA = (const GLushort *) srcRowA; 00422 const GLushort *rowB = (const GLushort *) srcRowB; 00423 GLushort *dst = (GLushort *) dstRow; 00424 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00425 i++, j += colStride, k += colStride) { 00426 const GLint rowAr0 = rowA[j] & 0x1f; 00427 const GLint rowAr1 = rowA[k] & 0x1f; 00428 const GLint rowBr0 = rowB[j] & 0x1f; 00429 const GLint rowBr1 = rowB[k] & 0x1f; 00430 const GLint rowAg0 = (rowA[j] >> 5) & 0x1f; 00431 const GLint rowAg1 = (rowA[k] >> 5) & 0x1f; 00432 const GLint rowBg0 = (rowB[j] >> 5) & 0x1f; 00433 const GLint rowBg1 = (rowB[k] >> 5) & 0x1f; 00434 const GLint rowAb0 = (rowA[j] >> 10) & 0x1f; 00435 const GLint rowAb1 = (rowA[k] >> 10) & 0x1f; 00436 const GLint rowBb0 = (rowB[j] >> 10) & 0x1f; 00437 const GLint rowBb1 = (rowB[k] >> 10) & 0x1f; 00438 const GLint rowAa0 = (rowA[j] >> 15) & 0x1; 00439 const GLint rowAa1 = (rowA[k] >> 15) & 0x1; 00440 const GLint rowBa0 = (rowB[j] >> 15) & 0x1; 00441 const GLint rowBa1 = (rowB[k] >> 15) & 0x1; 00442 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 00443 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 00444 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 00445 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; 00446 dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red; 00447 } 00448 } 00449 else if (datatype == GL_UNSIGNED_BYTE_3_3_2 && comps == 3) { 00450 GLuint i, j, k; 00451 const GLubyte *rowA = (const GLubyte *) srcRowA; 00452 const GLubyte *rowB = (const GLubyte *) srcRowB; 00453 GLubyte *dst = (GLubyte *) dstRow; 00454 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00455 i++, j += colStride, k += colStride) { 00456 const GLint rowAr0 = rowA[j] & 0x3; 00457 const GLint rowAr1 = rowA[k] & 0x3; 00458 const GLint rowBr0 = rowB[j] & 0x3; 00459 const GLint rowBr1 = rowB[k] & 0x3; 00460 const GLint rowAg0 = (rowA[j] >> 2) & 0x7; 00461 const GLint rowAg1 = (rowA[k] >> 2) & 0x7; 00462 const GLint rowBg0 = (rowB[j] >> 2) & 0x7; 00463 const GLint rowBg1 = (rowB[k] >> 2) & 0x7; 00464 const GLint rowAb0 = (rowA[j] >> 5) & 0x7; 00465 const GLint rowAb1 = (rowA[k] >> 5) & 0x7; 00466 const GLint rowBb0 = (rowB[j] >> 5) & 0x7; 00467 const GLint rowBb1 = (rowB[k] >> 5) & 0x7; 00468 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 00469 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 00470 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 00471 dst[i] = (blue << 5) | (green << 2) | red; 00472 } 00473 } 00474 else { 00475 _mesa_problem(NULL, "bad format in do_row()"); 00476 } 00477 } 00478 00479 00497 static void 00498 do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, 00499 const GLvoid *srcRowA, const GLvoid *srcRowB, 00500 const GLvoid *srcRowC, const GLvoid *srcRowD, 00501 GLint dstWidth, GLvoid *dstRow) 00502 { 00503 const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1; 00504 const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2; 00505 GLuint i, j, k; 00506 00507 ASSERT(comps >= 1); 00508 ASSERT(comps <= 4); 00509 00510 if ((datatype == GL_UNSIGNED_BYTE) && (comps == 4)) { 00511 DECLARE_ROW_POINTERS(GLubyte, 4); 00512 00513 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00514 i++, j += colStride, k += colStride) { 00515 FILTER_3D(0); 00516 FILTER_3D(1); 00517 FILTER_3D(2); 00518 FILTER_3D(3); 00519 } 00520 } 00521 else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 3)) { 00522 DECLARE_ROW_POINTERS(GLubyte, 3); 00523 00524 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00525 i++, j += colStride, k += colStride) { 00526 FILTER_3D(0); 00527 FILTER_3D(1); 00528 FILTER_3D(2); 00529 } 00530 } 00531 else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 2)) { 00532 DECLARE_ROW_POINTERS(GLubyte, 2); 00533 00534 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00535 i++, j += colStride, k += colStride) { 00536 FILTER_3D(0); 00537 FILTER_3D(1); 00538 } 00539 } 00540 else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 1)) { 00541 DECLARE_ROW_POINTERS(GLubyte, 1); 00542 00543 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00544 i++, j += colStride, k += colStride) { 00545 FILTER_3D(0); 00546 } 00547 } 00548 else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 4)) { 00549 DECLARE_ROW_POINTERS(GLushort, 4); 00550 00551 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00552 i++, j += colStride, k += colStride) { 00553 FILTER_3D(0); 00554 FILTER_3D(1); 00555 FILTER_3D(2); 00556 FILTER_3D(3); 00557 } 00558 } 00559 else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 3)) { 00560 DECLARE_ROW_POINTERS(GLushort, 3); 00561 00562 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00563 i++, j += colStride, k += colStride) { 00564 FILTER_3D(0); 00565 FILTER_3D(1); 00566 FILTER_3D(2); 00567 } 00568 } 00569 else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 2)) { 00570 DECLARE_ROW_POINTERS(GLushort, 2); 00571 00572 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00573 i++, j += colStride, k += colStride) { 00574 FILTER_3D(0); 00575 FILTER_3D(1); 00576 } 00577 } 00578 else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 1)) { 00579 DECLARE_ROW_POINTERS(GLushort, 1); 00580 00581 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00582 i++, j += colStride, k += colStride) { 00583 FILTER_3D(0); 00584 } 00585 } 00586 else if ((datatype == GL_FLOAT) && (comps == 4)) { 00587 DECLARE_ROW_POINTERS(GLfloat, 4); 00588 00589 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00590 i++, j += colStride, k += colStride) { 00591 FILTER_F_3D(0); 00592 FILTER_F_3D(1); 00593 FILTER_F_3D(2); 00594 FILTER_F_3D(3); 00595 } 00596 } 00597 else if ((datatype == GL_FLOAT) && (comps == 3)) { 00598 DECLARE_ROW_POINTERS(GLfloat, 3); 00599 00600 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00601 i++, j += colStride, k += colStride) { 00602 FILTER_F_3D(0); 00603 FILTER_F_3D(1); 00604 FILTER_F_3D(2); 00605 } 00606 } 00607 else if ((datatype == GL_FLOAT) && (comps == 2)) { 00608 DECLARE_ROW_POINTERS(GLfloat, 2); 00609 00610 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00611 i++, j += colStride, k += colStride) { 00612 FILTER_F_3D(0); 00613 FILTER_F_3D(1); 00614 } 00615 } 00616 else if ((datatype == GL_FLOAT) && (comps == 1)) { 00617 DECLARE_ROW_POINTERS(GLfloat, 1); 00618 00619 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00620 i++, j += colStride, k += colStride) { 00621 FILTER_F_3D(0); 00622 } 00623 } 00624 else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 4)) { 00625 DECLARE_ROW_POINTERS(GLhalfARB, 4); 00626 00627 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00628 i++, j += colStride, k += colStride) { 00629 FILTER_HF_3D(0); 00630 FILTER_HF_3D(1); 00631 FILTER_HF_3D(2); 00632 FILTER_HF_3D(3); 00633 } 00634 } 00635 else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 3)) { 00636 DECLARE_ROW_POINTERS(GLhalfARB, 4); 00637 00638 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00639 i++, j += colStride, k += colStride) { 00640 FILTER_HF_3D(0); 00641 FILTER_HF_3D(1); 00642 FILTER_HF_3D(2); 00643 } 00644 } 00645 else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 2)) { 00646 DECLARE_ROW_POINTERS(GLhalfARB, 4); 00647 00648 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00649 i++, j += colStride, k += colStride) { 00650 FILTER_HF_3D(0); 00651 FILTER_HF_3D(1); 00652 } 00653 } 00654 else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 1)) { 00655 DECLARE_ROW_POINTERS(GLhalfARB, 4); 00656 00657 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00658 i++, j += colStride, k += colStride) { 00659 FILTER_HF_3D(0); 00660 } 00661 } 00662 else if ((datatype == GL_UNSIGNED_INT) && (comps == 1)) { 00663 const GLuint *rowA = (const GLuint *) srcRowA; 00664 const GLuint *rowB = (const GLuint *) srcRowB; 00665 const GLuint *rowC = (const GLuint *) srcRowC; 00666 const GLuint *rowD = (const GLuint *) srcRowD; 00667 GLfloat *dst = (GLfloat *) dstRow; 00668 00669 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00670 i++, j += colStride, k += colStride) { 00671 const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k]) 00672 + ((uint64_t) rowB[j] + (uint64_t) rowB[k]) 00673 + ((uint64_t) rowC[j] + (uint64_t) rowC[k]) 00674 + ((uint64_t) rowD[j] + (uint64_t) rowD[k])); 00675 dst[i] = (GLfloat)((double) tmp * 0.125); 00676 } 00677 } 00678 else if ((datatype == GL_UNSIGNED_SHORT_5_6_5) && (comps == 3)) { 00679 DECLARE_ROW_POINTERS0(GLushort); 00680 00681 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00682 i++, j += colStride, k += colStride) { 00683 const GLint rowAr0 = rowA[j] & 0x1f; 00684 const GLint rowAr1 = rowA[k] & 0x1f; 00685 const GLint rowBr0 = rowB[j] & 0x1f; 00686 const GLint rowBr1 = rowB[k] & 0x1f; 00687 const GLint rowCr0 = rowC[j] & 0x1f; 00688 const GLint rowCr1 = rowC[k] & 0x1f; 00689 const GLint rowDr0 = rowD[j] & 0x1f; 00690 const GLint rowDr1 = rowD[k] & 0x1f; 00691 const GLint rowAg0 = (rowA[j] >> 5) & 0x3f; 00692 const GLint rowAg1 = (rowA[k] >> 5) & 0x3f; 00693 const GLint rowBg0 = (rowB[j] >> 5) & 0x3f; 00694 const GLint rowBg1 = (rowB[k] >> 5) & 0x3f; 00695 const GLint rowCg0 = (rowC[j] >> 5) & 0x3f; 00696 const GLint rowCg1 = (rowC[k] >> 5) & 0x3f; 00697 const GLint rowDg0 = (rowD[j] >> 5) & 0x3f; 00698 const GLint rowDg1 = (rowD[k] >> 5) & 0x3f; 00699 const GLint rowAb0 = (rowA[j] >> 11) & 0x1f; 00700 const GLint rowAb1 = (rowA[k] >> 11) & 0x1f; 00701 const GLint rowBb0 = (rowB[j] >> 11) & 0x1f; 00702 const GLint rowBb1 = (rowB[k] >> 11) & 0x1f; 00703 const GLint rowCb0 = (rowC[j] >> 11) & 0x1f; 00704 const GLint rowCb1 = (rowC[k] >> 11) & 0x1f; 00705 const GLint rowDb0 = (rowD[j] >> 11) & 0x1f; 00706 const GLint rowDb1 = (rowD[k] >> 11) & 0x1f; 00707 const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 00708 rowCr0, rowCr1, rowDr0, rowDr1); 00709 const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 00710 rowCg0, rowCg1, rowDg0, rowDg1); 00711 const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 00712 rowCb0, rowCb1, rowDb0, rowDb1); 00713 dst[i] = (b << 11) | (g << 5) | r; 00714 } 00715 } 00716 else if ((datatype == GL_UNSIGNED_SHORT_4_4_4_4) && (comps == 4)) { 00717 DECLARE_ROW_POINTERS0(GLushort); 00718 00719 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00720 i++, j += colStride, k += colStride) { 00721 const GLint rowAr0 = rowA[j] & 0xf; 00722 const GLint rowAr1 = rowA[k] & 0xf; 00723 const GLint rowBr0 = rowB[j] & 0xf; 00724 const GLint rowBr1 = rowB[k] & 0xf; 00725 const GLint rowCr0 = rowC[j] & 0xf; 00726 const GLint rowCr1 = rowC[k] & 0xf; 00727 const GLint rowDr0 = rowD[j] & 0xf; 00728 const GLint rowDr1 = rowD[k] & 0xf; 00729 const GLint rowAg0 = (rowA[j] >> 4) & 0xf; 00730 const GLint rowAg1 = (rowA[k] >> 4) & 0xf; 00731 const GLint rowBg0 = (rowB[j] >> 4) & 0xf; 00732 const GLint rowBg1 = (rowB[k] >> 4) & 0xf; 00733 const GLint rowCg0 = (rowC[j] >> 4) & 0xf; 00734 const GLint rowCg1 = (rowC[k] >> 4) & 0xf; 00735 const GLint rowDg0 = (rowD[j] >> 4) & 0xf; 00736 const GLint rowDg1 = (rowD[k] >> 4) & 0xf; 00737 const GLint rowAb0 = (rowA[j] >> 8) & 0xf; 00738 const GLint rowAb1 = (rowA[k] >> 8) & 0xf; 00739 const GLint rowBb0 = (rowB[j] >> 8) & 0xf; 00740 const GLint rowBb1 = (rowB[k] >> 8) & 0xf; 00741 const GLint rowCb0 = (rowC[j] >> 8) & 0xf; 00742 const GLint rowCb1 = (rowC[k] >> 8) & 0xf; 00743 const GLint rowDb0 = (rowD[j] >> 8) & 0xf; 00744 const GLint rowDb1 = (rowD[k] >> 8) & 0xf; 00745 const GLint rowAa0 = (rowA[j] >> 12) & 0xf; 00746 const GLint rowAa1 = (rowA[k] >> 12) & 0xf; 00747 const GLint rowBa0 = (rowB[j] >> 12) & 0xf; 00748 const GLint rowBa1 = (rowB[k] >> 12) & 0xf; 00749 const GLint rowCa0 = (rowC[j] >> 12) & 0xf; 00750 const GLint rowCa1 = (rowC[k] >> 12) & 0xf; 00751 const GLint rowDa0 = (rowD[j] >> 12) & 0xf; 00752 const GLint rowDa1 = (rowD[k] >> 12) & 0xf; 00753 const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 00754 rowCr0, rowCr1, rowDr0, rowDr1); 00755 const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 00756 rowCg0, rowCg1, rowDg0, rowDg1); 00757 const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 00758 rowCb0, rowCb1, rowDb0, rowDb1); 00759 const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, 00760 rowCa0, rowCa1, rowDa0, rowDa1); 00761 00762 dst[i] = (a << 12) | (b << 8) | (g << 4) | r; 00763 } 00764 } 00765 else if ((datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV) && (comps == 4)) { 00766 DECLARE_ROW_POINTERS0(GLushort); 00767 00768 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00769 i++, j += colStride, k += colStride) { 00770 const GLint rowAr0 = rowA[j] & 0x1f; 00771 const GLint rowAr1 = rowA[k] & 0x1f; 00772 const GLint rowBr0 = rowB[j] & 0x1f; 00773 const GLint rowBr1 = rowB[k] & 0x1f; 00774 const GLint rowCr0 = rowC[j] & 0x1f; 00775 const GLint rowCr1 = rowC[k] & 0x1f; 00776 const GLint rowDr0 = rowD[j] & 0x1f; 00777 const GLint rowDr1 = rowD[k] & 0x1f; 00778 const GLint rowAg0 = (rowA[j] >> 5) & 0x1f; 00779 const GLint rowAg1 = (rowA[k] >> 5) & 0x1f; 00780 const GLint rowBg0 = (rowB[j] >> 5) & 0x1f; 00781 const GLint rowBg1 = (rowB[k] >> 5) & 0x1f; 00782 const GLint rowCg0 = (rowC[j] >> 5) & 0x1f; 00783 const GLint rowCg1 = (rowC[k] >> 5) & 0x1f; 00784 const GLint rowDg0 = (rowD[j] >> 5) & 0x1f; 00785 const GLint rowDg1 = (rowD[k] >> 5) & 0x1f; 00786 const GLint rowAb0 = (rowA[j] >> 10) & 0x1f; 00787 const GLint rowAb1 = (rowA[k] >> 10) & 0x1f; 00788 const GLint rowBb0 = (rowB[j] >> 10) & 0x1f; 00789 const GLint rowBb1 = (rowB[k] >> 10) & 0x1f; 00790 const GLint rowCb0 = (rowC[j] >> 10) & 0x1f; 00791 const GLint rowCb1 = (rowC[k] >> 10) & 0x1f; 00792 const GLint rowDb0 = (rowD[j] >> 10) & 0x1f; 00793 const GLint rowDb1 = (rowD[k] >> 10) & 0x1f; 00794 const GLint rowAa0 = (rowA[j] >> 15) & 0x1; 00795 const GLint rowAa1 = (rowA[k] >> 15) & 0x1; 00796 const GLint rowBa0 = (rowB[j] >> 15) & 0x1; 00797 const GLint rowBa1 = (rowB[k] >> 15) & 0x1; 00798 const GLint rowCa0 = (rowC[j] >> 15) & 0x1; 00799 const GLint rowCa1 = (rowC[k] >> 15) & 0x1; 00800 const GLint rowDa0 = (rowD[j] >> 15) & 0x1; 00801 const GLint rowDa1 = (rowD[k] >> 15) & 0x1; 00802 const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 00803 rowCr0, rowCr1, rowDr0, rowDr1); 00804 const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 00805 rowCg0, rowCg1, rowDg0, rowDg1); 00806 const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 00807 rowCb0, rowCb1, rowDb0, rowDb1); 00808 const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, 00809 rowCa0, rowCa1, rowDa0, rowDa1); 00810 00811 dst[i] = (a << 15) | (b << 10) | (g << 5) | r; 00812 } 00813 } 00814 else if ((datatype == GL_UNSIGNED_BYTE_3_3_2) && (comps == 3)) { 00815 DECLARE_ROW_POINTERS0(GLushort); 00816 00817 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 00818 i++, j += colStride, k += colStride) { 00819 const GLint rowAr0 = rowA[j] & 0x3; 00820 const GLint rowAr1 = rowA[k] & 0x3; 00821 const GLint rowBr0 = rowB[j] & 0x3; 00822 const GLint rowBr1 = rowB[k] & 0x3; 00823 const GLint rowCr0 = rowC[j] & 0x3; 00824 const GLint rowCr1 = rowC[k] & 0x3; 00825 const GLint rowDr0 = rowD[j] & 0x3; 00826 const GLint rowDr1 = rowD[k] & 0x3; 00827 const GLint rowAg0 = (rowA[j] >> 2) & 0x7; 00828 const GLint rowAg1 = (rowA[k] >> 2) & 0x7; 00829 const GLint rowBg0 = (rowB[j] >> 2) & 0x7; 00830 const GLint rowBg1 = (rowB[k] >> 2) & 0x7; 00831 const GLint rowCg0 = (rowC[j] >> 2) & 0x7; 00832 const GLint rowCg1 = (rowC[k] >> 2) & 0x7; 00833 const GLint rowDg0 = (rowD[j] >> 2) & 0x7; 00834 const GLint rowDg1 = (rowD[k] >> 2) & 0x7; 00835 const GLint rowAb0 = (rowA[j] >> 5) & 0x7; 00836 const GLint rowAb1 = (rowA[k] >> 5) & 0x7; 00837 const GLint rowBb0 = (rowB[j] >> 5) & 0x7; 00838 const GLint rowBb1 = (rowB[k] >> 5) & 0x7; 00839 const GLint rowCb0 = (rowC[j] >> 5) & 0x7; 00840 const GLint rowCb1 = (rowC[k] >> 5) & 0x7; 00841 const GLint rowDb0 = (rowD[j] >> 5) & 0x7; 00842 const GLint rowDb1 = (rowD[k] >> 5) & 0x7; 00843 const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, 00844 rowCr0, rowCr1, rowDr0, rowDr1); 00845 const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, 00846 rowCg0, rowCg1, rowDg0, rowDg1); 00847 const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, 00848 rowCb0, rowCb1, rowDb0, rowDb1); 00849 dst[i] = (b << 5) | (g << 2) | r; 00850 } 00851 } 00852 else { 00853 _mesa_problem(NULL, "bad format in do_row()"); 00854 } 00855 } 00856 00857 00858 /* 00859 * These functions generate a 1/2-size mipmap image from a source image. 00860 * Texture borders are handled by copying or averaging the source image's 00861 * border texels, depending on the scale-down factor. 00862 */ 00863 00864 static void 00865 make_1d_mipmap(GLenum datatype, GLuint comps, GLint border, 00866 GLint srcWidth, const GLubyte *srcPtr, 00867 GLint dstWidth, GLubyte *dstPtr) 00868 { 00869 const GLint bpt = bytes_per_pixel(datatype, comps); 00870 const GLubyte *src; 00871 GLubyte *dst; 00872 00873 /* skip the border pixel, if any */ 00874 src = srcPtr + border * bpt; 00875 dst = dstPtr + border * bpt; 00876 00877 /* we just duplicate the input row, kind of hack, saves code */ 00878 do_row(datatype, comps, srcWidth - 2 * border, src, src, 00879 dstWidth - 2 * border, dst); 00880 00881 if (border) { 00882 /* copy left-most pixel from source */ 00883 MEMCPY(dstPtr, srcPtr, bpt); 00884 /* copy right-most pixel from source */ 00885 MEMCPY(dstPtr + (dstWidth - 1) * bpt, 00886 srcPtr + (srcWidth - 1) * bpt, 00887 bpt); 00888 } 00889 } 00890 00891 00892 static void 00893 make_2d_mipmap(GLenum datatype, GLuint comps, GLint border, 00894 GLint srcWidth, GLint srcHeight, 00895 const GLubyte *srcPtr, GLint srcRowStride, 00896 GLint dstWidth, GLint dstHeight, 00897 GLubyte *dstPtr, GLint dstRowStride) 00898 { 00899 const GLint bpt = bytes_per_pixel(datatype, comps); 00900 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ 00901 const GLint dstWidthNB = dstWidth - 2 * border; 00902 const GLint dstHeightNB = dstHeight - 2 * border; 00903 const GLint srcRowBytes = bpt * srcRowStride; 00904 const GLint dstRowBytes = bpt * dstRowStride; 00905 const GLubyte *srcA, *srcB; 00906 GLubyte *dst; 00907 GLint row; 00908 00909 /* Compute src and dst pointers, skipping any border */ 00910 srcA = srcPtr + border * ((srcWidth + 1) * bpt); 00911 if (srcHeight > 1) 00912 srcB = srcA + srcRowBytes; 00913 else 00914 srcB = srcA; 00915 dst = dstPtr + border * ((dstWidth + 1) * bpt); 00916 00917 for (row = 0; row < dstHeightNB; row++) { 00918 do_row(datatype, comps, srcWidthNB, srcA, srcB, 00919 dstWidthNB, dst); 00920 srcA += 2 * srcRowBytes; 00921 srcB += 2 * srcRowBytes; 00922 dst += dstRowBytes; 00923 } 00924 00925 /* This is ugly but probably won't be used much */ 00926 if (border > 0) { 00927 /* fill in dest border */ 00928 /* lower-left border pixel */ 00929 MEMCPY(dstPtr, srcPtr, bpt); 00930 /* lower-right border pixel */ 00931 MEMCPY(dstPtr + (dstWidth - 1) * bpt, 00932 srcPtr + (srcWidth - 1) * bpt, bpt); 00933 /* upper-left border pixel */ 00934 MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt, 00935 srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt); 00936 /* upper-right border pixel */ 00937 MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt, 00938 srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt); 00939 /* lower border */ 00940 do_row(datatype, comps, srcWidthNB, 00941 srcPtr + bpt, 00942 srcPtr + bpt, 00943 dstWidthNB, dstPtr + bpt); 00944 /* upper border */ 00945 do_row(datatype, comps, srcWidthNB, 00946 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, 00947 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, 00948 dstWidthNB, 00949 dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt); 00950 /* left and right borders */ 00951 if (srcHeight == dstHeight) { 00952 /* copy border pixel from src to dst */ 00953 for (row = 1; row < srcHeight; row++) { 00954 MEMCPY(dstPtr + dstWidth * row * bpt, 00955 srcPtr + srcWidth * row * bpt, bpt); 00956 MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt, 00957 srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt); 00958 } 00959 } 00960 else { 00961 /* average two src pixels each dest pixel */ 00962 for (row = 0; row < dstHeightNB; row += 2) { 00963 do_row(datatype, comps, 1, 00964 srcPtr + (srcWidth * (row * 2 + 1)) * bpt, 00965 srcPtr + (srcWidth * (row * 2 + 2)) * bpt, 00966 1, dstPtr + (dstWidth * row + 1) * bpt); 00967 do_row(datatype, comps, 1, 00968 srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt, 00969 srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt, 00970 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt); 00971 } 00972 } 00973 } 00974 } 00975 00976 00977 static void 00978 make_3d_mipmap(GLenum datatype, GLuint comps, GLint border, 00979 GLint srcWidth, GLint srcHeight, GLint srcDepth, 00980 const GLubyte *srcPtr, GLint srcRowStride, 00981 GLint dstWidth, GLint dstHeight, GLint dstDepth, 00982 GLubyte *dstPtr, GLint dstRowStride) 00983 { 00984 const GLint bpt = bytes_per_pixel(datatype, comps); 00985 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ 00986 const GLint srcDepthNB = srcDepth - 2 * border; 00987 const GLint dstWidthNB = dstWidth - 2 * border; 00988 const GLint dstHeightNB = dstHeight - 2 * border; 00989 const GLint dstDepthNB = dstDepth - 2 * border; 00990 GLint img, row; 00991 GLint bytesPerSrcImage, bytesPerDstImage; 00992 GLint bytesPerSrcRow, bytesPerDstRow; 00993 GLint srcImageOffset, srcRowOffset; 00994 00995 (void) srcDepthNB; /* silence warnings */ 00996 00997 00998 bytesPerSrcImage = srcWidth * srcHeight * bpt; 00999 bytesPerDstImage = dstWidth * dstHeight * bpt; 01000 01001 bytesPerSrcRow = srcWidth * bpt; 01002 bytesPerDstRow = dstWidth * bpt; 01003 01004 /* Offset between adjacent src images to be averaged together */ 01005 srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage; 01006 01007 /* Offset between adjacent src rows to be averaged together */ 01008 srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt; 01009 01010 /* 01011 * Need to average together up to 8 src pixels for each dest pixel. 01012 * Break that down into 3 operations: 01013 * 1. take two rows from source image and average them together. 01014 * 2. take two rows from next source image and average them together. 01015 * 3. take the two averaged rows and average them for the final dst row. 01016 */ 01017 01018 /* 01019 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n", 01020 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth); 01021 */ 01022 01023 for (img = 0; img < dstDepthNB; img++) { 01024 /* first source image pointer, skipping border */ 01025 const GLubyte *imgSrcA = srcPtr 01026 + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border 01027 + img * (bytesPerSrcImage + srcImageOffset); 01028 /* second source image pointer, skipping border */ 01029 const GLubyte *imgSrcB = imgSrcA + srcImageOffset; 01030 /* address of the dest image, skipping border */ 01031 GLubyte *imgDst = dstPtr 01032 + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border 01033 + img * bytesPerDstImage; 01034 01035 /* setup the four source row pointers and the dest row pointer */ 01036 const GLubyte *srcImgARowA = imgSrcA; 01037 const GLubyte *srcImgARowB = imgSrcA + srcRowOffset; 01038 const GLubyte *srcImgBRowA = imgSrcB; 01039 const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset; 01040 GLubyte *dstImgRow = imgDst; 01041 01042 for (row = 0; row < dstHeightNB; row++) { 01043 do_row_3D(datatype, comps, srcWidthNB, 01044 srcImgARowA, srcImgARowB, 01045 srcImgBRowA, srcImgBRowB, 01046 dstWidthNB, dstImgRow); 01047 01048 /* advance to next rows */ 01049 srcImgARowA += bytesPerSrcRow + srcRowOffset; 01050 srcImgARowB += bytesPerSrcRow + srcRowOffset; 01051 srcImgBRowA += bytesPerSrcRow + srcRowOffset; 01052 srcImgBRowB += bytesPerSrcRow + srcRowOffset; 01053 dstImgRow += bytesPerDstRow; 01054 } 01055 } 01056 01057 01058 /* Luckily we can leverage the make_2d_mipmap() function here! */ 01059 if (border > 0) { 01060 /* do front border image */ 01061 make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, srcPtr, srcRowStride, 01062 dstWidth, dstHeight, dstPtr, dstRowStride); 01063 /* do back border image */ 01064 make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, 01065 srcPtr + bytesPerSrcImage * (srcDepth - 1), srcRowStride, 01066 dstWidth, dstHeight, 01067 dstPtr + bytesPerDstImage * (dstDepth - 1), dstRowStride); 01068 /* do four remaining border edges that span the image slices */ 01069 if (srcDepth == dstDepth) { 01070 /* just copy border pixels from src to dst */ 01071 for (img = 0; img < dstDepthNB; img++) { 01072 const GLubyte *src; 01073 GLubyte *dst; 01074 01075 /* do border along [img][row=0][col=0] */ 01076 src = srcPtr + (img + 1) * bytesPerSrcImage; 01077 dst = dstPtr + (img + 1) * bytesPerDstImage; 01078 MEMCPY(dst, src, bpt); 01079 01080 /* do border along [img][row=dstHeight-1][col=0] */ 01081 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage 01082 + (srcHeight - 1) * bytesPerSrcRow; 01083 dst = dstPtr + (img + 1) * bytesPerDstImage 01084 + (dstHeight - 1) * bytesPerDstRow; 01085 MEMCPY(dst, src, bpt); 01086 01087 /* do border along [img][row=0][col=dstWidth-1] */ 01088 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage 01089 + (srcWidth - 1) * bpt; 01090 dst = dstPtr + (img + 1) * bytesPerDstImage 01091 + (dstWidth - 1) * bpt; 01092 MEMCPY(dst, src, bpt); 01093 01094 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ 01095 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage 01096 + (bytesPerSrcImage - bpt); 01097 dst = dstPtr + (img + 1) * bytesPerDstImage 01098 + (bytesPerDstImage - bpt); 01099 MEMCPY(dst, src, bpt); 01100 } 01101 } 01102 else { 01103 /* average border pixels from adjacent src image pairs */ 01104 ASSERT(srcDepthNB == 2 * dstDepthNB); 01105 for (img = 0; img < dstDepthNB; img++) { 01106 const GLubyte *src; 01107 GLubyte *dst; 01108 01109 /* do border along [img][row=0][col=0] */ 01110 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage; 01111 dst = dstPtr + (img + 1) * bytesPerDstImage; 01112 do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); 01113 01114 /* do border along [img][row=dstHeight-1][col=0] */ 01115 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage 01116 + (srcHeight - 1) * bytesPerSrcRow; 01117 dst = dstPtr + (img + 1) * bytesPerDstImage 01118 + (dstHeight - 1) * bytesPerDstRow; 01119 do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); 01120 01121 /* do border along [img][row=0][col=dstWidth-1] */ 01122 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage 01123 + (srcWidth - 1) * bpt; 01124 dst = dstPtr + (img + 1) * bytesPerDstImage 01125 + (dstWidth - 1) * bpt; 01126 do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); 01127 01128 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ 01129 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage 01130 + (bytesPerSrcImage - bpt); 01131 dst = dstPtr + (img + 1) * bytesPerDstImage 01132 + (bytesPerDstImage - bpt); 01133 do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst); 01134 } 01135 } 01136 } 01137 } 01138 01139 01140 static void 01141 make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border, 01142 GLint srcWidth, const GLubyte *srcPtr, GLuint srcRowStride, 01143 GLint dstWidth, GLint dstHeight, 01144 GLubyte *dstPtr, GLuint dstRowStride ) 01145 { 01146 const GLint bpt = bytes_per_pixel(datatype, comps); 01147 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ 01148 const GLint dstWidthNB = dstWidth - 2 * border; 01149 const GLint dstHeightNB = dstHeight - 2 * border; 01150 const GLint srcRowBytes = bpt * srcRowStride; 01151 const GLint dstRowBytes = bpt * dstRowStride; 01152 const GLubyte *src; 01153 GLubyte *dst; 01154 GLint row; 01155 01156 /* Compute src and dst pointers, skipping any border */ 01157 src = srcPtr + border * ((srcWidth + 1) * bpt); 01158 dst = dstPtr + border * ((dstWidth + 1) * bpt); 01159 01160 for (row = 0; row < dstHeightNB; row++) { 01161 do_row(datatype, comps, srcWidthNB, src, src, 01162 dstWidthNB, dst); 01163 src += srcRowBytes; 01164 dst += dstRowBytes; 01165 } 01166 01167 if (border) { 01168 /* copy left-most pixel from source */ 01169 MEMCPY(dstPtr, srcPtr, bpt); 01170 /* copy right-most pixel from source */ 01171 MEMCPY(dstPtr + (dstWidth - 1) * bpt, 01172 srcPtr + (srcWidth - 1) * bpt, 01173 bpt); 01174 } 01175 } 01176 01177 01183 static void 01184 make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border, 01185 GLint srcWidth, GLint srcHeight, 01186 const GLubyte *srcPtr, GLint srcRowStride, 01187 GLint dstWidth, GLint dstHeight, GLint dstDepth, 01188 GLubyte *dstPtr, GLint dstRowStride) 01189 { 01190 const GLint bpt = bytes_per_pixel(datatype, comps); 01191 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ 01192 const GLint dstWidthNB = dstWidth - 2 * border; 01193 const GLint dstHeightNB = dstHeight - 2 * border; 01194 const GLint dstDepthNB = dstDepth - 2 * border; 01195 const GLint srcRowBytes = bpt * srcRowStride; 01196 const GLint dstRowBytes = bpt * dstRowStride; 01197 const GLubyte *srcA, *srcB; 01198 GLubyte *dst; 01199 GLint layer; 01200 GLint row; 01201 01202 /* Compute src and dst pointers, skipping any border */ 01203 srcA = srcPtr + border * ((srcWidth + 1) * bpt); 01204 if (srcHeight > 1) 01205 srcB = srcA + srcRowBytes; 01206 else 01207 srcB = srcA; 01208 dst = dstPtr + border * ((dstWidth + 1) * bpt); 01209 01210 for (layer = 0; layer < dstDepthNB; layer++) { 01211 for (row = 0; row < dstHeightNB; row++) { 01212 do_row(datatype, comps, srcWidthNB, srcA, srcB, 01213 dstWidthNB, dst); 01214 srcA += 2 * srcRowBytes; 01215 srcB += 2 * srcRowBytes; 01216 dst += dstRowBytes; 01217 } 01218 01219 /* This is ugly but probably won't be used much */ 01220 if (border > 0) { 01221 /* fill in dest border */ 01222 /* lower-left border pixel */ 01223 MEMCPY(dstPtr, srcPtr, bpt); 01224 /* lower-right border pixel */ 01225 MEMCPY(dstPtr + (dstWidth - 1) * bpt, 01226 srcPtr + (srcWidth - 1) * bpt, bpt); 01227 /* upper-left border pixel */ 01228 MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt, 01229 srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt); 01230 /* upper-right border pixel */ 01231 MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt, 01232 srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt); 01233 /* lower border */ 01234 do_row(datatype, comps, srcWidthNB, 01235 srcPtr + bpt, 01236 srcPtr + bpt, 01237 dstWidthNB, dstPtr + bpt); 01238 /* upper border */ 01239 do_row(datatype, comps, srcWidthNB, 01240 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, 01241 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, 01242 dstWidthNB, 01243 dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt); 01244 /* left and right borders */ 01245 if (srcHeight == dstHeight) { 01246 /* copy border pixel from src to dst */ 01247 for (row = 1; row < srcHeight; row++) { 01248 MEMCPY(dstPtr + dstWidth * row * bpt, 01249 srcPtr + srcWidth * row * bpt, bpt); 01250 MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt, 01251 srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt); 01252 } 01253 } 01254 else { 01255 /* average two src pixels each dest pixel */ 01256 for (row = 0; row < dstHeightNB; row += 2) { 01257 do_row(datatype, comps, 1, 01258 srcPtr + (srcWidth * (row * 2 + 1)) * bpt, 01259 srcPtr + (srcWidth * (row * 2 + 2)) * bpt, 01260 1, dstPtr + (dstWidth * row + 1) * bpt); 01261 do_row(datatype, comps, 1, 01262 srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt, 01263 srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt, 01264 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt); 01265 } 01266 } 01267 } 01268 } 01269 } 01270 01271 01275 void 01276 _mesa_generate_mipmap_level(GLenum target, 01277 GLenum datatype, GLuint comps, 01278 GLint border, 01279 GLint srcWidth, GLint srcHeight, GLint srcDepth, 01280 const GLubyte *srcData, 01281 GLint srcRowStride, 01282 GLint dstWidth, GLint dstHeight, GLint dstDepth, 01283 GLubyte *dstData, 01284 GLint dstRowStride) 01285 { 01286 /* 01287 * We use simple 2x2 averaging to compute the next mipmap level. 01288 */ 01289 switch (target) { 01290 case GL_TEXTURE_1D: 01291 make_1d_mipmap(datatype, comps, border, 01292 srcWidth, srcData, 01293 dstWidth, dstData); 01294 break; 01295 case GL_TEXTURE_2D: 01296 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 01297 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 01298 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 01299 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 01300 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 01301 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 01302 make_2d_mipmap(datatype, comps, border, 01303 srcWidth, srcHeight, srcData, srcRowStride, 01304 dstWidth, dstHeight, dstData, dstRowStride); 01305 break; 01306 case GL_TEXTURE_3D: 01307 make_3d_mipmap(datatype, comps, border, 01308 srcWidth, srcHeight, srcDepth, 01309 srcData, srcRowStride, 01310 dstWidth, dstHeight, dstDepth, 01311 dstData, dstRowStride); 01312 break; 01313 case GL_TEXTURE_1D_ARRAY_EXT: 01314 make_1d_stack_mipmap(datatype, comps, border, 01315 srcWidth, srcData, srcRowStride, 01316 dstWidth, dstHeight, 01317 dstData, dstRowStride); 01318 break; 01319 case GL_TEXTURE_2D_ARRAY_EXT: 01320 make_2d_stack_mipmap(datatype, comps, border, 01321 srcWidth, srcHeight, 01322 srcData, srcRowStride, 01323 dstWidth, dstHeight, 01324 dstDepth, dstData, dstRowStride); 01325 break; 01326 case GL_TEXTURE_RECTANGLE_NV: 01327 /* no mipmaps, do nothing */ 01328 break; 01329 default: 01330 _mesa_problem(NULL, "bad dimensions in _mesa_generate_mipmaps"); 01331 return; 01332 } 01333 } 01334 01335 01340 static GLboolean 01341 next_mipmap_level_size(GLenum target, GLint border, 01342 GLint srcWidth, GLint srcHeight, GLint srcDepth, 01343 GLint *dstWidth, GLint *dstHeight, GLint *dstDepth) 01344 { 01345 if (srcWidth - 2 * border > 1) { 01346 *dstWidth = (srcWidth - 2 * border) / 2 + 2 * border; 01347 } 01348 else { 01349 *dstWidth = srcWidth; /* can't go smaller */ 01350 } 01351 01352 if ((srcHeight - 2 * border > 1) && 01353 (target != GL_TEXTURE_1D_ARRAY_EXT)) { 01354 *dstHeight = (srcHeight - 2 * border) / 2 + 2 * border; 01355 } 01356 else { 01357 *dstHeight = srcHeight; /* can't go smaller */ 01358 } 01359 01360 if ((srcDepth - 2 * border > 1) && 01361 (target != GL_TEXTURE_2D_ARRAY_EXT)) { 01362 *dstDepth = (srcDepth - 2 * border) / 2 + 2 * border; 01363 } 01364 else { 01365 *dstDepth = srcDepth; /* can't go smaller */ 01366 } 01367 01368 if (*dstWidth == srcWidth && 01369 *dstHeight == srcHeight && 01370 *dstDepth == srcDepth) { 01371 return GL_FALSE; 01372 } 01373 else { 01374 return GL_TRUE; 01375 } 01376 } 01377 01378 01379 01380 01386 void 01387 _mesa_generate_mipmap(GLcontext *ctx, GLenum target, 01388 struct gl_texture_object *texObj) 01389 { 01390 const struct gl_texture_image *srcImage; 01391 const struct gl_texture_format *convertFormat; 01392 const GLubyte *srcData = NULL; 01393 GLubyte *dstData = NULL; 01394 GLint level, maxLevels; 01395 GLenum datatype; 01396 GLuint comps; 01397 01398 ASSERT(texObj); 01399 /* XXX choose cube map face here??? */ 01400 srcImage = texObj->Image[0][texObj->BaseLevel]; 01401 ASSERT(srcImage); 01402 01403 maxLevels = _mesa_max_texture_levels(ctx, texObj->Target); 01404 ASSERT(maxLevels > 0); /* bad target */ 01405 01406 /* Find convertFormat - the format that do_row() will process */ 01407 if (srcImage->IsCompressed) { 01408 /* setup for compressed textures */ 01409 GLuint row; 01410 GLint components, size; 01411 GLchan *dst; 01412 01413 assert(texObj->Target == GL_TEXTURE_2D || 01414 texObj->Target == GL_TEXTURE_CUBE_MAP_ARB); 01415 01416 if (srcImage->_BaseFormat == GL_RGB) { 01417 convertFormat = &_mesa_texformat_rgb; 01418 components = 3; 01419 } 01420 else if (srcImage->_BaseFormat == GL_RGBA) { 01421 convertFormat = &_mesa_texformat_rgba; 01422 components = 4; 01423 } 01424 else { 01425 _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps"); 01426 return; 01427 } 01428 01429 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */ 01430 size = _mesa_bytes_per_pixel(srcImage->_BaseFormat, CHAN_TYPE) 01431 * srcImage->Width * srcImage->Height * srcImage->Depth + 20; 01432 /* 20 extra bytes, just be safe when calling last FetchTexel */ 01433 srcData = (GLubyte *) _mesa_malloc(size); 01434 if (!srcData) { 01435 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); 01436 return; 01437 } 01438 dstData = (GLubyte *) _mesa_malloc(size / 2); /* 1/4 would probably be OK */ 01439 if (!dstData) { 01440 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); 01441 _mesa_free((void *) srcData); 01442 return; 01443 } 01444 01445 /* decompress base image here */ 01446 dst = (GLchan *) srcData; 01447 for (row = 0; row < srcImage->Height; row++) { 01448 GLuint col; 01449 for (col = 0; col < srcImage->Width; col++) { 01450 srcImage->FetchTexelc(srcImage, col, row, 0, dst); 01451 dst += components; 01452 } 01453 } 01454 } 01455 else { 01456 /* uncompressed */ 01457 convertFormat = srcImage->TexFormat; 01458 } 01459 01460 _mesa_format_to_type_and_comps(convertFormat, &datatype, &comps); 01461 01462 for (level = texObj->BaseLevel; level < texObj->MaxLevel 01463 && level < maxLevels - 1; level++) { 01464 /* generate image[level+1] from image[level] */ 01465 const struct gl_texture_image *srcImage; 01466 struct gl_texture_image *dstImage; 01467 GLint srcWidth, srcHeight, srcDepth; 01468 GLint dstWidth, dstHeight, dstDepth; 01469 GLint border, bytesPerTexel; 01470 GLboolean nextLevel; 01471 01472 /* get src image parameters */ 01473 srcImage = _mesa_select_tex_image(ctx, texObj, target, level); 01474 ASSERT(srcImage); 01475 srcWidth = srcImage->Width; 01476 srcHeight = srcImage->Height; 01477 srcDepth = srcImage->Depth; 01478 border = srcImage->Border; 01479 01480 nextLevel = next_mipmap_level_size(target, border, 01481 srcWidth, srcHeight, srcDepth, 01482 &dstWidth, &dstHeight, &dstDepth); 01483 if (!nextLevel) { 01484 /* all done */ 01485 if (srcImage->IsCompressed) { 01486 _mesa_free((void *) srcData); 01487 _mesa_free(dstData); 01488 } 01489 return; 01490 } 01491 01492 /* get dest gl_texture_image */ 01493 dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1); 01494 if (!dstImage) { 01495 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); 01496 return; 01497 } 01498 01499 if (dstImage->ImageOffsets) 01500 _mesa_free(dstImage->ImageOffsets); 01501 01502 /* Free old image data */ 01503 if (dstImage->Data) 01504 ctx->Driver.FreeTexImageData(ctx, dstImage); 01505 01506 /* initialize new image */ 01507 _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, 01508 dstDepth, border, srcImage->InternalFormat); 01509 dstImage->DriverData = NULL; 01510 dstImage->TexFormat = srcImage->TexFormat; 01511 dstImage->FetchTexelc = srcImage->FetchTexelc; 01512 dstImage->FetchTexelf = srcImage->FetchTexelf; 01513 dstImage->IsCompressed = srcImage->IsCompressed; 01514 if (dstImage->IsCompressed) { 01515 dstImage->CompressedSize 01516 = ctx->Driver.CompressedTextureSize(ctx, dstImage->Width, 01517 dstImage->Height, 01518 dstImage->Depth, 01519 dstImage->TexFormat->MesaFormat); 01520 ASSERT(dstImage->CompressedSize > 0); 01521 } 01522 01523 ASSERT(dstImage->TexFormat); 01524 ASSERT(dstImage->FetchTexelc); 01525 ASSERT(dstImage->FetchTexelf); 01526 01527 /* Alloc new teximage data buffer. 01528 * Setup src and dest data pointers. 01529 */ 01530 if (dstImage->IsCompressed) { 01531 dstImage->Data = _mesa_alloc_texmemory(dstImage->CompressedSize); 01532 if (!dstImage->Data) { 01533 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); 01534 return; 01535 } 01536 /* srcData and dstData are already set */ 01537 ASSERT(srcData); 01538 ASSERT(dstData); 01539 } 01540 else { 01541 bytesPerTexel = dstImage->TexFormat->TexelBytes; 01542 ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0); 01543 dstImage->Data = _mesa_alloc_texmemory(dstWidth * dstHeight 01544 * dstDepth * bytesPerTexel); 01545 if (!dstImage->Data) { 01546 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); 01547 return; 01548 } 01549 srcData = (const GLubyte *) srcImage->Data; 01550 dstData = (GLubyte *) dstImage->Data; 01551 } 01552 01553 _mesa_generate_mipmap_level(target, datatype, comps, border, 01554 srcWidth, srcHeight, srcDepth, 01555 srcData, srcImage->RowStride, 01556 dstWidth, dstHeight, dstDepth, 01557 dstData, dstImage->RowStride); 01558 01559 01560 if (dstImage->IsCompressed) { 01561 GLubyte *temp; 01562 /* compress image from dstData into dstImage->Data */ 01563 const GLenum srcFormat = convertFormat->BaseFormat; 01564 GLint dstRowStride 01565 = _mesa_compressed_row_stride(dstImage->TexFormat->MesaFormat, dstWidth); 01566 ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA); 01567 dstImage->TexFormat->StoreImage(ctx, 2, dstImage->_BaseFormat, 01568 dstImage->TexFormat, 01569 dstImage->Data, 01570 0, 0, 0, /* dstX/Y/Zoffset */ 01571 dstRowStride, 0, /* strides */ 01572 dstWidth, dstHeight, 1, /* size */ 01573 srcFormat, CHAN_TYPE, 01574 dstData, /* src data, actually */ 01575 &ctx->DefaultPacking); 01576 /* swap src and dest pointers */ 01577 temp = (GLubyte *) srcData; 01578 srcData = dstData; 01579 dstData = temp; 01580 } 01581 01582 } /* loop over mipmap levels */ 01583 } 01584 01585 01593 void 01594 _mesa_rescale_teximage2d(GLuint bytesPerPixel, 01595 GLuint srcStrideInPixels, 01596 GLuint dstRowStride, 01597 GLint srcWidth, GLint srcHeight, 01598 GLint dstWidth, GLint dstHeight, 01599 const GLvoid *srcImage, GLvoid *dstImage) 01600 { 01601 GLint row, col; 01602 01603 #define INNER_LOOP( TYPE, HOP, WOP ) \ 01604 for ( row = 0 ; row < dstHeight ; row++ ) { \ 01605 GLint srcRow = row HOP hScale; \ 01606 for ( col = 0 ; col < dstWidth ; col++ ) { \ 01607 GLint srcCol = col WOP wScale; \ 01608 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \ 01609 } \ 01610 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \ 01611 } \ 01612 01613 #define RESCALE_IMAGE( TYPE ) \ 01614 do { \ 01615 const TYPE *src = (const TYPE *)srcImage; \ 01616 TYPE *dst = (TYPE *)dstImage; \ 01617 \ 01618 if ( srcHeight < dstHeight ) { \ 01619 const GLint hScale = dstHeight / srcHeight; \ 01620 if ( srcWidth < dstWidth ) { \ 01621 const GLint wScale = dstWidth / srcWidth; \ 01622 INNER_LOOP( TYPE, /, / ); \ 01623 } \ 01624 else { \ 01625 const GLint wScale = srcWidth / dstWidth; \ 01626 INNER_LOOP( TYPE, /, * ); \ 01627 } \ 01628 } \ 01629 else { \ 01630 const GLint hScale = srcHeight / dstHeight; \ 01631 if ( srcWidth < dstWidth ) { \ 01632 const GLint wScale = dstWidth / srcWidth; \ 01633 INNER_LOOP( TYPE, *, / ); \ 01634 } \ 01635 else { \ 01636 const GLint wScale = srcWidth / dstWidth; \ 01637 INNER_LOOP( TYPE, *, * ); \ 01638 } \ 01639 } \ 01640 } while (0) 01641 01642 switch ( bytesPerPixel ) { 01643 case 4: 01644 RESCALE_IMAGE( GLuint ); 01645 break; 01646 01647 case 2: 01648 RESCALE_IMAGE( GLushort ); 01649 break; 01650 01651 case 1: 01652 RESCALE_IMAGE( GLubyte ); 01653 break; 01654 default: 01655 _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d"); 01656 } 01657 } 01658 01659 01665 void 01666 _mesa_upscale_teximage2d(GLsizei inWidth, GLsizei inHeight, 01667 GLsizei outWidth, GLsizei outHeight, 01668 GLint comps, const GLchan *src, GLint srcRowStride, 01669 GLchan *dest ) 01670 { 01671 GLint i, j, k; 01672 01673 ASSERT(outWidth >= inWidth); 01674 ASSERT(outHeight >= inHeight); 01675 #if 0 01676 ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2); 01677 ASSERT((outWidth & 3) == 0); 01678 ASSERT((outHeight & 3) == 0); 01679 #endif 01680 01681 for (i = 0; i < outHeight; i++) { 01682 const GLint ii = i % inHeight; 01683 for (j = 0; j < outWidth; j++) { 01684 const GLint jj = j % inWidth; 01685 for (k = 0; k < comps; k++) { 01686 dest[(i * outWidth + j) * comps + k] 01687 = src[ii * srcRowStride + jj * comps + k]; 01688 } 01689 } 01690 } 01691 } 01692 Generated on Sun May 27 2012 04:20:22 for ReactOS by
1.7.6.1
|