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