draw_pipe_offset.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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    /* Window coords:
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    /* edge vectors e = v0 - v2, f = v1 - v2 */
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    /* (a,b) = cross(e,f).xy */
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     * Note: we're applying the offset and clamping per-vertex.
00095     * Ideally, the offset is applied per-fragment prior to fragment shading.
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 }

Generated on Tue Sep 29 06:25:14 2009 for Gallium3D by  doxygen 1.5.4