st_draw.c revision c03477050a6f51e601f75cb3c061a3e16a5b7171
1/************************************************************************** 2 * 3 * Copyright 2007 VMware, Inc. 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 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. 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 <keithw@vmware.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 = ctx->_Shader->CurrentProgram; 135 unsigned j; 136 137 for (j = 0; j < 3; j++) { 138 unsigned i; 139 140 if (shProg[j] == NULL || !shProg[j]->LinkStatus) 141 continue; 142 143 for (i = 0; i < shProg[j]->NumUserUniformStorage; i++) { 144 const struct gl_uniform_storage *u = &shProg[j]->UniformStorage[i]; 145 if (!u->initialized) { 146 _mesa_warning(ctx, 147 "Using shader with uninitialized uniform: %s", 148 u->name); 149 } 150 } 151 } 152} 153 154 155/** 156 * Translate OpenGL primtive type (GL_POINTS, GL_TRIANGLE_STRIP, etc) to 157 * the corresponding Gallium type. 158 */ 159static unsigned 160translate_prim(const struct gl_context *ctx, unsigned prim) 161{ 162 /* GL prims should match Gallium prims, spot-check a few */ 163 STATIC_ASSERT(GL_POINTS == PIPE_PRIM_POINTS); 164 STATIC_ASSERT(GL_QUADS == PIPE_PRIM_QUADS); 165 STATIC_ASSERT(GL_TRIANGLE_STRIP_ADJACENCY == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY); 166 167 return prim; 168} 169 170 171/** 172 * This function gets plugged into the VBO module and is called when 173 * we have something to render. 174 * Basically, translate the information into the format expected by gallium. 175 */ 176void 177st_draw_vbo(struct gl_context *ctx, 178 const struct _mesa_prim *prims, 179 GLuint nr_prims, 180 const struct _mesa_index_buffer *ib, 181 GLboolean index_bounds_valid, 182 GLuint min_index, 183 GLuint max_index, 184 struct gl_transform_feedback_object *tfb_vertcount, 185 struct gl_buffer_object *indirect) 186{ 187 struct st_context *st = st_context(ctx); 188 struct pipe_index_buffer ibuffer = {0}; 189 struct pipe_draw_info info; 190 const struct gl_client_array **arrays = ctx->Array._DrawArrays; 191 unsigned i; 192 193 /* Mesa core state should have been validated already */ 194 assert(ctx->NewState == 0x0); 195 196 /* Validate state. */ 197 if (st->dirty.st || ctx->NewDriverState) { 198 st_validate_state(st); 199 200#if 0 201 if (MESA_VERBOSE & VERBOSE_GLSL) { 202 check_uniforms(ctx); 203 } 204#else 205 (void) check_uniforms; 206#endif 207 } 208 209 if (st->vertex_array_out_of_memory) { 210 return; 211 } 212 213 util_draw_init_info(&info); 214 215 if (ib) { 216 /* Get index bounds for user buffers. */ 217 if (!index_bounds_valid) 218 if (!all_varyings_in_vbos(arrays)) 219 vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index, 220 nr_prims); 221 222 if (!setup_index_buffer(st, ib, &ibuffer)) { 223 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBegin/DrawElements/DrawArray"); 224 return; 225 } 226 227 info.indexed = TRUE; 228 if (min_index != ~0 && max_index != ~0) { 229 info.min_index = min_index; 230 info.max_index = max_index; 231 } 232 233 /* The VBO module handles restart for the non-indexed GLDrawArrays 234 * so we only set these fields for indexed drawing: 235 */ 236 info.primitive_restart = ctx->Array._PrimitiveRestart; 237 info.restart_index = ctx->Array.RestartIndex; 238 } 239 else { 240 /* Transform feedback drawing is always non-indexed. */ 241 /* Set info.count_from_stream_output. */ 242 if (tfb_vertcount) { 243 st_transform_feedback_draw_init(tfb_vertcount, &info); 244 } 245 } 246 247 /* do actual drawing */ 248 for (i = 0; i < nr_prims; i++) { 249 info.mode = translate_prim(ctx, prims[i].mode); 250 info.start = prims[i].start; 251 info.count = prims[i].count; 252 info.start_instance = prims[i].base_instance; 253 info.instance_count = prims[i].num_instances; 254 info.index_bias = prims[i].basevertex; 255 if (!ib) { 256 info.min_index = info.start; 257 info.max_index = info.start + info.count - 1; 258 } 259 260 if (ST_DEBUG & DEBUG_DRAW) { 261 debug_printf("st/draw: mode %s start %u count %u indexed %d\n", 262 u_prim_name(info.mode), 263 info.start, 264 info.count, 265 info.indexed); 266 } 267 268 if (info.count_from_stream_output) { 269 cso_draw_vbo(st->cso_context, &info); 270 } 271 else if (info.primitive_restart) { 272 /* don't trim, restarts might be inside index list */ 273 cso_draw_vbo(st->cso_context, &info); 274 } 275 else if (u_trim_pipe_prim(prims[i].mode, &info.count)) { 276 cso_draw_vbo(st->cso_context, &info); 277 } 278 } 279 280 if (ib && st->indexbuf_uploader && !_mesa_is_bufferobj(ib->obj)) { 281 pipe_resource_reference(&ibuffer.buffer, NULL); 282 } 283} 284 285 286void 287st_init_draw(struct st_context *st) 288{ 289 struct gl_context *ctx = st->ctx; 290 291 vbo_set_draw_func(ctx, st_draw_vbo); 292 293 st->draw = draw_create(st->pipe); /* for selection/feedback */ 294 295 /* Disable draw options that might convert points/lines to tris, etc. 296 * as that would foul-up feedback/selection mode. 297 */ 298 draw_wide_line_threshold(st->draw, 1000.0f); 299 draw_wide_point_threshold(st->draw, 1000.0f); 300 draw_enable_line_stipple(st->draw, FALSE); 301 draw_enable_point_sprites(st->draw, FALSE); 302} 303 304 305void 306st_destroy_draw(struct st_context *st) 307{ 308 draw_destroy(st->draw); 309} 310