/** * Translate a geometry program to create a new variant. */ static struct st_gp_variant * st_translate_geometry_program(struct st_context *st, struct st_geometry_program *stgp, const struct st_gp_variant_key *key) { GLuint inputMapping[VARYING_SLOT_MAX]; GLuint outputMapping[VARYING_SLOT_MAX]; struct pipe_context *pipe = st->pipe; GLuint attr; uint gs_num_inputs = 0; ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; uint gs_num_outputs = 0; GLint i; struct ureg_program *ureg; struct pipe_shader_state state = {0}; struct st_gp_variant *gpv; gpv = CALLOC_STRUCT(st_gp_variant); if (!gpv) return NULL; ureg = ureg_create(TGSI_PROCESSOR_GEOMETRY); if (ureg == NULL) { free(gpv); return NULL; } memset(inputMapping, 0, sizeof(inputMapping)); memset(outputMapping, 0, sizeof(outputMapping)); /* * Convert Mesa program inputs to TGSI input register semantics. */ for (attr = 0; attr < VARYING_SLOT_MAX; attr++) { if ((stgp->Base.Base.InputsRead & BITFIELD64_BIT(attr)) != 0) { const GLuint slot = gs_num_inputs++; inputMapping[attr] = slot; switch (attr) { case VARYING_SLOT_PRIMITIVE_ID: input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; input_semantic_index[slot] = 0; break; case VARYING_SLOT_POS: input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; input_semantic_index[slot] = 0; break; case VARYING_SLOT_COL0: input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; input_semantic_index[slot] = 0; break; case VARYING_SLOT_COL1: input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; input_semantic_index[slot] = 1; break; case VARYING_SLOT_FOGC: input_semantic_name[slot] = TGSI_SEMANTIC_FOG; input_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_VERTEX: input_semantic_name[slot] = TGSI_SEMANTIC_CLIPVERTEX; input_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST0: input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; input_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST1: input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; input_semantic_index[slot] = 1; break; case VARYING_SLOT_PSIZ: input_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; input_semantic_index[slot] = 0; break; case VARYING_SLOT_TEX0: case VARYING_SLOT_TEX1: case VARYING_SLOT_TEX2: case VARYING_SLOT_TEX3: case VARYING_SLOT_TEX4: case VARYING_SLOT_TEX5: case VARYING_SLOT_TEX6: case VARYING_SLOT_TEX7: if (st->needs_texcoord_semantic) { input_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD; input_semantic_index[slot] = attr - VARYING_SLOT_TEX0; break; } /* fall through */ case VARYING_SLOT_VAR0: default: assert(attr >= VARYING_SLOT_VAR0 && attr < VARYING_SLOT_MAX); input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; input_semantic_index[slot] = st_get_generic_varying_index(st, attr); break; } } } /* initialize output semantics to defaults */ for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; gs_output_semantic_index[i] = 0; } /* * Determine number of outputs, the (default) output register * mapping and the semantic information for each output. */ for (attr = 0; attr < VARYING_SLOT_MAX; attr++) { if (stgp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) { GLuint slot = gs_num_outputs++; outputMapping[attr] = slot; switch (attr) { case VARYING_SLOT_POS: assert(slot == 0); gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_COL0: gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_COL1: gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; gs_output_semantic_index[slot] = 1; break; case VARYING_SLOT_BFC0: gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_BFC1: gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; gs_output_semantic_index[slot] = 1; break; case VARYING_SLOT_FOGC: gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_PSIZ: gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_VERTEX: gs_output_semantic_name[slot] = TGSI_SEMANTIC_CLIPVERTEX; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST0: gs_output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST1: gs_output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; gs_output_semantic_index[slot] = 1; break; case VARYING_SLOT_LAYER: gs_output_semantic_name[slot] = TGSI_SEMANTIC_LAYER; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_PRIMITIVE_ID: gs_output_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_VIEWPORT: gs_output_semantic_name[slot] = TGSI_SEMANTIC_VIEWPORT_INDEX; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_TEX0: case VARYING_SLOT_TEX1: case VARYING_SLOT_TEX2: case VARYING_SLOT_TEX3: case VARYING_SLOT_TEX4: case VARYING_SLOT_TEX5: case VARYING_SLOT_TEX6: case VARYING_SLOT_TEX7: if (st->needs_texcoord_semantic) { gs_output_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD; gs_output_semantic_index[slot] = attr - VARYING_SLOT_TEX0; break; } /* fall through */ case VARYING_SLOT_VAR0: default: assert(slot < ARRAY_SIZE(gs_output_semantic_name)); assert(attr >= VARYING_SLOT_VAR0); gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; gs_output_semantic_index[slot] = st_get_generic_varying_index(st, attr); break; } } } ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, stgp->Base.InputType); ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, stgp->Base.OutputType); ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, stgp->Base.VerticesOut); ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS, stgp->Base.Invocations); st_translate_program(st->ctx, TGSI_PROCESSOR_GEOMETRY, ureg, stgp->glsl_to_tgsi, &stgp->Base.Base, /* inputs */ gs_num_inputs, inputMapping, input_semantic_name, input_semantic_index, NULL, NULL, /* outputs */ gs_num_outputs, outputMapping, gs_output_semantic_name, gs_output_semantic_index, FALSE, FALSE); state.tokens = ureg_get_tokens(ureg, NULL); ureg_destroy(ureg); st_translate_stream_output_info(stgp->glsl_to_tgsi, outputMapping, &state.stream_output); if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { _mesa_print_program(&stgp->Base.Base); debug_printf("\n"); } if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump(state.tokens, 0); debug_printf("\n"); } /* fill in new variant */ gpv->driver_shader = pipe->create_gs_state(pipe, &state); gpv->key = *key; ureg_free_tokens(state.tokens); return gpv; }
/** * Translate a Mesa fragment shader into a TGSI shader using extra info in * the key. * \return new fragment program variant */ static struct st_fp_variant * st_translate_fragment_program(struct st_context *st, struct st_fragment_program *stfp, const struct st_fp_variant_key *key) { struct pipe_context *pipe = st->pipe; struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant); GLboolean deleteFP = GL_FALSE; GLuint outputMapping[FRAG_RESULT_MAX]; GLuint inputMapping[VARYING_SLOT_MAX]; GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */ GLuint interpLocation[PIPE_MAX_SHADER_INPUTS]; GLuint attr; GLbitfield64 inputsRead; struct ureg_program *ureg; GLboolean write_all = GL_FALSE; ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; uint fs_num_inputs = 0; ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; uint fs_num_outputs = 0; if (!variant) return NULL; assert(!(key->bitmap && key->drawpixels)); if (key->bitmap) { /* glBitmap drawing */ struct gl_fragment_program *fp; /* we free this temp program below */ st_make_bitmap_fragment_program(st, &stfp->Base, &fp, &variant->bitmap_sampler); variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); stfp = st_fragment_program(fp); deleteFP = GL_TRUE; } else if (key->drawpixels) { /* glDrawPixels drawing */ struct gl_fragment_program *fp; /* we free this temp program below */ if (key->drawpixels_z || key->drawpixels_stencil) { fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z, key->drawpixels_stencil); } else { /* RGBA */ st_make_drawpix_fragment_program(st, &stfp->Base, &fp); variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); deleteFP = GL_TRUE; } stfp = st_fragment_program(fp); } if (!stfp->glsl_to_tgsi) _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); /* * Convert Mesa program inputs to TGSI input register semantics. */ inputsRead = stfp->Base.Base.InputsRead; for (attr = 0; attr < VARYING_SLOT_MAX; attr++) { if ((inputsRead & BITFIELD64_BIT(attr)) != 0) { const GLuint slot = fs_num_inputs++; inputMapping[attr] = slot; if (stfp->Base.IsCentroid & BITFIELD64_BIT(attr)) interpLocation[slot] = TGSI_INTERPOLATE_LOC_CENTROID; else if (stfp->Base.IsSample & BITFIELD64_BIT(attr)) interpLocation[slot] = TGSI_INTERPOLATE_LOC_SAMPLE; else interpLocation[slot] = TGSI_INTERPOLATE_LOC_CENTER; if (key->persample_shading) interpLocation[slot] = TGSI_INTERPOLATE_LOC_SAMPLE; switch (attr) { case VARYING_SLOT_POS: input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; case VARYING_SLOT_COL0: input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; input_semantic_index[slot] = 0; interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr], TRUE); break; case VARYING_SLOT_COL1: input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; input_semantic_index[slot] = 1; interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr], TRUE); break; case VARYING_SLOT_FOGC: input_semantic_name[slot] = TGSI_SEMANTIC_FOG; input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; case VARYING_SLOT_FACE: input_semantic_name[slot] = TGSI_SEMANTIC_FACE; input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; break; case VARYING_SLOT_PRIMITIVE_ID: input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; break; case VARYING_SLOT_LAYER: input_semantic_name[slot] = TGSI_SEMANTIC_LAYER; input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; break; case VARYING_SLOT_VIEWPORT: input_semantic_name[slot] = TGSI_SEMANTIC_VIEWPORT_INDEX; input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; break; case VARYING_SLOT_CLIP_DIST0: input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; case VARYING_SLOT_CLIP_DIST1: input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; input_semantic_index[slot] = 1; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; /* In most cases, there is nothing special about these * inputs, so adopt a convention to use the generic * semantic name and the mesa VARYING_SLOT_ number as the * index. * * All that is required is that the vertex shader labels * its own outputs similarly, and that the vertex shader * generates at least every output required by the * fragment shader plus fixed-function hardware (such as * BFC). * * However, some drivers may need us to identify the PNTC and TEXi * varyings if, for example, their capability to replace them with * sprite coordinates is limited. */ case VARYING_SLOT_PNTC: if (st->needs_texcoord_semantic) { input_semantic_name[slot] = TGSI_SEMANTIC_PCOORD; input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; } /* fall through */ case VARYING_SLOT_TEX0: case VARYING_SLOT_TEX1: case VARYING_SLOT_TEX2: case VARYING_SLOT_TEX3: case VARYING_SLOT_TEX4: case VARYING_SLOT_TEX5: case VARYING_SLOT_TEX6: case VARYING_SLOT_TEX7: if (st->needs_texcoord_semantic) { input_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD; input_semantic_index[slot] = attr - VARYING_SLOT_TEX0; interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr], FALSE); break; } /* fall through */ case VARYING_SLOT_VAR0: default: /* Semantic indices should be zero-based because drivers may choose * to assign a fixed slot determined by that index. * This is useful because ARB_separate_shader_objects uses location * qualifiers for linkage, and if the semantic index corresponds to * these locations, linkage passes in the driver become unecessary. * * If needs_texcoord_semantic is true, no semantic indices will be * consumed for the TEXi varyings, and we can base the locations of * the user varyings on VAR0. Otherwise, we use TEX0 as base index. */ assert(attr >= VARYING_SLOT_TEX0); input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; input_semantic_index[slot] = st_get_generic_varying_index(st, attr); if (attr == VARYING_SLOT_PNTC) interpMode[slot] = TGSI_INTERPOLATE_LINEAR; else interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr], FALSE); break; } } else { inputMapping[attr] = -1; } } /* * Semantics and mapping for outputs */ { uint numColors = 0; GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten; /* if z is written, emit that first */ if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION; fs_output_semantic_index[fs_num_outputs] = 0; outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs; fs_num_outputs++; outputsWritten &= ~(1 << FRAG_RESULT_DEPTH); } if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) { fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL; fs_output_semantic_index[fs_num_outputs] = 0; outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs; fs_num_outputs++; outputsWritten &= ~(1 << FRAG_RESULT_STENCIL); } if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK)) { fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_SAMPLEMASK; fs_output_semantic_index[fs_num_outputs] = 0; outputMapping[FRAG_RESULT_SAMPLE_MASK] = fs_num_outputs; fs_num_outputs++; outputsWritten &= ~(1 << FRAG_RESULT_SAMPLE_MASK); } /* handle remaining outputs (color) */ for (attr = 0; attr < FRAG_RESULT_MAX; attr++) { if (outputsWritten & BITFIELD64_BIT(attr)) { switch (attr) { case FRAG_RESULT_DEPTH: case FRAG_RESULT_STENCIL: case FRAG_RESULT_SAMPLE_MASK: /* handled above */ assert(0); break; case FRAG_RESULT_COLOR: write_all = GL_TRUE; /* fallthrough */ default: assert(attr == FRAG_RESULT_COLOR || (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX)); fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR; fs_output_semantic_index[fs_num_outputs] = numColors; outputMapping[attr] = fs_num_outputs; numColors++; break; } fs_num_outputs++; } } } ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); if (ureg == NULL) { free(variant); return NULL; } if (ST_DEBUG & DEBUG_MESA) { _mesa_print_program(&stfp->Base.Base); _mesa_print_program_parameters(st->ctx, &stfp->Base.Base); debug_printf("\n"); } if (write_all == GL_TRUE) ureg_property(ureg, TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS, 1); if (stfp->Base.FragDepthLayout != FRAG_DEPTH_LAYOUT_NONE) { switch (stfp->Base.FragDepthLayout) { case FRAG_DEPTH_LAYOUT_ANY: ureg_property(ureg, TGSI_PROPERTY_FS_DEPTH_LAYOUT, TGSI_FS_DEPTH_LAYOUT_ANY); break; case FRAG_DEPTH_LAYOUT_GREATER: ureg_property(ureg, TGSI_PROPERTY_FS_DEPTH_LAYOUT, TGSI_FS_DEPTH_LAYOUT_GREATER); break; case FRAG_DEPTH_LAYOUT_LESS: ureg_property(ureg, TGSI_PROPERTY_FS_DEPTH_LAYOUT, TGSI_FS_DEPTH_LAYOUT_LESS); break; case FRAG_DEPTH_LAYOUT_UNCHANGED: ureg_property(ureg, TGSI_PROPERTY_FS_DEPTH_LAYOUT, TGSI_FS_DEPTH_LAYOUT_UNCHANGED); break; default: assert(0); } } if (stfp->glsl_to_tgsi) st_translate_program(st->ctx, TGSI_PROCESSOR_FRAGMENT, ureg, stfp->glsl_to_tgsi, &stfp->Base.Base, /* inputs */ fs_num_inputs, inputMapping, input_semantic_name, input_semantic_index, interpMode, interpLocation, /* outputs */ fs_num_outputs, outputMapping, fs_output_semantic_name, fs_output_semantic_index, FALSE, key->clamp_color ); else st_translate_mesa_program(st->ctx, TGSI_PROCESSOR_FRAGMENT, ureg, &stfp->Base.Base, /* inputs */ fs_num_inputs, inputMapping, input_semantic_name, input_semantic_index, interpMode, /* outputs */ fs_num_outputs, outputMapping, fs_output_semantic_name, fs_output_semantic_index, FALSE, key->clamp_color); variant->tgsi.tokens = ureg_get_tokens( ureg, NULL ); ureg_destroy( ureg ); if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump(variant->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/); debug_printf("\n"); } /* fill in variant */ variant->driver_shader = pipe->create_fs_state(pipe, &variant->tgsi); variant->key = *key; if (deleteFP) { /* Free the temporary program made above */ struct gl_fragment_program *fp = &stfp->Base; _mesa_reference_fragprog(st->ctx, &fp, NULL); } return variant; }
static void update_raster_state( struct st_context *st ) { struct gl_context *ctx = st->ctx; struct pipe_rasterizer_state *raster = &st->state.rasterizer; const struct gl_vertex_program *vertProg = ctx->VertexProgram._Current; const struct gl_fragment_program *fragProg = ctx->FragmentProgram._Current; uint i; memset(raster, 0, sizeof(*raster)); /* _NEW_POLYGON, _NEW_BUFFERS */ { raster->front_ccw = (ctx->Polygon.FrontFace == GL_CCW); /* _NEW_TRANSFORM */ if (ctx->Transform.ClipOrigin == GL_UPPER_LEFT) { raster->front_ccw ^= 1; } /* * Gallium's surfaces are Y=0=TOP orientation. OpenGL is the * opposite. Window system surfaces are Y=0=TOP. Mesa's FBOs * must match OpenGL conventions so FBOs use Y=0=BOTTOM. In that * case, we must invert Y and flip the notion of front vs. back. */ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) { /* Drawing to an FBO. The viewport will be inverted. */ raster->front_ccw ^= 1; } } /* _NEW_LIGHT */ raster->flatshade = ctx->Light.ShadeModel == GL_FLAT; raster->flatshade_first = ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION_EXT; /* _NEW_LIGHT | _NEW_PROGRAM */ raster->light_twoside = ctx->VertexProgram._TwoSideEnabled; /*_NEW_LIGHT | _NEW_BUFFERS */ raster->clamp_vertex_color = !st->clamp_vert_color_in_shader && ctx->Light._ClampVertexColor; /* _NEW_POLYGON */ if (ctx->Polygon.CullFlag) { switch (ctx->Polygon.CullFaceMode) { case GL_FRONT: raster->cull_face = PIPE_FACE_FRONT; break; case GL_BACK: raster->cull_face = PIPE_FACE_BACK; break; case GL_FRONT_AND_BACK: raster->cull_face = PIPE_FACE_FRONT_AND_BACK; break; } } else { raster->cull_face = PIPE_FACE_NONE; } /* _NEW_POLYGON */ { if (ST_DEBUG & DEBUG_WIREFRAME) { raster->fill_front = PIPE_POLYGON_MODE_LINE; raster->fill_back = PIPE_POLYGON_MODE_LINE; } else { raster->fill_front = translate_fill( ctx->Polygon.FrontMode ); raster->fill_back = translate_fill( ctx->Polygon.BackMode ); } /* Simplify when culling is active: */ if (raster->cull_face & PIPE_FACE_FRONT) { raster->fill_front = raster->fill_back; } if (raster->cull_face & PIPE_FACE_BACK) { raster->fill_back = raster->fill_front; } } /* _NEW_POLYGON */ if (ctx->Polygon.OffsetPoint || ctx->Polygon.OffsetLine || ctx->Polygon.OffsetFill) { raster->offset_point = ctx->Polygon.OffsetPoint; raster->offset_line = ctx->Polygon.OffsetLine; raster->offset_tri = ctx->Polygon.OffsetFill; raster->offset_units = ctx->Polygon.OffsetUnits; raster->offset_scale = ctx->Polygon.OffsetFactor; raster->offset_clamp = ctx->Polygon.OffsetClamp; } raster->poly_smooth = ctx->Polygon.SmoothFlag; raster->poly_stipple_enable = ctx->Polygon.StippleFlag; /* _NEW_POINT */ raster->point_size = ctx->Point.Size; raster->point_smooth = !ctx->Point.PointSprite && ctx->Point.SmoothFlag; /* _NEW_POINT | _NEW_PROGRAM */ if (ctx->Point.PointSprite) { /* origin */ if ((ctx->Point.SpriteOrigin == GL_UPPER_LEFT) ^ (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM)) raster->sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT; else raster->sprite_coord_mode = PIPE_SPRITE_COORD_LOWER_LEFT; /* Coord replacement flags. If bit 'k' is set that means * that we need to replace GENERIC[k] attrib with an automatically * computed texture coord. */ for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) { if (ctx->Point.CoordReplace[i]) { raster->sprite_coord_enable |= 1 << i; } } if (!st->needs_texcoord_semantic && fragProg->Base.InputsRead & VARYING_BIT_PNTC) { raster->sprite_coord_enable |= 1 << st_get_generic_varying_index(st, VARYING_SLOT_PNTC); } raster->point_quad_rasterization = 1; } /* ST_NEW_VERTEX_PROGRAM */ if (vertProg) { if (vertProg->Base.Id == 0) { if (vertProg->Base.OutputsWritten & BITFIELD64_BIT(VARYING_SLOT_PSIZ)) { /* generated program which emits point size */ raster->point_size_per_vertex = TRUE; } } else if (ctx->VertexProgram.PointSizeEnabled) { /* user-defined program and GL_VERTEX_PROGRAM_POINT_SIZE set */ raster->point_size_per_vertex = ctx->VertexProgram.PointSizeEnabled; } } if (!raster->point_size_per_vertex) { /* clamp size now */ raster->point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize); } /* _NEW_LINE */ raster->line_smooth = ctx->Line.SmoothFlag; if (ctx->Line.SmoothFlag) { raster->line_width = CLAMP(ctx->Line.Width, ctx->Const.MinLineWidthAA, ctx->Const.MaxLineWidthAA); } else { raster->line_width = CLAMP(ctx->Line.Width, ctx->Const.MinLineWidth, ctx->Const.MaxLineWidth); } raster->line_stipple_enable = ctx->Line.StippleFlag; raster->line_stipple_pattern = ctx->Line.StipplePattern; /* GL stipple factor is in [1,256], remap to [0, 255] here */ raster->line_stipple_factor = ctx->Line.StippleFactor - 1; /* _NEW_MULTISAMPLE */ raster->multisample = ctx->Multisample._Enabled; /* _NEW_MULTISAMPLE | _NEW_BUFFERS */ raster->force_persample_interp = !st->force_persample_in_shader && ctx->Multisample._Enabled && ctx->Multisample.SampleShading && ctx->Multisample.MinSampleShadingValue * ctx->DrawBuffer->Visual.samples > 1; /* _NEW_SCISSOR */ raster->scissor = ctx->Scissor.EnableFlags; /* _NEW_FRAG_CLAMP */ raster->clamp_fragment_color = !st->clamp_frag_color_in_shader && ctx->Color._ClampFragmentColor; raster->half_pixel_center = 1; if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) raster->bottom_edge_rule = 1; /* _NEW_TRANSFORM */ if (ctx->Transform.ClipOrigin == GL_UPPER_LEFT) raster->bottom_edge_rule ^= 1; /* ST_NEW_RASTERIZER */ raster->rasterizer_discard = ctx->RasterDiscard; if (st->edgeflag_culls_prims) { /* All edge flags are FALSE. Cull the affected faces. */ if (raster->fill_front != PIPE_POLYGON_MODE_FILL) raster->cull_face |= PIPE_FACE_FRONT; if (raster->fill_back != PIPE_POLYGON_MODE_FILL) raster->cull_face |= PIPE_FACE_BACK; } /* _NEW_TRANSFORM */ raster->depth_clip = !ctx->Transform.DepthClamp; raster->clip_plane_enable = ctx->Transform.ClipPlanesEnabled; raster->clip_halfz = (ctx->Transform.ClipDepthMode == GL_ZERO_TO_ONE); cso_set_rasterizer(st->cso_context, raster); }
/** * Translate a Mesa vertex shader into a TGSI shader. * \param outputMapping to map vertex program output registers (VARYING_SLOT_x) * to TGSI output slots * \param tokensOut destination for TGSI tokens * \return pointer to cached pipe_shader object. */ void st_prepare_vertex_program(struct gl_context *ctx, struct st_vertex_program *stvp) { struct st_context *st = st_context(ctx); GLuint attr; stvp->num_inputs = 0; stvp->num_outputs = 0; if (stvp->Base.IsPositionInvariant) _mesa_insert_mvp_code(ctx, &stvp->Base); /* * Determine number of inputs, the mappings between VERT_ATTRIB_x * and TGSI generic input indexes, plus input attrib semantic info. */ for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { if ((stvp->Base.Base.InputsRead & BITFIELD64_BIT(attr)) != 0) { stvp->input_to_index[attr] = stvp->num_inputs; stvp->index_to_input[stvp->num_inputs] = attr; stvp->num_inputs++; if ((stvp->Base.Base.DoubleInputsRead & BITFIELD64_BIT(attr)) != 0) { /* add placeholder for second part of a double attribute */ stvp->index_to_input[stvp->num_inputs] = ST_DOUBLE_ATTRIB_PLACEHOLDER; stvp->num_inputs++; } } } /* bit of a hack, presetup potentially unused edgeflag input */ stvp->input_to_index[VERT_ATTRIB_EDGEFLAG] = stvp->num_inputs; stvp->index_to_input[stvp->num_inputs] = VERT_ATTRIB_EDGEFLAG; /* Compute mapping of vertex program outputs to slots. */ for (attr = 0; attr < VARYING_SLOT_MAX; attr++) { if ((stvp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) == 0) { stvp->result_to_output[attr] = ~0; } else { unsigned slot = stvp->num_outputs++; stvp->result_to_output[attr] = slot; switch (attr) { case VARYING_SLOT_POS: stvp->output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; stvp->output_semantic_index[slot] = 0; break; case VARYING_SLOT_COL0: stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stvp->output_semantic_index[slot] = 0; break; case VARYING_SLOT_COL1: stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stvp->output_semantic_index[slot] = 1; break; case VARYING_SLOT_BFC0: stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; stvp->output_semantic_index[slot] = 0; break; case VARYING_SLOT_BFC1: stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; stvp->output_semantic_index[slot] = 1; break; case VARYING_SLOT_FOGC: stvp->output_semantic_name[slot] = TGSI_SEMANTIC_FOG; stvp->output_semantic_index[slot] = 0; break; case VARYING_SLOT_PSIZ: stvp->output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; stvp->output_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST0: stvp->output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; stvp->output_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST1: stvp->output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; stvp->output_semantic_index[slot] = 1; break; case VARYING_SLOT_EDGE: assert(0); break; case VARYING_SLOT_CLIP_VERTEX: stvp->output_semantic_name[slot] = TGSI_SEMANTIC_CLIPVERTEX; stvp->output_semantic_index[slot] = 0; break; case VARYING_SLOT_LAYER: stvp->output_semantic_name[slot] = TGSI_SEMANTIC_LAYER; stvp->output_semantic_index[slot] = 0; break; case VARYING_SLOT_VIEWPORT: stvp->output_semantic_name[slot] = TGSI_SEMANTIC_VIEWPORT_INDEX; stvp->output_semantic_index[slot] = 0; break; case VARYING_SLOT_TEX0: case VARYING_SLOT_TEX1: case VARYING_SLOT_TEX2: case VARYING_SLOT_TEX3: case VARYING_SLOT_TEX4: case VARYING_SLOT_TEX5: case VARYING_SLOT_TEX6: case VARYING_SLOT_TEX7: if (st->needs_texcoord_semantic) { stvp->output_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD; stvp->output_semantic_index[slot] = attr - VARYING_SLOT_TEX0; break; } /* fall through */ case VARYING_SLOT_VAR0: default: assert(attr < VARYING_SLOT_MAX); stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stvp->output_semantic_index[slot] = st_get_generic_varying_index(st, attr); break; } } } /* similar hack to above, presetup potentially unused edgeflag output */ stvp->result_to_output[VARYING_SLOT_EDGE] = stvp->num_outputs; stvp->output_semantic_name[stvp->num_outputs] = TGSI_SEMANTIC_EDGEFLAG; stvp->output_semantic_index[stvp->num_outputs] = 0; }
/** * Translate a geometry program to create a new variant. */ static struct st_gp_variant * st_translate_geometry_program(struct st_context *st, struct st_geometry_program *stgp, const struct st_gp_variant_key *key) { GLuint inputMapping[VARYING_SLOT_MAX]; GLuint outputMapping[VARYING_SLOT_MAX]; struct pipe_context *pipe = st->pipe; GLuint attr; GLbitfield64 inputsRead; GLuint vslot = 0; uint gs_num_inputs = 0; uint gs_builtin_inputs = 0; uint gs_array_offset = 0; ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; uint gs_num_outputs = 0; GLint i; GLuint maxSlot = 0; struct ureg_program *ureg; struct st_gp_variant *gpv; gpv = CALLOC_STRUCT(st_gp_variant); if (!gpv) return NULL; if (!stgp->glsl_to_tgsi) { _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT); } ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY ); if (ureg == NULL) { free(gpv); return NULL; } /* which vertex output goes to the first geometry input */ vslot = 0; memset(inputMapping, 0, sizeof(inputMapping)); memset(outputMapping, 0, sizeof(outputMapping)); /* * Convert Mesa program inputs to TGSI input register semantics. */ inputsRead = stgp->Base.Base.InputsRead; for (attr = 0; attr < VARYING_SLOT_MAX; attr++) { if ((inputsRead & BITFIELD64_BIT(attr)) != 0) { const GLuint slot = gs_num_inputs; gs_num_inputs++; inputMapping[attr] = slot; stgp->input_map[slot + gs_array_offset] = vslot - gs_builtin_inputs; stgp->input_to_index[attr] = vslot; stgp->index_to_input[vslot] = attr; ++vslot; if (attr != VARYING_SLOT_PRIMITIVE_ID) { gs_array_offset += 2; } else ++gs_builtin_inputs; #if 0 debug_printf("input map at %d = %d\n", slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]); #endif switch (attr) { case VARYING_SLOT_PRIMITIVE_ID: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; stgp->input_semantic_index[slot] = 0; break; case VARYING_SLOT_POS: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; stgp->input_semantic_index[slot] = 0; break; case VARYING_SLOT_COL0: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stgp->input_semantic_index[slot] = 0; break; case VARYING_SLOT_COL1: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stgp->input_semantic_index[slot] = 1; break; case VARYING_SLOT_FOGC: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG; stgp->input_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_VERTEX: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_CLIPVERTEX; stgp->input_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST0: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; stgp->input_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST1: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; stgp->input_semantic_index[slot] = 1; break; case VARYING_SLOT_PSIZ: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; stgp->input_semantic_index[slot] = 0; break; case VARYING_SLOT_TEX0: case VARYING_SLOT_TEX1: case VARYING_SLOT_TEX2: case VARYING_SLOT_TEX3: case VARYING_SLOT_TEX4: case VARYING_SLOT_TEX5: case VARYING_SLOT_TEX6: case VARYING_SLOT_TEX7: if (st->needs_texcoord_semantic) { stgp->input_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD; stgp->input_semantic_index[slot] = attr - VARYING_SLOT_TEX0; break; } /* fall through */ case VARYING_SLOT_VAR0: default: assert(attr >= VARYING_SLOT_VAR0 && attr < VARYING_SLOT_MAX); stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stgp->input_semantic_index[slot] = st_get_generic_varying_index(st, attr); break; } } } /* initialize output semantics to defaults */ for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; gs_output_semantic_index[i] = 0; } /* * Determine number of outputs, the (default) output register * mapping and the semantic information for each output. */ for (attr = 0; attr < VARYING_SLOT_MAX; attr++) { if (stgp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) { GLuint slot; slot = gs_num_outputs; gs_num_outputs++; outputMapping[attr] = slot; switch (attr) { case VARYING_SLOT_POS: assert(slot == 0); gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_COL0: gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_COL1: gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; gs_output_semantic_index[slot] = 1; break; case VARYING_SLOT_BFC0: gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_BFC1: gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; gs_output_semantic_index[slot] = 1; break; case VARYING_SLOT_FOGC: gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_PSIZ: gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_VERTEX: gs_output_semantic_name[slot] = TGSI_SEMANTIC_CLIPVERTEX; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST0: gs_output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST1: gs_output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; gs_output_semantic_index[slot] = 1; break; case VARYING_SLOT_LAYER: gs_output_semantic_name[slot] = TGSI_SEMANTIC_LAYER; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_PRIMITIVE_ID: gs_output_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_VIEWPORT: gs_output_semantic_name[slot] = TGSI_SEMANTIC_VIEWPORT_INDEX; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_TEX0: case VARYING_SLOT_TEX1: case VARYING_SLOT_TEX2: case VARYING_SLOT_TEX3: case VARYING_SLOT_TEX4: case VARYING_SLOT_TEX5: case VARYING_SLOT_TEX6: case VARYING_SLOT_TEX7: if (st->needs_texcoord_semantic) { gs_output_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD; gs_output_semantic_index[slot] = attr - VARYING_SLOT_TEX0; break; } /* fall through */ case VARYING_SLOT_VAR0: default: assert(slot < Elements(gs_output_semantic_name)); assert(attr >= VARYING_SLOT_VAR0); gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; gs_output_semantic_index[slot] = st_get_generic_varying_index(st, attr); break; } } } /* find max output slot referenced to compute gs_num_outputs */ for (attr = 0; attr < VARYING_SLOT_MAX; attr++) { if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot) maxSlot = outputMapping[attr]; } gs_num_outputs = maxSlot + 1; #if 0 /* debug */ { GLuint i; printf("outputMapping? %d\n", outputMapping ? 1 : 0); if (outputMapping) { printf("attr -> slot\n"); for (i = 0; i < 16; i++) { printf(" %2d %3d\n", i, outputMapping[i]); } } printf("slot sem_name sem_index\n"); for (i = 0; i < gs_num_outputs; i++) { printf(" %2d %d %d\n", i, gs_output_semantic_name[i], gs_output_semantic_index[i]); } } #endif /* free old shader state, if any */ if (stgp->tgsi.tokens) { st_free_tokens(stgp->tgsi.tokens); stgp->tgsi.tokens = NULL; } ureg_property_gs_input_prim(ureg, stgp->Base.InputType); ureg_property_gs_output_prim(ureg, stgp->Base.OutputType); ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut); ureg_property_gs_invocations(ureg, stgp->Base.Invocations); if (stgp->glsl_to_tgsi) st_translate_program(st->ctx, TGSI_PROCESSOR_GEOMETRY, ureg, stgp->glsl_to_tgsi, &stgp->Base.Base, /* inputs */ gs_num_inputs, inputMapping, stgp->input_semantic_name, stgp->input_semantic_index, NULL, NULL, /* outputs */ gs_num_outputs, outputMapping, gs_output_semantic_name, gs_output_semantic_index, FALSE, FALSE); else st_translate_mesa_program(st->ctx, TGSI_PROCESSOR_GEOMETRY, ureg, &stgp->Base.Base, /* inputs */ gs_num_inputs, inputMapping, stgp->input_semantic_name, stgp->input_semantic_index, NULL, /* outputs */ gs_num_outputs, outputMapping, gs_output_semantic_name, gs_output_semantic_index, FALSE, FALSE); stgp->num_inputs = gs_num_inputs; stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); ureg_destroy( ureg ); if (stgp->glsl_to_tgsi) { st_translate_stream_output_info(stgp->glsl_to_tgsi, outputMapping, &stgp->tgsi.stream_output); } if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { _mesa_print_program(&stgp->Base.Base); debug_printf("\n"); } if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump(stgp->tgsi.tokens, 0); debug_printf("\n"); } /* fill in new variant */ gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); gpv->key = *key; return gpv; }