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 struct twoside_stage {
00039 struct draw_stage stage;
00040 float sign;
00041 uint attrib_front0, attrib_back0;
00042 uint attrib_front1, attrib_back1;
00043 };
00044
00045
00046 static INLINE struct twoside_stage *twoside_stage( struct draw_stage *stage )
00047 {
00048 return (struct twoside_stage *)stage;
00049 }
00050
00051
00052
00053
00057 static INLINE struct vertex_header *
00058 copy_bfc( struct twoside_stage *twoside,
00059 const struct vertex_header *v,
00060 unsigned idx )
00061 {
00062 struct vertex_header *tmp = dup_vert( &twoside->stage, v, idx );
00063
00064 if (twoside->attrib_back0) {
00065 COPY_4FV(tmp->data[twoside->attrib_front0],
00066 tmp->data[twoside->attrib_back0]);
00067 }
00068 if (twoside->attrib_back1) {
00069 COPY_4FV(tmp->data[twoside->attrib_front1],
00070 tmp->data[twoside->attrib_back1]);
00071 }
00072
00073 return tmp;
00074 }
00075
00076
00077
00078
00079 static void twoside_tri( struct draw_stage *stage,
00080 struct prim_header *header )
00081 {
00082 struct twoside_stage *twoside = twoside_stage(stage);
00083
00084 if (header->det * twoside->sign < 0.0) {
00085
00086 struct prim_header tmp;
00087
00088 tmp.det = header->det;
00089 tmp.flags = header->flags;
00090 tmp.pad = header->pad;
00091
00092 tmp.v[0] = copy_bfc(twoside, header->v[0], 0);
00093 tmp.v[1] = copy_bfc(twoside, header->v[1], 1);
00094 tmp.v[2] = copy_bfc(twoside, header->v[2], 2);
00095
00096 stage->next->tri( stage->next, &tmp );
00097 }
00098 else {
00099 stage->next->tri( stage->next, header );
00100 }
00101 }
00102
00103
00104
00105 static void twoside_first_tri( struct draw_stage *stage,
00106 struct prim_header *header )
00107 {
00108 struct twoside_stage *twoside = twoside_stage(stage);
00109 const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader;
00110 uint i;
00111
00112 twoside->attrib_front0 = 0;
00113 twoside->attrib_front1 = 0;
00114 twoside->attrib_back0 = 0;
00115 twoside->attrib_back1 = 0;
00116
00117
00118 for (i = 0; i < vs->info.num_outputs; i++) {
00119 if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_COLOR) {
00120 if (vs->info.output_semantic_index[i] == 0)
00121 twoside->attrib_front0 = i;
00122 else
00123 twoside->attrib_front1 = i;
00124 }
00125 if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) {
00126 if (vs->info.output_semantic_index[i] == 0)
00127 twoside->attrib_back0 = i;
00128 else
00129 twoside->attrib_back1 = i;
00130 }
00131 }
00132
00133 if (!twoside->attrib_back0)
00134 twoside->attrib_front0 = 0;
00135
00136 if (!twoside->attrib_back1)
00137 twoside->attrib_front1 = 0;
00138
00139
00140
00141
00142
00143
00144 twoside->sign = (stage->draw->rasterizer->front_winding == PIPE_WINDING_CCW) ? -1.0f : 1.0f;
00145
00146 stage->tri = twoside_tri;
00147 stage->tri( stage, header );
00148 }
00149
00150
00151 static void twoside_flush( struct draw_stage *stage, unsigned flags )
00152 {
00153 stage->tri = twoside_first_tri;
00154 stage->next->flush( stage->next, flags );
00155 }
00156
00157
00158 static void twoside_reset_stipple_counter( struct draw_stage *stage )
00159 {
00160 stage->next->reset_stipple_counter( stage->next );
00161 }
00162
00163
00164 static void twoside_destroy( struct draw_stage *stage )
00165 {
00166 draw_free_temp_verts( stage );
00167 FREE( stage );
00168 }
00169
00170
00174 struct draw_stage *draw_twoside_stage( struct draw_context *draw )
00175 {
00176 struct twoside_stage *twoside = CALLOC_STRUCT(twoside_stage);
00177 if (twoside == NULL)
00178 goto fail;
00179
00180 if (!draw_alloc_temp_verts( &twoside->stage, 3 ))
00181 goto fail;
00182
00183 twoside->stage.draw = draw;
00184 twoside->stage.next = NULL;
00185 twoside->stage.point = draw_pipe_passthrough_point;
00186 twoside->stage.line = draw_pipe_passthrough_line;
00187 twoside->stage.tri = twoside_first_tri;
00188 twoside->stage.flush = twoside_flush;
00189 twoside->stage.reset_stipple_counter = twoside_reset_stipple_counter;
00190 twoside->stage.destroy = twoside_destroy;
00191
00192 return &twoside->stage;
00193
00194 fail:
00195 if (twoside)
00196 twoside->stage.destroy( &twoside->stage );
00197
00198 return NULL;
00199 }