st_atom_sampler.c revision 5d5db24a26415cdec4b3d3f2a92bae7112c9f884
1/************************************************************************** 2 * 3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /* 29 * Authors: 30 * Keith Whitwell <keith@tungstengraphics.com> 31 * Brian Paul 32 */ 33 34 35#include "main/macros.h" 36 37#include "st_context.h" 38#include "st_cb_texture.h" 39#include "st_format.h" 40#include "st_atom.h" 41#include "pipe/p_context.h" 42#include "pipe/p_defines.h" 43 44#include "cso_cache/cso_context.h" 45 46 47/** 48 * Convert GLenum texcoord wrap tokens to pipe tokens. 49 */ 50static GLuint 51gl_wrap_xlate(GLenum wrap) 52{ 53 switch (wrap) { 54 case GL_REPEAT: 55 return PIPE_TEX_WRAP_REPEAT; 56 case GL_CLAMP: 57 return PIPE_TEX_WRAP_CLAMP; 58 case GL_CLAMP_TO_EDGE: 59 return PIPE_TEX_WRAP_CLAMP_TO_EDGE; 60 case GL_CLAMP_TO_BORDER: 61 return PIPE_TEX_WRAP_CLAMP_TO_BORDER; 62 case GL_MIRRORED_REPEAT: 63 return PIPE_TEX_WRAP_MIRROR_REPEAT; 64 case GL_MIRROR_CLAMP_EXT: 65 return PIPE_TEX_WRAP_MIRROR_CLAMP; 66 case GL_MIRROR_CLAMP_TO_EDGE_EXT: 67 return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; 68 case GL_MIRROR_CLAMP_TO_BORDER_EXT: 69 return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER; 70 default: 71 assert(0); 72 return 0; 73 } 74} 75 76 77static GLuint 78gl_filter_to_mip_filter(GLenum filter) 79{ 80 switch (filter) { 81 case GL_NEAREST: 82 case GL_LINEAR: 83 return PIPE_TEX_MIPFILTER_NONE; 84 85 case GL_NEAREST_MIPMAP_NEAREST: 86 case GL_LINEAR_MIPMAP_NEAREST: 87 return PIPE_TEX_MIPFILTER_NEAREST; 88 89 case GL_NEAREST_MIPMAP_LINEAR: 90 case GL_LINEAR_MIPMAP_LINEAR: 91 return PIPE_TEX_MIPFILTER_LINEAR; 92 93 default: 94 assert(0); 95 return PIPE_TEX_MIPFILTER_NONE; 96 } 97} 98 99 100static GLuint 101gl_filter_to_img_filter(GLenum filter) 102{ 103 switch (filter) { 104 case GL_NEAREST: 105 case GL_NEAREST_MIPMAP_NEAREST: 106 case GL_NEAREST_MIPMAP_LINEAR: 107 return PIPE_TEX_FILTER_NEAREST; 108 109 case GL_LINEAR: 110 case GL_LINEAR_MIPMAP_NEAREST: 111 case GL_LINEAR_MIPMAP_LINEAR: 112 return PIPE_TEX_FILTER_LINEAR; 113 114 default: 115 assert(0); 116 return PIPE_TEX_FILTER_NEAREST; 117 } 118} 119 120 121static void 122update_samplers(struct st_context *st) 123{ 124 struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current; 125 struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current; 126 const GLbitfield samplersUsed = (vprog->Base.SamplersUsed | 127 fprog->Base.SamplersUsed); 128 GLuint su; 129 130 st->state.num_samplers = 0; 131 132 /* loop over sampler units (aka tex image units) */ 133 for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) { 134 struct pipe_sampler_state *sampler = st->state.samplers + su; 135 136 memset(sampler, 0, sizeof(*sampler)); 137 138 if (samplersUsed & (1 << su)) { 139 struct gl_texture_object *texobj; 140 struct gl_texture_image *teximg; 141 GLuint texUnit; 142 143 if (fprog->Base.SamplersUsed & (1 << su)) 144 texUnit = fprog->Base.SamplerUnits[su]; 145 else 146 texUnit = vprog->Base.SamplerUnits[su]; 147 148 texobj = st->ctx->Texture.Unit[texUnit]._Current; 149 if (!texobj) { 150 texobj = st_get_default_texture(st); 151 } 152 153 teximg = texobj->Image[0][texobj->BaseLevel]; 154 155 sampler->wrap_s = gl_wrap_xlate(texobj->WrapS); 156 sampler->wrap_t = gl_wrap_xlate(texobj->WrapT); 157 sampler->wrap_r = gl_wrap_xlate(texobj->WrapR); 158 159 sampler->min_img_filter = gl_filter_to_img_filter(texobj->MinFilter); 160 sampler->min_mip_filter = gl_filter_to_mip_filter(texobj->MinFilter); 161 sampler->mag_img_filter = gl_filter_to_img_filter(texobj->MagFilter); 162 163 if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB) 164 sampler->normalized_coords = 1; 165 166 sampler->lod_bias = st->ctx->Texture.Unit[texUnit].LodBias + 167 texobj->LodBias; 168 169 sampler->min_lod = texobj->BaseLevel + texobj->MinLod; 170 if (sampler->min_lod < texobj->BaseLevel) 171 sampler->min_lod = texobj->BaseLevel; 172 173 sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel, 174 (texobj->MaxLod + texobj->BaseLevel)); 175 if (sampler->max_lod < sampler->min_lod) { 176 /* The GL spec doesn't seem to specify what to do in this case. 177 * Swap the values. 178 */ 179 float tmp = sampler->max_lod; 180 sampler->max_lod = sampler->min_lod; 181 sampler->min_lod = tmp; 182 assert(sampler->min_lod <= sampler->max_lod); 183 } 184 185 st_translate_color(texobj->BorderColor.f, 186 teximg ? teximg->_BaseFormat : GL_RGBA, 187 sampler->border_color); 188 189 sampler->max_anisotropy = (texobj->MaxAnisotropy == 1.0 ? 0 : (GLuint)texobj->MaxAnisotropy); 190 191 /* only care about ARB_shadow, not SGI shadow */ 192 if (texobj->CompareMode == GL_COMPARE_R_TO_TEXTURE) { 193 sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; 194 sampler->compare_func 195 = st_compare_func_to_pipe(texobj->CompareFunc); 196 } 197 198 st->state.num_samplers = su + 1; 199 200 /*printf("%s su=%u non-null\n", __FUNCTION__, su);*/ 201 cso_single_sampler(st->cso_context, su, sampler); 202 if (su < st->ctx->Const.MaxVertexTextureImageUnits) { 203 cso_single_vertex_sampler(st->cso_context, su, sampler); 204 } 205 } 206 else { 207 /*printf("%s su=%u null\n", __FUNCTION__, su);*/ 208 cso_single_sampler(st->cso_context, su, NULL); 209 if (su < st->ctx->Const.MaxVertexTextureImageUnits) { 210 cso_single_vertex_sampler(st->cso_context, su, NULL); 211 } 212 } 213 } 214 215 cso_single_sampler_done(st->cso_context); 216 if (st->ctx->Const.MaxVertexTextureImageUnits > 0) { 217 cso_single_vertex_sampler_done(st->cso_context); 218 } 219} 220 221 222const struct st_tracked_state st_update_sampler = { 223 "st_update_sampler", /* name */ 224 { /* dirty */ 225 _NEW_TEXTURE, /* mesa */ 226 0, /* st */ 227 }, 228 update_samplers /* update */ 229}; 230