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 * GL_SELECT and GL_FEEDBACK render modes. 30 * Basically, we use a private instance of the 'draw' module for doing 31 * selection/feedback. It would be nice to use the transform_feedback 32 * hardware feature, but it's defined as happening pre-clip and we want 33 * post-clipped primitives. Also, there's concerns about the efficiency 34 * of using the hardware for this anyway. 35 * 36 * Authors: 37 * Brian Paul 38 */ 39 40#include "main/imports.h" 41#include "main/context.h" 42#include "main/feedback.h" 43#include "main/mfeatures.h" 44 45#include "vbo/vbo.h" 46 47#include "st_context.h" 48#include "st_draw.h" 49#include "st_cb_feedback.h" 50 51#include "pipe/p_context.h" 52#include "pipe/p_defines.h" 53 54#include "draw/draw_context.h" 55#include "draw/draw_pipe.h" 56 57 58#if FEATURE_feedback 59 60/** 61 * This is actually used for both feedback and selection. 62 */ 63struct feedback_stage 64{ 65 struct draw_stage stage; /**< Base class */ 66 struct gl_context *ctx; /**< Rendering context */ 67 GLboolean reset_stipple_counter; 68}; 69 70 71/********************************************************************** 72 * GL Feedback functions 73 **********************************************************************/ 74 75static INLINE struct feedback_stage * 76feedback_stage( struct draw_stage *stage ) 77{ 78 return (struct feedback_stage *)stage; 79} 80 81 82static void 83feedback_vertex(struct gl_context *ctx, const struct draw_context *draw, 84 const struct vertex_header *v) 85{ 86 const struct st_context *st = st_context(ctx); 87 GLfloat win[4]; 88 const GLfloat *color, *texcoord; 89 GLuint slot; 90 91 /* Recall that Y=0=Top of window for Gallium wincoords */ 92 win[0] = v->data[0][0]; 93 win[1] = ctx->DrawBuffer->Height - v->data[0][1]; 94 win[2] = v->data[0][2]; 95 win[3] = 1.0F / v->data[0][3]; 96 97 /* XXX 98 * When we compute vertex layout, save info about position of the 99 * color and texcoord attribs to use here. 100 */ 101 102 slot = st->vertex_result_to_slot[VERT_RESULT_COL0]; 103 if (slot != ~0U) 104 color = v->data[slot]; 105 else 106 color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; 107 108 slot = st->vertex_result_to_slot[VERT_RESULT_TEX0]; 109 if (slot != ~0U) 110 texcoord = v->data[slot]; 111 else 112 texcoord = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; 113 114 _mesa_feedback_vertex(ctx, win, color, texcoord); 115} 116 117 118static void 119feedback_tri( struct draw_stage *stage, struct prim_header *prim ) 120{ 121 struct feedback_stage *fs = feedback_stage(stage); 122 struct draw_context *draw = stage->draw; 123 _mesa_feedback_token(fs->ctx, (GLfloat) GL_POLYGON_TOKEN); 124 _mesa_feedback_token(fs->ctx, (GLfloat) 3); /* three vertices */ 125 feedback_vertex(fs->ctx, draw, prim->v[0]); 126 feedback_vertex(fs->ctx, draw, prim->v[1]); 127 feedback_vertex(fs->ctx, draw, prim->v[2]); 128} 129 130 131static void 132feedback_line( struct draw_stage *stage, struct prim_header *prim ) 133{ 134 struct feedback_stage *fs = feedback_stage(stage); 135 struct draw_context *draw = stage->draw; 136 if (fs->reset_stipple_counter) { 137 _mesa_feedback_token(fs->ctx, (GLfloat) GL_LINE_RESET_TOKEN); 138 fs->reset_stipple_counter = GL_FALSE; 139 } 140 else { 141 _mesa_feedback_token(fs->ctx, (GLfloat) GL_LINE_TOKEN); 142 } 143 feedback_vertex(fs->ctx, draw, prim->v[0]); 144 feedback_vertex(fs->ctx, draw, prim->v[1]); 145} 146 147 148static void 149feedback_point( struct draw_stage *stage, struct prim_header *prim ) 150{ 151 struct feedback_stage *fs = feedback_stage(stage); 152 struct draw_context *draw = stage->draw; 153 _mesa_feedback_token(fs->ctx, (GLfloat) GL_POINT_TOKEN); 154 feedback_vertex(fs->ctx, draw, prim->v[0]); 155} 156 157 158static void 159feedback_flush( struct draw_stage *stage, unsigned flags ) 160{ 161 /* no-op */ 162} 163 164 165static void 166feedback_reset_stipple_counter( struct draw_stage *stage ) 167{ 168 struct feedback_stage *fs = feedback_stage(stage); 169 fs->reset_stipple_counter = GL_TRUE; 170} 171 172 173static void 174feedback_destroy( struct draw_stage *stage ) 175{ 176 /* no-op */ 177} 178 179/** 180 * Create GL feedback drawing stage. 181 */ 182static struct draw_stage * 183draw_glfeedback_stage(struct gl_context *ctx, struct draw_context *draw) 184{ 185 struct feedback_stage *fs = ST_CALLOC_STRUCT(feedback_stage); 186 187 fs->stage.draw = draw; 188 fs->stage.next = NULL; 189 fs->stage.point = feedback_point; 190 fs->stage.line = feedback_line; 191 fs->stage.tri = feedback_tri; 192 fs->stage.flush = feedback_flush; 193 fs->stage.reset_stipple_counter = feedback_reset_stipple_counter; 194 fs->stage.destroy = feedback_destroy; 195 fs->ctx = ctx; 196 197 return &fs->stage; 198} 199 200 201 202/********************************************************************** 203 * GL Selection functions 204 **********************************************************************/ 205 206static void 207select_tri( struct draw_stage *stage, struct prim_header *prim ) 208{ 209 struct feedback_stage *fs = feedback_stage(stage); 210 _mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] ); 211 _mesa_update_hitflag( fs->ctx, prim->v[1]->data[0][2] ); 212 _mesa_update_hitflag( fs->ctx, prim->v[2]->data[0][2] ); 213} 214 215static void 216select_line( struct draw_stage *stage, struct prim_header *prim ) 217{ 218 struct feedback_stage *fs = feedback_stage(stage); 219 _mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] ); 220 _mesa_update_hitflag( fs->ctx, prim->v[1]->data[0][2] ); 221} 222 223 224static void 225select_point( struct draw_stage *stage, struct prim_header *prim ) 226{ 227 struct feedback_stage *fs = feedback_stage(stage); 228 _mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] ); 229} 230 231 232static void 233select_flush( struct draw_stage *stage, unsigned flags ) 234{ 235 /* no-op */ 236} 237 238 239static void 240select_reset_stipple_counter( struct draw_stage *stage ) 241{ 242 /* no-op */ 243} 244 245static void 246select_destroy( struct draw_stage *stage ) 247{ 248 /* no-op */ 249} 250 251 252/** 253 * Create GL selection mode drawing stage. 254 */ 255static struct draw_stage * 256draw_glselect_stage(struct gl_context *ctx, struct draw_context *draw) 257{ 258 struct feedback_stage *fs = ST_CALLOC_STRUCT(feedback_stage); 259 260 fs->stage.draw = draw; 261 fs->stage.next = NULL; 262 fs->stage.point = select_point; 263 fs->stage.line = select_line; 264 fs->stage.tri = select_tri; 265 fs->stage.flush = select_flush; 266 fs->stage.reset_stipple_counter = select_reset_stipple_counter; 267 fs->stage.destroy = select_destroy; 268 fs->ctx = ctx; 269 270 return &fs->stage; 271} 272 273 274static void 275st_RenderMode(struct gl_context *ctx, GLenum newMode ) 276{ 277 struct st_context *st = st_context(ctx); 278 struct draw_context *draw = st->draw; 279 280 if (newMode == GL_RENDER) { 281 /* restore normal VBO draw function */ 282 vbo_set_draw_func(ctx, st_draw_vbo); 283 } 284 else if (newMode == GL_SELECT) { 285 if (!st->selection_stage) 286 st->selection_stage = draw_glselect_stage(ctx, draw); 287 draw_set_rasterize_stage(draw, st->selection_stage); 288 /* Plug in new vbo draw function */ 289 vbo_set_draw_func(ctx, st_feedback_draw_vbo); 290 } 291 else { 292 if (!st->feedback_stage) 293 st->feedback_stage = draw_glfeedback_stage(ctx, draw); 294 draw_set_rasterize_stage(draw, st->feedback_stage); 295 /* Plug in new vbo draw function */ 296 vbo_set_draw_func(ctx, st_feedback_draw_vbo); 297 /* need to generate/use a vertex program that emits pos/color/tex */ 298 st->dirty.st |= ST_NEW_VERTEX_PROGRAM; 299 } 300} 301 302 303 304void st_init_feedback_functions(struct dd_function_table *functions) 305{ 306 functions->RenderMode = st_RenderMode; 307} 308 309#endif /* FEATURE_feedback */ 310