00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "util/u_math.h"
00032 #include "util/u_memory.h"
00033 #include "pipe/p_defines.h"
00034 #include "pipe/p_shader_tokens.h"
00035 #include "draw_vs.h"
00036 #include "draw_pipe.h"
00037
00038
00039 struct widepoint_stage {
00040 struct draw_stage stage;
00041
00042 float half_point_size;
00043 float point_size_min;
00044 float point_size_max;
00045
00046 float xbias;
00047 float ybias;
00048
00049 uint texcoord_slot[PIPE_MAX_SHADER_OUTPUTS];
00050 uint texcoord_mode[PIPE_MAX_SHADER_OUTPUTS];
00051 uint num_texcoords;
00052
00053 int psize_slot;
00054
00055 int point_coord_fs_input;
00056 };
00057
00058
00059
00060 static INLINE struct widepoint_stage *
00061 widepoint_stage( struct draw_stage *stage )
00062 {
00063 return (struct widepoint_stage *)stage;
00064 }
00065
00066
00067
00068
00074 static void set_texcoords(const struct widepoint_stage *wide,
00075 struct vertex_header *v, const float tc[4])
00076 {
00077 uint i;
00078 for (i = 0; i < wide->num_texcoords; i++) {
00079 if (wide->texcoord_mode[i] != PIPE_SPRITE_COORD_NONE) {
00080 uint j = wide->texcoord_slot[i];
00081 v->data[j][0] = tc[0];
00082 if (wide->texcoord_mode[i] == PIPE_SPRITE_COORD_LOWER_LEFT)
00083 v->data[j][1] = 1.0f - tc[1];
00084 else
00085 v->data[j][1] = tc[1];
00086 v->data[j][2] = tc[2];
00087 v->data[j][3] = tc[3];
00088 }
00089 }
00090
00091 if (wide->point_coord_fs_input >= 0) {
00092
00093 uint k = wide->stage.draw->extra_vp_outputs.slot;
00094 v->data[k][2] = tc[0];
00095 v->data[k][3] = tc[1];
00096 }
00097 }
00098
00099
00100
00101
00102
00103
00104
00105 static void widepoint_point( struct draw_stage *stage,
00106 struct prim_header *header )
00107 {
00108 const struct widepoint_stage *wide = widepoint_stage(stage);
00109 const unsigned pos = stage->draw->vs.position_output;
00110 const boolean sprite = (boolean) stage->draw->rasterizer->point_sprite;
00111 float half_size;
00112 float left_adj, right_adj, bot_adj, top_adj;
00113
00114 struct prim_header tri;
00115
00116
00117 struct vertex_header *v0 = dup_vert(stage, header->v[0], 0);
00118 struct vertex_header *v1 = dup_vert(stage, header->v[0], 1);
00119 struct vertex_header *v2 = dup_vert(stage, header->v[0], 2);
00120 struct vertex_header *v3 = dup_vert(stage, header->v[0], 3);
00121
00122 float *pos0 = v0->data[pos];
00123 float *pos1 = v1->data[pos];
00124 float *pos2 = v2->data[pos];
00125 float *pos3 = v3->data[pos];
00126
00127
00128 if (wide->psize_slot >= 0) {
00129 half_size = header->v[0]->data[wide->psize_slot][0];
00130
00131
00132
00133 half_size = CLAMP(half_size,
00134 wide->point_size_min,
00135 wide->point_size_max);
00136
00137 half_size *= 0.5f;
00138 }
00139 else {
00140 half_size = wide->half_point_size;
00141 }
00142
00143 left_adj = -half_size + wide->xbias;
00144 right_adj = half_size + wide->xbias;
00145 bot_adj = half_size + wide->ybias;
00146 top_adj = -half_size + wide->ybias;
00147
00148 pos0[0] += left_adj;
00149 pos0[1] += top_adj;
00150
00151 pos1[0] += left_adj;
00152 pos1[1] += bot_adj;
00153
00154 pos2[0] += right_adj;
00155 pos2[1] += top_adj;
00156
00157 pos3[0] += right_adj;
00158 pos3[1] += bot_adj;
00159
00160 if (sprite) {
00161 static const float tex00[4] = { 0, 0, 0, 1 };
00162 static const float tex01[4] = { 0, 1, 0, 1 };
00163 static const float tex11[4] = { 1, 1, 0, 1 };
00164 static const float tex10[4] = { 1, 0, 0, 1 };
00165 set_texcoords( wide, v0, tex00 );
00166 set_texcoords( wide, v1, tex01 );
00167 set_texcoords( wide, v2, tex10 );
00168 set_texcoords( wide, v3, tex11 );
00169 }
00170
00171 tri.det = header->det;
00172 tri.v[0] = v0;
00173 tri.v[1] = v2;
00174 tri.v[2] = v3;
00175 stage->next->tri( stage->next, &tri );
00176
00177 tri.v[0] = v0;
00178 tri.v[1] = v3;
00179 tri.v[2] = v1;
00180 stage->next->tri( stage->next, &tri );
00181 }
00182
00183
00184 static void widepoint_first_point( struct draw_stage *stage,
00185 struct prim_header *header )
00186 {
00187 struct widepoint_stage *wide = widepoint_stage(stage);
00188 struct draw_context *draw = stage->draw;
00189
00190 wide->half_point_size = 0.5f * draw->rasterizer->point_size;
00191 wide->point_size_min = draw->rasterizer->point_size_min;
00192 wide->point_size_max = draw->rasterizer->point_size_max;
00193 wide->xbias = 0.0;
00194 wide->ybias = 0.0;
00195
00196 if (draw->rasterizer->gl_rasterization_rules) {
00197 wide->xbias = 0.125;
00198 }
00199
00200
00201 if ((draw->rasterizer->point_size > draw->pipeline.wide_point_threshold) ||
00202 (draw->rasterizer->point_sprite && draw->pipeline.point_sprite)) {
00203 stage->point = widepoint_point;
00204 }
00205 else {
00206 stage->point = draw_pipe_passthrough_point;
00207 }
00208
00209 if (draw->rasterizer->point_sprite) {
00210
00211 const struct draw_vertex_shader *vs = draw->vs.vertex_shader;
00212 uint i, j = 0;
00213 for (i = 0; i < vs->info.num_outputs; i++) {
00214 if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_GENERIC) {
00215 wide->texcoord_slot[j] = i;
00216 wide->texcoord_mode[j] = draw->rasterizer->sprite_coord_mode[j];
00217 j++;
00218 }
00219 }
00220 wide->num_texcoords = j;
00221
00222
00223 wide->point_coord_fs_input = 0;
00224
00225
00226 draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
00227 draw->extra_vp_outputs.semantic_index = 0;
00228 draw->extra_vp_outputs.slot = draw->vs.num_vs_outputs;
00229 }
00230 else {
00231 wide->point_coord_fs_input = -1;
00232 draw->extra_vp_outputs.slot = 0;
00233 }
00234
00235 wide->psize_slot = -1;
00236 if (draw->rasterizer->point_size_per_vertex) {
00237
00238 const struct draw_vertex_shader *vs = draw->vs.vertex_shader;
00239 uint i;
00240 for (i = 0; i < vs->info.num_outputs; i++) {
00241 if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) {
00242 wide->psize_slot = i;
00243 break;
00244 }
00245 }
00246 }
00247
00248 stage->point( stage, header );
00249 }
00250
00251
00252 static void widepoint_flush( struct draw_stage *stage, unsigned flags )
00253 {
00254 stage->point = widepoint_first_point;
00255 stage->next->flush( stage->next, flags );
00256 }
00257
00258
00259 static void widepoint_reset_stipple_counter( struct draw_stage *stage )
00260 {
00261 stage->next->reset_stipple_counter( stage->next );
00262 }
00263
00264
00265 static void widepoint_destroy( struct draw_stage *stage )
00266 {
00267 draw_free_temp_verts( stage );
00268 FREE( stage );
00269 }
00270
00271
00272 struct draw_stage *draw_wide_point_stage( struct draw_context *draw )
00273 {
00274 struct widepoint_stage *wide = CALLOC_STRUCT(widepoint_stage);
00275 if (wide == NULL)
00276 goto fail;
00277
00278 if (!draw_alloc_temp_verts( &wide->stage, 4 ))
00279 goto fail;
00280
00281 wide->stage.draw = draw;
00282 wide->stage.next = NULL;
00283 wide->stage.point = widepoint_first_point;
00284 wide->stage.line = draw_pipe_passthrough_line;
00285 wide->stage.tri = draw_pipe_passthrough_tri;
00286 wide->stage.flush = widepoint_flush;
00287 wide->stage.reset_stipple_counter = widepoint_reset_stipple_counter;
00288 wide->stage.destroy = widepoint_destroy;
00289
00290 return &wide->stage;
00291
00292 fail:
00293 if (wide)
00294 wide->stage.destroy( &wide->stage );
00295
00296 return NULL;
00297 }