st_draw.c revision d0eaf6752d6faa8a17e3270b9e64b7c09ef705c2
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 * Authors: 35 * Keith Whitwell <keith@tungstengraphics.com> 36 */ 37 38 39#include "main/imports.h" 40#include "main/image.h" 41#include "main/bufferobj.h" 42#include "main/macros.h" 43 44#include "vbo/vbo.h" 45 46#include "st_context.h" 47#include "st_atom.h" 48#include "st_cb_bufferobjects.h" 49#include "st_cb_xformfb.h" 50#include "st_debug.h" 51#include "st_draw.h" 52#include "st_program.h" 53 54#include "pipe/p_context.h" 55#include "pipe/p_defines.h" 56#include "util/u_inlines.h" 57#include "util/u_format.h" 58#include "util/u_prim.h" 59#include "util/u_draw_quad.h" 60#include "util/u_upload_mgr.h" 61#include "draw/draw_context.h" 62#include "cso_cache/cso_context.h" 63 64#include "../glsl/ir_uniform.h" 65 66 67/** 68 * This is very similar to vbo_all_varyings_in_vbos() but we are 69 * only interested in per-vertex data. See bug 38626. 70 */ 71static GLboolean 72all_varyings_in_vbos(const struct gl_client_array *arrays[]) 73{ 74 GLuint i; 75 76 for (i = 0; i < VERT_ATTRIB_MAX; i++) 77 if (arrays[i]->StrideB && 78 !arrays[i]->InstanceDivisor && 79 !_mesa_is_bufferobj(arrays[i]->BufferObj)) 80 return GL_FALSE; 81 82 return GL_TRUE; 83} 84 85 86/** 87 * Basically, translate Mesa's index buffer information into 88 * a pipe_index_buffer object. 89 * \return TRUE or FALSE for success/failure 90 */ 91static boolean 92setup_index_buffer(struct st_context *st, 93 const struct _mesa_index_buffer *ib, 94 struct pipe_index_buffer *ibuffer) 95{ 96 struct gl_buffer_object *bufobj = ib->obj; 97 98 ibuffer->index_size = vbo_sizeof_ib_type(ib->type); 99 100 /* get/create the index buffer object */ 101 if (_mesa_is_bufferobj(bufobj)) { 102 /* indices are in a real VBO */ 103 ibuffer->buffer = st_buffer_object(bufobj)->buffer; 104 ibuffer->offset = pointer_to_offset(ib->ptr); 105 } 106 else if (st->indexbuf_uploader) { 107 /* upload indexes from user memory into a real buffer */ 108 if (u_upload_data(st->indexbuf_uploader, 0, 109 ib->count * ibuffer->index_size, ib->ptr, 110 &ibuffer->offset, &ibuffer->buffer) != PIPE_OK) { 111 /* out of memory */ 112 return FALSE; 113 } 114 u_upload_unmap(st->indexbuf_uploader); 115 } 116 else { 117 /* indices are in user space memory */ 118 ibuffer->user_buffer = ib->ptr; 119 } 120 121 cso_set_index_buffer(st->cso_context, ibuffer); 122 return TRUE; 123} 124 125 126/** 127 * Prior to drawing, check that any uniforms referenced by the 128 * current shader have been set. If a uniform has not been set, 129 * issue a warning. 130 */ 131static void 132check_uniforms(struct gl_context *ctx) 133{ 134 struct gl_shader_program *shProg[3] = { 135 ctx->Shader.CurrentVertexProgram, 136 ctx->Shader.CurrentGeometryProgram, 137 ctx->Shader.CurrentFragmentProgram, 138 }; 139 unsigned j; 140 141 for (j = 0; j < 3; j++) { 142 unsigned i; 143 144 if (shProg[j] == NULL || !shProg[j]->LinkStatus) 145 continue; 146 147 for (i = 0; i < shProg[j]->NumUserUniformStorage; i++) { 148 const struct gl_uniform_storage *u = &shProg[j]->UniformStorage[i]; 149 if (!u->initialized) { 150 _mesa_warning(ctx, 151 "Using shader with uninitialized uniform: %s", 152 u->name); 153 } 154 } 155 } 156} 157 158 159/** 160 * Translate OpenGL primtive type (GL_POINTS, GL_TRIANGLE_STRIP, etc) to 161 * the corresponding Gallium type. 162 */ 163static unsigned 164translate_prim(const struct gl_context *ctx, unsigned prim) 165{ 166 /* GL prims should match Gallium prims, spot-check a few */ 167 STATIC_ASSERT(GL_POINTS == PIPE_PRIM_POINTS); 168 STATIC_ASSERT(GL_QUADS == PIPE_PRIM_QUADS); 169 STATIC_ASSERT(GL_TRIANGLE_STRIP_ADJACENCY == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY); 170 171 /* Avoid quadstrips if it's easy to do so: 172 * Note: it's important to do the correct trimming if we change the 173 * prim type! We do that wherever this function is called. 174 */ 175 if (prim == GL_QUAD_STRIP && 176 ctx->Light.ShadeModel != GL_FLAT && 177 ctx->Polygon.FrontMode == GL_FILL && 178 ctx->Polygon.BackMode == GL_FILL) 179 prim = GL_TRIANGLE_STRIP; 180 181 return prim; 182} 183 184 185/** 186 * This function gets plugged into the VBO module and is called when 187 * we have something to render. 188 * Basically, translate the information into the format expected by gallium. 189 */ 190void 191st_draw_vbo(struct gl_context *ctx, 192 const struct _mesa_prim *prims, 193 GLuint nr_prims, 194 const struct _mesa_index_buffer *ib, 195 GLboolean index_bounds_valid, 196 GLuint min_index, 197 GLuint max_index, 198 struct gl_transform_feedback_object *tfb_vertcount) 199{ 200 struct st_context *st = st_context(ctx); 201 struct pipe_index_buffer ibuffer = {0}; 202 struct pipe_draw_info info; 203 const struct gl_client_array **arrays = ctx->Array._DrawArrays; 204 unsigned i; 205 206 /* Mesa core state should have been validated already */ 207 assert(ctx->NewState == 0x0); 208 209 /* Validate state. */ 210 if (st->dirty.st || ctx->NewDriverState) { 211 st_validate_state(st); 212 213#if 0 214 if (MESA_VERBOSE & VERBOSE_GLSL) { 215 check_uniforms(ctx); 216 } 217#else 218 (void) check_uniforms; 219#endif 220 } 221 222 if (st->vertex_array_out_of_memory) { 223 return; 224 } 225 226 util_draw_init_info(&info); 227 228 if (ib) { 229 /* Get index bounds for user buffers. */ 230 if (!index_bounds_valid) 231 if (!all_varyings_in_vbos(arrays)) 232 vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index, 233 nr_prims); 234 235 if (!setup_index_buffer(st, ib, &ibuffer)) { 236 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBegin/DrawElements/DrawArray"); 237 return; 238 } 239 240 info.indexed = TRUE; 241 if (min_index != ~0 && max_index != ~0) { 242 info.min_index = min_index; 243 info.max_index = max_index; 244 } 245 246 /* The VBO module handles restart for the non-indexed GLDrawArrays 247 * so we only set these fields for indexed drawing: 248 */ 249 info.primitive_restart = ctx->Array._PrimitiveRestart; 250 info.restart_index = ctx->Array.RestartIndex; 251 } 252 else { 253 /* Transform feedback drawing is always non-indexed. */ 254 /* Set info.count_from_stream_output. */ 255 if (tfb_vertcount) { 256 st_transform_feedback_draw_init(tfb_vertcount, &info); 257 } 258 } 259 260 /* do actual drawing */ 261 for (i = 0; i < nr_prims; i++) { 262 info.mode = translate_prim(ctx, prims[i].mode); 263 info.start = prims[i].start; 264 info.count = prims[i].count; 265 info.start_instance = prims[i].base_instance; 266 info.instance_count = prims[i].num_instances; 267 info.index_bias = prims[i].basevertex; 268 if (!ib) { 269 info.min_index = info.start; 270 info.max_index = info.start + info.count - 1; 271 } 272 273 if (ST_DEBUG & DEBUG_DRAW) { 274 debug_printf("st/draw: mode %s start %u count %u indexed %d\n", 275 u_prim_name(info.mode), 276 info.start, 277 info.count, 278 info.indexed); 279 } 280 281 if (info.count_from_stream_output) { 282 cso_draw_vbo(st->cso_context, &info); 283 } 284 else if (info.primitive_restart) { 285 /* don't trim, restarts might be inside index list */ 286 cso_draw_vbo(st->cso_context, &info); 287 } 288 else if (u_trim_pipe_prim(prims[i].mode, &info.count)) { 289 cso_draw_vbo(st->cso_context, &info); 290 } 291 } 292 293 if (ib && st->indexbuf_uploader && !_mesa_is_bufferobj(ib->obj)) { 294 pipe_resource_reference(&ibuffer.buffer, NULL); 295 } 296} 297 298 299void 300st_init_draw(struct st_context *st) 301{ 302 struct gl_context *ctx = st->ctx; 303 304 vbo_set_draw_func(ctx, st_draw_vbo); 305 306 st->draw = draw_create(st->pipe); /* for selection/feedback */ 307 308 /* Disable draw options that might convert points/lines to tris, etc. 309 * as that would foul-up feedback/selection mode. 310 */ 311 draw_wide_line_threshold(st->draw, 1000.0f); 312 draw_wide_point_threshold(st->draw, 1000.0f); 313 draw_enable_line_stipple(st->draw, FALSE); 314 draw_enable_point_sprites(st->draw, FALSE); 315} 316 317 318void 319st_destroy_draw(struct st_context *st) 320{ 321 draw_destroy(st->draw); 322} 323