st_atom_sampler.c revision 819e786339fe0eebcd6e8e0ec9e501da548846ba
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#include "main/mtypes.h" 37#include "main/samplerobj.h" 38#include "main/texobj.h" 39 40#include "st_context.h" 41#include "st_cb_texture.h" 42#include "st_format.h" 43#include "st_atom.h" 44#include "st_texture.h" 45#include "pipe/p_context.h" 46#include "pipe/p_defines.h" 47 48#include "cso_cache/cso_context.h" 49 50 51/** 52 * Convert GLenum texcoord wrap tokens to pipe tokens. 53 */ 54static GLuint 55gl_wrap_xlate(GLenum wrap) 56{ 57 switch (wrap) { 58 case GL_REPEAT: 59 return PIPE_TEX_WRAP_REPEAT; 60 case GL_CLAMP: 61 return PIPE_TEX_WRAP_CLAMP; 62 case GL_CLAMP_TO_EDGE: 63 return PIPE_TEX_WRAP_CLAMP_TO_EDGE; 64 case GL_CLAMP_TO_BORDER: 65 return PIPE_TEX_WRAP_CLAMP_TO_BORDER; 66 case GL_MIRRORED_REPEAT: 67 return PIPE_TEX_WRAP_MIRROR_REPEAT; 68 case GL_MIRROR_CLAMP_EXT: 69 return PIPE_TEX_WRAP_MIRROR_CLAMP; 70 case GL_MIRROR_CLAMP_TO_EDGE_EXT: 71 return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; 72 case GL_MIRROR_CLAMP_TO_BORDER_EXT: 73 return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER; 74 default: 75 assert(0); 76 return 0; 77 } 78} 79 80 81static GLuint 82gl_filter_to_mip_filter(GLenum filter) 83{ 84 switch (filter) { 85 case GL_NEAREST: 86 case GL_LINEAR: 87 return PIPE_TEX_MIPFILTER_NONE; 88 89 case GL_NEAREST_MIPMAP_NEAREST: 90 case GL_LINEAR_MIPMAP_NEAREST: 91 return PIPE_TEX_MIPFILTER_NEAREST; 92 93 case GL_NEAREST_MIPMAP_LINEAR: 94 case GL_LINEAR_MIPMAP_LINEAR: 95 return PIPE_TEX_MIPFILTER_LINEAR; 96 97 default: 98 assert(0); 99 return PIPE_TEX_MIPFILTER_NONE; 100 } 101} 102 103 104static GLuint 105gl_filter_to_img_filter(GLenum filter) 106{ 107 switch (filter) { 108 case GL_NEAREST: 109 case GL_NEAREST_MIPMAP_NEAREST: 110 case GL_NEAREST_MIPMAP_LINEAR: 111 return PIPE_TEX_FILTER_NEAREST; 112 113 case GL_LINEAR: 114 case GL_LINEAR_MIPMAP_NEAREST: 115 case GL_LINEAR_MIPMAP_LINEAR: 116 return PIPE_TEX_FILTER_LINEAR; 117 118 default: 119 assert(0); 120 return PIPE_TEX_FILTER_NEAREST; 121 } 122} 123 124 125static void 126convert_sampler(struct st_context *st, 127 struct pipe_sampler_state *sampler, 128 GLuint texUnit) 129{ 130 struct gl_texture_object *texobj; 131 struct gl_context *ctx = st->ctx; 132 struct gl_sampler_object *msamp; 133 134 texobj = ctx->Texture.Unit[texUnit]._Current; 135 if (!texobj) { 136 texobj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX); 137 } 138 139 msamp = _mesa_get_samplerobj(ctx, texUnit); 140 141 memset(sampler, 0, sizeof(*sampler)); 142 sampler->wrap_s = gl_wrap_xlate(msamp->WrapS); 143 sampler->wrap_t = gl_wrap_xlate(msamp->WrapT); 144 sampler->wrap_r = gl_wrap_xlate(msamp->WrapR); 145 146 sampler->min_img_filter = gl_filter_to_img_filter(msamp->MinFilter); 147 sampler->min_mip_filter = gl_filter_to_mip_filter(msamp->MinFilter); 148 sampler->mag_img_filter = gl_filter_to_img_filter(msamp->MagFilter); 149 150 if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB) 151 sampler->normalized_coords = 1; 152 153 sampler->lod_bias = ctx->Texture.Unit[texUnit].LodBias + msamp->LodBias; 154 155 sampler->min_lod = CLAMP(msamp->MinLod, 156 0.0f, 157 (GLfloat) texobj->MaxLevel - texobj->BaseLevel); 158 sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel - texobj->BaseLevel, 159 msamp->MaxLod); 160 if (sampler->max_lod < sampler->min_lod) { 161 /* The GL spec doesn't seem to specify what to do in this case. 162 * Swap the values. 163 */ 164 float tmp = sampler->max_lod; 165 sampler->max_lod = sampler->min_lod; 166 sampler->min_lod = tmp; 167 assert(sampler->min_lod <= sampler->max_lod); 168 } 169 170 if (msamp->BorderColor.ui[0] || 171 msamp->BorderColor.ui[1] || 172 msamp->BorderColor.ui[2] || 173 msamp->BorderColor.ui[3]) { 174 struct gl_texture_image *teximg; 175 176 teximg = texobj->Image[0][texobj->BaseLevel]; 177 178 st_translate_color(msamp->BorderColor.f, 179 teximg ? teximg->_BaseFormat : GL_RGBA, 180 sampler->border_color.f); 181 } 182 183 sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ? 184 0 : (GLuint) msamp->MaxAnisotropy); 185 186 /* only care about ARB_shadow, not SGI shadow */ 187 if (msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) { 188 sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; 189 sampler->compare_func 190 = st_compare_func_to_pipe(msamp->CompareFunc); 191 } 192 193 sampler->seamless_cube_map = 194 ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless; 195} 196 197 198static void 199update_vertex_samplers(struct st_context *st) 200{ 201 const struct gl_context *ctx = st->ctx; 202 struct gl_vertex_program *vprog = ctx->VertexProgram._Current; 203 GLuint su; 204 GLuint samplers_used = vprog->Base.SamplersUsed; 205 const GLuint old_max = st->state.num_vertex_samplers; 206 207 if (st->state.num_vertex_samplers == 0 && vprog->Base.SamplersUsed == 0) 208 return; 209 210 st->state.num_vertex_samplers = 0; 211 212 /* loop over sampler units (aka tex image units) */ 213 for (su = 0; su < ctx->Const.MaxVertexTextureImageUnits; su++, samplers_used >>= 1) { 214 struct pipe_sampler_state *sampler = st->state.vertex_samplers + su; 215 216 if (samplers_used & 1) { 217 GLuint texUnit = vprog->Base.SamplerUnits[su]; 218 219 convert_sampler(st, sampler, texUnit); 220 221 st->state.num_vertex_samplers = su + 1; 222 223 cso_single_sampler(st->cso_context, PIPE_SHADER_VERTEX, su, sampler); 224 } 225 else if (samplers_used != 0 || su < old_max) { 226 cso_single_sampler(st->cso_context, PIPE_SHADER_VERTEX, su, NULL); 227 } else { 228 /* if we've reset all the old samplers and we have no more new ones */ 229 break; 230 } 231 } 232 cso_single_sampler_done(st->cso_context, PIPE_SHADER_VERTEX); 233} 234 235 236static void 237update_fragment_samplers(struct st_context *st) 238{ 239 const struct gl_context *ctx = st->ctx; 240 struct gl_fragment_program *fprog = ctx->FragmentProgram._Current; 241 GLuint su; 242 GLuint samplers_used = fprog->Base.SamplersUsed; 243 const GLuint old_max = st->state.num_fragment_samplers; 244 245 if (st->state.num_fragment_samplers == 0 && fprog->Base.SamplersUsed == 0) 246 return; 247 248 st->state.num_fragment_samplers = 0; 249 250 /* loop over sampler units (aka tex image units) */ 251 for (su = 0; su < ctx->Const.MaxTextureImageUnits; su++, samplers_used >>= 1) { 252 struct pipe_sampler_state *sampler = st->state.fragment_samplers + su; 253 254 if (samplers_used & 1) { 255 GLuint texUnit = fprog->Base.SamplerUnits[su]; 256 257 convert_sampler(st, sampler, texUnit); 258 259 st->state.num_fragment_samplers = su + 1; 260 261 cso_single_sampler(st->cso_context, PIPE_SHADER_FRAGMENT, su, sampler); 262 } 263 else if (samplers_used != 0 || su < old_max) { 264 cso_single_sampler(st->cso_context, PIPE_SHADER_FRAGMENT, su, NULL); 265 } else { 266 /* if we've reset all the old samplers and we have no more new ones */ 267 break; 268 } 269 } 270 271 cso_single_sampler_done(st->cso_context, PIPE_SHADER_FRAGMENT); 272} 273 274 275static void 276update_samplers(struct st_context *st) 277{ 278 update_fragment_samplers(st); 279 update_vertex_samplers(st); 280} 281 282 283const struct st_tracked_state st_update_sampler = { 284 "st_update_sampler", /* name */ 285 { /* dirty */ 286 _NEW_TEXTURE, /* mesa */ 287 0, /* st */ 288 }, 289 update_samplers /* update */ 290}; 291