draw_pipe_wide_point.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 
00028 /* Authors:  Keith Whitwell <keith@tungstengraphics.com>
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       /* put gl_PointCoord into extra vertex output's zw components */
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 /* If there are lots of sprite points (and why wouldn't there be?) it
00101  * would probably be more sensible to change hardware setup to
00102  * optimize this rather than doing the whole thing in software like
00103  * this.
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    /* four dups of original vertex */
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    /* point size is either per-vertex or fixed size */
00128    if (wide->psize_slot >= 0) {
00129       half_size = header->v[0]->data[wide->psize_slot][0];
00130 
00131       /* XXX: temporary -- do this in the vertex shader??
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;  /* only the sign matters */
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    /* XXX we won't know the real size if it's computed by the vertex shader! */
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       /* find vertex shader texcoord outputs */
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       /* find fragment shader PointCoord/Fog input */
00223       wide->point_coord_fs_input = 0; /* XXX fix this! */
00224 
00225       /* setup extra vp output (point coord implemented as a texcoord) */
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       /* find PSIZ vertex output */
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 }

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