st_atom_rasterizer.c revision 6c534b830c6f5427c391c5225c34561141c201ba
1/************************************************************************** 2 * 3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /* 29 * Authors: 30 * Keith Whitwell <keith@tungstengraphics.com> 31 */ 32 33#include "main/macros.h" 34#include "st_context.h" 35#include "st_atom.h" 36#include "pipe/p_context.h" 37#include "pipe/p_defines.h" 38#include "cso_cache/cso_context.h" 39 40 41static GLuint translate_fill( GLenum mode ) 42{ 43 switch (mode) { 44 case GL_POINT: 45 return PIPE_POLYGON_MODE_POINT; 46 case GL_LINE: 47 return PIPE_POLYGON_MODE_LINE; 48 case GL_FILL: 49 return PIPE_POLYGON_MODE_FILL; 50 default: 51 assert(0); 52 return 0; 53 } 54} 55 56static GLboolean get_offset_flag( GLuint fill_mode, 57 const struct gl_polygon_attrib *p ) 58{ 59 switch (fill_mode) { 60 case PIPE_POLYGON_MODE_POINT: 61 return p->OffsetPoint; 62 case PIPE_POLYGON_MODE_LINE: 63 return p->OffsetLine; 64 case PIPE_POLYGON_MODE_FILL: 65 return p->OffsetFill; 66 default: 67 assert(0); 68 return 0; 69 } 70} 71 72 73static void update_raster_state( struct st_context *st ) 74{ 75 GLcontext *ctx = st->ctx; 76 struct pipe_rasterizer_state *raster = &st->state.rasterizer; 77 const struct gl_vertex_program *vertProg = ctx->VertexProgram._Current; 78 uint i; 79 80 memset(raster, 0, sizeof(*raster)); 81 82 raster->origin_lower_left = 1; /* Always true for OpenGL */ 83 84 /* _NEW_POLYGON, _NEW_BUFFERS 85 */ 86 { 87 if (ctx->Polygon.FrontFace == GL_CCW) 88 raster->front_winding = PIPE_WINDING_CCW; 89 else 90 raster->front_winding = PIPE_WINDING_CW; 91 92 /* XXX 93 * I think the intention here is that user-created framebuffer objects 94 * use Y=0=TOP layout instead of OpenGL's normal Y=0=bottom layout. 95 * Flipping Y changes CW to CCW and vice-versa. 96 * But this is an implementation/driver-specific artifact - remove... 97 */ 98 if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0) 99 raster->front_winding ^= PIPE_WINDING_BOTH; 100 } 101 102 /* _NEW_LIGHT 103 */ 104 if (ctx->Light.ShadeModel == GL_FLAT) 105 raster->flatshade = 1; 106 107 /* _NEW_LIGHT | _NEW_PROGRAM 108 * 109 * Back-face colors can come from traditional lighting (when 110 * GL_LIGHT_MODEL_TWO_SIDE is set) or from vertex programs (when 111 * GL_VERTEX_PROGRAM_TWO_SIDE is set). Note the logic here. 112 */ 113 if (ctx->VertexProgram._Current) { 114 if (ctx->VertexProgram._Enabled) { 115 /* user-defined program */ 116 raster->light_twoside = ctx->VertexProgram.TwoSideEnabled; 117 } 118 else { 119 /* TNL-generated program */ 120 raster->light_twoside = ctx->Light.Enabled && ctx->Light.Model.TwoSide; 121 } 122 } 123 else if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) { 124 raster->light_twoside = 1; 125 } 126 127 /* _NEW_POLYGON 128 */ 129 if (ctx->Polygon.CullFlag) { 130 if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { 131 raster->cull_mode = PIPE_WINDING_BOTH; 132 } 133 else if (ctx->Polygon.CullFaceMode == GL_FRONT) { 134 raster->cull_mode = raster->front_winding; 135 } 136 else { 137 raster->cull_mode = raster->front_winding ^ PIPE_WINDING_BOTH; 138 } 139 } 140 141 /* _NEW_POLYGON 142 */ 143 { 144 GLuint fill_front = translate_fill( ctx->Polygon.FrontMode ); 145 GLuint fill_back = translate_fill( ctx->Polygon.BackMode ); 146 147 if (raster->front_winding == PIPE_WINDING_CW) { 148 raster->fill_cw = fill_front; 149 raster->fill_ccw = fill_back; 150 } 151 else { 152 raster->fill_cw = fill_back; 153 raster->fill_ccw = fill_front; 154 } 155 156 /* Simplify when culling is active: 157 */ 158 if (raster->cull_mode & PIPE_WINDING_CW) { 159 raster->fill_cw = raster->fill_ccw; 160 } 161 162 if (raster->cull_mode & PIPE_WINDING_CCW) { 163 raster->fill_ccw = raster->fill_cw; 164 } 165 } 166 167 /* _NEW_POLYGON 168 */ 169 if (ctx->Polygon.OffsetUnits != 0.0 || 170 ctx->Polygon.OffsetFactor != 0.0) { 171 raster->offset_cw = get_offset_flag( raster->fill_cw, &ctx->Polygon ); 172 raster->offset_ccw = get_offset_flag( raster->fill_ccw, &ctx->Polygon ); 173 raster->offset_units = ctx->Polygon.OffsetUnits; 174 raster->offset_scale = ctx->Polygon.OffsetFactor; 175 } 176 177 if (ctx->Polygon.SmoothFlag) 178 raster->poly_smooth = 1; 179 180 if (ctx->Polygon.StippleFlag) 181 raster->poly_stipple_enable = 1; 182 183 184 /* _NEW_BUFFERS, _NEW_POLYGON 185 */ 186 if (raster->fill_cw != PIPE_POLYGON_MODE_FILL || 187 raster->fill_ccw != PIPE_POLYGON_MODE_FILL) 188 { 189 GLfloat mrd = (ctx->DrawBuffer ? 190 ctx->DrawBuffer->_MRD : 191 1.0f); 192 193 raster->offset_units = ctx->Polygon.OffsetFactor * mrd; 194 raster->offset_scale = (ctx->Polygon.OffsetUnits * mrd * 195 st->polygon_offset_scale); 196 } 197 198 /* _NEW_POINT 199 */ 200 raster->point_size = ctx->Point.Size; 201 202 raster->point_size_min = 0; /* temporary, will go away */ 203 raster->point_size_max = 1000; /* temporary, will go away */ 204 205 raster->point_smooth = ctx->Point.SmoothFlag; 206 raster->point_sprite = ctx->Point.PointSprite; 207 for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) { 208 if (ctx->Point.CoordReplace[i]) { 209 if (ctx->Point.SpriteOrigin == GL_UPPER_LEFT) 210 raster->sprite_coord_mode[i] = PIPE_SPRITE_COORD_UPPER_LEFT; 211 else 212 raster->sprite_coord_mode[i] = PIPE_SPRITE_COORD_LOWER_LEFT; 213 } 214 else { 215 raster->sprite_coord_mode[i] = PIPE_SPRITE_COORD_NONE; 216 } 217 } 218 if (vertProg) { 219 if (vertProg->Base.Id == 0) { 220 if (vertProg->Base.OutputsWritten & (1 << VERT_RESULT_PSIZ)) { 221 /* generated program which emits point size */ 222 raster->point_size_per_vertex = TRUE; 223 } 224 } 225 else if (ctx->VertexProgram.PointSizeEnabled) { 226 /* user-defined program and GL_VERTEX_PROGRAM_POINT_SIZE set */ 227 raster->point_size_per_vertex = ctx->VertexProgram.PointSizeEnabled; 228 } 229 } 230 if (!raster->point_size_per_vertex) { 231 /* clamp size now */ 232 raster->point_size = CLAMP(ctx->Point.Size, 233 ctx->Point.MinSize, 234 ctx->Point.MaxSize); 235 } 236 237 /* _NEW_LINE 238 */ 239 raster->line_smooth = ctx->Line.SmoothFlag; 240 if (ctx->Line.SmoothFlag) { 241 raster->line_width = CLAMP(ctx->Line.Width, 242 ctx->Const.MinLineWidthAA, 243 ctx->Const.MaxLineWidthAA); 244 } 245 else { 246 raster->line_width = CLAMP(ctx->Line.Width, 247 ctx->Const.MinLineWidth, 248 ctx->Const.MaxLineWidth); 249 } 250 251 raster->line_stipple_enable = ctx->Line.StippleFlag; 252 raster->line_stipple_pattern = ctx->Line.StipplePattern; 253 /* GL stipple factor is in [1,256], remap to [0, 255] here */ 254 raster->line_stipple_factor = ctx->Line.StippleFactor - 1; 255 256 /* _NEW_MULTISAMPLE */ 257 if (ctx->Multisample._Enabled) 258 raster->multisample = 1; 259 260 /* _NEW_SCISSOR */ 261 if (ctx->Scissor.Enabled) 262 raster->scissor = 1; 263 264 raster->gl_rasterization_rules = 1; 265 266 cso_set_rasterizer(st->cso_context, raster); 267} 268 269const struct st_tracked_state st_update_rasterizer = { 270 "st_update_rasterizer", /* name */ 271 { /* dirty */ 272 (_NEW_LIGHT | _NEW_POLYGON | _NEW_LINE | _NEW_SCISSOR | /* mesa */ 273 _NEW_POINT | _NEW_BUFFERS | _NEW_MULTISAMPLE), 274 0, /* st */ 275 }, 276 update_raster_state /* update */ 277}; 278