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