1 /**************************************************************************
3 * Copyright 2007 VMware, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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 VMWARE 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.
26 **************************************************************************/
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.
40 #include "main/imports.h"
41 #include "main/context.h"
42 #include "main/feedback.h"
46 #include "st_context.h"
48 #include "st_cb_feedback.h"
49 #include "st_program.h"
51 #include "pipe/p_context.h"
52 #include "pipe/p_defines.h"
54 #include "draw/draw_context.h"
55 #include "draw/draw_pipe.h"
59 * This is actually used for both feedback and selection.
63 struct draw_stage stage
; /**< Base class */
64 struct gl_context
*ctx
; /**< Rendering context */
65 GLboolean reset_stipple_counter
;
69 /**********************************************************************
70 * GL Feedback functions
71 **********************************************************************/
73 static inline struct feedback_stage
*
74 feedback_stage( struct draw_stage
*stage
)
76 return (struct feedback_stage
*)stage
;
81 feedback_vertex(struct gl_context
*ctx
, const struct draw_context
*draw
,
82 const struct vertex_header
*v
)
84 const struct st_context
*st
= st_context(ctx
);
86 const GLfloat
*color
, *texcoord
;
89 win
[0] = v
->data
[0][0];
90 if (st_fb_orientation(ctx
->DrawBuffer
) == Y_0_TOP
)
91 win
[1] = ctx
->DrawBuffer
->Height
- v
->data
[0][1];
93 win
[1] = v
->data
[0][1];
94 win
[2] = v
->data
[0][2];
95 win
[3] = 1.0F
/ v
->data
[0][3];
98 * When we compute vertex layout, save info about position of the
99 * color and texcoord attribs to use here.
102 slot
= st
->vp
->result_to_output
[VARYING_SLOT_COL0
];
104 color
= v
->data
[slot
];
106 color
= ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
];
108 slot
= st
->vp
->result_to_output
[VARYING_SLOT_TEX0
];
110 texcoord
= v
->data
[slot
];
112 texcoord
= ctx
->Current
.Attrib
[VERT_ATTRIB_TEX0
];
114 _mesa_feedback_vertex(ctx
, win
, color
, texcoord
);
119 feedback_tri( struct draw_stage
*stage
, struct prim_header
*prim
)
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]);
132 feedback_line( struct draw_stage
*stage
, struct prim_header
*prim
)
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
;
141 _mesa_feedback_token(fs
->ctx
, (GLfloat
) GL_LINE_TOKEN
);
143 feedback_vertex(fs
->ctx
, draw
, prim
->v
[0]);
144 feedback_vertex(fs
->ctx
, draw
, prim
->v
[1]);
149 feedback_point( struct draw_stage
*stage
, struct prim_header
*prim
)
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]);
159 feedback_flush( struct draw_stage
*stage
, unsigned flags
)
166 feedback_reset_stipple_counter( struct draw_stage
*stage
)
168 struct feedback_stage
*fs
= feedback_stage(stage
);
169 fs
->reset_stipple_counter
= GL_TRUE
;
174 feedback_destroy( struct draw_stage
*stage
)
180 * Create GL feedback drawing stage.
182 static struct draw_stage
*
183 draw_glfeedback_stage(struct gl_context
*ctx
, struct draw_context
*draw
)
185 struct feedback_stage
*fs
= ST_CALLOC_STRUCT(feedback_stage
);
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
;
202 /**********************************************************************
203 * GL Selection functions
204 **********************************************************************/
207 select_tri( struct draw_stage
*stage
, struct prim_header
*prim
)
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] );
216 select_line( struct draw_stage
*stage
, struct prim_header
*prim
)
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] );
225 select_point( struct draw_stage
*stage
, struct prim_header
*prim
)
227 struct feedback_stage
*fs
= feedback_stage(stage
);
228 _mesa_update_hitflag( fs
->ctx
, prim
->v
[0]->data
[0][2] );
233 select_flush( struct draw_stage
*stage
, unsigned flags
)
240 select_reset_stipple_counter( struct draw_stage
*stage
)
246 select_destroy( struct draw_stage
*stage
)
253 * Create GL selection mode drawing stage.
255 static struct draw_stage
*
256 draw_glselect_stage(struct gl_context
*ctx
, struct draw_context
*draw
)
258 struct feedback_stage
*fs
= ST_CALLOC_STRUCT(feedback_stage
);
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
;
275 st_RenderMode(struct gl_context
*ctx
, GLenum newMode
)
277 struct st_context
*st
= st_context(ctx
);
278 struct draw_context
*draw
= st_get_draw_context(st
);
283 if (newMode
== GL_RENDER
) {
284 /* restore normal VBO draw function */
287 else if (newMode
== GL_SELECT
) {
288 if (!st
->selection_stage
)
289 st
->selection_stage
= draw_glselect_stage(ctx
, draw
);
290 draw_set_rasterize_stage(draw
, st
->selection_stage
);
291 /* Plug in new vbo draw function */
292 vbo_set_draw_func(ctx
, st_feedback_draw_vbo
);
295 struct gl_program
*vp
= st
->ctx
->VertexProgram
._Current
;
297 if (!st
->feedback_stage
)
298 st
->feedback_stage
= draw_glfeedback_stage(ctx
, draw
);
299 draw_set_rasterize_stage(draw
, st
->feedback_stage
);
300 /* Plug in new vbo draw function */
301 vbo_set_draw_func(ctx
, st_feedback_draw_vbo
);
302 /* need to generate/use a vertex program that emits pos/color/tex */
304 st
->dirty
|= ST_NEW_VERTEX_PROGRAM(st
, st_vertex_program(vp
));
310 void st_init_feedback_functions(struct dd_function_table
*functions
)
312 functions
->RenderMode
= st_RenderMode
;