vbo_save_draw.c revision 3464ebd5
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.2 4 * 5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25/* Author: 26 * Keith Whitwell <keith@tungstengraphics.com> 27 */ 28 29#include "main/glheader.h" 30#include "main/bufferobj.h" 31#include "main/context.h" 32#include "main/imports.h" 33#include "main/mfeatures.h" 34#include "main/mtypes.h" 35#include "main/macros.h" 36#include "main/light.h" 37#include "main/state.h" 38 39#include "vbo_context.h" 40 41 42#if FEATURE_dlist 43 44 45/** 46 * After playback, copy everything but the position from the 47 * last vertex to the saved state 48 */ 49static void 50_playback_copy_to_current(struct gl_context *ctx, 51 const struct vbo_save_vertex_list *node) 52{ 53 struct vbo_context *vbo = vbo_context(ctx); 54 GLfloat vertex[VBO_ATTRIB_MAX * 4]; 55 GLfloat *data; 56 GLuint i, offset; 57 58 if (node->current_size == 0) 59 return; 60 61 if (node->current_data) { 62 data = node->current_data; 63 } 64 else { 65 data = vertex; 66 67 if (node->count) 68 offset = (node->buffer_offset + 69 (node->count-1) * node->vertex_size * sizeof(GLfloat)); 70 else 71 offset = node->buffer_offset; 72 73 ctx->Driver.GetBufferSubData( ctx, 0, offset, 74 node->vertex_size * sizeof(GLfloat), 75 data, node->vertex_store->bufferobj ); 76 77 data += node->attrsz[0]; /* skip vertex position */ 78 } 79 80 for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { 81 if (node->attrsz[i]) { 82 GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; 83 GLfloat tmp[4]; 84 85 COPY_CLEAN_4V(tmp, 86 node->attrsz[i], 87 data); 88 89 if (memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) { 90 memcpy(current, tmp, 4 * sizeof(GLfloat)); 91 92 vbo->currval[i].Size = node->attrsz[i]; 93 assert(vbo->currval[i].Type == GL_FLOAT); 94 vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat); 95 96 if (i >= VBO_ATTRIB_FIRST_MATERIAL && 97 i <= VBO_ATTRIB_LAST_MATERIAL) 98 ctx->NewState |= _NEW_LIGHT; 99 100 ctx->NewState |= _NEW_CURRENT_ATTRIB; 101 } 102 103 data += node->attrsz[i]; 104 } 105 } 106 107 /* Colormaterial -- this kindof sucks. 108 */ 109 if (ctx->Light.ColorMaterialEnabled) { 110 _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]); 111 } 112 113 /* CurrentExecPrimitive 114 */ 115 if (node->prim_count) { 116 const struct _mesa_prim *prim = &node->prim[node->prim_count - 1]; 117 if (prim->end) 118 ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; 119 else 120 ctx->Driver.CurrentExecPrimitive = prim->mode; 121 } 122} 123 124 125 126/** 127 * Treat the vertex storage as a VBO, define vertex arrays pointing 128 * into it: 129 */ 130static void vbo_bind_vertex_list(struct gl_context *ctx, 131 const struct vbo_save_vertex_list *node) 132{ 133 struct vbo_context *vbo = vbo_context(ctx); 134 struct vbo_save_context *save = &vbo->save; 135 struct gl_client_array *arrays = save->arrays; 136 GLuint buffer_offset = node->buffer_offset; 137 const GLuint *map; 138 GLuint attr; 139 GLubyte node_attrsz[VBO_ATTRIB_MAX]; /* copy of node->attrsz[] */ 140 GLbitfield varying_inputs = 0x0; 141 142 memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz)); 143 144 /* Install the default (ie Current) attributes first, then overlay 145 * all active ones. 146 */ 147 switch (get_program_mode(ctx)) { 148 case VP_NONE: 149 for (attr = 0; attr < 16; attr++) { 150 save->inputs[attr] = &vbo->legacy_currval[attr]; 151 } 152 for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) { 153 save->inputs[attr + 16] = &vbo->mat_currval[attr]; 154 } 155 map = vbo->map_vp_none; 156 break; 157 case VP_NV: 158 case VP_ARB: 159 /* The aliasing of attributes for NV vertex programs has already 160 * occurred. NV vertex programs cannot access material values, 161 * nor attributes greater than VERT_ATTRIB_TEX7. 162 */ 163 for (attr = 0; attr < 16; attr++) { 164 save->inputs[attr] = &vbo->legacy_currval[attr]; 165 save->inputs[attr + 16] = &vbo->generic_currval[attr]; 166 } 167 map = vbo->map_vp_arb; 168 169 /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read. 170 * In that case we effectively need to route the data from 171 * glVertexAttrib(0, val) calls to feed into the GENERIC0 input. 172 */ 173 if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 && 174 (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) { 175 save->inputs[16] = save->inputs[0]; 176 node_attrsz[16] = node_attrsz[0]; 177 node_attrsz[0] = 0; 178 } 179 break; 180 default: 181 assert(0); 182 } 183 184 for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { 185 const GLuint src = map[attr]; 186 187 if (node_attrsz[src]) { 188 /* override the default array set above */ 189 save->inputs[attr] = &arrays[attr]; 190 191 arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset; 192 arrays[attr].Size = node->attrsz[src]; 193 arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat); 194 arrays[attr].Stride = node->vertex_size * sizeof(GLfloat); 195 arrays[attr].Type = GL_FLOAT; 196 arrays[attr].Format = GL_RGBA; 197 arrays[attr].Enabled = 1; 198 arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat); 199 _mesa_reference_buffer_object(ctx, 200 &arrays[attr].BufferObj, 201 node->vertex_store->bufferobj); 202 arrays[attr]._MaxElement = node->count; /* ??? */ 203 204 assert(arrays[attr].BufferObj->Name); 205 206 buffer_offset += node->attrsz[src] * sizeof(GLfloat); 207 varying_inputs |= 1<<attr; 208 ctx->NewState |= _NEW_ARRAY; 209 } 210 } 211 212 _mesa_set_varying_vp_inputs( ctx, varying_inputs ); 213} 214 215 216static void 217vbo_save_loopback_vertex_list(struct gl_context *ctx, 218 const struct vbo_save_vertex_list *list) 219{ 220 const char *buffer = ctx->Driver.MapBuffer(ctx, 221 GL_ARRAY_BUFFER_ARB, 222 GL_READ_ONLY, /* ? */ 223 list->vertex_store->bufferobj); 224 225 vbo_loopback_vertex_list(ctx, 226 (const GLfloat *)(buffer + list->buffer_offset), 227 list->attrsz, 228 list->prim, 229 list->prim_count, 230 list->wrap_count, 231 list->vertex_size); 232 233 ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, 234 list->vertex_store->bufferobj); 235} 236 237 238/** 239 * Execute the buffer and save copied verts. 240 * This is called from the display list code when executing 241 * a drawing command. 242 */ 243void 244vbo_save_playback_vertex_list(struct gl_context *ctx, void *data) 245{ 246 const struct vbo_save_vertex_list *node = 247 (const struct vbo_save_vertex_list *) data; 248 struct vbo_save_context *save = &vbo_context(ctx)->save; 249 250 FLUSH_CURRENT(ctx, 0); 251 252 if (node->prim_count > 0) { 253 254 if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END && 255 node->prim[0].begin) { 256 257 /* Degenerate case: list is called inside begin/end pair and 258 * includes operations such as glBegin or glDrawArrays. 259 */ 260 if (0) 261 printf("displaylist recursive begin"); 262 263 vbo_save_loopback_vertex_list( ctx, node ); 264 return; 265 } 266 else if (save->replay_flags) { 267 /* Various degnerate cases: translate into immediate mode 268 * calls rather than trying to execute in place. 269 */ 270 vbo_save_loopback_vertex_list( ctx, node ); 271 return; 272 } 273 274 if (ctx->NewState) 275 _mesa_update_state( ctx ); 276 277 /* XXX also need to check if shader enabled, but invalid */ 278 if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) || 279 (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) { 280 _mesa_error(ctx, GL_INVALID_OPERATION, 281 "glBegin (invalid vertex/fragment program)"); 282 return; 283 } 284 285 vbo_bind_vertex_list( ctx, node ); 286 287 /* Again... 288 */ 289 if (ctx->NewState) 290 _mesa_update_state( ctx ); 291 292 if (node->count > 0) { 293 vbo_context(ctx)->draw_prims(ctx, 294 save->inputs, 295 node->prim, 296 node->prim_count, 297 NULL, 298 GL_TRUE, 299 0, /* Node is a VBO, so this is ok */ 300 node->count - 1); 301 } 302 } 303 304 /* Copy to current? 305 */ 306 _playback_copy_to_current( ctx, node ); 307} 308 309 310#endif /* FEATURE_dlist */ 311