u_gen_mipmap.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  *
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  *
00026  **************************************************************************/
00027 
00036 #include "pipe/p_context.h"
00037 #include "pipe/p_debug.h"
00038 #include "pipe/p_defines.h"
00039 #include "pipe/p_inlines.h"
00040 #include "pipe/p_winsys.h"
00041 #include "pipe/p_shader_tokens.h"
00042 
00043 #include "util/u_memory.h"
00044 #include "util/u_draw_quad.h"
00045 #include "util/u_gen_mipmap.h"
00046 #include "util/u_simple_shaders.h"
00047 
00048 #include "tgsi/tgsi_build.h"
00049 #include "tgsi/tgsi_dump.h"
00050 #include "tgsi/tgsi_parse.h"
00051 
00052 #include "cso_cache/cso_context.h"
00053 
00054 
00055 struct gen_mipmap_state
00056 {
00057    struct pipe_context *pipe;
00058    struct cso_context *cso;
00059 
00060    struct pipe_blend_state blend;
00061    struct pipe_depth_stencil_alpha_state depthstencil;
00062    struct pipe_rasterizer_state rasterizer;
00063    struct pipe_sampler_state sampler;
00064    struct pipe_viewport_state viewport;
00065 
00066    struct pipe_shader_state vert_shader;
00067    struct pipe_shader_state frag_shader;
00068    void *vs;
00069    void *fs;
00070 
00071    struct pipe_buffer *vbuf;  
00072    unsigned vbuf_slot;
00073 
00074    float vertices[4][2][4];   
00075 };
00076 
00077 
00078 
00079 enum dtype
00080 {
00081    UBYTE,
00082    UBYTE_3_3_2,
00083    USHORT,
00084    USHORT_4_4_4_4,
00085    USHORT_5_6_5,
00086    USHORT_1_5_5_5_REV,
00087    UINT,
00088    FLOAT,
00089    HALF_FLOAT
00090 };
00091 
00092 
00093 typedef ushort half_float;
00094 
00095 
00096 #if 0
00097 extern half_float
00098 float_to_half(float f);
00099 
00100 extern float
00101 half_to_float(half_float h);
00102 #endif
00103 
00104 
00113 static void
00114 do_row(enum dtype datatype, uint comps, int srcWidth,
00115        const void *srcRowA, const void *srcRowB,
00116        int dstWidth, void *dstRow)
00117 {
00118    const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
00119    const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
00120 
00121    assert(comps >= 1);
00122    assert(comps <= 4);
00123 
00124    /* This assertion is no longer valid with non-power-of-2 textures
00125    assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
00126    */
00127 
00128    if (datatype == UBYTE && comps == 4) {
00129       uint i, j, k;
00130       const ubyte(*rowA)[4] = (const ubyte(*)[4]) srcRowA;
00131       const ubyte(*rowB)[4] = (const ubyte(*)[4]) srcRowB;
00132       ubyte(*dst)[4] = (ubyte(*)[4]) dstRow;
00133       for (i = j = 0, k = k0; i < (uint) dstWidth;
00134            i++, j += colStride, k += colStride) {
00135          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
00136          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
00137          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
00138          dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
00139       }
00140    }
00141    else if (datatype == UBYTE && comps == 3) {
00142       uint i, j, k;
00143       const ubyte(*rowA)[3] = (const ubyte(*)[3]) srcRowA;
00144       const ubyte(*rowB)[3] = (const ubyte(*)[3]) srcRowB;
00145       ubyte(*dst)[3] = (ubyte(*)[3]) dstRow;
00146       for (i = j = 0, k = k0; i < (uint) dstWidth;
00147            i++, j += colStride, k += colStride) {
00148          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
00149          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
00150          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
00151       }
00152    }
00153    else if (datatype == UBYTE && comps == 2) {
00154       uint i, j, k;
00155       const ubyte(*rowA)[2] = (const ubyte(*)[2]) srcRowA;
00156       const ubyte(*rowB)[2] = (const ubyte(*)[2]) srcRowB;
00157       ubyte(*dst)[2] = (ubyte(*)[2]) dstRow;
00158       for (i = j = 0, k = k0; i < (uint) dstWidth;
00159            i++, j += colStride, k += colStride) {
00160          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
00161          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
00162       }
00163    }
00164    else if (datatype == UBYTE && comps == 1) {
00165       uint i, j, k;
00166       const ubyte *rowA = (const ubyte *) srcRowA;
00167       const ubyte *rowB = (const ubyte *) srcRowB;
00168       ubyte *dst = (ubyte *) dstRow;
00169       for (i = j = 0, k = k0; i < (uint) dstWidth;
00170            i++, j += colStride, k += colStride) {
00171          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
00172       }
00173    }
00174 
00175    else if (datatype == USHORT && comps == 4) {
00176       uint i, j, k;
00177       const ushort(*rowA)[4] = (const ushort(*)[4]) srcRowA;
00178       const ushort(*rowB)[4] = (const ushort(*)[4]) srcRowB;
00179       ushort(*dst)[4] = (ushort(*)[4]) dstRow;
00180       for (i = j = 0, k = k0; i < (uint) dstWidth;
00181            i++, j += colStride, k += colStride) {
00182          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
00183          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
00184          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
00185          dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
00186       }
00187    }
00188    else if (datatype == USHORT && comps == 3) {
00189       uint i, j, k;
00190       const ushort(*rowA)[3] = (const ushort(*)[3]) srcRowA;
00191       const ushort(*rowB)[3] = (const ushort(*)[3]) srcRowB;
00192       ushort(*dst)[3] = (ushort(*)[3]) dstRow;
00193       for (i = j = 0, k = k0; i < (uint) dstWidth;
00194            i++, j += colStride, k += colStride) {
00195          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
00196          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
00197          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
00198       }
00199    }
00200    else if (datatype == USHORT && comps == 2) {
00201       uint i, j, k;
00202       const ushort(*rowA)[2] = (const ushort(*)[2]) srcRowA;
00203       const ushort(*rowB)[2] = (const ushort(*)[2]) srcRowB;
00204       ushort(*dst)[2] = (ushort(*)[2]) dstRow;
00205       for (i = j = 0, k = k0; i < (uint) dstWidth;
00206            i++, j += colStride, k += colStride) {
00207          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
00208          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
00209       }
00210    }
00211    else if (datatype == USHORT && comps == 1) {
00212       uint i, j, k;
00213       const ushort *rowA = (const ushort *) srcRowA;
00214       const ushort *rowB = (const ushort *) srcRowB;
00215       ushort *dst = (ushort *) dstRow;
00216       for (i = j = 0, k = k0; i < (uint) dstWidth;
00217            i++, j += colStride, k += colStride) {
00218          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
00219       }
00220    }
00221 
00222    else if (datatype == FLOAT && comps == 4) {
00223       uint i, j, k;
00224       const float(*rowA)[4] = (const float(*)[4]) srcRowA;
00225       const float(*rowB)[4] = (const float(*)[4]) srcRowB;
00226       float(*dst)[4] = (float(*)[4]) dstRow;
00227       for (i = j = 0, k = k0; i < (uint) dstWidth;
00228            i++, j += colStride, k += colStride) {
00229          dst[i][0] = (rowA[j][0] + rowA[k][0] +
00230                       rowB[j][0] + rowB[k][0]) * 0.25F;
00231          dst[i][1] = (rowA[j][1] + rowA[k][1] +
00232                       rowB[j][1] + rowB[k][1]) * 0.25F;
00233          dst[i][2] = (rowA[j][2] + rowA[k][2] +
00234                       rowB[j][2] + rowB[k][2]) * 0.25F;
00235          dst[i][3] = (rowA[j][3] + rowA[k][3] +
00236                       rowB[j][3] + rowB[k][3]) * 0.25F;
00237       }
00238    }
00239    else if (datatype == FLOAT && comps == 3) {
00240       uint i, j, k;
00241       const float(*rowA)[3] = (const float(*)[3]) srcRowA;
00242       const float(*rowB)[3] = (const float(*)[3]) srcRowB;
00243       float(*dst)[3] = (float(*)[3]) dstRow;
00244       for (i = j = 0, k = k0; i < (uint) dstWidth;
00245            i++, j += colStride, k += colStride) {
00246          dst[i][0] = (rowA[j][0] + rowA[k][0] +
00247                       rowB[j][0] + rowB[k][0]) * 0.25F;
00248          dst[i][1] = (rowA[j][1] + rowA[k][1] +
00249                       rowB[j][1] + rowB[k][1]) * 0.25F;
00250          dst[i][2] = (rowA[j][2] + rowA[k][2] +
00251                       rowB[j][2] + rowB[k][2]) * 0.25F;
00252       }
00253    }
00254    else if (datatype == FLOAT && comps == 2) {
00255       uint i, j, k;
00256       const float(*rowA)[2] = (const float(*)[2]) srcRowA;
00257       const float(*rowB)[2] = (const float(*)[2]) srcRowB;
00258       float(*dst)[2] = (float(*)[2]) dstRow;
00259       for (i = j = 0, k = k0; i < (uint) dstWidth;
00260            i++, j += colStride, k += colStride) {
00261          dst[i][0] = (rowA[j][0] + rowA[k][0] +
00262                       rowB[j][0] + rowB[k][0]) * 0.25F;
00263          dst[i][1] = (rowA[j][1] + rowA[k][1] +
00264                       rowB[j][1] + rowB[k][1]) * 0.25F;
00265       }
00266    }
00267    else if (datatype == FLOAT && comps == 1) {
00268       uint i, j, k;
00269       const float *rowA = (const float *) srcRowA;
00270       const float *rowB = (const float *) srcRowB;
00271       float *dst = (float *) dstRow;
00272       for (i = j = 0, k = k0; i < (uint) dstWidth;
00273            i++, j += colStride, k += colStride) {
00274          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
00275       }
00276    }
00277 
00278 #if 0
00279    else if (datatype == HALF_FLOAT && comps == 4) {
00280       uint i, j, k, comp;
00281       const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA;
00282       const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB;
00283       half_float(*dst)[4] = (half_float(*)[4]) dstRow;
00284       for (i = j = 0, k = k0; i < (uint) dstWidth;
00285            i++, j += colStride, k += colStride) {
00286          for (comp = 0; comp < 4; comp++) {
00287             float aj, ak, bj, bk;
00288             aj = half_to_float(rowA[j][comp]);
00289             ak = half_to_float(rowA[k][comp]);
00290             bj = half_to_float(rowB[j][comp]);
00291             bk = half_to_float(rowB[k][comp]);
00292             dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
00293          }
00294       }
00295    }
00296    else if (datatype == HALF_FLOAT && comps == 3) {
00297       uint i, j, k, comp;
00298       const half_float(*rowA)[3] = (const half_float(*)[3]) srcRowA;
00299       const half_float(*rowB)[3] = (const half_float(*)[3]) srcRowB;
00300       half_float(*dst)[3] = (half_float(*)[3]) dstRow;
00301       for (i = j = 0, k = k0; i < (uint) dstWidth;
00302            i++, j += colStride, k += colStride) {
00303          for (comp = 0; comp < 3; comp++) {
00304             float aj, ak, bj, bk;
00305             aj = half_to_float(rowA[j][comp]);
00306             ak = half_to_float(rowA[k][comp]);
00307             bj = half_to_float(rowB[j][comp]);
00308             bk = half_to_float(rowB[k][comp]);
00309             dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
00310          }
00311       }
00312    }
00313    else if (datatype == HALF_FLOAT && comps == 2) {
00314       uint i, j, k, comp;
00315       const half_float(*rowA)[2] = (const half_float(*)[2]) srcRowA;
00316       const half_float(*rowB)[2] = (const half_float(*)[2]) srcRowB;
00317       half_float(*dst)[2] = (half_float(*)[2]) dstRow;
00318       for (i = j = 0, k = k0; i < (uint) dstWidth;
00319            i++, j += colStride, k += colStride) {
00320          for (comp = 0; comp < 2; comp++) {
00321             float aj, ak, bj, bk;
00322             aj = half_to_float(rowA[j][comp]);
00323             ak = half_to_float(rowA[k][comp]);
00324             bj = half_to_float(rowB[j][comp]);
00325             bk = half_to_float(rowB[k][comp]);
00326             dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
00327          }
00328       }
00329    }
00330    else if (datatype == HALF_FLOAT && comps == 1) {
00331       uint i, j, k;
00332       const half_float *rowA = (const half_float *) srcRowA;
00333       const half_float *rowB = (const half_float *) srcRowB;
00334       half_float *dst = (half_float *) dstRow;
00335       for (i = j = 0, k = k0; i < (uint) dstWidth;
00336            i++, j += colStride, k += colStride) {
00337          float aj, ak, bj, bk;
00338          aj = half_to_float(rowA[j]);
00339          ak = half_to_float(rowA[k]);
00340          bj = half_to_float(rowB[j]);
00341          bk = half_to_float(rowB[k]);
00342          dst[i] = float_to_half((aj + ak + bj + bk) * 0.25F);
00343       }
00344    }
00345 #endif
00346 
00347    else if (datatype == UINT && comps == 1) {
00348       uint i, j, k;
00349       const uint *rowA = (const uint *) srcRowA;
00350       const uint *rowB = (const uint *) srcRowB;
00351       uint *dst = (uint *) dstRow;
00352       for (i = j = 0, k = k0; i < (uint) dstWidth;
00353            i++, j += colStride, k += colStride) {
00354          dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4;
00355       }
00356    }
00357 
00358    else if (datatype == USHORT_5_6_5 && comps == 3) {
00359       uint i, j, k;
00360       const ushort *rowA = (const ushort *) srcRowA;
00361       const ushort *rowB = (const ushort *) srcRowB;
00362       ushort *dst = (ushort *) dstRow;
00363       for (i = j = 0, k = k0; i < (uint) dstWidth;
00364            i++, j += colStride, k += colStride) {
00365          const int rowAr0 = rowA[j] & 0x1f;
00366          const int rowAr1 = rowA[k] & 0x1f;
00367          const int rowBr0 = rowB[j] & 0x1f;
00368          const int rowBr1 = rowB[k] & 0x1f;
00369          const int rowAg0 = (rowA[j] >> 5) & 0x3f;
00370          const int rowAg1 = (rowA[k] >> 5) & 0x3f;
00371          const int rowBg0 = (rowB[j] >> 5) & 0x3f;
00372          const int rowBg1 = (rowB[k] >> 5) & 0x3f;
00373          const int rowAb0 = (rowA[j] >> 11) & 0x1f;
00374          const int rowAb1 = (rowA[k] >> 11) & 0x1f;
00375          const int rowBb0 = (rowB[j] >> 11) & 0x1f;
00376          const int rowBb1 = (rowB[k] >> 11) & 0x1f;
00377          const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
00378          const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
00379          const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
00380          dst[i] = (blue << 11) | (green << 5) | red;
00381       }
00382    }
00383    else if (datatype == USHORT_4_4_4_4 && comps == 4) {
00384       uint i, j, k;
00385       const ushort *rowA = (const ushort *) srcRowA;
00386       const ushort *rowB = (const ushort *) srcRowB;
00387       ushort *dst = (ushort *) dstRow;
00388       for (i = j = 0, k = k0; i < (uint) dstWidth;
00389            i++, j += colStride, k += colStride) {
00390          const int rowAr0 = rowA[j] & 0xf;
00391          const int rowAr1 = rowA[k] & 0xf;
00392          const int rowBr0 = rowB[j] & 0xf;
00393          const int rowBr1 = rowB[k] & 0xf;
00394          const int rowAg0 = (rowA[j] >> 4) & 0xf;
00395          const int rowAg1 = (rowA[k] >> 4) & 0xf;
00396          const int rowBg0 = (rowB[j] >> 4) & 0xf;
00397          const int rowBg1 = (rowB[k] >> 4) & 0xf;
00398          const int rowAb0 = (rowA[j] >> 8) & 0xf;
00399          const int rowAb1 = (rowA[k] >> 8) & 0xf;
00400          const int rowBb0 = (rowB[j] >> 8) & 0xf;
00401          const int rowBb1 = (rowB[k] >> 8) & 0xf;
00402          const int rowAa0 = (rowA[j] >> 12) & 0xf;
00403          const int rowAa1 = (rowA[k] >> 12) & 0xf;
00404          const int rowBa0 = (rowB[j] >> 12) & 0xf;
00405          const int rowBa1 = (rowB[k] >> 12) & 0xf;
00406          const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
00407          const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
00408          const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
00409          const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
00410          dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
00411       }
00412    }
00413    else if (datatype == USHORT_1_5_5_5_REV && comps == 4) {
00414       uint i, j, k;
00415       const ushort *rowA = (const ushort *) srcRowA;
00416       const ushort *rowB = (const ushort *) srcRowB;
00417       ushort *dst = (ushort *) dstRow;
00418       for (i = j = 0, k = k0; i < (uint) dstWidth;
00419            i++, j += colStride, k += colStride) {
00420          const int rowAr0 = rowA[j] & 0x1f;
00421          const int rowAr1 = rowA[k] & 0x1f;
00422          const int rowBr0 = rowB[j] & 0x1f;
00423          const int rowBr1 = rowB[k] & 0x1f;
00424          const int rowAg0 = (rowA[j] >> 5) & 0x1f;
00425          const int rowAg1 = (rowA[k] >> 5) & 0x1f;
00426          const int rowBg0 = (rowB[j] >> 5) & 0x1f;
00427          const int rowBg1 = (rowB[k] >> 5) & 0x1f;
00428          const int rowAb0 = (rowA[j] >> 10) & 0x1f;
00429          const int rowAb1 = (rowA[k] >> 10) & 0x1f;
00430          const int rowBb0 = (rowB[j] >> 10) & 0x1f;
00431          const int rowBb1 = (rowB[k] >> 10) & 0x1f;
00432          const int rowAa0 = (rowA[j] >> 15) & 0x1;
00433          const int rowAa1 = (rowA[k] >> 15) & 0x1;
00434          const int rowBa0 = (rowB[j] >> 15) & 0x1;
00435          const int rowBa1 = (rowB[k] >> 15) & 0x1;
00436          const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
00437          const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
00438          const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
00439          const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
00440          dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
00441       }
00442    }
00443    else if (datatype == UBYTE_3_3_2 && comps == 3) {
00444       uint i, j, k;
00445       const ubyte *rowA = (const ubyte *) srcRowA;
00446       const ubyte *rowB = (const ubyte *) srcRowB;
00447       ubyte *dst = (ubyte *) dstRow;
00448       for (i = j = 0, k = k0; i < (uint) dstWidth;
00449            i++, j += colStride, k += colStride) {
00450          const int rowAr0 = rowA[j] & 0x3;
00451          const int rowAr1 = rowA[k] & 0x3;
00452          const int rowBr0 = rowB[j] & 0x3;
00453          const int rowBr1 = rowB[k] & 0x3;
00454          const int rowAg0 = (rowA[j] >> 2) & 0x7;
00455          const int rowAg1 = (rowA[k] >> 2) & 0x7;
00456          const int rowBg0 = (rowB[j] >> 2) & 0x7;
00457          const int rowBg1 = (rowB[k] >> 2) & 0x7;
00458          const int rowAb0 = (rowA[j] >> 5) & 0x7;
00459          const int rowAb1 = (rowA[k] >> 5) & 0x7;
00460          const int rowBb0 = (rowB[j] >> 5) & 0x7;
00461          const int rowBb1 = (rowB[k] >> 5) & 0x7;
00462          const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
00463          const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
00464          const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
00465          dst[i] = (blue << 5) | (green << 2) | red;
00466       }
00467    }
00468    else {
00469       debug_printf("bad format in do_row()");
00470    }
00471 }
00472 
00473 
00474 static void
00475 format_to_type_comps(enum pipe_format pformat,
00476                      enum dtype *datatype, uint *comps)
00477 {
00478    switch (pformat) {
00479    case PIPE_FORMAT_A8R8G8B8_UNORM:
00480    case PIPE_FORMAT_X8R8G8B8_UNORM:
00481    case PIPE_FORMAT_B8G8R8A8_UNORM:
00482    case PIPE_FORMAT_B8G8R8X8_UNORM:
00483       *datatype = UBYTE;
00484       *comps = 4;
00485       return;
00486    case PIPE_FORMAT_A1R5G5B5_UNORM:
00487       *datatype = USHORT_1_5_5_5_REV;
00488       *comps = 4;
00489       return;
00490    case PIPE_FORMAT_A4R4G4B4_UNORM:
00491       *datatype = USHORT_4_4_4_4;
00492       *comps = 4;
00493       return;
00494    case PIPE_FORMAT_R5G6B5_UNORM:
00495       *datatype = USHORT_5_6_5;
00496       *comps = 3;
00497       return;
00498    case PIPE_FORMAT_L8_UNORM:
00499    case PIPE_FORMAT_A8_UNORM:
00500    case PIPE_FORMAT_I8_UNORM:
00501       *datatype = UBYTE;
00502       *comps = 1;
00503       return;
00504    case PIPE_FORMAT_A8L8_UNORM:
00505       *datatype = UBYTE;
00506       *comps = 2;
00507       return;
00508    default:
00509       assert(0);
00510       *datatype = UBYTE;
00511       *comps = 0;
00512       break;
00513    }
00514 }
00515 
00516 
00517 static void
00518 reduce_1d(enum pipe_format pformat,
00519           int srcWidth, const ubyte *srcPtr,
00520           int dstWidth, ubyte *dstPtr)
00521 {
00522    enum dtype datatype;
00523    uint comps;
00524 
00525    format_to_type_comps(pformat, &datatype, &comps);
00526 
00527    /* we just duplicate the input row, kind of hack, saves code */
00528    do_row(datatype, comps,
00529           srcWidth, srcPtr, srcPtr,
00530           dstWidth, dstPtr);
00531 }
00532 
00533 
00537 static void
00538 reduce_2d(enum pipe_format pformat,
00539           int srcWidth, int srcHeight,
00540           int srcRowStride, const ubyte *srcPtr,
00541           int dstWidth, int dstHeight,
00542           int dstRowStride, ubyte *dstPtr)
00543 {
00544    enum dtype datatype;
00545    uint comps;
00546    const int bpt = pf_get_size(pformat);
00547    const ubyte *srcA, *srcB;
00548    ubyte *dst;
00549    int row;
00550 
00551    format_to_type_comps(pformat, &datatype, &comps);
00552 
00553    if (!srcRowStride)
00554       srcRowStride = bpt * srcWidth;
00555 
00556    if (!dstRowStride)
00557       dstRowStride = bpt * dstWidth;
00558 
00559    /* Compute src and dst pointers */
00560    srcA = srcPtr;
00561    if (srcHeight > 1) 
00562       srcB = srcA + srcRowStride;
00563    else
00564       srcB = srcA;
00565    dst = dstPtr;
00566 
00567    for (row = 0; row < dstHeight; row++) {
00568       do_row(datatype, comps,
00569              srcWidth, srcA, srcB,
00570              dstWidth, dst);
00571       srcA += 2 * srcRowStride;
00572       srcB += 2 * srcRowStride;
00573       dst += dstRowStride;
00574    }
00575 }
00576 
00577 
00578 static void
00579 make_1d_mipmap(struct gen_mipmap_state *ctx,
00580                struct pipe_texture *pt,
00581                uint face, uint baseLevel, uint lastLevel)
00582 {
00583    struct pipe_context *pipe = ctx->pipe;
00584    struct pipe_screen *screen = pipe->screen;
00585    const uint zslice = 0;
00586    uint dstLevel;
00587 
00588    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
00589       const uint srcLevel = dstLevel - 1;
00590       struct pipe_surface *srcSurf, *dstSurf;
00591       void *srcMap, *dstMap;
00592       
00593       srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice,
00594                                         PIPE_BUFFER_USAGE_CPU_READ);
00595 
00596       dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
00597                                         PIPE_BUFFER_USAGE_CPU_WRITE);
00598 
00599       srcMap = ((ubyte *) pipe_buffer_map(screen, srcSurf->buffer,
00600                                           PIPE_BUFFER_USAGE_CPU_READ)
00601                 + srcSurf->offset);
00602       dstMap = ((ubyte *) pipe_buffer_map(screen, dstSurf->buffer,
00603                                           PIPE_BUFFER_USAGE_CPU_WRITE)
00604                 + dstSurf->offset);
00605 
00606       reduce_1d(pt->format,
00607                 srcSurf->width, srcMap,
00608                 dstSurf->width, dstMap);
00609 
00610       pipe_buffer_unmap(screen, srcSurf->buffer);
00611       pipe_buffer_unmap(screen, dstSurf->buffer);
00612 
00613       pipe_surface_reference(&srcSurf, NULL);
00614       pipe_surface_reference(&dstSurf, NULL);
00615    }
00616 }
00617 
00618 
00619 static void
00620 make_2d_mipmap(struct gen_mipmap_state *ctx,
00621                struct pipe_texture *pt,
00622                uint face, uint baseLevel, uint lastLevel)
00623 {
00624    struct pipe_context *pipe = ctx->pipe;
00625    struct pipe_screen *screen = pipe->screen;
00626    const uint zslice = 0;
00627    uint dstLevel;
00628    
00629    assert(pt->block.width == 1);
00630    assert(pt->block.height == 1);
00631 
00632    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
00633       const uint srcLevel = dstLevel - 1;
00634       struct pipe_surface *srcSurf, *dstSurf;
00635       ubyte *srcMap, *dstMap;
00636       
00637       srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice,
00638                                         PIPE_BUFFER_USAGE_CPU_READ);
00639       dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
00640                                         PIPE_BUFFER_USAGE_CPU_WRITE);
00641 
00642       srcMap = ((ubyte *) pipe_buffer_map(screen, srcSurf->buffer,
00643                                           PIPE_BUFFER_USAGE_CPU_READ)
00644                 + srcSurf->offset);
00645       dstMap = ((ubyte *) pipe_buffer_map(screen, dstSurf->buffer,
00646                                           PIPE_BUFFER_USAGE_CPU_WRITE)
00647                 + dstSurf->offset);
00648 
00649       reduce_2d(pt->format,
00650                 srcSurf->width, srcSurf->height,
00651                 srcSurf->stride, srcMap,
00652                 dstSurf->width, dstSurf->height,
00653                 dstSurf->stride, dstMap);
00654 
00655       pipe_buffer_unmap(screen, srcSurf->buffer);
00656       pipe_buffer_unmap(screen, dstSurf->buffer);
00657 
00658       pipe_surface_reference(&srcSurf, NULL);
00659       pipe_surface_reference(&dstSurf, NULL);
00660    }
00661 }
00662 
00663 
00664 static void
00665 make_3d_mipmap(struct gen_mipmap_state *ctx,
00666                struct pipe_texture *pt,
00667                uint face, uint baseLevel, uint lastLevel)
00668 {
00669 }
00670 
00671 
00672 static void
00673 fallback_gen_mipmap(struct gen_mipmap_state *ctx,
00674                     struct pipe_texture *pt,
00675                     uint face, uint baseLevel, uint lastLevel)
00676 {
00677    switch (pt->target) {
00678    case PIPE_TEXTURE_1D:
00679       make_1d_mipmap(ctx, pt, face, baseLevel, lastLevel);
00680       break;
00681    case PIPE_TEXTURE_2D:
00682    case PIPE_TEXTURE_CUBE:
00683       make_2d_mipmap(ctx, pt, face, baseLevel, lastLevel);
00684       break;
00685    case PIPE_TEXTURE_3D:
00686       make_3d_mipmap(ctx, pt, face, baseLevel, lastLevel);
00687       break;
00688    default:
00689       assert(0);
00690    }
00691 }
00692 
00693 
00699 struct gen_mipmap_state *
00700 util_create_gen_mipmap(struct pipe_context *pipe,
00701                        struct cso_context *cso)
00702 {
00703    struct gen_mipmap_state *ctx;
00704    uint i;
00705 
00706    ctx = CALLOC_STRUCT(gen_mipmap_state);
00707    if (!ctx)
00708       return NULL;
00709 
00710    ctx->pipe = pipe;
00711    ctx->cso = cso;
00712 
00713    /* disabled blending/masking */
00714    memset(&ctx->blend, 0, sizeof(ctx->blend));
00715    ctx->blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
00716    ctx->blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
00717    ctx->blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
00718    ctx->blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
00719    ctx->blend.colormask = PIPE_MASK_RGBA;
00720 
00721    /* no-op depth/stencil/alpha */
00722    memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
00723 
00724    /* rasterizer */
00725    memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
00726    ctx->rasterizer.front_winding = PIPE_WINDING_CW;
00727    ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
00728    ctx->rasterizer.bypass_clipping = 1;
00729    /*ctx->rasterizer.bypass_vs = 1;*/
00730    ctx->rasterizer.gl_rasterization_rules = 1;
00731 
00732    /* sampler state */
00733    memset(&ctx->sampler, 0, sizeof(ctx->sampler));
00734    ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
00735    ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
00736    ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
00737    ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
00738    ctx->sampler.normalized_coords = 1;
00739 
00740    /* viewport state (identity, verts are in wincoords) */
00741    ctx->viewport.scale[0] = 1.0;
00742    ctx->viewport.scale[1] = 1.0;
00743    ctx->viewport.scale[2] = 1.0;
00744    ctx->viewport.scale[3] = 1.0;
00745    ctx->viewport.translate[0] = 0.0;
00746    ctx->viewport.translate[1] = 0.0;
00747    ctx->viewport.translate[2] = 0.0;
00748    ctx->viewport.translate[3] = 0.0;
00749 
00750    /* vertex shader */
00751    {
00752       const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
00753                                       TGSI_SEMANTIC_GENERIC };
00754       const uint semantic_indexes[] = { 0, 0 };
00755       ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
00756                                                     semantic_indexes,
00757                                                     &ctx->vert_shader);
00758    }
00759 
00760    /* fragment shader */
00761    ctx->fs = util_make_fragment_tex_shader(pipe, &ctx->frag_shader);
00762 
00763    /* vertex data that doesn't change */
00764    for (i = 0; i < 4; i++) {
00765       ctx->vertices[i][0][2] = 0.0f; /* z */
00766       ctx->vertices[i][0][3] = 1.0f; /* w */
00767       ctx->vertices[i][1][2] = 0.0f; /* r */
00768       ctx->vertices[i][1][3] = 1.0f; /* q */
00769    }
00770 
00771    /* Note: the actual vertex buffer is allocated as needed below */
00772 
00773    return ctx;
00774 }
00775 
00776 
00781 static unsigned
00782 get_next_slot(struct gen_mipmap_state *ctx)
00783 {
00784    const unsigned max_slots = 4096 / sizeof ctx->vertices;
00785 
00786    if (ctx->vbuf_slot >= max_slots) 
00787       util_gen_mipmap_flush( ctx );
00788 
00789    if (!ctx->vbuf) {
00790       ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
00791                                      32,
00792                                      PIPE_BUFFER_USAGE_VERTEX,
00793                                      max_slots * sizeof ctx->vertices);
00794    }
00795    
00796    return ctx->vbuf_slot++ * sizeof ctx->vertices;
00797 }
00798 
00799 
00800 static unsigned
00801 set_vertex_data(struct gen_mipmap_state *ctx, float width, float height)
00802 {
00803    void *buf;
00804    unsigned offset;
00805 
00806    ctx->vertices[0][0][0] = 0.0f; /*x*/
00807    ctx->vertices[0][0][1] = 0.0f; /*y*/
00808    ctx->vertices[0][1][0] = 0.0f; /*s*/
00809    ctx->vertices[0][1][1] = 0.0f; /*t*/
00810 
00811    ctx->vertices[1][0][0] = width;
00812    ctx->vertices[1][0][1] = 0.0f;
00813    ctx->vertices[1][1][0] = 1.0f;
00814    ctx->vertices[1][1][1] = 0.0f;
00815 
00816    ctx->vertices[2][0][0] = width;
00817    ctx->vertices[2][0][1] = height;
00818    ctx->vertices[2][1][0] = 1.0f;
00819    ctx->vertices[2][1][1] = 1.0f;
00820 
00821    ctx->vertices[3][0][0] = 0.0f;
00822    ctx->vertices[3][0][1] = height;
00823    ctx->vertices[3][1][0] = 0.0f;
00824    ctx->vertices[3][1][1] = 1.0f;
00825 
00826    offset = get_next_slot( ctx );
00827 
00828    buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
00829                          PIPE_BUFFER_USAGE_CPU_WRITE);
00830 
00831    memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices));
00832 
00833    pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
00834 
00835    return offset;
00836 }
00837 
00838 
00839 
00843 void
00844 util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
00845 {
00846    struct pipe_context *pipe = ctx->pipe;
00847 
00848    pipe->delete_vs_state(pipe, ctx->vs);
00849    pipe->delete_fs_state(pipe, ctx->fs);
00850 
00851    FREE((void*) ctx->vert_shader.tokens);
00852    FREE((void*) ctx->frag_shader.tokens);
00853 
00854    pipe_buffer_reference(pipe->screen, &ctx->vbuf, NULL);
00855 
00856    FREE(ctx);
00857 }
00858 
00859 
00860 
00861 /* Release vertex buffer at end of frame to avoid synchronous
00862  * rendering.
00863  */
00864 void util_gen_mipmap_flush( struct gen_mipmap_state *ctx )
00865 {
00866    pipe_buffer_reference(ctx->pipe->screen, &ctx->vbuf, NULL);
00867    ctx->vbuf_slot = 0;
00868 } 
00869 
00870 
00882 void
00883 util_gen_mipmap(struct gen_mipmap_state *ctx,
00884                 struct pipe_texture *pt,
00885                 uint face, uint baseLevel, uint lastLevel, uint filter)
00886 {
00887    struct pipe_context *pipe = ctx->pipe;
00888    struct pipe_screen *screen = pipe->screen;
00889    struct pipe_framebuffer_state fb;
00890    uint dstLevel;
00891    uint zslice = 0;
00892    uint offset;
00893 
00894    /* check if we can render in the texture's format */
00895    if (!screen->is_format_supported(screen, pt->format, PIPE_TEXTURE_2D,
00896                                     PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
00897       fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
00898       return;
00899    }
00900 
00901    /* save state (restored below) */
00902    cso_save_blend(ctx->cso);
00903    cso_save_depth_stencil_alpha(ctx->cso);
00904    cso_save_rasterizer(ctx->cso);
00905    cso_save_samplers(ctx->cso);
00906    cso_save_sampler_textures(ctx->cso);
00907    cso_save_framebuffer(ctx->cso);
00908    cso_save_fragment_shader(ctx->cso);
00909    cso_save_vertex_shader(ctx->cso);
00910    cso_save_viewport(ctx->cso);
00911 
00912    /* bind our state */
00913    cso_set_blend(ctx->cso, &ctx->blend);
00914    cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
00915    cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
00916    cso_set_viewport(ctx->cso, &ctx->viewport);
00917 
00918    cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
00919    cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
00920 
00921    /* init framebuffer state */
00922    memset(&fb, 0, sizeof(fb));
00923    fb.num_cbufs = 1;
00924 
00925    /* set min/mag to same filter for faster sw speed */
00926    ctx->sampler.mag_img_filter = filter;
00927    ctx->sampler.min_img_filter = filter;
00928 
00929    /*
00930     * XXX for small mipmap levels, it may be faster to use the software
00931     * fallback path...
00932     */
00933    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
00934       const uint srcLevel = dstLevel - 1;
00935 
00936       struct pipe_surface *surf = 
00937          screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
00938                                  PIPE_BUFFER_USAGE_GPU_WRITE);
00939 
00940       /*
00941        * Setup framebuffer / dest surface
00942        */
00943       fb.cbufs[0] = surf;
00944       fb.width = pt->width[dstLevel];
00945       fb.height = pt->height[dstLevel];
00946       cso_set_framebuffer(ctx->cso, &fb);
00947 
00948       /*
00949        * Setup sampler state
00950        * Note: we should only have to set the min/max LOD clamps to ensure
00951        * we grab texels from the right mipmap level.  But some hardware
00952        * has trouble with min clamping so we also set the lod_bias to
00953        * try to work around that.
00954        */
00955       ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
00956       ctx->sampler.lod_bias = (float) srcLevel;
00957       cso_single_sampler(ctx->cso, 0, &ctx->sampler);
00958       cso_single_sampler_done(ctx->cso);
00959 
00960       cso_set_sampler_textures(ctx->cso, 1, &pt);
00961 
00962       /* quad coords in window coords (bypassing clipping, viewport mapping) */
00963       offset = set_vertex_data(ctx,
00964                                (float) pt->width[dstLevel],
00965                                (float) pt->height[dstLevel]);
00966 
00967       util_draw_vertex_buffer(ctx->pipe, 
00968                               ctx->vbuf,
00969                               offset,
00970                               PIPE_PRIM_TRIANGLE_FAN,
00971                               4,  /* verts */
00972                               2); /* attribs/vert */
00973 
00974       pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
00975 
00976       /* need to signal that the texture has changed _after_ rendering to it */
00977       pipe_surface_reference( &surf, NULL );
00978    }
00979 
00980    /* restore state we changed */
00981    cso_restore_blend(ctx->cso);
00982    cso_restore_depth_stencil_alpha(ctx->cso);
00983    cso_restore_rasterizer(ctx->cso);
00984    cso_restore_samplers(ctx->cso);
00985    cso_restore_sampler_textures(ctx->cso);
00986    cso_restore_framebuffer(ctx->cso);
00987    cso_restore_fragment_shader(ctx->cso);
00988    cso_restore_vertex_shader(ctx->cso);
00989    cso_restore_viewport(ctx->cso);
00990 }

Generated on Tue Sep 29 06:25:15 2009 for Gallium3D by  doxygen 1.5.4