Plug in selection/feedback code.
[mesa.git] / src / mesa / state_tracker / st_draw.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 * Authors:
30 * Keith Whitwell <keith@tungstengraphics.com>
31 */
32
33 #include "main/imports.h"
34
35 #include "vbo/vbo.h"
36 #include "vbo/vbo_context.h"
37
38 #include "tnl/t_vp_build.h"
39
40 #include "st_context.h"
41 #include "st_atom.h"
42 #include "st_draw.h"
43 #include "st_cb_bufferobjects.h"
44 #include "pipe/p_context.h"
45 #include "pipe/p_defines.h"
46 #include "pipe/p_winsys.h"
47 #include "pipe/tgsi/exec/tgsi_attribs.h"
48
49 #include "pipe/draw/draw_private.h"
50 #include "pipe/draw/draw_context.h"
51
52
53 static GLuint
54 pipe_vertex_format(GLenum format, GLuint size)
55 {
56 static const GLuint float_fmts[4] = {
57 PIPE_FORMAT_R32_FLOAT,
58 PIPE_FORMAT_R32G32_FLOAT,
59 PIPE_FORMAT_R32G32B32_FLOAT,
60 PIPE_FORMAT_R32G32B32A32_FLOAT,
61 };
62
63 assert(format >= GL_BYTE);
64 assert(format <= GL_DOUBLE);
65 assert(size >= 1);
66 assert(size <= 4);
67
68 switch (format) {
69 case GL_FLOAT:
70 return float_fmts[size - 1];
71 default:
72 assert(0);
73 }
74 }
75
76
77 /**
78 * Convert a mesa vertex attribute to a TGSI attribute
79 */
80 static GLuint
81 tgsi_attrib_to_mesa_attrib(GLuint attr)
82 {
83 switch (attr) {
84 case TGSI_ATTRIB_POS:
85 return VERT_ATTRIB_POS;
86 case TGSI_ATTRIB_WEIGHT:
87 return VERT_ATTRIB_WEIGHT;
88 case TGSI_ATTRIB_NORMAL:
89 return VERT_ATTRIB_NORMAL;
90 case TGSI_ATTRIB_COLOR0:
91 return VERT_ATTRIB_COLOR0;
92 case TGSI_ATTRIB_COLOR1:
93 return VERT_ATTRIB_COLOR1;
94 case TGSI_ATTRIB_FOG:
95 return VERT_ATTRIB_FOG;
96 case TGSI_ATTRIB_COLOR_INDEX:
97 return VERT_ATTRIB_COLOR_INDEX;
98 case TGSI_ATTRIB_EDGEFLAG:
99 return VERT_ATTRIB_EDGEFLAG;
100 case TGSI_ATTRIB_TEX0:
101 return VERT_ATTRIB_TEX0;
102 case TGSI_ATTRIB_TEX1:
103 return VERT_ATTRIB_TEX1;
104 case TGSI_ATTRIB_TEX2:
105 return VERT_ATTRIB_TEX2;
106 case TGSI_ATTRIB_TEX3:
107 return VERT_ATTRIB_TEX3;
108 case TGSI_ATTRIB_TEX4:
109 return VERT_ATTRIB_TEX4;
110 case TGSI_ATTRIB_TEX5:
111 return VERT_ATTRIB_TEX5;
112 case TGSI_ATTRIB_TEX6:
113 return VERT_ATTRIB_TEX6;
114 case TGSI_ATTRIB_TEX7:
115 return VERT_ATTRIB_TEX7;
116 case TGSI_ATTRIB_VAR0:
117 return VERT_ATTRIB_GENERIC0;
118 case TGSI_ATTRIB_VAR1:
119 return VERT_ATTRIB_GENERIC1;
120 case TGSI_ATTRIB_VAR2:
121 return VERT_ATTRIB_GENERIC2;
122 case TGSI_ATTRIB_VAR3:
123 return VERT_ATTRIB_GENERIC3;
124 case TGSI_ATTRIB_VAR4:
125 return VERT_ATTRIB_GENERIC4;
126 case TGSI_ATTRIB_VAR5:
127 return VERT_ATTRIB_GENERIC5;
128 case TGSI_ATTRIB_VAR6:
129 return VERT_ATTRIB_GENERIC6;
130 case TGSI_ATTRIB_VAR7:
131 return VERT_ATTRIB_GENERIC7;
132 default:
133 assert(0);
134 return 0;
135 }
136 }
137
138
139
140 /**
141 * The default attribute buffer is basically a copy of the
142 * ctx->Current.Attrib[] array. It's used when the vertex program
143 * references an attribute for which we don't have a VBO/array.
144 */
145 static void
146 create_default_attribs_buffer(struct st_context *st)
147 {
148 struct pipe_context *pipe = st->pipe;
149 st->default_attrib_buffer = pipe->winsys->buffer_create( pipe->winsys, 32 );
150 }
151
152
153 static void
154 destroy_default_attribs_buffer(struct st_context *st)
155 {
156 struct pipe_context *pipe = st->pipe;
157 pipe->winsys->buffer_reference(pipe->winsys,
158 &st->default_attrib_buffer, NULL);
159 }
160
161
162 static void
163 update_default_attribs_buffer(GLcontext *ctx)
164 {
165 struct pipe_context *pipe = ctx->st->pipe;
166 struct pipe_buffer_handle *buf = ctx->st->default_attrib_buffer;
167 const unsigned size = sizeof(ctx->Current.Attrib);
168 const void *data = ctx->Current.Attrib;
169 pipe->winsys->buffer_data(pipe->winsys, buf, size, data);
170 }
171
172
173 /**
174 * This function gets plugged into the VBO module and is called when
175 * we have something to render.
176 * Basically, translate the information into the format expected by pipe.
177 */
178 void
179 st_draw_vbo(GLcontext *ctx,
180 const struct gl_client_array **arrays,
181 const struct _mesa_prim *prims,
182 GLuint nr_prims,
183 const struct _mesa_index_buffer *ib,
184 GLuint min_index,
185 GLuint max_index)
186 {
187 struct pipe_context *pipe = ctx->st->pipe;
188 GLuint attr, i;
189 GLbitfield attrsNeeded;
190 const unsigned attr0_offset = (unsigned) arrays[0]->Ptr;
191
192 st_validate_state(ctx->st);
193 update_default_attribs_buffer(ctx);
194
195 /* this must be after state validation */
196 attrsNeeded = ctx->st->state.vs.inputs_read;
197
198 /* tell pipe about the vertex array element/attributes */
199 for (attr = 0; attr < 16; attr++) {
200 struct pipe_vertex_buffer vbuffer;
201 struct pipe_vertex_element velement;
202
203 vbuffer.buffer = NULL;
204 vbuffer.pitch = 0;
205 velement.src_offset = 0;
206 velement.vertex_buffer_index = 0;
207 velement.src_format = 0;
208
209 if (attrsNeeded & (1 << attr)) {
210 const GLuint mesaAttr = tgsi_attrib_to_mesa_attrib(attr);
211 struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
212
213 if (bufobj && bufobj->Name) {
214 struct st_buffer_object *stobj = st_buffer_object(bufobj);
215 /* Recall that for VBOs, the gl_client_array->Ptr field is
216 * really an offset from the start of the VBO, not a pointer.
217 */
218 unsigned offset = (unsigned) arrays[mesaAttr]->Ptr;
219
220 assert(stobj->buffer);
221
222 vbuffer.buffer = stobj->buffer;
223 vbuffer.buffer_offset = attr0_offset; /* in bytes */
224 vbuffer.pitch = arrays[mesaAttr]->StrideB; /* in bytes */
225 vbuffer.max_index = 0; /* need this? */
226
227 velement.src_offset = offset - attr0_offset; /* bytes */
228 velement.vertex_buffer_index = attr;
229 velement.dst_offset = 0; /* need this? */
230 velement.src_format = pipe_vertex_format(arrays[mesaAttr]->Type,
231 arrays[mesaAttr]->Size);
232 assert(velement.src_format);
233 }
234 else {
235 /* use the default attribute buffer */
236 vbuffer.buffer = ctx->st->default_attrib_buffer;
237 vbuffer.buffer_offset = 0;
238 vbuffer.pitch = 0; /* must be zero! */
239 vbuffer.max_index = 1;
240
241 velement.src_offset = attr * 4 * sizeof(GLfloat);
242 velement.vertex_buffer_index = attr;
243 velement.dst_offset = 0;
244 velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
245 }
246 }
247
248 if (attr == 0)
249 assert(vbuffer.buffer);
250
251 pipe->set_vertex_buffer(pipe, attr, &vbuffer);
252 pipe->set_vertex_element(pipe, attr, &velement);
253 }
254
255 /* do actual drawing */
256 if (ib) {
257 /* indexed primitive */
258 struct gl_buffer_object *bufobj = ib->obj;
259 struct pipe_buffer_handle *bh = NULL;
260 unsigned indexSize;
261
262 if (bufobj && bufobj->Name) {
263 /* elements/indexes are in a real VBO */
264 struct st_buffer_object *stobj = st_buffer_object(bufobj);
265 bh = stobj->buffer;
266 switch (ib->type) {
267 case GL_UNSIGNED_INT:
268 indexSize = 4;
269 break;
270 case GL_UNSIGNED_SHORT:
271 indexSize = 2;
272 break;
273 default:
274 assert(0);
275 }
276 }
277 else {
278 assert(0);
279 }
280
281 for (i = 0; i < nr_prims; i++) {
282 pipe->draw_elements(pipe, bh, indexSize,
283 prims[i].mode, prims[i].start, prims[i].count);
284 }
285 }
286 else {
287 /* non-indexed */
288 for (i = 0; i < nr_prims; i++) {
289 pipe->draw_arrays(pipe, prims[i].mode, prims[i].start, prims[i].count);
290 }
291 }
292 }
293
294
295
296 /**
297 * Utility function for drawing simple primitives (such as quads for
298 * glClear and glDrawPixels). Coordinates are in screen space.
299 * \param mode one of PIPE_PRIM_x
300 * \param numVertex number of vertices
301 * \param verts vertex data (all attributes are float[4])
302 * \param numAttribs number of attributes per vertex
303 * \param attribs index of each attribute (0=pos, 3=color, etc)
304 */
305 void
306 st_draw_vertices(GLcontext *ctx, unsigned prim,
307 unsigned numVertex, float *verts,
308 unsigned numAttribs, const unsigned attribs[])
309 {
310 const float width = ctx->DrawBuffer->Width;
311 const float height = ctx->DrawBuffer->Height;
312 const unsigned vertex_bytes = numVertex * numAttribs * 4 * sizeof(float);
313 struct pipe_context *pipe = ctx->st->pipe;
314 struct pipe_buffer_handle *vbuf;
315 struct pipe_vertex_buffer vbuffer;
316 struct pipe_vertex_element velement;
317 unsigned i;
318
319 assert(numAttribs > 0);
320 assert(attribs[0] == 0); /* position */
321
322 /* convert to clip coords */
323 for (i = 0; i < numVertex; i++) {
324 float x = verts[i * numAttribs * 4 + 0];
325 float y = verts[i * numAttribs * 4 + 1];
326 x = x / width * 2.0 - 1.0;
327 y = y / height * 2.0 - 1.0;
328 verts[i * numAttribs * 4 + 0] = x;
329 verts[i * numAttribs * 4 + 1] = y;
330 }
331
332 /* XXX create one-time */
333 vbuf = pipe->winsys->buffer_create(pipe->winsys, 32);
334 pipe->winsys->buffer_data(pipe->winsys, vbuf, vertex_bytes, verts);
335
336 /* tell pipe about the vertex buffer */
337 vbuffer.buffer = vbuf;
338 vbuffer.pitch = numAttribs * 4 * sizeof(float); /* vertex size */
339 vbuffer.buffer_offset = 0;
340 pipe->set_vertex_buffer(pipe, 0, &vbuffer);
341
342 /* tell pipe about the vertex attributes */
343 for (i = 0; i < numAttribs; i++) {
344 velement.src_offset = i * 4 * sizeof(GLfloat);
345 velement.vertex_buffer_index = 0;
346 velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
347 velement.dst_offset = 0;
348 pipe->set_vertex_element(pipe, attribs[i], &velement);
349 }
350
351 /* draw */
352 pipe->draw_arrays(pipe, prim, 0, numVertex);
353
354 /* XXX: do one-time */
355 pipe->winsys->buffer_reference(pipe->winsys, &vbuf, NULL);
356 }
357
358
359
360
361 /**
362 * Called by VBO to draw arrays when in selection or feedback mode.
363 * This is very much like the normal draw_vbo() function above.
364 * Look at code refactoring some day.
365 * Might move this into the failover module some day.
366 */
367 void
368 st_feedback_draw_vbo(GLcontext *ctx,
369 const struct gl_client_array **arrays,
370 const struct _mesa_prim *prims,
371 GLuint nr_prims,
372 const struct _mesa_index_buffer *ib,
373 GLuint min_index,
374 GLuint max_index)
375 {
376 struct st_context *st = ctx->st;
377 struct pipe_context *pipe = st->pipe;
378 struct draw_context *draw = st->draw;
379 GLuint attr, i;
380 GLbitfield attrsNeeded;
381 const unsigned attr0_offset = (unsigned) arrays[0]->Ptr;
382 struct pipe_buffer_handle *index_buffer_handle = 0;
383
384 assert(ctx->RenderMode == GL_SELECT ||
385 ctx->RenderMode == GL_FEEDBACK);
386 assert(draw);
387
388 /*
389 * Set up the draw module's state.
390 *
391 * We'd like to do this less frequently, but the normal state-update
392 * code sends state updates to the pipe, not to our private draw module.
393 */
394 assert(draw);
395 draw_set_viewport_state(draw, &st->state.viewport);
396 draw_set_clip_state(draw, &st->state.clip);
397 draw_set_setup_state(draw, &st->state.setup);
398 draw_set_vertex_shader(draw, &st->state.vs);
399 /* XXX need to set vertex info too */
400
401
402 update_default_attribs_buffer(ctx);
403
404 /* this must be after state validation */
405 attrsNeeded = ctx->st->state.vs.inputs_read;
406
407 /* tell draw module about the vertex array element/attributes */
408 for (attr = 0; attr < 16; attr++) {
409 struct pipe_vertex_buffer vbuffer;
410 struct pipe_vertex_element velement;
411 void *map;
412
413 vbuffer.buffer = NULL;
414 vbuffer.pitch = 0;
415 velement.src_offset = 0;
416 velement.vertex_buffer_index = 0;
417 velement.src_format = 0;
418
419 if (attrsNeeded & (1 << attr)) {
420 const GLuint mesaAttr = tgsi_attrib_to_mesa_attrib(attr);
421 struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
422
423 if (bufobj && bufobj->Name) {
424 struct st_buffer_object *stobj = st_buffer_object(bufobj);
425 /* Recall that for VBOs, the gl_client_array->Ptr field is
426 * really an offset from the start of the VBO, not a pointer.
427 */
428 unsigned offset = (unsigned) arrays[mesaAttr]->Ptr;
429
430 assert(stobj->buffer);
431
432 vbuffer.buffer = stobj->buffer;
433 vbuffer.buffer_offset = attr0_offset; /* in bytes */
434 vbuffer.pitch = arrays[mesaAttr]->StrideB; /* in bytes */
435 vbuffer.max_index = 0; /* need this? */
436
437 velement.src_offset = offset - attr0_offset; /* bytes */
438 velement.vertex_buffer_index = attr;
439 velement.dst_offset = 0; /* need this? */
440 velement.src_format = pipe_vertex_format(arrays[mesaAttr]->Type,
441 arrays[mesaAttr]->Size);
442 assert(velement.src_format);
443 }
444 else {
445 /* use the default attribute buffer */
446 vbuffer.buffer = ctx->st->default_attrib_buffer;
447 vbuffer.buffer_offset = 0;
448 vbuffer.pitch = 0; /* must be zero! */
449 vbuffer.max_index = 1;
450
451 velement.src_offset = attr * 4 * sizeof(GLfloat);
452 velement.vertex_buffer_index = attr;
453 velement.dst_offset = 0;
454 velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
455 }
456 }
457
458 if (attr == 0)
459 assert(vbuffer.buffer);
460
461 draw_set_vertex_buffer(draw, attr, &vbuffer);
462 draw_set_vertex_element(draw, attr, &velement);
463
464 /* map the attrib buffer */
465 if (vbuffer.buffer) {
466 map = pipe->winsys->buffer_map(pipe->winsys,
467 vbuffer.buffer,
468 PIPE_BUFFER_FLAG_READ);
469 draw_set_mapped_vertex_buffer(draw, attr, map);
470 }
471 }
472
473
474 if (ib) {
475 unsigned indexSize;
476 struct gl_buffer_object *bufobj = ib->obj;
477 struct st_buffer_object *stobj = st_buffer_object(bufobj);
478 index_buffer_handle = stobj->buffer;
479 void *map;
480
481 switch (ib->type) {
482 case GL_UNSIGNED_INT:
483 indexSize = 4;
484 break;
485 case GL_UNSIGNED_SHORT:
486 indexSize = 2;
487 break;
488 default:
489 assert(0);
490 }
491
492 map = pipe->winsys->buffer_map(pipe->winsys,
493 index_buffer_handle,
494 PIPE_BUFFER_FLAG_READ);
495 draw_set_mapped_element_buffer(draw, indexSize, map);
496 }
497
498
499 /* draw here */
500 for (i = 0; i < nr_prims; i++) {
501 draw_arrays(draw, prims[i].mode, prims[i].start, prims[i].count);
502 }
503
504
505 /*
506 * unmap vertex/index buffers
507 */
508 for (i = 0; i < PIPE_ATTRIB_MAX; i++) {
509 if (draw->vertex_buffer[i].buffer) {
510 pipe->winsys->buffer_unmap(pipe->winsys,
511 draw->vertex_buffer[i].buffer);
512 draw_set_mapped_vertex_buffer(draw, i, NULL);
513 }
514 }
515 if (ib) {
516 pipe->winsys->buffer_unmap(pipe->winsys, index_buffer_handle);
517 draw_set_mapped_element_buffer(draw, 0, NULL);
518 }
519 }
520
521
522
523 /* This is all a hack to keep using tnl until we have vertex programs
524 * up and running.
525 */
526 void st_init_draw( struct st_context *st )
527 {
528 GLcontext *ctx = st->ctx;
529 struct vbo_context *vbo = (struct vbo_context *) ctx->swtnl_im;
530
531 create_default_attribs_buffer(st);
532
533 assert(vbo);
534 assert(vbo->draw_prims);
535 vbo->draw_prims = st_draw_vbo;
536
537 _tnl_ProgramCacheInit( ctx );
538 }
539
540
541 void st_destroy_draw( struct st_context *st )
542 {
543 destroy_default_attribs_buffer(st);
544 }
545
546