1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2003 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci/** 29bf215546Sopenharmony_ci * State validation for vertex/fragment shaders. 30bf215546Sopenharmony_ci * Note that we have to delay most vertex/fragment shader translation 31bf215546Sopenharmony_ci * until rendering time since the linkage between the vertex outputs and 32bf215546Sopenharmony_ci * fragment inputs can vary depending on the pairing of shaders. 33bf215546Sopenharmony_ci * 34bf215546Sopenharmony_ci * Authors: 35bf215546Sopenharmony_ci * Brian Paul 36bf215546Sopenharmony_ci */ 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci#include "main/mtypes.h" 40bf215546Sopenharmony_ci#include "main/framebuffer.h" 41bf215546Sopenharmony_ci#include "main/state.h" 42bf215546Sopenharmony_ci#include "main/texobj.h" 43bf215546Sopenharmony_ci#include "main/texstate.h" 44bf215546Sopenharmony_ci#include "program/program.h" 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci#include "pipe/p_context.h" 47bf215546Sopenharmony_ci#include "pipe/p_shader_tokens.h" 48bf215546Sopenharmony_ci#include "util/u_simple_shaders.h" 49bf215546Sopenharmony_ci#include "cso_cache/cso_context.h" 50bf215546Sopenharmony_ci#include "util/u_debug.h" 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci#include "st_context.h" 53bf215546Sopenharmony_ci#include "st_atom.h" 54bf215546Sopenharmony_ci#include "st_program.h" 55bf215546Sopenharmony_ci#include "st_texture.h" 56bf215546Sopenharmony_ci#include "st_util.h" 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_cistatic unsigned 60bf215546Sopenharmony_ciget_texture_index(struct gl_context *ctx, const unsigned unit) 61bf215546Sopenharmony_ci{ 62bf215546Sopenharmony_ci struct gl_texture_object *texObj = _mesa_get_tex_unit(ctx, unit)->_Current; 63bf215546Sopenharmony_ci gl_texture_index index; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci if (texObj) { 66bf215546Sopenharmony_ci index = _mesa_tex_target_to_index(ctx, texObj->Target); 67bf215546Sopenharmony_ci } else { 68bf215546Sopenharmony_ci /* fallback for missing texture */ 69bf215546Sopenharmony_ci index = TEXTURE_2D_INDEX; 70bf215546Sopenharmony_ci } 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci return index; 73bf215546Sopenharmony_ci} 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_cistatic void 76bf215546Sopenharmony_ciupdate_gl_clamp(struct st_context *st, struct gl_program *prog, uint32_t *gl_clamp) 77bf215546Sopenharmony_ci{ 78bf215546Sopenharmony_ci if (!st->emulate_gl_clamp) 79bf215546Sopenharmony_ci return; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci gl_clamp[0] = gl_clamp[1] = gl_clamp[2] = 0; 82bf215546Sopenharmony_ci GLbitfield samplers_used = prog->SamplersUsed; 83bf215546Sopenharmony_ci unsigned unit; 84bf215546Sopenharmony_ci /* same as st_atom_sampler.c */ 85bf215546Sopenharmony_ci for (unit = 0; samplers_used; unit++, samplers_used >>= 1) { 86bf215546Sopenharmony_ci unsigned tex_unit = prog->SamplerUnits[unit]; 87bf215546Sopenharmony_ci if (samplers_used & 1 && 88bf215546Sopenharmony_ci (st->ctx->Texture.Unit[tex_unit]._Current->Target != GL_TEXTURE_BUFFER || 89bf215546Sopenharmony_ci st->texture_buffer_sampler)) { 90bf215546Sopenharmony_ci const struct gl_texture_object *texobj; 91bf215546Sopenharmony_ci struct gl_context *ctx = st->ctx; 92bf215546Sopenharmony_ci const struct gl_sampler_object *msamp; 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci texobj = ctx->Texture.Unit[tex_unit]._Current; 95bf215546Sopenharmony_ci assert(texobj); 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci msamp = _mesa_get_samplerobj(ctx, tex_unit); 98bf215546Sopenharmony_ci if (is_wrap_gl_clamp(msamp->Attrib.WrapS)) 99bf215546Sopenharmony_ci gl_clamp[0] |= BITFIELD64_BIT(unit); 100bf215546Sopenharmony_ci if (is_wrap_gl_clamp(msamp->Attrib.WrapT)) 101bf215546Sopenharmony_ci gl_clamp[1] |= BITFIELD64_BIT(unit); 102bf215546Sopenharmony_ci if (is_wrap_gl_clamp(msamp->Attrib.WrapR)) 103bf215546Sopenharmony_ci gl_clamp[2] |= BITFIELD64_BIT(unit); 104bf215546Sopenharmony_ci } 105bf215546Sopenharmony_ci } 106bf215546Sopenharmony_ci} 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci/** 109bf215546Sopenharmony_ci * Update fragment program state/atom. This involves translating the 110bf215546Sopenharmony_ci * Mesa fragment program into a gallium fragment program and binding it. 111bf215546Sopenharmony_ci */ 112bf215546Sopenharmony_civoid 113bf215546Sopenharmony_cist_update_fp( struct st_context *st ) 114bf215546Sopenharmony_ci{ 115bf215546Sopenharmony_ci struct gl_program *fp; 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci assert(st->ctx->FragmentProgram._Current); 118bf215546Sopenharmony_ci fp = st->ctx->FragmentProgram._Current; 119bf215546Sopenharmony_ci assert(fp->Target == GL_FRAGMENT_PROGRAM_ARB); 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci void *shader; 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci if (st->shader_has_one_variant[MESA_SHADER_FRAGMENT] && 124bf215546Sopenharmony_ci !fp->ati_fs && /* ATI_fragment_shader always has multiple variants */ 125bf215546Sopenharmony_ci !fp->ExternalSamplersUsed /* external samplers need variants */) { 126bf215546Sopenharmony_ci shader = fp->variants->driver_shader; 127bf215546Sopenharmony_ci } else { 128bf215546Sopenharmony_ci struct st_fp_variant_key key; 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci /* use memset, not an initializer to be sure all memory is zeroed */ 131bf215546Sopenharmony_ci memset(&key, 0, sizeof(key)); 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci key.st = st->has_shareable_shaders ? NULL : st; 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci key.lower_flatshade = st->lower_flatshade && 136bf215546Sopenharmony_ci st->ctx->Light.ShadeModel == GL_FLAT; 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci /* _NEW_COLOR */ 139bf215546Sopenharmony_ci key.lower_alpha_func = COMPARE_FUNC_ALWAYS; 140bf215546Sopenharmony_ci if (st->lower_alpha_test && _mesa_is_alpha_test_enabled(st->ctx)) 141bf215546Sopenharmony_ci key.lower_alpha_func = st->ctx->Color.AlphaFunc; 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci /* _NEW_LIGHT_STATE | _NEW_PROGRAM */ 144bf215546Sopenharmony_ci key.lower_two_sided_color = st->lower_two_sided_color && 145bf215546Sopenharmony_ci _mesa_vertex_program_two_side_enabled(st->ctx); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci /* _NEW_POINT | _NEW_PROGRAM */ 148bf215546Sopenharmony_ci if (st->lower_texcoord_replace && st->ctx->Point.PointSprite && 149bf215546Sopenharmony_ci st->ctx->Point.CoordReplace) 150bf215546Sopenharmony_ci key.lower_texcoord_replace = st->ctx->Point.CoordReplace; 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci /* gl_driver_flags::NewFragClamp */ 153bf215546Sopenharmony_ci key.clamp_color = st->clamp_frag_color_in_shader && 154bf215546Sopenharmony_ci st->ctx->Color._ClampFragmentColor; 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci /* _NEW_MULTISAMPLE | _NEW_BUFFERS */ 157bf215546Sopenharmony_ci key.persample_shading = 158bf215546Sopenharmony_ci st->force_persample_in_shader && 159bf215546Sopenharmony_ci _mesa_is_multisample_enabled(st->ctx) && 160bf215546Sopenharmony_ci st->ctx->Multisample.SampleShading && 161bf215546Sopenharmony_ci st->ctx->Multisample.MinSampleShadingValue * 162bf215546Sopenharmony_ci _mesa_geometric_samples(st->ctx->DrawBuffer) > 1; 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci if (fp->ati_fs) { 165bf215546Sopenharmony_ci key.fog = st->ctx->Fog._PackedEnabledMode; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci for (unsigned u = 0; u < MAX_NUM_FRAGMENT_REGISTERS_ATI; u++) { 168bf215546Sopenharmony_ci key.texture_index[u] = get_texture_index(st->ctx, u); 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci } 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci key.external = st_get_external_sampler_key(st, fp); 173bf215546Sopenharmony_ci update_gl_clamp(st, st->ctx->FragmentProgram._Current, key.gl_clamp); 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci simple_mtx_lock(&st->ctx->Shared->Mutex); 176bf215546Sopenharmony_ci shader = st_get_fp_variant(st, fp, &key)->base.driver_shader; 177bf215546Sopenharmony_ci simple_mtx_unlock(&st->ctx->Shared->Mutex); 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci _mesa_reference_program(st->ctx, &st->fp, fp); 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci cso_set_fragment_shader_handle(st->cso_context, shader); 183bf215546Sopenharmony_ci} 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci/** 187bf215546Sopenharmony_ci * Update vertex program state/atom. This involves translating the 188bf215546Sopenharmony_ci * Mesa vertex program into a gallium fragment program and binding it. 189bf215546Sopenharmony_ci */ 190bf215546Sopenharmony_civoid 191bf215546Sopenharmony_cist_update_vp( struct st_context *st ) 192bf215546Sopenharmony_ci{ 193bf215546Sopenharmony_ci struct gl_program *vp; 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci /* find active shader and params -- Should be covered by 196bf215546Sopenharmony_ci * ST_NEW_VERTEX_PROGRAM 197bf215546Sopenharmony_ci */ 198bf215546Sopenharmony_ci assert(st->ctx->VertexProgram._Current); 199bf215546Sopenharmony_ci vp = st->ctx->VertexProgram._Current; 200bf215546Sopenharmony_ci assert(vp->Target == GL_VERTEX_PROGRAM_ARB); 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci if (st->shader_has_one_variant[MESA_SHADER_VERTEX] && 203bf215546Sopenharmony_ci !st->vertdata_edgeflags) { 204bf215546Sopenharmony_ci st->vp_variant = st_common_variant(vp->variants); 205bf215546Sopenharmony_ci } else { 206bf215546Sopenharmony_ci struct st_common_variant_key key; 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci memset(&key, 0, sizeof(key)); 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci key.st = st->has_shareable_shaders ? NULL : st; 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci /* When this is true, we will add an extra input to the vertex 213bf215546Sopenharmony_ci * shader translation (for edgeflags), an extra output with 214bf215546Sopenharmony_ci * edgeflag semantics, and extend the vertex shader to pass through 215bf215546Sopenharmony_ci * the input to the output. We'll need to use similar logic to set 216bf215546Sopenharmony_ci * up the extra vertex_element input for edgeflags. 217bf215546Sopenharmony_ci */ 218bf215546Sopenharmony_ci key.passthrough_edgeflags = st->vertdata_edgeflags; 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci key.clamp_color = st->clamp_vert_color_in_shader && 221bf215546Sopenharmony_ci st->ctx->Light._ClampVertexColor && 222bf215546Sopenharmony_ci (vp->info.outputs_written & 223bf215546Sopenharmony_ci (VARYING_SLOT_COL0 | 224bf215546Sopenharmony_ci VARYING_SLOT_COL1 | 225bf215546Sopenharmony_ci VARYING_SLOT_BFC0 | 226bf215546Sopenharmony_ci VARYING_SLOT_BFC1)); 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci if (!st->ctx->GeometryProgram._Current && 229bf215546Sopenharmony_ci !st->ctx->TessEvalProgram._Current) { 230bf215546Sopenharmony_ci /* _NEW_POINT */ 231bf215546Sopenharmony_ci if (st->lower_point_size) 232bf215546Sopenharmony_ci key.export_point_size = !st->ctx->VertexProgram.PointSizeEnabled && !st->ctx->PointSizeIsSet; 233bf215546Sopenharmony_ci /* _NEW_TRANSFORM */ 234bf215546Sopenharmony_ci if (st->lower_ucp && st_user_clip_planes_enabled(st->ctx)) 235bf215546Sopenharmony_ci key.lower_ucp = st->ctx->Transform.ClipPlanesEnabled; 236bf215546Sopenharmony_ci } 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci update_gl_clamp(st, st->ctx->VertexProgram._Current, key.gl_clamp); 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci simple_mtx_lock(&st->ctx->Shared->Mutex); 241bf215546Sopenharmony_ci st->vp_variant = st_get_common_variant(st, vp, &key); 242bf215546Sopenharmony_ci simple_mtx_unlock(&st->ctx->Shared->Mutex); 243bf215546Sopenharmony_ci } 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci _mesa_reference_program(st->ctx, &st->vp, vp); 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci cso_set_vertex_shader_handle(st->cso_context, 248bf215546Sopenharmony_ci st->vp_variant->base.driver_shader); 249bf215546Sopenharmony_ci} 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_cistatic void * 253bf215546Sopenharmony_cist_update_common_program(struct st_context *st, struct gl_program *prog, 254bf215546Sopenharmony_ci unsigned pipe_shader, struct gl_program **dst) 255bf215546Sopenharmony_ci{ 256bf215546Sopenharmony_ci if (!prog) { 257bf215546Sopenharmony_ci _mesa_reference_program(st->ctx, dst, NULL); 258bf215546Sopenharmony_ci return NULL; 259bf215546Sopenharmony_ci } 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci _mesa_reference_program(st->ctx, dst, prog); 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci if (st->shader_has_one_variant[prog->info.stage]) 264bf215546Sopenharmony_ci return prog->variants->driver_shader; 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci struct st_common_variant_key key; 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci /* use memset, not an initializer to be sure all memory is zeroed */ 269bf215546Sopenharmony_ci memset(&key, 0, sizeof(key)); 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci key.st = st->has_shareable_shaders ? NULL : st; 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci if (pipe_shader == PIPE_SHADER_GEOMETRY || 274bf215546Sopenharmony_ci pipe_shader == PIPE_SHADER_TESS_EVAL) { 275bf215546Sopenharmony_ci key.clamp_color = st->clamp_vert_color_in_shader && 276bf215546Sopenharmony_ci st->ctx->Light._ClampVertexColor && 277bf215546Sopenharmony_ci (prog->info.outputs_written & 278bf215546Sopenharmony_ci (VARYING_SLOT_COL0 | 279bf215546Sopenharmony_ci VARYING_SLOT_COL1 | 280bf215546Sopenharmony_ci VARYING_SLOT_BFC0 | 281bf215546Sopenharmony_ci VARYING_SLOT_BFC1)); 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci if (st->lower_ucp && st_user_clip_planes_enabled(st->ctx) && 284bf215546Sopenharmony_ci (pipe_shader == PIPE_SHADER_GEOMETRY || 285bf215546Sopenharmony_ci !st->ctx->GeometryProgram._Current)) 286bf215546Sopenharmony_ci key.lower_ucp = st->ctx->Transform.ClipPlanesEnabled; 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci if (st->lower_point_size) 289bf215546Sopenharmony_ci key.export_point_size = !st->ctx->VertexProgram.PointSizeEnabled && !st->ctx->PointSizeIsSet; 290bf215546Sopenharmony_ci } 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci update_gl_clamp(st, prog, key.gl_clamp); 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci simple_mtx_lock(&st->ctx->Shared->Mutex); 295bf215546Sopenharmony_ci void *result = st_get_common_variant(st, prog, &key)->base.driver_shader; 296bf215546Sopenharmony_ci simple_mtx_unlock(&st->ctx->Shared->Mutex); 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci return result; 299bf215546Sopenharmony_ci} 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_civoid 303bf215546Sopenharmony_cist_update_gp(struct st_context *st) 304bf215546Sopenharmony_ci{ 305bf215546Sopenharmony_ci void *shader = st_update_common_program(st, 306bf215546Sopenharmony_ci st->ctx->GeometryProgram._Current, 307bf215546Sopenharmony_ci PIPE_SHADER_GEOMETRY, &st->gp); 308bf215546Sopenharmony_ci cso_set_geometry_shader_handle(st->cso_context, shader); 309bf215546Sopenharmony_ci} 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_civoid 313bf215546Sopenharmony_cist_update_tcp(struct st_context *st) 314bf215546Sopenharmony_ci{ 315bf215546Sopenharmony_ci void *shader = st_update_common_program(st, 316bf215546Sopenharmony_ci st->ctx->TessCtrlProgram._Current, 317bf215546Sopenharmony_ci PIPE_SHADER_TESS_CTRL, &st->tcp); 318bf215546Sopenharmony_ci cso_set_tessctrl_shader_handle(st->cso_context, shader); 319bf215546Sopenharmony_ci} 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_civoid 323bf215546Sopenharmony_cist_update_tep(struct st_context *st) 324bf215546Sopenharmony_ci{ 325bf215546Sopenharmony_ci void *shader = st_update_common_program(st, 326bf215546Sopenharmony_ci st->ctx->TessEvalProgram._Current, 327bf215546Sopenharmony_ci PIPE_SHADER_TESS_EVAL, &st->tep); 328bf215546Sopenharmony_ci cso_set_tesseval_shader_handle(st->cso_context, shader); 329bf215546Sopenharmony_ci} 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_civoid 333bf215546Sopenharmony_cist_update_cp(struct st_context *st) 334bf215546Sopenharmony_ci{ 335bf215546Sopenharmony_ci void *shader = st_update_common_program(st, 336bf215546Sopenharmony_ci st->ctx->ComputeProgram._Current, 337bf215546Sopenharmony_ci PIPE_SHADER_COMPUTE, &st->cp); 338bf215546Sopenharmony_ci cso_set_compute_shader_handle(st->cso_context, shader); 339bf215546Sopenharmony_ci} 340