📄 vbo_save_api.c
字号:
/* Called only when buffers are wrapped as the result of filling the * vertex_store struct. */static void _save_wrap_filled_vertex( GLcontext *ctx ){ struct vbo_save_context *save = &vbo_context(ctx)->save; GLfloat *data = save->copied.buffer; GLuint i; /* Emit a glEnd to close off the last vertex list. */ _save_wrap_buffers( ctx ); /* Copy stored stored vertices to start of new list. */ assert(save->max_vert - save->vert_count > save->copied.nr); for (i = 0 ; i < save->copied.nr ; i++) { _mesa_memcpy( save->vbptr, data, save->vertex_size * sizeof(GLfloat)); data += save->vertex_size; save->vbptr += save->vertex_size; save->vert_count++; }}static void _save_copy_to_current( GLcontext *ctx ){ struct vbo_save_context *save = &vbo_context(ctx)->save; GLuint i; for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { if (save->attrsz[i]) { save->currentsz[i][0] = save->attrsz[i]; COPY_CLEAN_4V(save->current[i], save->attrsz[i], save->attrptr[i]); } }}static void _save_copy_from_current( GLcontext *ctx ){ struct vbo_save_context *save = &vbo_context(ctx)->save; GLint i; for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { switch (save->attrsz[i]) { case 4: save->attrptr[i][3] = save->current[i][3]; case 3: save->attrptr[i][2] = save->current[i][2]; case 2: save->attrptr[i][1] = save->current[i][1]; case 1: save->attrptr[i][0] = save->current[i][0]; case 0: break; } }}/* Flush existing data, set new attrib size, replay copied vertices. */ static void _save_upgrade_vertex( GLcontext *ctx, GLuint attr, GLuint newsz ){ struct vbo_save_context *save = &vbo_context(ctx)->save; GLuint oldsz; GLuint i; GLfloat *tmp; /* Store the current run of vertices, and emit a GL_END. Emit a * BEGIN in the new buffer. */ if (save->vert_count) _save_wrap_buffers( ctx ); else assert( save->copied.nr == 0 ); /* Do a COPY_TO_CURRENT to ensure back-copying works for the case * when the attribute already exists in the vertex and is having * its size increased. */ _save_copy_to_current( ctx ); /* Fix up sizes: */ oldsz = save->attrsz[attr]; save->attrsz[attr] = newsz; save->vertex_size += newsz - oldsz; save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) / save->vertex_size); save->vert_count = 0; /* Recalculate all the attrptr[] values: */ for (i = 0, tmp = save->vertex ; i < VBO_ATTRIB_MAX ; i++) { if (save->attrsz[i]) { save->attrptr[i] = tmp; tmp += save->attrsz[i]; } else save->attrptr[i] = NULL; /* will not be dereferenced. */ } /* Copy from current to repopulate the vertex with correct values. */ _save_copy_from_current( ctx ); /* Replay stored vertices to translate them to new format here. * * If there are copied vertices and the new (upgraded) attribute * has not been defined before, this list is somewhat degenerate, * and will need fixup at runtime. */ if (save->copied.nr) { GLfloat *data = save->copied.buffer; GLfloat *dest = save->buffer; GLuint j; /* Need to note this and fix up at runtime (or loopback): */ if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) { assert(oldsz == 0); save->dangling_attr_ref = GL_TRUE; } for (i = 0 ; i < save->copied.nr ; i++) { for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { if (save->attrsz[j]) { if (j == attr) { if (oldsz) { COPY_CLEAN_4V( dest, oldsz, data ); data += oldsz; dest += newsz; } else { COPY_SZ_4V( dest, newsz, save->current[attr] ); dest += newsz; } } else { GLint sz = save->attrsz[j]; COPY_SZ_4V( dest, sz, data ); data += sz; dest += sz; } } } } save->vbptr = dest; save->vert_count += save->copied.nr; }}static void save_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz ){ struct vbo_save_context *save = &vbo_context(ctx)->save; if (sz > save->attrsz[attr]) { /* New size is larger. Need to flush existing vertices and get * an enlarged vertex format. */ _save_upgrade_vertex( ctx, attr, sz ); } else if (sz < save->active_sz[attr]) { static GLfloat id[4] = { 0, 0, 0, 1 }; GLuint i; /* New size is equal or smaller - just need to fill in some * zeros. */ for (i = sz ; i <= save->attrsz[attr] ; i++) save->attrptr[attr][i-1] = id[i-1]; } save->active_sz[attr] = sz;}static void _save_reset_vertex( GLcontext *ctx ){ struct vbo_save_context *save = &vbo_context(ctx)->save; GLuint i; for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { save->attrsz[i] = 0; save->active_sz[i] = 0; } save->vertex_size = 0;}#define ERROR() _mesa_compile_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );/* Only one size for each attribute may be active at once. Eg. if * Color3f is installed/active, then Color4f may not be, even if the * vertex actually contains 4 color coordinates. This is because the * 3f version won't otherwise set color[3] to 1.0 -- this is the job * of the chooser function when switching between Color4f and Color3f. */#define ATTR( A, N, V0, V1, V2, V3 ) \do { \ struct vbo_save_context *save = &vbo_context(ctx)->save; \ \ if (save->active_sz[A] != N) \ save_fixup_vertex(ctx, A, N); \ \ { \ GLfloat *dest = save->attrptr[A]; \ if (N>0) dest[0] = V0; \ if (N>1) dest[1] = V1; \ if (N>2) dest[2] = V2; \ if (N>3) dest[3] = V3; \ } \ \ if ((A) == 0) { \ GLuint i; \ \ for (i = 0; i < save->vertex_size; i++) \ save->vbptr[i] = save->vertex[i]; \ \ save->vbptr += save->vertex_size; \ \ if (++save->vert_count >= save->max_vert) \ _save_wrap_filled_vertex( ctx ); \ } \} while (0)#define TAG(x) _save_##x#include "vbo_attrib_tmp.h"/* Cope with EvalCoord/CallList called within a begin/end object: * -- Flush current buffer * -- Fallback to opcodes for the rest of the begin/end object. */#define DO_FALLBACK(ctx) \do { \ struct vbo_save_context *save = &vbo_context(ctx)->save; \ \ if (save->vert_count || save->prim_count) \ _save_compile_vertex_list( ctx ); \ \ _save_copy_to_current( ctx ); \ _save_reset_vertex( ctx ); \ _save_reset_counters( ctx ); \ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); \ ctx->Driver.SaveNeedFlush = 0; \} while (0)static void GLAPIENTRY _save_EvalCoord1f( GLfloat u ){ GET_CURRENT_CONTEXT(ctx); DO_FALLBACK(ctx); ctx->Save->EvalCoord1f( u );}static void GLAPIENTRY _save_EvalCoord1fv( const GLfloat *v ){ GET_CURRENT_CONTEXT(ctx); DO_FALLBACK(ctx); ctx->Save->EvalCoord1fv( v );}static void GLAPIENTRY _save_EvalCoord2f( GLfloat u, GLfloat v ){ GET_CURRENT_CONTEXT(ctx); DO_FALLBACK(ctx); ctx->Save->EvalCoord2f( u, v );}static void GLAPIENTRY _save_EvalCoord2fv( const GLfloat *v ){ GET_CURRENT_CONTEXT(ctx); DO_FALLBACK(ctx); ctx->Save->EvalCoord2fv( v );}static void GLAPIENTRY _save_EvalPoint1( GLint i ){ GET_CURRENT_CONTEXT(ctx); DO_FALLBACK(ctx); ctx->Save->EvalPoint1( i );}static void GLAPIENTRY _save_EvalPoint2( GLint i, GLint j ){ GET_CURRENT_CONTEXT(ctx); DO_FALLBACK(ctx); ctx->Save->EvalPoint2( i, j );}static void GLAPIENTRY _save_CallList( GLuint l ){ GET_CURRENT_CONTEXT(ctx); DO_FALLBACK(ctx); ctx->Save->CallList( l );}static void GLAPIENTRY _save_CallLists( GLsizei n, GLenum type, const GLvoid *v ){ GET_CURRENT_CONTEXT(ctx); DO_FALLBACK(ctx); ctx->Save->CallLists( n, type, v );}/* This begin is hooked into ... Updating of * ctx->Driver.CurrentSavePrimitive is already taken care of. */GLboolean vbo_save_NotifyBegin( GLcontext *ctx, GLenum mode ){ struct vbo_save_context *save = &vbo_context(ctx)->save; GLuint i = save->prim_count++; assert(i < save->prim_max); save->prim[i].mode = mode & ~VBO_SAVE_PRIM_WEAK; save->prim[i].begin = 1; save->prim[i].end = 0; save->prim[i].weak = (mode & VBO_SAVE_PRIM_WEAK) ? 1 : 0; save->prim[i].pad = 0; save->prim[i].start = save->vert_count; save->prim[i].count = 0; _mesa_install_save_vtxfmt( ctx, &save->vtxfmt ); ctx->Driver.SaveNeedFlush = 1; return GL_TRUE;}static void GLAPIENTRY _save_End( void ){ GET_CURRENT_CONTEXT( ctx ); struct vbo_save_context *save = &vbo_context(ctx)->save; GLint i = save->prim_count - 1; ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END; save->prim[i].end = 1; save->prim[i].count = (save->vert_count - save->prim[i].start); if (i == (GLint) save->prim_max - 1) { _save_compile_vertex_list( ctx ); assert(save->copied.nr == 0); } /* Swap out this vertex format while outside begin/end. Any color, * etc. received between here and the next begin will be compiled * as opcodes. */ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );}/* These are all errors as this vtxfmt is only installed inside * begin/end pairs. */static void GLAPIENTRY _save_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices){ GET_CURRENT_CONTEXT(ctx); (void) mode; (void) count; (void) type; (void) indices; _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );}static void GLAPIENTRY _save_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices){ GET_CURRENT_CONTEXT(ctx); (void) mode; (void) start; (void) end; (void) count; (void) type; (void) indices; _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" );}static void GLAPIENTRY _save_DrawArrays(GLenum mode, GLint start, GLsizei count){ GET_CURRENT_CONTEXT(ctx); (void) mode; (void) start; (void) count; _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -