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 (at) vmware.com> 31 * Brian Paul 32 */ 33 34 35 #include "main/context.h" 36 #include "main/macros.h" 37 #include "main/mtypes.h" 38 #include "main/samplerobj.h" 39 #include "main/teximage.h" 40 #include "main/texobj.h" 41 #include "program/prog_instruction.h" 42 43 #include "st_context.h" 44 #include "st_atom.h" 45 #include "st_sampler_view.h" 46 #include "st_texture.h" 47 #include "st_format.h" 48 #include "st_cb_texture.h" 49 #include "pipe/p_context.h" 50 #include "util/u_format.h" 51 #include "util/u_inlines.h" 52 #include "cso_cache/cso_context.h" 53 54 55 static GLboolean 56 update_single_texture(struct st_context *st, 57 struct pipe_sampler_view **sampler_view, 58 GLuint texUnit, unsigned glsl_version) 59 { 60 struct gl_context *ctx = st->ctx; 61 const struct gl_sampler_object *samp; 62 struct gl_texture_object *texObj; 63 struct st_texture_object *stObj; 64 GLboolean retval; 65 66 samp = _mesa_get_samplerobj(ctx, texUnit); 67 68 texObj = ctx->Texture.Unit[texUnit]._Current; 69 70 if (!texObj) { 71 texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX); 72 samp = &texObj->Sampler; 73 } 74 stObj = st_texture_object(texObj); 75 76 retval = st_finalize_texture(ctx, st->pipe, texObj, 0); 77 if (!retval) { 78 /* out of mem */ 79 return GL_FALSE; 80 } 81 82 /* Check a few pieces of state outside the texture object to see if we 83 * need to force revalidation. 84 */ 85 if (stObj->prev_glsl_version != glsl_version || 86 stObj->prev_sRGBDecode != samp->sRGBDecode) { 87 88 st_texture_release_all_sampler_views(st, stObj); 89 90 stObj->prev_glsl_version = glsl_version; 91 stObj->prev_sRGBDecode = samp->sRGBDecode; 92 } 93 94 *sampler_view = 95 st_get_texture_sampler_view_from_stobj(st, stObj, samp, glsl_version); 96 return GL_TRUE; 97 } 98 99 100 101 static void 102 update_textures(struct st_context *st, 103 gl_shader_stage mesa_shader, 104 const struct gl_program *prog, 105 unsigned max_units, 106 struct pipe_sampler_view **sampler_views, 107 unsigned *num_textures) 108 { 109 const GLuint old_max = *num_textures; 110 GLbitfield samplers_used = prog->SamplersUsed; 111 GLbitfield free_slots = ~prog->SamplersUsed; 112 GLbitfield external_samplers_used = prog->ExternalSamplersUsed; 113 GLuint unit; 114 enum pipe_shader_type shader_stage = st_shader_stage_to_ptarget(mesa_shader); 115 116 if (samplers_used == 0x0 && old_max == 0) 117 return; 118 119 *num_textures = 0; 120 121 /* loop over sampler units (aka tex image units) */ 122 for (unit = 0; unit < max_units; unit++, samplers_used >>= 1) { 123 struct pipe_sampler_view *sampler_view = NULL; 124 125 if (samplers_used & 1) { 126 /* prog->sh.data is NULL if it's ARB_fragment_program */ 127 unsigned glsl_version = prog->sh.data ? prog->sh.data->Version : 0; 128 const GLuint texUnit = prog->SamplerUnits[unit]; 129 GLboolean retval; 130 131 retval = update_single_texture(st, &sampler_view, texUnit, 132 glsl_version); 133 if (retval == GL_FALSE) 134 continue; 135 136 *num_textures = unit + 1; 137 } 138 else if (samplers_used == 0 && unit >= old_max) { 139 /* if we've reset all the old views and we have no more new ones */ 140 break; 141 } 142 143 pipe_sampler_view_reference(&(sampler_views[unit]), sampler_view); 144 } 145 146 /* For any external samplers with multiplaner YUV, stuff the additional 147 * sampler views we need at the end. 148 * 149 * Trying to cache the sampler view in the stObj looks painful, so just 150 * re-create the sampler view for the extra planes each time. Main use 151 * case is video playback (ie. fps games wouldn't be using this) so I 152 * guess no point to try to optimize this feature. 153 */ 154 while (unlikely(external_samplers_used)) { 155 GLuint unit = u_bit_scan(&external_samplers_used); 156 GLuint extra = 0; 157 struct st_texture_object *stObj = 158 st_get_texture_object(st->ctx, prog, unit); 159 struct pipe_sampler_view tmpl; 160 161 if (!stObj) 162 continue; 163 164 /* use original view as template: */ 165 tmpl = *sampler_views[unit]; 166 167 switch (st_get_view_format(stObj)) { 168 case PIPE_FORMAT_NV12: 169 /* we need one additional R8G8 view: */ 170 tmpl.format = PIPE_FORMAT_RG88_UNORM; 171 tmpl.swizzle_g = PIPE_SWIZZLE_Y; /* tmpl from Y plane is R8 */ 172 extra = u_bit_scan(&free_slots); 173 sampler_views[extra] = 174 st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl); 175 break; 176 case PIPE_FORMAT_IYUV: 177 /* we need two additional R8 views: */ 178 tmpl.format = PIPE_FORMAT_R8_UNORM; 179 extra = u_bit_scan(&free_slots); 180 sampler_views[extra] = 181 st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl); 182 extra = u_bit_scan(&free_slots); 183 sampler_views[extra] = 184 st->pipe->create_sampler_view(st->pipe, stObj->pt->next->next, &tmpl); 185 break; 186 default: 187 break; 188 } 189 190 *num_textures = MAX2(*num_textures, extra + 1); 191 } 192 193 cso_set_sampler_views(st->cso_context, 194 shader_stage, 195 *num_textures, 196 sampler_views); 197 } 198 199 200 201 static void 202 update_vertex_textures(struct st_context *st) 203 { 204 const struct gl_context *ctx = st->ctx; 205 206 if (ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits > 0) { 207 update_textures(st, 208 MESA_SHADER_VERTEX, 209 ctx->VertexProgram._Current, 210 ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits, 211 st->state.sampler_views[PIPE_SHADER_VERTEX], 212 &st->state.num_sampler_views[PIPE_SHADER_VERTEX]); 213 } 214 } 215 216 217 static void 218 update_fragment_textures(struct st_context *st) 219 { 220 const struct gl_context *ctx = st->ctx; 221 222 update_textures(st, 223 MESA_SHADER_FRAGMENT, 224 ctx->FragmentProgram._Current, 225 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits, 226 st->state.sampler_views[PIPE_SHADER_FRAGMENT], 227 &st->state.num_sampler_views[PIPE_SHADER_FRAGMENT]); 228 } 229 230 231 static void 232 update_geometry_textures(struct st_context *st) 233 { 234 const struct gl_context *ctx = st->ctx; 235 236 if (ctx->GeometryProgram._Current) { 237 update_textures(st, 238 MESA_SHADER_GEOMETRY, 239 ctx->GeometryProgram._Current, 240 ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits, 241 st->state.sampler_views[PIPE_SHADER_GEOMETRY], 242 &st->state.num_sampler_views[PIPE_SHADER_GEOMETRY]); 243 } 244 } 245 246 247 static void 248 update_tessctrl_textures(struct st_context *st) 249 { 250 const struct gl_context *ctx = st->ctx; 251 252 if (ctx->TessCtrlProgram._Current) { 253 update_textures(st, 254 MESA_SHADER_TESS_CTRL, 255 ctx->TessCtrlProgram._Current, 256 ctx->Const.Program[MESA_SHADER_TESS_CTRL].MaxTextureImageUnits, 257 st->state.sampler_views[PIPE_SHADER_TESS_CTRL], 258 &st->state.num_sampler_views[PIPE_SHADER_TESS_CTRL]); 259 } 260 } 261 262 263 static void 264 update_tesseval_textures(struct st_context *st) 265 { 266 const struct gl_context *ctx = st->ctx; 267 268 if (ctx->TessEvalProgram._Current) { 269 update_textures(st, 270 MESA_SHADER_TESS_EVAL, 271 ctx->TessEvalProgram._Current, 272 ctx->Const.Program[MESA_SHADER_TESS_EVAL].MaxTextureImageUnits, 273 st->state.sampler_views[PIPE_SHADER_TESS_EVAL], 274 &st->state.num_sampler_views[PIPE_SHADER_TESS_EVAL]); 275 } 276 } 277 278 279 static void 280 update_compute_textures(struct st_context *st) 281 { 282 const struct gl_context *ctx = st->ctx; 283 284 if (ctx->ComputeProgram._Current) { 285 update_textures(st, 286 MESA_SHADER_COMPUTE, 287 ctx->ComputeProgram._Current, 288 ctx->Const.Program[MESA_SHADER_COMPUTE].MaxTextureImageUnits, 289 st->state.sampler_views[PIPE_SHADER_COMPUTE], 290 &st->state.num_sampler_views[PIPE_SHADER_COMPUTE]); 291 } 292 } 293 294 295 const struct st_tracked_state st_update_fragment_texture = { 296 update_fragment_textures /* update */ 297 }; 298 299 300 const struct st_tracked_state st_update_vertex_texture = { 301 update_vertex_textures /* update */ 302 }; 303 304 305 const struct st_tracked_state st_update_geometry_texture = { 306 update_geometry_textures /* update */ 307 }; 308 309 310 const struct st_tracked_state st_update_tessctrl_texture = { 311 update_tessctrl_textures /* update */ 312 }; 313 314 315 const struct st_tracked_state st_update_tesseval_texture = { 316 update_tesseval_textures /* update */ 317 }; 318 319 320 const struct st_tracked_state st_update_compute_texture = { 321 update_compute_textures /* update */ 322 }; 323