/** * Allocate an extra vertex/geometry shader vertex attribute, if it doesn't * exist already. * * This is used by some of the optional draw module stages such * as wide_point which may need to allocate additional generic/texcoord * attributes. */ int draw_alloc_extra_vertex_attrib(struct draw_context *draw, uint semantic_name, uint semantic_index) { int slot; uint num_outputs; uint n; slot = draw_find_shader_output(draw, semantic_name, semantic_index); if (slot > 0) { return slot; } num_outputs = draw_current_shader_outputs(draw); n = draw->extra_shader_outputs.num; assert(n < Elements(draw->extra_shader_outputs.semantic_name)); draw->extra_shader_outputs.semantic_name[n] = semantic_name; draw->extra_shader_outputs.semantic_index[n] = semantic_index; draw->extra_shader_outputs.slot[n] = num_outputs + n; draw->extra_shader_outputs.num++; return draw->extra_shader_outputs.slot[n]; }
static void aapoint_first_point(struct draw_stage *stage, struct prim_header *header) { auto struct aapoint_stage *aapoint = aapoint_stage(stage); struct draw_context *draw = stage->draw; struct pipe_context *pipe = draw->pipe; const struct pipe_rasterizer_state *rast = draw->rasterizer; void *r; assert(draw->rasterizer->point_smooth); if (draw->rasterizer->point_size <= 2.0) aapoint->radius = 1.0; else aapoint->radius = 0.5f * draw->rasterizer->point_size; /* * Bind (generate) our fragprog. */ bind_aapoint_fragment_shader(aapoint); /* update vertex attrib info */ aapoint->tex_slot = draw_current_shader_outputs(draw); assert(aapoint->tex_slot > 0); /* output[0] is vertex pos */ aapoint->pos_slot = draw_current_shader_position_output(draw); draw->extra_shader_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; draw->extra_shader_outputs.semantic_index = aapoint->fs->generic_attrib; draw->extra_shader_outputs.slot = aapoint->tex_slot; /* find psize slot in post-transform vertex */ aapoint->psize_slot = -1; if (draw->rasterizer->point_size_per_vertex) { /* find PSIZ vertex output */ const struct draw_vertex_shader *vs = draw->vs.vertex_shader; uint i; for (i = 0; i < vs->info.num_outputs; i++) { if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) { aapoint->psize_slot = i; break; } } } draw->suspend_flushing = TRUE; /* Disable triangle culling, stippling, unfilled mode etc. */ r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade); pipe->bind_rasterizer_state(pipe, r); draw->suspend_flushing = FALSE; /* now really draw first point */ stage->point = aapoint_point; stage->point(stage, header); }
static void aaline_first_line(struct draw_stage *stage, struct prim_header *header) { auto struct aaline_stage *aaline = aaline_stage(stage); struct draw_context *draw = stage->draw; struct pipe_context *pipe = draw->pipe; const struct pipe_rasterizer_state *rast = draw->rasterizer; uint num_samplers; void *r; assert(draw->rasterizer->line_smooth); if (draw->rasterizer->line_width <= 2.2) aaline->half_line_width = 1.1f; else aaline->half_line_width = 0.5f * draw->rasterizer->line_width; /* * Bind (generate) our fragprog, sampler and texture */ if (!bind_aaline_fragment_shader(aaline)) { stage->line = draw_pipe_passthrough_line; stage->line(stage, header); return; } /* update vertex attrib info */ aaline->tex_slot = draw_current_shader_outputs(draw); aaline->pos_slot = draw_current_shader_position_output(draw);; /* allocate the extra post-transformed vertex attribute */ (void) draw_alloc_extra_vertex_attrib(draw, TGSI_SEMANTIC_GENERIC, aaline->fs->generic_attrib); /* how many samplers? */ /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */ num_samplers = MAX2(aaline->num_sampler_views, aaline->num_samplers); num_samplers = MAX2(num_samplers, aaline->fs->sampler_unit + 1); aaline->state.sampler[aaline->fs->sampler_unit] = aaline->sampler_cso; pipe_sampler_view_reference(&aaline->state.sampler_views[aaline->fs->sampler_unit], aaline->sampler_view); draw->suspend_flushing = TRUE; aaline->driver_bind_sampler_states(pipe, num_samplers, aaline->state.sampler); aaline->driver_set_sampler_views(pipe, num_samplers, aaline->state.sampler_views); /* Disable triangle culling, stippling, unfilled mode etc. */ r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade); pipe->bind_rasterizer_state(pipe, r); draw->suspend_flushing = FALSE; /* now really draw first line */ stage->line = aaline_line; stage->line(stage, header); }
/** * Allocate an extra vertex/geometry shader vertex attribute. * This is used by some of the optional draw module stages such * as wide_point which may need to allocate additional generic/texcoord * attributes. */ int draw_alloc_extra_vertex_attrib(struct draw_context *draw, uint semantic_name, uint semantic_index) { const int num_outputs = draw_current_shader_outputs(draw); const int n = draw->extra_shader_outputs.num; assert(n < Elements(draw->extra_shader_outputs.semantic_name)); draw->extra_shader_outputs.semantic_name[n] = semantic_name; draw->extra_shader_outputs.semantic_index[n] = semantic_index; draw->extra_shader_outputs.slot[n] = num_outputs + n; draw->extra_shader_outputs.num++; return draw->extra_shader_outputs.slot[n]; }
/* Interpolate between two vertices to produce a third. */ static void interp( const struct clip_stage *clip, struct vertex_header *dst, float t, const struct vertex_header *out, const struct vertex_header *in ) { const unsigned nr_attrs = draw_current_shader_outputs(clip->stage.draw); const unsigned pos_attr = draw_current_shader_position_output(clip->stage.draw); unsigned j; /* Vertex header. */ dst->clipmask = 0; dst->edgeflag = 0; /* will get overwritten later */ dst->pad = 0; dst->vertex_id = UNDEFINED_VERTEX_ID; /* Interpolate the clip-space coords. */ interp_attr(dst->clip, t, in->clip, out->clip); /* Do the projective divide and viewport transformation to get * new window coordinates: */ { const float *pos = dst->clip; const float *scale = clip->stage.draw->viewport.scale; const float *trans = clip->stage.draw->viewport.translate; const float oow = 1.0f / pos[3]; dst->data[pos_attr][0] = pos[0] * oow * scale[0] + trans[0]; dst->data[pos_attr][1] = pos[1] * oow * scale[1] + trans[1]; dst->data[pos_attr][2] = pos[2] * oow * scale[2] + trans[2]; dst->data[pos_attr][3] = oow; } /* Other attributes */ for (j = 0; j < nr_attrs; j++) { if (j != pos_attr) interp_attr(dst->data[j], t, in->data[j], out->data[j]); } }
/** * Compute interpolated vertex attributes for 'dst' at position 't' * between 'v0' and 'v1'. * XXX using linear interpolation for all attribs at this time. */ static void screen_interp( struct draw_context *draw, struct vertex_header *dst, float t, const struct vertex_header *v0, const struct vertex_header *v1 ) { uint attr; uint num_outputs = draw_current_shader_outputs(draw); for (attr = 0; attr < num_outputs; attr++) { const float *val0 = v0->data[attr]; const float *val1 = v1->data[attr]; float *newv = dst->data[attr]; uint i; for (i = 0; i < 4; i++) { newv[i] = val0[i] + t * (val1[i] - val0[i]); } } }
/* Interpolate between two vertices to produce a third. */ static void interp( const struct clip_stage *clip, struct vertex_header *dst, float t, const struct vertex_header *out, const struct vertex_header *in ) { const unsigned nr_attrs = draw_current_shader_outputs(clip->stage.draw); const unsigned pos_attr = draw_current_shader_position_output(clip->stage.draw); const unsigned clip_attr = draw_current_shader_clipvertex_output(clip->stage.draw); unsigned j; float t_nopersp; /* Vertex header. */ dst->clipmask = 0; dst->edgeflag = 0; /* will get overwritten later */ dst->have_clipdist = in->have_clipdist; dst->vertex_id = UNDEFINED_VERTEX_ID; /* Interpolate the clip-space coords. */ interp_attr(dst->clip, t, in->clip, out->clip); /* interpolate the clip-space position */ interp_attr(dst->pre_clip_pos, t, in->pre_clip_pos, out->pre_clip_pos); /* Do the projective divide and viewport transformation to get * new window coordinates: */ { const float *pos = dst->pre_clip_pos; const float *scale = clip->stage.draw->viewport.scale; const float *trans = clip->stage.draw->viewport.translate; const float oow = 1.0f / pos[3]; dst->data[pos_attr][0] = pos[0] * oow * scale[0] + trans[0]; dst->data[pos_attr][1] = pos[1] * oow * scale[1] + trans[1]; dst->data[pos_attr][2] = pos[2] * oow * scale[2] + trans[2]; dst->data[pos_attr][3] = oow; } /** * Compute the t in screen-space instead of 3d space to use * for noperspective interpolation. * * The points can be aligned with the X axis, so in that case try * the Y. When both points are at the same screen position, we can * pick whatever value (the interpolated point won't be in front * anyway), so just use the 3d t. */ { int k; t_nopersp = t; /* find either in.x != out.x or in.y != out.y */ for (k = 0; k < 2; k++) { if (in->clip[k] != out->clip[k]) { /* do divide by W, then compute linear interpolation factor */ float in_coord = in->clip[k] / in->clip[3]; float out_coord = out->clip[k] / out->clip[3]; float dst_coord = dst->clip[k] / dst->clip[3]; t_nopersp = (dst_coord - out_coord) / (in_coord - out_coord); break; } } } /* Other attributes */ for (j = 0; j < nr_attrs; j++) { if (j != pos_attr && j != clip_attr) { if (clip->noperspective_attribs[j]) interp_attr(dst->data[j], t_nopersp, in->data[j], out->data[j]); else interp_attr(dst->data[j], t, in->data[j], out->data[j]); } } }