Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 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 | * This file implements the st_draw_vbo() function which is called from |
||
30 | * Mesa's VBO module. All point/line/triangle rendering is done through |
||
31 | * this function whether the user called glBegin/End, glDrawArrays, |
||
32 | * glDrawElements, glEvalMesh, or glCalList, etc. |
||
33 | * |
||
34 | * We basically convert the VBO's vertex attribute/array information into |
||
35 | * Gallium vertex state, bind the vertex buffer objects and call |
||
36 | * pipe->draw_elements(), pipe->draw_range_elements() or pipe->draw_arrays(). |
||
37 | * |
||
38 | * Authors: |
||
39 | * Keith Whitwell |
||
40 | */ |
||
41 | |||
42 | |||
43 | #include "main/imports.h" |
||
44 | #include "main/image.h" |
||
45 | #include "main/macros.h" |
||
46 | #include "program/prog_uniform.h" |
||
47 | |||
48 | #include "vbo/vbo.h" |
||
49 | |||
50 | #include "st_context.h" |
||
51 | #include "st_atom.h" |
||
52 | #include "st_cb_bufferobjects.h" |
||
53 | #include "st_draw.h" |
||
54 | #include "st_program.h" |
||
55 | |||
56 | #include "pipe/p_context.h" |
||
57 | #include "pipe/p_defines.h" |
||
58 | #include "util/u_inlines.h" |
||
59 | #include "util/u_format.h" |
||
60 | #include "util/u_prim.h" |
||
61 | #include "util/u_draw_quad.h" |
||
62 | #include "draw/draw_context.h" |
||
63 | #include "cso_cache/cso_context.h" |
||
64 | |||
65 | |||
66 | static GLuint double_types[4] = { |
||
67 | PIPE_FORMAT_R64_FLOAT, |
||
68 | PIPE_FORMAT_R64G64_FLOAT, |
||
69 | PIPE_FORMAT_R64G64B64_FLOAT, |
||
70 | PIPE_FORMAT_R64G64B64A64_FLOAT |
||
71 | }; |
||
72 | |||
73 | static GLuint float_types[4] = { |
||
74 | PIPE_FORMAT_R32_FLOAT, |
||
75 | PIPE_FORMAT_R32G32_FLOAT, |
||
76 | PIPE_FORMAT_R32G32B32_FLOAT, |
||
77 | PIPE_FORMAT_R32G32B32A32_FLOAT |
||
78 | }; |
||
79 | |||
80 | static GLuint half_float_types[4] = { |
||
81 | PIPE_FORMAT_R16_FLOAT, |
||
82 | PIPE_FORMAT_R16G16_FLOAT, |
||
83 | PIPE_FORMAT_R16G16B16_FLOAT, |
||
84 | PIPE_FORMAT_R16G16B16A16_FLOAT |
||
85 | }; |
||
86 | |||
87 | static GLuint uint_types_norm[4] = { |
||
88 | PIPE_FORMAT_R32_UNORM, |
||
89 | PIPE_FORMAT_R32G32_UNORM, |
||
90 | PIPE_FORMAT_R32G32B32_UNORM, |
||
91 | PIPE_FORMAT_R32G32B32A32_UNORM |
||
92 | }; |
||
93 | |||
94 | static GLuint uint_types_scale[4] = { |
||
95 | PIPE_FORMAT_R32_USCALED, |
||
96 | PIPE_FORMAT_R32G32_USCALED, |
||
97 | PIPE_FORMAT_R32G32B32_USCALED, |
||
98 | PIPE_FORMAT_R32G32B32A32_USCALED |
||
99 | }; |
||
100 | |||
101 | static GLuint int_types_norm[4] = { |
||
102 | PIPE_FORMAT_R32_SNORM, |
||
103 | PIPE_FORMAT_R32G32_SNORM, |
||
104 | PIPE_FORMAT_R32G32B32_SNORM, |
||
105 | PIPE_FORMAT_R32G32B32A32_SNORM |
||
106 | }; |
||
107 | |||
108 | static GLuint int_types_scale[4] = { |
||
109 | PIPE_FORMAT_R32_SSCALED, |
||
110 | PIPE_FORMAT_R32G32_SSCALED, |
||
111 | PIPE_FORMAT_R32G32B32_SSCALED, |
||
112 | PIPE_FORMAT_R32G32B32A32_SSCALED |
||
113 | }; |
||
114 | |||
115 | static GLuint ushort_types_norm[4] = { |
||
116 | PIPE_FORMAT_R16_UNORM, |
||
117 | PIPE_FORMAT_R16G16_UNORM, |
||
118 | PIPE_FORMAT_R16G16B16_UNORM, |
||
119 | PIPE_FORMAT_R16G16B16A16_UNORM |
||
120 | }; |
||
121 | |||
122 | static GLuint ushort_types_scale[4] = { |
||
123 | PIPE_FORMAT_R16_USCALED, |
||
124 | PIPE_FORMAT_R16G16_USCALED, |
||
125 | PIPE_FORMAT_R16G16B16_USCALED, |
||
126 | PIPE_FORMAT_R16G16B16A16_USCALED |
||
127 | }; |
||
128 | |||
129 | static GLuint short_types_norm[4] = { |
||
130 | PIPE_FORMAT_R16_SNORM, |
||
131 | PIPE_FORMAT_R16G16_SNORM, |
||
132 | PIPE_FORMAT_R16G16B16_SNORM, |
||
133 | PIPE_FORMAT_R16G16B16A16_SNORM |
||
134 | }; |
||
135 | |||
136 | static GLuint short_types_scale[4] = { |
||
137 | PIPE_FORMAT_R16_SSCALED, |
||
138 | PIPE_FORMAT_R16G16_SSCALED, |
||
139 | PIPE_FORMAT_R16G16B16_SSCALED, |
||
140 | PIPE_FORMAT_R16G16B16A16_SSCALED |
||
141 | }; |
||
142 | |||
143 | static GLuint ubyte_types_norm[4] = { |
||
144 | PIPE_FORMAT_R8_UNORM, |
||
145 | PIPE_FORMAT_R8G8_UNORM, |
||
146 | PIPE_FORMAT_R8G8B8_UNORM, |
||
147 | PIPE_FORMAT_R8G8B8A8_UNORM |
||
148 | }; |
||
149 | |||
150 | static GLuint ubyte_types_scale[4] = { |
||
151 | PIPE_FORMAT_R8_USCALED, |
||
152 | PIPE_FORMAT_R8G8_USCALED, |
||
153 | PIPE_FORMAT_R8G8B8_USCALED, |
||
154 | PIPE_FORMAT_R8G8B8A8_USCALED |
||
155 | }; |
||
156 | |||
157 | static GLuint byte_types_norm[4] = { |
||
158 | PIPE_FORMAT_R8_SNORM, |
||
159 | PIPE_FORMAT_R8G8_SNORM, |
||
160 | PIPE_FORMAT_R8G8B8_SNORM, |
||
161 | PIPE_FORMAT_R8G8B8A8_SNORM |
||
162 | }; |
||
163 | |||
164 | static GLuint byte_types_scale[4] = { |
||
165 | PIPE_FORMAT_R8_SSCALED, |
||
166 | PIPE_FORMAT_R8G8_SSCALED, |
||
167 | PIPE_FORMAT_R8G8B8_SSCALED, |
||
168 | PIPE_FORMAT_R8G8B8A8_SSCALED |
||
169 | }; |
||
170 | |||
171 | static GLuint fixed_types[4] = { |
||
172 | PIPE_FORMAT_R32_FIXED, |
||
173 | PIPE_FORMAT_R32G32_FIXED, |
||
174 | PIPE_FORMAT_R32G32B32_FIXED, |
||
175 | PIPE_FORMAT_R32G32B32A32_FIXED |
||
176 | }; |
||
177 | |||
178 | |||
179 | |||
180 | /** |
||
181 | * Return a PIPE_FORMAT_x for the given GL datatype and size. |
||
182 | */ |
||
183 | GLuint |
||
184 | st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, |
||
185 | GLboolean normalized) |
||
186 | { |
||
187 | assert((type >= GL_BYTE && type <= GL_DOUBLE) || |
||
188 | type == GL_FIXED || type == GL_HALF_FLOAT); |
||
189 | assert(size >= 1); |
||
190 | assert(size <= 4); |
||
191 | assert(format == GL_RGBA || format == GL_BGRA); |
||
192 | |||
193 | if (format == GL_BGRA) { |
||
194 | /* this is an odd-ball case */ |
||
195 | assert(type == GL_UNSIGNED_BYTE); |
||
196 | assert(normalized); |
||
197 | return PIPE_FORMAT_B8G8R8A8_UNORM; |
||
198 | } |
||
199 | |||
200 | if (normalized) { |
||
201 | switch (type) { |
||
202 | case GL_DOUBLE: return double_types[size-1]; |
||
203 | case GL_FLOAT: return float_types[size-1]; |
||
204 | case GL_HALF_FLOAT: return half_float_types[size-1]; |
||
205 | case GL_INT: return int_types_norm[size-1]; |
||
206 | case GL_SHORT: return short_types_norm[size-1]; |
||
207 | case GL_BYTE: return byte_types_norm[size-1]; |
||
208 | case GL_UNSIGNED_INT: return uint_types_norm[size-1]; |
||
209 | case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1]; |
||
210 | case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1]; |
||
211 | case GL_FIXED: return fixed_types[size-1]; |
||
212 | default: assert(0); return 0; |
||
213 | } |
||
214 | } |
||
215 | else { |
||
216 | switch (type) { |
||
217 | case GL_DOUBLE: return double_types[size-1]; |
||
218 | case GL_FLOAT: return float_types[size-1]; |
||
219 | case GL_HALF_FLOAT: return half_float_types[size-1]; |
||
220 | case GL_INT: return int_types_scale[size-1]; |
||
221 | case GL_SHORT: return short_types_scale[size-1]; |
||
222 | case GL_BYTE: return byte_types_scale[size-1]; |
||
223 | case GL_UNSIGNED_INT: return uint_types_scale[size-1]; |
||
224 | case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1]; |
||
225 | case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1]; |
||
226 | case GL_FIXED: return fixed_types[size-1]; |
||
227 | default: assert(0); return 0; |
||
228 | } |
||
229 | } |
||
230 | return 0; /* silence compiler warning */ |
||
231 | } |
||
232 | |||
233 | |||
234 | |||
235 | |||
236 | |||
237 | /** |
||
238 | * Examine the active arrays to determine if we have interleaved |
||
239 | * vertex arrays all living in one VBO, or all living in user space. |
||
240 | * \param userSpace returns whether the arrays are in user space. |
||
241 | */ |
||
242 | static GLboolean |
||
243 | is_interleaved_arrays(const struct st_vertex_program *vp, |
||
244 | const struct st_vp_varient *vpv, |
||
245 | const struct gl_client_array **arrays, |
||
246 | GLboolean *userSpace) |
||
247 | { |
||
248 | GLuint attr; |
||
249 | const struct gl_buffer_object *firstBufObj = NULL; |
||
250 | GLint firstStride = -1; |
||
251 | GLuint num_client_arrays = 0; |
||
252 | const GLubyte *client_addr = NULL; |
||
253 | |||
254 | for (attr = 0; attr < vpv->num_inputs; attr++) { |
||
255 | const GLuint mesaAttr = vp->index_to_input[attr]; |
||
256 | const struct gl_buffer_object *bufObj = arrays[mesaAttr]->BufferObj; |
||
257 | const GLsizei stride = arrays[mesaAttr]->StrideB; /* in bytes */ |
||
258 | |||
259 | if (firstStride < 0) { |
||
260 | firstStride = stride; |
||
261 | } |
||
262 | else if (firstStride != stride) { |
||
263 | return GL_FALSE; |
||
264 | } |
||
265 | |||
266 | if (!bufObj || !bufObj->Name) { |
||
267 | num_client_arrays++; |
||
268 | /* Try to detect if the client-space arrays are |
||
269 | * "close" to each other. |
||
270 | */ |
||
271 | if (!client_addr) { |
||
272 | client_addr = arrays[mesaAttr]->Ptr; |
||
273 | } |
||
274 | else if (abs(arrays[mesaAttr]->Ptr - client_addr) > firstStride) { |
||
275 | /* arrays start too far apart */ |
||
276 | return GL_FALSE; |
||
277 | } |
||
278 | } |
||
279 | else if (!firstBufObj) { |
||
280 | firstBufObj = bufObj; |
||
281 | } |
||
282 | else if (bufObj != firstBufObj) { |
||
283 | return GL_FALSE; |
||
284 | } |
||
285 | } |
||
286 | |||
287 | *userSpace = (num_client_arrays == vpv->num_inputs); |
||
288 | /* debug_printf("user space: %s (%d arrays, %d inputs)\n", |
||
289 | (int)*userSpace ? "Yes" : "No", num_client_arrays, vp->num_inputs); */ |
||
290 | |||
291 | return GL_TRUE; |
||
292 | } |
||
293 | |||
294 | |||
295 | /** |
||
296 | * Compute the memory range occupied by the arrays. |
||
297 | */ |
||
298 | static void |
||
299 | get_arrays_bounds(const struct st_vertex_program *vp, |
||
300 | const struct st_vp_varient *vpv, |
||
301 | const struct gl_client_array **arrays, |
||
302 | GLuint max_index, |
||
303 | const GLubyte **low, const GLubyte **high) |
||
304 | { |
||
305 | const GLubyte *low_addr = NULL; |
||
306 | const GLubyte *high_addr = NULL; |
||
307 | GLuint attr; |
||
308 | |||
309 | /* debug_printf("get_arrays_bounds: Handling %u attrs\n", vpv->num_inputs); */ |
||
310 | |||
311 | for (attr = 0; attr < vpv->num_inputs; attr++) { |
||
312 | const GLuint mesaAttr = vp->index_to_input[attr]; |
||
313 | const GLint stride = arrays[mesaAttr]->StrideB; |
||
314 | const GLubyte *start = arrays[mesaAttr]->Ptr; |
||
315 | const unsigned sz = (arrays[mesaAttr]->Size * |
||
316 | _mesa_sizeof_type(arrays[mesaAttr]->Type)); |
||
317 | const GLubyte *end = start + (max_index * stride) + sz; |
||
318 | |||
319 | /* debug_printf("attr %u: stride %d size %u start %p end %p\n", |
||
320 | attr, stride, sz, start, end); */ |
||
321 | |||
322 | if (attr == 0) { |
||
323 | low_addr = start; |
||
324 | high_addr = end; |
||
325 | } |
||
326 | else { |
||
327 | low_addr = MIN2(low_addr, start); |
||
328 | high_addr = MAX2(high_addr, end); |
||
329 | } |
||
330 | } |
||
331 | |||
332 | *low = low_addr; |
||
333 | *high = high_addr; |
||
334 | } |
||
335 | |||
336 | |||
337 | /** |
||
338 | * Set up for drawing interleaved arrays that all live in one VBO |
||
339 | * or all live in user space. |
||
340 | * \param vbuffer returns vertex buffer info |
||
341 | * \param velements returns vertex element info |
||
342 | */ |
||
343 | static void |
||
344 | setup_interleaved_attribs(struct gl_context *ctx, |
||
345 | const struct st_vertex_program *vp, |
||
346 | const struct st_vp_varient *vpv, |
||
347 | const struct gl_client_array **arrays, |
||
348 | GLuint max_index, |
||
349 | GLboolean userSpace, |
||
350 | struct pipe_vertex_buffer *vbuffer, |
||
351 | struct pipe_vertex_element velements[]) |
||
352 | { |
||
353 | struct st_context *st = st_context(ctx); |
||
354 | struct pipe_context *pipe = st->pipe; |
||
355 | GLuint attr; |
||
356 | const GLubyte *offset0 = NULL; |
||
357 | |||
358 | for (attr = 0; attr < vpv->num_inputs; attr++) { |
||
359 | const GLuint mesaAttr = vp->index_to_input[attr]; |
||
360 | struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; |
||
361 | struct st_buffer_object *stobj = st_buffer_object(bufobj); |
||
362 | GLsizei stride = arrays[mesaAttr]->StrideB; |
||
363 | |||
364 | /*printf("stobj %u = %p\n", attr, (void*)stobj);*/ |
||
365 | |||
366 | if (attr == 0) { |
||
367 | const GLubyte *low, *high; |
||
368 | |||
369 | get_arrays_bounds(vp, vpv, arrays, max_index, &low, &high); |
||
370 | /* debug_printf("buffer range: %p %p range %d max index %u\n", |
||
371 | low, high, high - low, max_index); */ |
||
372 | |||
373 | offset0 = low; |
||
374 | if (userSpace) { |
||
375 | vbuffer->buffer = |
||
376 | pipe_user_buffer_create(pipe->screen, (void *) low, high - low, |
||
377 | PIPE_BIND_VERTEX_BUFFER); |
||
378 | vbuffer->buffer_offset = 0; |
||
379 | } |
||
380 | else { |
||
381 | vbuffer->buffer = NULL; |
||
382 | pipe_resource_reference(&vbuffer->buffer, stobj->buffer); |
||
383 | vbuffer->buffer_offset = pointer_to_offset(low); |
||
384 | } |
||
385 | vbuffer->stride = stride; /* in bytes */ |
||
386 | vbuffer->max_index = max_index; |
||
387 | } |
||
388 | |||
389 | velements[attr].src_offset = |
||
390 | (unsigned) (arrays[mesaAttr]->Ptr - offset0); |
||
391 | velements[attr].instance_divisor = 0; |
||
392 | velements[attr].vertex_buffer_index = 0; |
||
393 | velements[attr].src_format = |
||
394 | st_pipe_vertex_format(arrays[mesaAttr]->Type, |
||
395 | arrays[mesaAttr]->Size, |
||
396 | arrays[mesaAttr]->Format, |
||
397 | arrays[mesaAttr]->Normalized); |
||
398 | assert(velements[attr].src_format); |
||
399 | } |
||
400 | } |
||
401 | |||
402 | |||
403 | /** |
||
404 | * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each |
||
405 | * vertex attribute. |
||
406 | * \param vbuffer returns vertex buffer info |
||
407 | * \param velements returns vertex element info |
||
408 | */ |
||
409 | static void |
||
410 | setup_non_interleaved_attribs(struct gl_context *ctx, |
||
411 | const struct st_vertex_program *vp, |
||
412 | const struct st_vp_varient *vpv, |
||
413 | const struct gl_client_array **arrays, |
||
414 | GLuint max_index, |
||
415 | GLboolean *userSpace, |
||
416 | struct pipe_vertex_buffer vbuffer[], |
||
417 | struct pipe_vertex_element velements[]) |
||
418 | { |
||
419 | struct st_context *st = st_context(ctx); |
||
420 | struct pipe_context *pipe = st->pipe; |
||
421 | GLuint attr; |
||
422 | |||
423 | for (attr = 0; attr < vpv->num_inputs; attr++) { |
||
424 | const GLuint mesaAttr = vp->index_to_input[attr]; |
||
425 | struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; |
||
426 | GLsizei stride = arrays[mesaAttr]->StrideB; |
||
427 | |||
428 | *userSpace = GL_FALSE; |
||
429 | |||
430 | if (bufobj && bufobj->Name) { |
||
431 | /* Attribute data is in a VBO. |
||
432 | * Recall that for VBOs, the gl_client_array->Ptr field is |
||
433 | * really an offset from the start of the VBO, not a pointer. |
||
434 | */ |
||
435 | struct st_buffer_object *stobj = st_buffer_object(bufobj); |
||
436 | assert(stobj->buffer); |
||
437 | /*printf("stobj %u = %p\n", attr, (void*) stobj);*/ |
||
438 | |||
439 | vbuffer[attr].buffer = NULL; |
||
440 | pipe_resource_reference(&vbuffer[attr].buffer, stobj->buffer); |
||
441 | vbuffer[attr].buffer_offset = pointer_to_offset(arrays[mesaAttr]->Ptr); |
||
442 | velements[attr].src_offset = 0; |
||
443 | } |
||
444 | else { |
||
445 | /* attribute data is in user-space memory, not a VBO */ |
||
446 | uint bytes; |
||
447 | /*printf("user-space array %d stride %d\n", attr, stride);*/ |
||
448 | |||
449 | *userSpace = GL_TRUE; |
||
450 | |||
451 | /* wrap user data */ |
||
452 | if (arrays[mesaAttr]->Ptr) { |
||
453 | /* user's vertex array */ |
||
454 | if (arrays[mesaAttr]->StrideB) { |
||
455 | bytes = arrays[mesaAttr]->StrideB * (max_index + 1); |
||
456 | } |
||
457 | else { |
||
458 | bytes = arrays[mesaAttr]->Size |
||
459 | * _mesa_sizeof_type(arrays[mesaAttr]->Type); |
||
460 | } |
||
461 | vbuffer[attr].buffer = |
||
462 | pipe_user_buffer_create(pipe->screen, |
||
463 | (void *) arrays[mesaAttr]->Ptr, bytes, |
||
464 | PIPE_BIND_VERTEX_BUFFER); |
||
465 | } |
||
466 | else { |
||
467 | /* no array, use ctx->Current.Attrib[] value */ |
||
468 | bytes = sizeof(ctx->Current.Attrib[0]); |
||
469 | vbuffer[attr].buffer = |
||
470 | pipe_user_buffer_create(pipe->screen, |
||
471 | (void *) ctx->Current.Attrib[mesaAttr], |
||
472 | bytes, |
||
473 | PIPE_BIND_VERTEX_BUFFER); |
||
474 | stride = 0; |
||
475 | } |
||
476 | |||
477 | vbuffer[attr].buffer_offset = 0; |
||
478 | velements[attr].src_offset = 0; |
||
479 | } |
||
480 | |||
481 | assert(velements[attr].src_offset <= 2048); /* 11-bit field */ |
||
482 | |||
483 | /* common-case setup */ |
||
484 | vbuffer[attr].stride = stride; /* in bytes */ |
||
485 | vbuffer[attr].max_index = max_index; |
||
486 | velements[attr].instance_divisor = 0; |
||
487 | velements[attr].vertex_buffer_index = attr; |
||
488 | velements[attr].src_format |
||
489 | = st_pipe_vertex_format(arrays[mesaAttr]->Type, |
||
490 | arrays[mesaAttr]->Size, |
||
491 | arrays[mesaAttr]->Format, |
||
492 | arrays[mesaAttr]->Normalized); |
||
493 | assert(velements[attr].src_format); |
||
494 | } |
||
495 | } |
||
496 | |||
497 | |||
498 | static void |
||
499 | setup_index_buffer(struct gl_context *ctx, |
||
500 | const struct _mesa_index_buffer *ib, |
||
501 | struct pipe_index_buffer *ibuffer) |
||
502 | { |
||
503 | struct st_context *st = st_context(ctx); |
||
504 | struct pipe_context *pipe = st->pipe; |
||
505 | |||
506 | memset(ibuffer, 0, sizeof(*ibuffer)); |
||
507 | if (ib) { |
||
508 | struct gl_buffer_object *bufobj = ib->obj; |
||
509 | |||
510 | switch (ib->type) { |
||
511 | case GL_UNSIGNED_INT: |
||
512 | ibuffer->index_size = 4; |
||
513 | break; |
||
514 | case GL_UNSIGNED_SHORT: |
||
515 | ibuffer->index_size = 2; |
||
516 | break; |
||
517 | case GL_UNSIGNED_BYTE: |
||
518 | ibuffer->index_size = 1; |
||
519 | break; |
||
520 | default: |
||
521 | assert(0); |
||
522 | return; |
||
523 | } |
||
524 | |||
525 | /* get/create the index buffer object */ |
||
526 | if (bufobj && bufobj->Name) { |
||
527 | /* elements/indexes are in a real VBO */ |
||
528 | struct st_buffer_object *stobj = st_buffer_object(bufobj); |
||
529 | pipe_resource_reference(&ibuffer->buffer, stobj->buffer); |
||
530 | ibuffer->offset = pointer_to_offset(ib->ptr); |
||
531 | } |
||
532 | else { |
||
533 | /* element/indicies are in user space memory */ |
||
534 | ibuffer->buffer = |
||
535 | pipe_user_buffer_create(pipe->screen, (void *) ib->ptr, |
||
536 | ib->count * ibuffer->index_size, |
||
537 | PIPE_BIND_INDEX_BUFFER); |
||
538 | } |
||
539 | } |
||
540 | } |
||
541 | |||
542 | /** |
||
543 | * Prior to drawing, check that any uniforms referenced by the |
||
544 | * current shader have been set. If a uniform has not been set, |
||
545 | * issue a warning. |
||
546 | */ |
||
547 | static void |
||
548 | check_uniforms(struct gl_context *ctx) |
||
549 | { |
||
550 | struct gl_shader_program *shProg[3] = { |
||
551 | ctx->Shader.CurrentVertexProgram, |
||
552 | ctx->Shader.CurrentGeometryProgram, |
||
553 | ctx->Shader.CurrentFragmentProgram, |
||
554 | }; |
||
555 | unsigned j; |
||
556 | |||
557 | for (j = 0; j < 3; j++) { |
||
558 | unsigned i; |
||
559 | |||
560 | if (shProg[j] == NULL || !shProg[j]->LinkStatus) |
||
561 | continue; |
||
562 | |||
563 | for (i = 0; i < shProg[j]->Uniforms->NumUniforms; i++) { |
||
564 | const struct gl_uniform *u = &shProg[j]->Uniforms->Uniforms[i]; |
||
565 | if (!u->Initialized) { |
||
566 | _mesa_warning(ctx, |
||
567 | "Using shader with uninitialized uniform: %s", |
||
568 | u->Name); |
||
569 | } |
||
570 | } |
||
571 | } |
||
572 | } |
||
573 | |||
574 | |||
575 | /** |
||
576 | * Translate OpenGL primtive type (GL_POINTS, GL_TRIANGLE_STRIP, etc) to |
||
577 | * the corresponding Gallium type. |
||
578 | */ |
||
579 | static unsigned |
||
580 | translate_prim(const struct gl_context *ctx, unsigned prim) |
||
581 | { |
||
582 | /* GL prims should match Gallium prims, spot-check a few */ |
||
583 | assert(GL_POINTS == PIPE_PRIM_POINTS); |
||
584 | assert(GL_QUADS == PIPE_PRIM_QUADS); |
||
585 | assert(GL_TRIANGLE_STRIP_ADJACENCY == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY); |
||
586 | |||
587 | /* Avoid quadstrips if it's easy to do so: |
||
588 | * Note: it's imporant to do the correct trimming if we change the prim type! |
||
589 | * We do that wherever this function is called. |
||
590 | */ |
||
591 | if (prim == GL_QUAD_STRIP && |
||
592 | ctx->Light.ShadeModel != GL_FLAT && |
||
593 | ctx->Polygon.FrontMode == GL_FILL && |
||
594 | ctx->Polygon.BackMode == GL_FILL) |
||
595 | prim = GL_TRIANGLE_STRIP; |
||
596 | |||
597 | return prim; |
||
598 | } |
||
599 | |||
600 | |||
601 | |||
602 | /** |
||
603 | * This function gets plugged into the VBO module and is called when |
||
604 | * we have something to render. |
||
605 | * Basically, translate the information into the format expected by gallium. |
||
606 | */ |
||
607 | void |
||
608 | st_draw_vbo(struct gl_context *ctx, |
||
609 | const struct gl_client_array **arrays, |
||
610 | const struct _mesa_prim *prims, |
||
611 | GLuint nr_prims, |
||
612 | const struct _mesa_index_buffer *ib, |
||
613 | GLboolean index_bounds_valid, |
||
614 | GLuint min_index, |
||
615 | GLuint max_index) |
||
616 | { |
||
617 | struct st_context *st = st_context(ctx); |
||
618 | struct pipe_context *pipe = st->pipe; |
||
619 | const struct st_vertex_program *vp; |
||
620 | const struct st_vp_varient *vpv; |
||
621 | struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; |
||
622 | GLuint attr; |
||
623 | struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; |
||
624 | unsigned num_vbuffers, num_velements; |
||
625 | struct pipe_index_buffer ibuffer; |
||
626 | GLboolean userSpace = GL_FALSE; |
||
627 | GLboolean vertDataEdgeFlags; |
||
628 | struct pipe_draw_info info; |
||
629 | unsigned i; |
||
630 | |||
631 | /* Mesa core state should have been validated already */ |
||
632 | assert(ctx->NewState == 0x0); |
||
633 | |||
634 | /* Gallium probably doesn't want this in some cases. */ |
||
635 | if (!index_bounds_valid) |
||
636 | if (!vbo_all_varyings_in_vbos(arrays)) |
||
637 | vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); |
||
638 | |||
639 | /* sanity check for pointer arithmetic below */ |
||
640 | assert(sizeof(arrays[0]->Ptr[0]) == 1); |
||
641 | |||
642 | vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj && |
||
643 | arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name; |
||
644 | if (vertDataEdgeFlags != st->vertdata_edgeflags) { |
||
645 | st->vertdata_edgeflags = vertDataEdgeFlags; |
||
646 | st->dirty.st |= ST_NEW_EDGEFLAGS_DATA; |
||
647 | } |
||
648 | |||
649 | st_validate_state(st); |
||
650 | |||
651 | /* must get these after state validation! */ |
||
652 | vp = st->vp; |
||
653 | vpv = st->vp_varient; |
||
654 | |||
655 | #if 0 |
||
656 | if (MESA_VERBOSE & VERBOSE_GLSL) { |
||
657 | check_uniforms(ctx); |
||
658 | } |
||
659 | #else |
||
660 | (void) check_uniforms; |
||
661 | #endif |
||
662 | |||
663 | memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs); |
||
664 | /* |
||
665 | * Setup the vbuffer[] and velements[] arrays. |
||
666 | */ |
||
667 | if (is_interleaved_arrays(vp, vpv, arrays, &userSpace)) { |
||
668 | /*printf("Draw interleaved\n");*/ |
||
669 | setup_interleaved_attribs(ctx, vp, vpv, arrays, max_index, userSpace, |
||
670 | vbuffer, velements); |
||
671 | num_vbuffers = 1; |
||
672 | num_velements = vpv->num_inputs; |
||
673 | if (num_velements == 0) |
||
674 | num_vbuffers = 0; |
||
675 | } |
||
676 | else { |
||
677 | /*printf("Draw non-interleaved\n");*/ |
||
678 | setup_non_interleaved_attribs(ctx, vp, vpv, arrays, max_index, |
||
679 | &userSpace, vbuffer, velements); |
||
680 | num_vbuffers = vpv->num_inputs; |
||
681 | num_velements = vpv->num_inputs; |
||
682 | } |
||
683 | |||
684 | #if 0 |
||
685 | { |
||
686 | GLuint i; |
||
687 | for (i = 0; i < num_vbuffers; i++) { |
||
688 | printf("buffers[%d].stride = %u\n", i, vbuffer[i].stride); |
||
689 | printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index); |
||
690 | printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset); |
||
691 | printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer); |
||
692 | } |
||
693 | for (i = 0; i < num_velements; i++) { |
||
694 | printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index); |
||
695 | printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset); |
||
696 | printf("vlements[%d].format = %s\n", i, util_format_name(velements[i].src_format)); |
||
697 | } |
||
698 | } |
||
699 | #endif |
||
700 | |||
701 | pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer); |
||
702 | cso_set_vertex_elements(st->cso_context, num_velements, velements); |
||
703 | |||
704 | setup_index_buffer(ctx, ib, &ibuffer); |
||
705 | pipe->set_index_buffer(pipe, &ibuffer); |
||
706 | |||
707 | util_draw_init_info(&info); |
||
708 | if (ib) { |
||
709 | info.indexed = TRUE; |
||
710 | if (min_index != ~0 && max_index != ~0) { |
||
711 | info.min_index = min_index; |
||
712 | info.max_index = max_index; |
||
713 | } |
||
714 | } |
||
715 | |||
716 | info.primitive_restart = st->ctx->Array.PrimitiveRestart; |
||
717 | info.restart_index = st->ctx->Array.RestartIndex; |
||
718 | |||
719 | /* do actual drawing */ |
||
720 | for (i = 0; i < nr_prims; i++) { |
||
721 | info.mode = translate_prim( ctx, prims[i].mode ); |
||
722 | info.start = prims[i].start; |
||
723 | info.count = prims[i].count; |
||
724 | info.instance_count = prims[i].num_instances; |
||
725 | info.index_bias = prims[i].basevertex; |
||
726 | if (!ib) { |
||
727 | info.min_index = info.start; |
||
728 | info.max_index = info.start + info.count - 1; |
||
729 | } |
||
730 | |||
731 | if (u_trim_pipe_prim(info.mode, &info.count)) |
||
732 | pipe->draw_vbo(pipe, &info); |
||
733 | } |
||
734 | |||
735 | pipe_resource_reference(&ibuffer.buffer, NULL); |
||
736 | |||
737 | /* unreference buffers (frees wrapped user-space buffer objects) */ |
||
738 | for (attr = 0; attr < num_vbuffers; attr++) { |
||
739 | pipe_resource_reference(&vbuffer[attr].buffer, NULL); |
||
740 | assert(!vbuffer[attr].buffer); |
||
741 | } |
||
742 | |||
743 | if (userSpace) |
||
744 | { |
||
745 | pipe->set_vertex_buffers(pipe, 0, NULL); |
||
746 | } |
||
747 | } |
||
748 | |||
749 | |||
750 | void st_init_draw( struct st_context *st ) |
||
751 | { |
||
752 | struct gl_context *ctx = st->ctx; |
||
753 | |||
754 | vbo_set_draw_func(ctx, st_draw_vbo); |
||
755 | |||
756 | #if FEATURE_feedback || FEATURE_rastpos |
||
757 | st->draw = draw_create(st->pipe); /* for selection/feedback */ |
||
758 | |||
759 | /* Disable draw options that might convert points/lines to tris, etc. |
||
760 | * as that would foul-up feedback/selection mode. |
||
761 | */ |
||
762 | draw_wide_line_threshold(st->draw, 1000.0f); |
||
763 | draw_wide_point_threshold(st->draw, 1000.0f); |
||
764 | draw_enable_line_stipple(st->draw, FALSE); |
||
765 | draw_enable_point_sprites(st->draw, FALSE); |
||
766 | #endif |
||
767 | } |
||
768 | |||
769 | |||
770 | void st_destroy_draw( struct st_context *st ) |
||
771 | { |
||
772 | #if FEATURE_feedback || FEATURE_rastpos |
||
773 | draw_destroy(st->draw); |
||
774 | #endif |
||
775 | }>>>>>>=>>>>>>=>=> |
||
776 |