1/************************************************************************** 2 * 3 * Copyright 2007 VMware, Inc. 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 VMWARE 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 <keithw@vmware.com> 31 * Brian Paul 32 */ 33 34 35#include "main/macros.h" 36#include "main/glformats.h" 37#include "main/samplerobj.h" 38#include "main/teximage.h" 39#include "main/texobj.h" 40 41#include "st_context.h" 42#include "st_cb_texture.h" 43#include "st_format.h" 44#include "st_atom.h" 45#include "st_sampler_view.h" 46#include "st_texture.h" 47#include "pipe/p_context.h" 48#include "pipe/p_defines.h" 49 50#include "cso_cache/cso_context.h" 51 52#include "util/format/u_format.h" 53 54 55/** 56 * Convert a gl_sampler_object to a pipe_sampler_state object. 57 */ 58void 59st_convert_sampler(const struct st_context *st, 60 const struct gl_texture_object *texobj, 61 const struct gl_sampler_object *msamp, 62 float tex_unit_lod_bias, 63 struct pipe_sampler_state *sampler, 64 bool seamless_cube_map) 65{ 66 memcpy(sampler, &msamp->Attrib.state, sizeof(*sampler)); 67 68 sampler->seamless_cube_map |= seamless_cube_map; 69 70 if (texobj->_IsIntegerFormat && st->ctx->Const.ForceIntegerTexNearest) { 71 sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST; 72 sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST; 73 } 74 75 if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB || st->lower_rect_tex) 76 sampler->normalized_coords = 1; 77 78 sampler->lod_bias += tex_unit_lod_bias; 79 80 /* Check that only wrap modes using the border color have the first bit 81 * set. 82 */ 83 STATIC_ASSERT(PIPE_TEX_WRAP_CLAMP & 0x1); 84 STATIC_ASSERT(PIPE_TEX_WRAP_CLAMP_TO_BORDER & 0x1); 85 STATIC_ASSERT(PIPE_TEX_WRAP_MIRROR_CLAMP & 0x1); 86 STATIC_ASSERT(PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER & 0x1); 87 STATIC_ASSERT(((PIPE_TEX_WRAP_REPEAT | 88 PIPE_TEX_WRAP_CLAMP_TO_EDGE | 89 PIPE_TEX_WRAP_MIRROR_REPEAT | 90 PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE) & 0x1) == 0); 91 92 /* For non-black borders... */ 93 if (msamp->Attrib.IsBorderColorNonZero && 94 /* This is true if wrap modes are using the border color: */ 95 (sampler->wrap_s | sampler->wrap_t | sampler->wrap_r) & 0x1) { 96 GLenum texBaseFormat = _mesa_base_tex_image(texobj)->_BaseFormat; 97 const GLboolean is_integer = 98 texobj->_IsIntegerFormat || texobj->StencilSampling || 99 texBaseFormat == GL_STENCIL_INDEX; 100 101 if (texobj->StencilSampling) 102 texBaseFormat = GL_STENCIL_INDEX; 103 104 if (st->apply_texture_swizzle_to_border_color) { 105 const struct gl_texture_object *stobj = st_texture_object_const(texobj); 106 /* XXX: clean that up to not use the sampler view at all */ 107 const struct st_sampler_view *sv = st_texture_get_current_sampler_view(st, stobj); 108 109 if (sv) { 110 struct pipe_sampler_view *view = sv->view; 111 union pipe_color_union tmp = sampler->border_color; 112 const unsigned char swz[4] = 113 { 114 view->swizzle_r, 115 view->swizzle_g, 116 view->swizzle_b, 117 view->swizzle_a, 118 }; 119 120 st_translate_color(&tmp, texBaseFormat, is_integer); 121 122 util_format_apply_color_swizzle(&sampler->border_color, 123 &tmp, swz, is_integer); 124 } else { 125 st_translate_color(&sampler->border_color, 126 texBaseFormat, is_integer); 127 } 128 } else { 129 st_translate_color(&sampler->border_color, 130 texBaseFormat, is_integer); 131 if (st->use_format_with_border_color) 132 sampler->border_color_format = st_get_sampler_view_format(st, texobj, 133 msamp->Attrib.sRGBDecode == GL_SKIP_DECODE_EXT); 134 } 135 sampler->border_color_is_integer = is_integer; 136 } 137 138 /* If sampling a depth texture and using shadow comparison */ 139 if (msamp->Attrib.CompareMode == GL_COMPARE_R_TO_TEXTURE) { 140 GLenum texBaseFormat = _mesa_base_tex_image(texobj)->_BaseFormat; 141 142 if (texBaseFormat == GL_DEPTH_COMPONENT || 143 (texBaseFormat == GL_DEPTH_STENCIL && !texobj->StencilSampling)) 144 sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; 145 } 146} 147 148/** 149 * Get a pipe_sampler_state object from a texture unit. 150 */ 151void 152st_convert_sampler_from_unit(const struct st_context *st, 153 struct pipe_sampler_state *sampler, 154 GLuint texUnit) 155{ 156 const struct gl_texture_object *texobj; 157 struct gl_context *ctx = st->ctx; 158 const struct gl_sampler_object *msamp; 159 160 texobj = ctx->Texture.Unit[texUnit]._Current; 161 assert(texobj); 162 163 msamp = _mesa_get_samplerobj(ctx, texUnit); 164 165 st_convert_sampler(st, texobj, msamp, ctx->Texture.Unit[texUnit].LodBiasQuantized, 166 sampler, ctx->Texture.CubeMapSeamless); 167} 168 169 170/** 171 * Update the gallium driver's sampler state for fragment, vertex or 172 * geometry shader stage. 173 */ 174static void 175update_shader_samplers(struct st_context *st, 176 enum pipe_shader_type shader_stage, 177 const struct gl_program *prog, 178 struct pipe_sampler_state *samplers, 179 unsigned *out_num_samplers) 180{ 181 struct gl_context *ctx = st->ctx; 182 GLbitfield samplers_used = prog->SamplersUsed; 183 GLbitfield free_slots = ~prog->SamplersUsed; 184 GLbitfield external_samplers_used = prog->ExternalSamplersUsed; 185 unsigned unit, num_samplers; 186 struct pipe_sampler_state local_samplers[PIPE_MAX_SAMPLERS]; 187 const struct pipe_sampler_state *states[PIPE_MAX_SAMPLERS]; 188 189 if (samplers_used == 0x0) { 190 if (out_num_samplers) 191 *out_num_samplers = 0; 192 return; 193 } 194 195 if (!samplers) 196 samplers = local_samplers; 197 198 num_samplers = util_last_bit(samplers_used); 199 200 /* loop over sampler units (aka tex image units) */ 201 for (unit = 0; samplers_used; unit++, samplers_used >>= 1) { 202 struct pipe_sampler_state *sampler = samplers + unit; 203 unsigned tex_unit = prog->SamplerUnits[unit]; 204 205 /* Don't update the sampler for TBOs. cso_context will not bind sampler 206 * states that are NULL. 207 */ 208 if (samplers_used & 1 && 209 (ctx->Texture.Unit[tex_unit]._Current->Target != GL_TEXTURE_BUFFER || 210 st->texture_buffer_sampler)) { 211 st_convert_sampler_from_unit(st, sampler, tex_unit); 212 states[unit] = sampler; 213 } else { 214 states[unit] = NULL; 215 } 216 } 217 218 /* For any external samplers with multiplaner YUV, stuff the additional 219 * sampler states we need at the end. 220 * 221 * Just re-use the existing sampler-state from the primary slot. 222 */ 223 while (unlikely(external_samplers_used)) { 224 GLuint unit = u_bit_scan(&external_samplers_used); 225 GLuint extra = 0; 226 struct gl_texture_object *stObj = 227 st_get_texture_object(st->ctx, prog, unit); 228 struct pipe_sampler_state *sampler = samplers + unit; 229 230 /* if resource format matches then YUV wasn't lowered */ 231 if (!stObj || st_get_view_format(stObj) == stObj->pt->format) 232 continue; 233 234 switch (st_get_view_format(stObj)) { 235 case PIPE_FORMAT_NV12: 236 if (stObj->pt->format == PIPE_FORMAT_R8_G8B8_420_UNORM) 237 /* no additional views needed */ 238 break; 239 FALLTHROUGH; 240 case PIPE_FORMAT_P010: 241 case PIPE_FORMAT_P012: 242 case PIPE_FORMAT_P016: 243 case PIPE_FORMAT_Y210: 244 case PIPE_FORMAT_Y212: 245 case PIPE_FORMAT_Y216: 246 case PIPE_FORMAT_YUYV: 247 case PIPE_FORMAT_UYVY: 248 if (stObj->pt->format == PIPE_FORMAT_R8G8_R8B8_UNORM || 249 stObj->pt->format == PIPE_FORMAT_G8R8_B8R8_UNORM) { 250 /* no additional views needed */ 251 break; 252 } 253 254 /* we need one additional sampler: */ 255 extra = u_bit_scan(&free_slots); 256 states[extra] = sampler; 257 break; 258 case PIPE_FORMAT_IYUV: 259 /* we need two additional samplers: */ 260 extra = u_bit_scan(&free_slots); 261 states[extra] = sampler; 262 extra = u_bit_scan(&free_slots); 263 states[extra] = sampler; 264 break; 265 default: 266 break; 267 } 268 269 num_samplers = MAX2(num_samplers, extra + 1); 270 } 271 272 cso_set_samplers(st->cso_context, shader_stage, num_samplers, states); 273 274 if (out_num_samplers) 275 *out_num_samplers = num_samplers; 276} 277 278 279void 280st_update_vertex_samplers(struct st_context *st) 281{ 282 const struct gl_context *ctx = st->ctx; 283 284 update_shader_samplers(st, 285 PIPE_SHADER_VERTEX, 286 ctx->VertexProgram._Current, 287 st->state.vert_samplers, 288 &st->state.num_vert_samplers); 289} 290 291 292void 293st_update_tessctrl_samplers(struct st_context *st) 294{ 295 const struct gl_context *ctx = st->ctx; 296 297 if (ctx->TessCtrlProgram._Current) { 298 update_shader_samplers(st, 299 PIPE_SHADER_TESS_CTRL, 300 ctx->TessCtrlProgram._Current, NULL, NULL); 301 } 302} 303 304 305void 306st_update_tesseval_samplers(struct st_context *st) 307{ 308 const struct gl_context *ctx = st->ctx; 309 310 if (ctx->TessEvalProgram._Current) { 311 update_shader_samplers(st, 312 PIPE_SHADER_TESS_EVAL, 313 ctx->TessEvalProgram._Current, NULL, NULL); 314 } 315} 316 317 318void 319st_update_geometry_samplers(struct st_context *st) 320{ 321 const struct gl_context *ctx = st->ctx; 322 323 if (ctx->GeometryProgram._Current) { 324 update_shader_samplers(st, 325 PIPE_SHADER_GEOMETRY, 326 ctx->GeometryProgram._Current, NULL, NULL); 327 } 328} 329 330 331void 332st_update_fragment_samplers(struct st_context *st) 333{ 334 const struct gl_context *ctx = st->ctx; 335 336 update_shader_samplers(st, 337 PIPE_SHADER_FRAGMENT, 338 ctx->FragmentProgram._Current, 339 st->state.frag_samplers, 340 &st->state.num_frag_samplers); 341} 342 343 344void 345st_update_compute_samplers(struct st_context *st) 346{ 347 const struct gl_context *ctx = st->ctx; 348 349 if (ctx->ComputeProgram._Current) { 350 update_shader_samplers(st, 351 PIPE_SHADER_COMPUTE, 352 ctx->ComputeProgram._Current, NULL, NULL); 353 } 354} 355