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
00035 #include "util/u_math.h"
00036 #include "util/u_memory.h"
00037 #include "draw_pipe.h"
00038
00039
00040
00041 struct offset_stage {
00042 struct draw_stage stage;
00043
00044 float scale;
00045 float units;
00046 };
00047
00048
00049
00050 static INLINE struct offset_stage *offset_stage( struct draw_stage *stage )
00051 {
00052 return (struct offset_stage *) stage;
00053 }
00054
00055
00056
00057
00058
00063 static void do_offset_tri( struct draw_stage *stage,
00064 struct prim_header *header )
00065 {
00066 const unsigned pos = stage->draw->vs.position_output;
00067 struct offset_stage *offset = offset_stage(stage);
00068 float inv_det = 1.0f / header->det;
00069
00070
00071
00072 float *v0 = header->v[0]->data[pos];
00073 float *v1 = header->v[1]->data[pos];
00074 float *v2 = header->v[2]->data[pos];
00075
00076
00077 float ex = v0[0] - v2[0];
00078 float ey = v0[1] - v2[1];
00079 float ez = v0[2] - v2[2];
00080 float fx = v1[0] - v2[0];
00081 float fy = v1[1] - v2[1];
00082 float fz = v1[2] - v2[2];
00083
00084
00085 float a = ey*fz - ez*fy;
00086 float b = ez*fx - ex*fz;
00087
00088 float dzdx = fabsf(a * inv_det);
00089 float dzdy = fabsf(b * inv_det);
00090
00091 float zoffset = offset->units + MAX2(dzdx, dzdy) * offset->scale;
00092
00093
00094
00095
00096
00097 v0[2] = CLAMP(v0[2] + zoffset, 0.0f, 1.0f);
00098 v1[2] = CLAMP(v1[2] + zoffset, 0.0f, 1.0f);
00099 v2[2] = CLAMP(v2[2] + zoffset, 0.0f, 1.0f);
00100
00101 stage->next->tri( stage->next, header );
00102 }
00103
00104
00105 static void offset_tri( struct draw_stage *stage,
00106 struct prim_header *header )
00107 {
00108 struct prim_header tmp;
00109
00110 tmp.det = header->det;
00111 tmp.flags = header->flags;
00112 tmp.pad = header->pad;
00113 tmp.v[0] = dup_vert(stage, header->v[0], 0);
00114 tmp.v[1] = dup_vert(stage, header->v[1], 1);
00115 tmp.v[2] = dup_vert(stage, header->v[2], 2);
00116
00117 do_offset_tri( stage, &tmp );
00118 }
00119
00120
00121 static void offset_first_tri( struct draw_stage *stage,
00122 struct prim_header *header )
00123 {
00124 struct offset_stage *offset = offset_stage(stage);
00125
00126 offset->units = (float) (stage->draw->rasterizer->offset_units * stage->draw->mrd);
00127 offset->scale = stage->draw->rasterizer->offset_scale;
00128
00129 stage->tri = offset_tri;
00130 stage->tri( stage, header );
00131 }
00132
00133
00134
00135
00136 static void offset_flush( struct draw_stage *stage,
00137 unsigned flags )
00138 {
00139 stage->tri = offset_first_tri;
00140 stage->next->flush( stage->next, flags );
00141 }
00142
00143
00144 static void offset_reset_stipple_counter( struct draw_stage *stage )
00145 {
00146 stage->next->reset_stipple_counter( stage->next );
00147 }
00148
00149
00150 static void offset_destroy( struct draw_stage *stage )
00151 {
00152 draw_free_temp_verts( stage );
00153 FREE( stage );
00154 }
00155
00156
00160 struct draw_stage *draw_offset_stage( struct draw_context *draw )
00161 {
00162 struct offset_stage *offset = CALLOC_STRUCT(offset_stage);
00163 if (offset == NULL)
00164 goto fail;
00165
00166 draw_alloc_temp_verts( &offset->stage, 3 );
00167
00168 offset->stage.draw = draw;
00169 offset->stage.next = NULL;
00170 offset->stage.point = draw_pipe_passthrough_point;
00171 offset->stage.line = draw_pipe_passthrough_line;
00172 offset->stage.tri = offset_first_tri;
00173 offset->stage.flush = offset_flush;
00174 offset->stage.reset_stipple_counter = offset_reset_stipple_counter;
00175 offset->stage.destroy = offset_destroy;
00176
00177 return &offset->stage;
00178
00179 fail:
00180 if (offset)
00181 offset->stage.destroy( &offset->stage );
00182
00183 return NULL;
00184 }