/* If there are lots of sprite points (and why wouldn't there be?) it * would probably be more sensible to change hardware setup to * optimize this rather than doing the whole thing in software like * this. */ static void widepoint_point( struct draw_stage *stage, struct prim_header *header ) { const struct widepoint_stage *wide = widepoint_stage(stage); const unsigned pos = draw_current_shader_position_output(stage->draw); const boolean sprite = (boolean) stage->draw->rasterizer->point_quad_rasterization; float half_size; float left_adj, right_adj, bot_adj, top_adj; struct prim_header tri; /* four dups of original vertex */ struct vertex_header *v0 = dup_vert(stage, header->v[0], 0); struct vertex_header *v1 = dup_vert(stage, header->v[0], 1); struct vertex_header *v2 = dup_vert(stage, header->v[0], 2); struct vertex_header *v3 = dup_vert(stage, header->v[0], 3); float *pos0 = v0->data[pos]; float *pos1 = v1->data[pos]; float *pos2 = v2->data[pos]; float *pos3 = v3->data[pos]; /* point size is either per-vertex or fixed size */ if (wide->psize_slot >= 0) { half_size = header->v[0]->data[wide->psize_slot][0]; half_size *= 0.5f; } else { half_size = wide->half_point_size; } left_adj = -half_size + wide->xbias; right_adj = half_size + wide->xbias; bot_adj = half_size + wide->ybias; top_adj = -half_size + wide->ybias; pos0[0] += left_adj; pos0[1] += top_adj; pos1[0] += left_adj; pos1[1] += bot_adj; pos2[0] += right_adj; pos2[1] += top_adj; pos3[0] += right_adj; pos3[1] += bot_adj; if (sprite) { static const float tex00[4] = { 0, 0, 0, 1 }; static const float tex01[4] = { 0, 1, 0, 1 }; static const float tex11[4] = { 1, 1, 0, 1 }; static const float tex10[4] = { 1, 0, 0, 1 }; set_texcoords( wide, v0, tex00 ); set_texcoords( wide, v1, tex01 ); set_texcoords( wide, v2, tex10 ); set_texcoords( wide, v3, tex11 ); } tri.det = header->det; /* only the sign matters */ tri.v[0] = v0; tri.v[1] = v2; tri.v[2] = v3; stage->next->tri( stage->next, &tri ); tri.v[0] = v0; tri.v[1] = v3; tri.v[2] = v1; stage->next->tri( stage->next, &tri ); }
static void widepoint_first_point(struct draw_stage *stage, struct prim_header *header) { struct widepoint_stage *wide = widepoint_stage(stage); struct draw_context *draw = stage->draw; struct pipe_context *pipe = draw->pipe; const struct pipe_rasterizer_state *rast = draw->rasterizer; void *r; wide->half_point_size = 0.5f * rast->point_size; wide->xbias = 0.0; wide->ybias = 0.0; if (rast->half_pixel_center) { wide->xbias = 0.125; wide->ybias = -0.125; } /* Disable triangle culling, stippling, unfilled mode etc. */ r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade); draw->suspend_flushing = TRUE; pipe->bind_rasterizer_state(pipe, r); draw->suspend_flushing = FALSE; /* XXX we won't know the real size if it's computed by the vertex shader! */ if ((rast->point_size > draw->pipeline.wide_point_threshold) || (rast->point_quad_rasterization && draw->pipeline.point_sprite)) { stage->point = widepoint_point; } else { stage->point = draw_pipe_passthrough_point; } draw_remove_extra_vertex_attribs(draw); if (rast->point_quad_rasterization) { const struct draw_fragment_shader *fs = draw->fs.fragment_shader; uint i; assert(fs); wide->num_texcoord_gen = 0; /* Loop over fragment shader inputs looking for the PCOORD input or inputs * for which bit 'k' in sprite_coord_enable is set. */ for (i = 0; i < fs->info.num_inputs; i++) { int slot; const unsigned sn = fs->info.input_semantic_name[i]; const unsigned si = fs->info.input_semantic_index[i]; if (sn == wide->sprite_coord_semantic) { /* Note that sprite_coord_enable is a bitfield of 32 bits. */ if (si >= 32 || !(rast->sprite_coord_enable & (1 << si))) continue; } else if (sn != TGSI_SEMANTIC_PCOORD) { continue; } /* OK, this generic attribute needs to be replaced with a * sprite coord (see above). */ slot = draw_alloc_extra_vertex_attrib(draw, sn, si); /* add this slot to the texcoord-gen list */ wide->texcoord_gen_slot[wide->num_texcoord_gen++] = slot; } } wide->psize_slot = -1; if (rast->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) { wide->psize_slot = i; break; } } } stage->point( stage, header ); }
static void widepoint_first_point( struct draw_stage *stage, struct prim_header *header ) { struct widepoint_stage *wide = widepoint_stage(stage); struct draw_context *draw = stage->draw; wide->half_point_size = 0.5f * draw->rasterizer->point_size; wide->point_size_min = draw->rasterizer->point_size_min; wide->point_size_max = draw->rasterizer->point_size_max; wide->xbias = 0.0; wide->ybias = 0.0; if (draw->rasterizer->gl_rasterization_rules) { wide->xbias = 0.125; } /* XXX we won't know the real size if it's computed by the vertex shader! */ if ((draw->rasterizer->point_size > draw->pipeline.wide_point_threshold) || (draw->rasterizer->point_sprite && draw->pipeline.point_sprite)) { stage->point = widepoint_point; } else { stage->point = draw_pipe_passthrough_point; } if (draw->rasterizer->point_sprite) { /* find vertex shader texcoord outputs */ const struct draw_vertex_shader *vs = draw->vs.vertex_shader; uint i, j = 0; for (i = 0; i < vs->info.num_outputs; i++) { if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_GENERIC) { wide->texcoord_slot[j] = i; wide->texcoord_mode[j] = draw->rasterizer->sprite_coord_mode[j]; j++; } } wide->num_texcoords = j; /* find fragment shader PointCoord/Fog input */ wide->point_coord_fs_input = 0; /* XXX fix this! */ /* setup extra vp output (point coord implemented as a texcoord) */ draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; draw->extra_vp_outputs.semantic_index = 0; draw->extra_vp_outputs.slot = draw->vs.num_vs_outputs; } else { wide->point_coord_fs_input = -1; draw->extra_vp_outputs.slot = 0; } wide->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) { wide->psize_slot = i; break; } } } stage->point( stage, header ); }