summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2008-09-18 13:14:36 +1000
committerBen Skeggs <skeggsb@gmail.com>2008-09-18 13:14:36 +1000
commitb1d8b6c4d986a6526f20e1e89982036f0ba85222 (patch)
tree5ca75a54aff8c5504731fe1e3dead9bbe3b92c44
parent6fca18696d0e6a243f6fbb5a30de45100a8e5fa0 (diff)
parenta06d38a74e865a0373a7314aad26b25c27ef8c57 (diff)
Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
-rw-r--r--progs/egl/eglinfo.c15
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_context.c24
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_wide_point.c4
-rw-r--r--src/gallium/auxiliary/tgsi/Makefile1
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_info.c4
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sanity.c22
-rw-r--r--src/gallium/auxiliary/util/u_math.h6
-rw-r--r--src/gallium/drivers/cell/ppu/cell_pipe_state.c6
-rw-r--r--src/gallium/drivers/trace/README2
-rw-r--r--src/gallium/winsys/xlib/xm_winsys.c17
-rw-r--r--src/mesa/main/bufferobj.c5
-rw-r--r--src/mesa/main/dlist.c7
-rw-r--r--src/mesa/main/mtypes.h9
-rw-r--r--src/mesa/main/state.c8
-rw-r--r--src/mesa/shader/shader_api.c81
-rw-r--r--src/mesa/shader/slang/slang_link.c196
-rw-r--r--src/mesa/shader/slang/slang_link.h8
-rw-r--r--src/mesa/state_tracker/st_atom_rasterizer.c2
-rw-r--r--src/mesa/state_tracker/st_cb_fbo.c1
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c8
-rw-r--r--src/mesa/state_tracker/st_context.c19
-rw-r--r--src/mesa/state_tracker/st_context.h6
-rw-r--r--src/mesa/state_tracker/st_framebuffer.c11
-rw-r--r--src/mesa/state_tracker/st_mesa_to_tgsi.c26
-rw-r--r--src/mesa/state_tracker/st_program.c5
-rw-r--r--src/mesa/vbo/vbo_context.c10
-rw-r--r--src/mesa/vbo/vbo_save_api.c26
27 files changed, 349 insertions, 180 deletions
diff --git a/progs/egl/eglinfo.c b/progs/egl/eglinfo.c
index 89feec9be..14620a975 100644
--- a/progs/egl/eglinfo.c
+++ b/progs/egl/eglinfo.c
@@ -48,9 +48,9 @@ PrintConfigs(EGLDisplay d)
eglGetConfigs(d, configs, MAX_CONFIGS, &numConfigs);
printf("Configurations:\n");
- printf(" bf lv d st colorbuffer dp st vis supported\n");
- printf(" id sz l b ro r g b a th cl id surfaces \n");
- printf("---------------------------------------------------\n");
+ printf(" bf lv d st colorbuffer dp st ms vis supported\n");
+ printf(" id sz l b ro r g b a th cl ns b id surfaces \n");
+ printf("--------------------------------------------------------\n");
for (i = 0; i < numConfigs; i++) {
EGLint id, size, level;
EGLint red, green, blue, alpha;
@@ -58,6 +58,7 @@ PrintConfigs(EGLDisplay d)
EGLint surfaces;
EGLint doubleBuf = 1, stereo = 0;
EGLint vid;
+ EGLint samples, sampleBuffers;
char surfString[100] = "";
eglGetConfigAttrib(d, configs[i], EGL_CONFIG_ID, &id);
@@ -73,6 +74,9 @@ PrintConfigs(EGLDisplay d)
eglGetConfigAttrib(d, configs[i], EGL_NATIVE_VISUAL_ID, &vid);
eglGetConfigAttrib(d, configs[i], EGL_SURFACE_TYPE, &surfaces);
+ eglGetConfigAttrib(d, configs[i], EGL_SAMPLES, &samples);
+ eglGetConfigAttrib(d, configs[i], EGL_SAMPLE_BUFFERS, &sampleBuffers);
+
if (surfaces & EGL_WINDOW_BIT)
strcat(surfString, "win,");
if (surfaces & EGL_PBUFFER_BIT)
@@ -86,12 +90,13 @@ PrintConfigs(EGLDisplay d)
if (strlen(surfString) > 0)
surfString[strlen(surfString) - 1] = 0;
- printf("0x%02x %2d %2d %c %c %2d %2d %2d %2d %2d %2d 0x%02x %-12s\n",
+ printf("0x%02x %2d %2d %c %c %2d %2d %2d %2d %2d %2d %2d%2d 0x%02x %-12s\n",
id, size, level,
doubleBuf ? 'y' : '.',
stereo ? 'y' : '.',
red, green, blue, alpha,
- depth, stencil, vid, surfString);
+ depth, stencil,
+ samples, sampleBuffers, vid, surfString);
}
}
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
index f22ba4082..b1ccfc037 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.c
+++ b/src/gallium/auxiliary/cso_cache/cso_context.c
@@ -765,12 +765,30 @@ void cso_restore_vertex_shader(struct cso_context *ctx)
}
+/**
+ * Copy framebuffer state from src to dst with refcounting of surfaces.
+ */
+static void
+copy_framebuffer_state(struct pipe_framebuffer_state *dst,
+ const struct pipe_framebuffer_state *src)
+{
+ uint i;
+
+ dst->width = src->width;
+ dst->height = src->height;
+ dst->num_cbufs = src->num_cbufs;
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+ pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
+ }
+ pipe_surface_reference(&dst->zsbuf, src->zsbuf);
+}
+
enum pipe_error cso_set_framebuffer(struct cso_context *ctx,
const struct pipe_framebuffer_state *fb)
{
if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) {
- ctx->fb = *fb;
+ copy_framebuffer_state(&ctx->fb, fb);
ctx->pipe->set_framebuffer_state(ctx->pipe, fb);
}
return PIPE_OK;
@@ -778,13 +796,13 @@ enum pipe_error cso_set_framebuffer(struct cso_context *ctx,
void cso_save_framebuffer(struct cso_context *ctx)
{
- ctx->fb_saved = ctx->fb;
+ copy_framebuffer_state(&ctx->fb_saved, &ctx->fb);
}
void cso_restore_framebuffer(struct cso_context *ctx)
{
if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) {
- ctx->fb = ctx->fb_saved;
+ copy_framebuffer_state(&ctx->fb, &ctx->fb_saved);
ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb);
}
}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c
index 4f1326053..e1af9e56a 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c
@@ -222,8 +222,8 @@ static void widepoint_first_point( struct draw_stage *stage,
/* find fragment shader PointCoord/Fog input */
wide->point_coord_fs_input = 0; /* XXX fix this! */
- /* setup extra vp output */
- draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_FOG;
+ /* setup extra vp output (point coord implemented as a texcoord) */
+ draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
draw->extra_vp_outputs.semantic_index = 0;
draw->extra_vp_outputs.slot = draw->vs.num_vs_outputs;
}
diff --git a/src/gallium/auxiliary/tgsi/Makefile b/src/gallium/auxiliary/tgsi/Makefile
index 806a2bd4c..c5d208208 100644
--- a/src/gallium/auxiliary/tgsi/Makefile
+++ b/src/gallium/auxiliary/tgsi/Makefile
@@ -4,6 +4,7 @@ include $(TOP)/configs/current
LIBNAME = tgsi
C_SOURCES = \
+ tgsi_sanity.c \
tgsi_build.c \
tgsi_dump.c \
tgsi_exec.c \
diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c
index a4899cd4c..68c7a6b7f 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_info.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_info.c
@@ -69,7 +69,7 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] =
{ 1, 1, 0, 0, "COS" },
{ 1, 1, 0, 0, "DDX" },
{ 1, 1, 0, 0, "DDY" },
- { 0, 1, 0, 0, "KILP" },
+ { 0, 0, 0, 0, "KILP" },
{ 1, 1, 0, 0, "PK2H" },
{ 1, 1, 0, 0, "PK2US" },
{ 1, 1, 0, 0, "PK4B" },
@@ -146,7 +146,7 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] =
{ 0, 1, 0, 0, "CALLNZ" },
{ 0, 1, 0, 0, "IFC" },
{ 0, 1, 0, 0, "BREAKC" },
- { 0, 0, 0, 0, "KIL" },
+ { 0, 1, 0, 0, "KIL" },
{ 0, 0, 0, 0, "END" },
{ 1, 1, 0, 0, "SWZ" }
};
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
index c65902729..11659247c 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
@@ -152,6 +152,12 @@ check_register_usage(
{
if (!check_file_name( ctx, file ))
return FALSE;
+
+ if (index < 0 || index > MAX_REGISTERS) {
+ report_error( ctx, "%s[%i]: Invalid index %s", file_names[file], index, name );
+ return FALSE;
+ }
+
if (indirect_access) {
if (!is_any_register_declared( ctx, file ))
report_error( ctx, "%s: Undeclared %s register", file_names[file], name );
@@ -174,12 +180,10 @@ iter_instruction(
const struct tgsi_opcode_info *info;
uint i;
- /* There must be no other instructions after END.
- */
- if (ctx->index_of_END != ~0) {
- report_error( ctx, "Unexpected instruction after END" );
- }
- else if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
+ if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
+ if (ctx->index_of_END != ~0) {
+ report_error( ctx, "Too many END instructions" );
+ }
ctx->index_of_END = ctx->num_instructions;
}
@@ -301,10 +305,10 @@ epilog(
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
uint file;
- /* There must be an END instruction at the end.
+ /* There must be an END instruction somewhere.
*/
- if (ctx->index_of_END == ~0 || ctx->index_of_END != ctx->num_instructions - 1) {
- report_error( ctx, "Expected END at end of instruction sequence" );
+ if (ctx->index_of_END == ~0) {
+ report_error( ctx, "Missing END instruction" );
}
/* Check if all declared registers were used.
diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h
index 9b4ca3937..0b10622ee 100644
--- a/src/gallium/auxiliary/util/u_math.h
+++ b/src/gallium/auxiliary/util/u_math.h
@@ -272,8 +272,10 @@ util_fast_log2(float val)
static INLINE float
util_fast_pow(float x, float y)
{
- /* XXX this test may need adjustment */
- if (y >= 3.0 && -0.02f <= x && x <= 0.02f)
+ /* XXX these tests may need adjustment */
+ if (y >= 3.0f && (-0.02f <= x && x <= 0.02f))
+ return 0.0f;
+ if (y >= 50.0f && (-0.9f <= x && x <= 0.9f))
return 0.0f;
return util_fast_exp2(util_fast_log2(x) * y);
}
diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c
index e04cf5f27..475c6ef0c 100644
--- a/src/gallium/drivers/cell/ppu/cell_pipe_state.c
+++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c
@@ -48,8 +48,9 @@ cell_create_blend_state(struct pipe_context *pipe,
struct cell_blend_state *cb = MALLOC(sizeof(struct cell_blend_state));
(void) memcpy(cb, blend, sizeof(*blend));
+#if 0
cell_generate_alpha_blend(cb);
-
+#endif
return cb;
}
@@ -100,8 +101,9 @@ cell_create_depth_stencil_alpha_state(struct pipe_context *pipe,
MALLOC(sizeof(struct cell_depth_stencil_alpha_state));
(void) memcpy(cdsa, depth_stencil, sizeof(*depth_stencil));
+#if 0
cell_generate_depth_stencil_test(cdsa);
-
+#endif
return cdsa;
}
diff --git a/src/gallium/drivers/trace/README b/src/gallium/drivers/trace/README
index e7a2f12b0..f0e1cd596 100644
--- a/src/gallium/drivers/trace/README
+++ b/src/gallium/drivers/trace/README
@@ -10,7 +10,7 @@ This directory contains a Gallium3D pipe driver which traces all incoming calls.
To build, invoke scons on the top dir as
- scons statetrackers=mesa drivers=softpipe,i915simple,trace winsys=xlib
+ scons statetrackers=mesa drivers=softpipe,i965simple,trace winsys=xlib
= Usage =
diff --git a/src/gallium/winsys/xlib/xm_winsys.c b/src/gallium/winsys/xlib/xm_winsys.c
index 2acbc94fc..3334af175 100644
--- a/src/gallium/winsys/xlib/xm_winsys.c
+++ b/src/gallium/winsys/xlib/xm_winsys.c
@@ -349,19 +349,26 @@ xmesa_display_surface_tiled(XMesaBuffer b, const struct pipe_surface *surf)
if (x + w > surf->width)
w = surf->width - x;
- offset *= 4 * TILE_SIZE * TILE_SIZE;
-
- twiddle_tile((uint *) ((char *) xm_buf->data + offset),
- tmpTile);
- ximage->data = (char*) tmpTile;
+ /* offset in pixels */
+ offset *= TILE_SIZE * TILE_SIZE;
if (XSHM_ENABLED(xm_buf)) {
+ ximage->data = (char *) xm_buf->data + 4 * offset;
+ /* make copy of tile data */
+ memcpy(tmpTile, (uint *) ximage->data, sizeof(tmpTile));
+ /* twiddle from temp to ximage in shared memory */
+ twiddle_tile(tmpTile, (uint *) ximage->data);
+ /* display image in shared memory */
#if defined(USE_XSHM) && !defined(XFree86Server)
XShmPutImage(b->xm_visual->display, b->drawable, b->gc,
ximage, 0, 0, x, y, w, h, False);
#endif
}
else {
+ /* twiddel from ximage buffer to temp tile */
+ twiddle_tile((uint *) xm_buf->data + offset, tmpTile);
+ /* display temp tile data */
+ ximage->data = (char *) tmpTile;
XPutImage(b->xm_visual->display, b->drawable, b->gc,
ximage, 0, 0, x, y, w, h);
}
diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c
index f1e0932b0..ecdb4d219 100644
--- a/src/mesa/main/bufferobj.c
+++ b/src/mesa/main/bufferobj.c
@@ -205,11 +205,14 @@ _mesa_reference_buffer_object(GLcontext *ctx,
if (deleteFlag) {
/* some sanity checking: don't delete a buffer still in use */
+#if 0
+ /* unfortunately, these tests are invalid during context tear-down */
ASSERT(ctx->Array.ArrayBufferObj != bufObj);
ASSERT(ctx->Array.ElementArrayBufferObj != bufObj);
ASSERT(ctx->Array.ArrayObj->Vertex.BufferObj != bufObj);
- ASSERT(ctx->Driver.DeleteBuffer);
+#endif
+ ASSERT(ctx->Driver.DeleteBuffer);
ctx->Driver.DeleteBuffer(ctx, oldObj);
}
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
index b4ed300b2..ffe6dbfe0 100644
--- a/src/mesa/main/dlist.c
+++ b/src/mesa/main/dlist.c
@@ -6737,6 +6737,11 @@ _mesa_EndList(void)
_mesa_error(ctx, GL_INVALID_OPERATION, "glEndList");
return;
}
+
+ /* Call before emitting END_OF_LIST, in case the driver wants to
+ * emit opcodes itself.
+ */
+ ctx->Driver.EndList(ctx);
(void) ALLOC_INSTRUCTION(ctx, OPCODE_END_OF_LIST, 0);
@@ -6750,8 +6755,6 @@ _mesa_EndList(void)
if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST)
mesa_print_display_list(ctx->ListState.CurrentListNum);
- ctx->Driver.EndList(ctx);
-
ctx->ListState.CurrentList = NULL;
ctx->ListState.CurrentListNum = 0;
ctx->ListState.CurrentListPtr = NULL;
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 71a4ca55b..a5e1cf6a2 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1953,7 +1953,10 @@ struct gl_fragment_program
{
struct gl_program Base; /**< base class */
GLenum FogOption;
- GLboolean UsesKill;
+ GLboolean UsesKill; /**< shader uses KIL instruction */
+ GLboolean UsesPointCoord; /**< shader uses gl_PointCoord */
+ GLboolean UsesFrontFacing; /**< shader used gl_FrontFacing */
+ GLboolean UsesFogFragCoord; /**< shader used gl_FogFragCoord */
};
@@ -2143,12 +2146,14 @@ struct gl_shader_program
GLuint NumShaders; /**< number of attached shaders */
struct gl_shader **Shaders; /**< List of attached the shaders */
+ /** User-defined attribute bindings (glBindAttribLocation) */
+ struct gl_program_parameter_list *Attributes;
+
/* post-link info: */
struct gl_vertex_program *VertexProgram; /**< Linked vertex program */
struct gl_fragment_program *FragmentProgram; /**< Linked fragment prog */
struct gl_uniform_list *Uniforms;
struct gl_program_parameter_list *Varying;
- struct gl_program_parameter_list *Attributes; /**< Vertex attributes */
GLboolean LinkStatus; /**< GL_LINK_STATUS */
GLboolean Validated;
GLchar *InfoLog;
diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
index 344af91e1..d355f78a0 100644
--- a/src/mesa/main/state.c
+++ b/src/mesa/main/state.c
@@ -295,10 +295,10 @@ static void
update_multisample(GLcontext *ctx)
{
ctx->Multisample._Enabled = GL_FALSE;
- if (ctx->DrawBuffer) {
- if (ctx->DrawBuffer->Visual.sampleBuffers)
- ctx->Multisample._Enabled = GL_TRUE;
- }
+ if (ctx->Multisample.Enabled &&
+ ctx->DrawBuffer &&
+ ctx->DrawBuffer->Visual.sampleBuffers)
+ ctx->Multisample._Enabled = GL_TRUE;
}
diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c
index d8b210be5..decdec53e 100644
--- a/src/mesa/shader/shader_api.c
+++ b/src/mesa/shader/shader_api.c
@@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.2
*
* Copyright (C) 2004-2008 Brian Paul All Rights Reserved.
*
@@ -497,10 +497,14 @@ _mesa_get_attrib_location(GLcontext *ctx, GLuint program,
if (!name)
return -1;
- if (shProg->Attributes) {
- GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
- if (i >= 0) {
- return shProg->Attributes->Parameters[i].StateIndexes[0];
+ if (shProg->VertexProgram) {
+ const struct gl_program_parameter_list *attribs =
+ shProg->VertexProgram->Base.Attributes;
+ if (attribs) {
+ GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
+ if (i >= 0) {
+ return attribs->Parameters[i].StateIndexes[0];
+ }
}
}
return -1;
@@ -513,7 +517,7 @@ _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
{
struct gl_shader_program *shProg;
const GLint size = -1; /* unknown size */
- GLint i, oldIndex;
+ GLint i;
GLenum datatype = GL_FLOAT_VEC4;
shProg = _mesa_lookup_shader_program_err(ctx, program,
@@ -536,14 +540,6 @@ _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
return;
}
- if (shProg->LinkStatus) {
- /* get current index/location for the attribute */
- oldIndex = _mesa_get_attrib_location(ctx, program, name);
- }
- else {
- oldIndex = -1;
- }
-
/* this will replace the current value if it's already in the list */
i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
if (i < 0) {
@@ -551,12 +547,10 @@ _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
return;
}
- if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) {
- /* If the index changed, need to search/replace references to that attribute
- * in the vertex program.
- */
- _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
- }
+ /*
+ * Note that this attribute binding won't go into effect until
+ * glLinkProgram is called again.
+ */
}
@@ -798,24 +792,29 @@ _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
GLsizei maxLength, GLsizei *length, GLint *size,
GLenum *type, GLchar *nameOut)
{
+ const struct gl_program_parameter_list *attribs = NULL;
struct gl_shader_program *shProg;
shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
if (!shProg)
return;
- if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
+ if (shProg->VertexProgram)
+ attribs = shProg->VertexProgram->Base.Attributes;
+
+ if (!attribs || index >= attribs->NumParameters) {
_mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
return;
}
- copy_string(nameOut, maxLength, length,
- shProg->Attributes->Parameters[index].Name);
+ copy_string(nameOut, maxLength, length, attribs->Parameters[index].Name);
+
if (size)
- *size = shProg->Attributes->Parameters[index].Size
- / sizeof_glsl_type(shProg->Attributes->Parameters[index].DataType);
+ *size = attribs->Parameters[index].Size
+ / sizeof_glsl_type(attribs->Parameters[index].DataType);
+
if (type)
- *type = shProg->Attributes->Parameters[index].DataType;
+ *type = attribs->Parameters[index].DataType;
}
@@ -937,6 +936,7 @@ static void
_mesa_get_programiv(GLcontext *ctx, GLuint program,
GLenum pname, GLint *params)
{
+ const struct gl_program_parameter_list *attribs;
struct gl_shader_program *shProg
= _mesa_lookup_shader_program(ctx, program);
@@ -945,6 +945,11 @@ _mesa_get_programiv(GLcontext *ctx, GLuint program,
return;
}
+ if (shProg->VertexProgram)
+ attribs = shProg->VertexProgram->Base.Attributes;
+ else
+ attribs = NULL;
+
switch (pname) {
case GL_DELETE_STATUS:
*params = shProg->DeletePending;
@@ -962,11 +967,10 @@ _mesa_get_programiv(GLcontext *ctx, GLuint program,
*params = shProg->NumShaders;
break;
case GL_ACTIVE_ATTRIBUTES:
- *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
+ *params = attribs ? attribs->NumParameters : 0;
break;
case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
- *params = _mesa_longest_parameter_name(shProg->Attributes,
- PROGRAM_INPUT) + 1;
+ *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
break;
case GL_ACTIVE_UNIFORMS:
*params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
@@ -1108,7 +1112,8 @@ get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
/**
* Determine the number of rows and columns occupied by a uniform
- * according to its datatype.
+ * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4),
+ * the number of rows = 1 and cols = number of elements in the vector.
*/
static void
get_uniform_rows_cols(const struct gl_program_parameter *p,
@@ -1117,11 +1122,17 @@ get_uniform_rows_cols(const struct gl_program_parameter *p,
get_matrix_dims(p->DataType, rows, cols);
if (*rows == 0 && *cols == 0) {
/* not a matrix type, probably a float or vector */
- *rows = p->Size / 4 + 1;
- if (p->Size % 4 == 0)
- *cols = 4;
- else
- *cols = p->Size % 4;
+ if (p->Size <= 4) {
+ *rows = 1;
+ *cols = p->Size;
+ }
+ else {
+ *rows = p->Size / 4 + 1;
+ if (p->Size % 4 == 0)
+ *cols = 4;
+ else
+ *cols = p->Size % 4;
+ }
}
}
diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c
index 57dbfc238..dd7d5be6d 100644
--- a/src/mesa/shader/slang/slang_link.c
+++ b/src/mesa/shader/slang/slang_link.c
@@ -1,8 +1,8 @@
/*
* Mesa 3-D graphics library
- * Version: 6.5.3
+ * Version: 7.2
*
- * Copyright (C) 2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -42,6 +42,24 @@
#include "slang_link.h"
+/** cast wrapper */
+static struct gl_vertex_program *
+vertex_program(struct gl_program *prog)
+{
+ assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
+ return (struct gl_vertex_program *) prog;
+}
+
+
+/** cast wrapper */
+static struct gl_fragment_program *
+fragment_program(struct gl_program *prog)
+{
+ assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
+ return (struct gl_fragment_program *) prog;
+}
+
+
/**
* Record a linking error.
*/
@@ -215,74 +233,112 @@ link_uniform_vars(struct gl_shader_program *shProg,
* For example, if the vertex shader declared "attribute vec4 foobar" we'll
* allocate a generic vertex attribute for "foobar" and plug that value into
* the vertex program instructions.
+ * But if the user called glBindAttributeLocation(), those bindings will
+ * have priority.
*/
static GLboolean
_slang_resolve_attributes(struct gl_shader_program *shProg,
- struct gl_program *prog)
+ const struct gl_program *origProg,
+ struct gl_program *linkedProg)
{
+ GLint attribMap[MAX_VERTEX_ATTRIBS];
GLuint i, j;
GLbitfield usedAttributes;
- assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
+ assert(origProg != linkedProg);
+ assert(origProg->Target == GL_VERTEX_PROGRAM_ARB);
+ assert(linkedProg->Target == GL_VERTEX_PROGRAM_ARB);
if (!shProg->Attributes)
shProg->Attributes = _mesa_new_parameter_list();
+ if (linkedProg->Attributes) {
+ _mesa_free_parameter_list(linkedProg->Attributes);
+ }
+ linkedProg->Attributes = _mesa_new_parameter_list();
+
+
/* Build a bitmask indicating which attribute indexes have been
* explicitly bound by the user with glBindAttributeLocation().
*/
usedAttributes = 0x0;
for (i = 0; i < shProg->Attributes->NumParameters; i++) {
GLint attr = shProg->Attributes->Parameters[i].StateIndexes[0];
- usedAttributes |= attr;
+ usedAttributes |= (1 << attr);
+ }
+
+ /* initialize the generic attribute map entries to -1 */
+ for (i = 0; i < MAX_VERTEX_ATTRIBS; i++) {
+ attribMap[i] = -1;
}
/*
* Scan program for generic attribute references
*/
- for (i = 0; i < prog->NumInstructions; i++) {
- struct prog_instruction *inst = prog->Instructions + i;
+ for (i = 0; i < linkedProg->NumInstructions; i++) {
+ struct prog_instruction *inst = linkedProg->Instructions + i;
for (j = 0; j < 3; j++) {
if (inst->SrcReg[j].File == PROGRAM_INPUT &&
inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) {
- /* this is a generic attrib */
- const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0;
- const char *name = prog->Attributes->Parameters[k].Name;
- /* See if this attrib name is in the program's attribute list
- * (i.e. was bound by the user).
+ /*
+ * OK, we've found a generic vertex attribute reference.
*/
- GLint index = _mesa_lookup_parameter_index(shProg->Attributes,
- -1, name);
- GLint attr;
- if (index >= 0) {
- /* found, user must have specified a binding */
- attr = shProg->Attributes->Parameters[index].StateIndexes[0];
- }
- else {
- /* Not found, choose our own attribute number.
- * Start at 1 since generic attribute 0 always aliases
- * glVertex/position.
+ const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0;
+
+ GLint attr = attribMap[k];
+
+ if (attr < 0) {
+ /* Need to figure out attribute mapping now.
+ */
+ const char *name = origProg->Attributes->Parameters[k].Name;
+ const GLint size = origProg->Attributes->Parameters[k].Size;
+ const GLenum type =origProg->Attributes->Parameters[k].DataType;
+ GLint index;
+
+ /* See if there's a user-defined attribute binding for
+ * this name.
*/
- GLint size = prog->Attributes->Parameters[k].Size;
- GLenum datatype = prog->Attributes->Parameters[k].DataType;
- for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) {
- if (((1 << attr) & usedAttributes) == 0)
- break;
+ index = _mesa_lookup_parameter_index(shProg->Attributes,
+ -1, name);
+ if (index >= 0) {
+ /* Found a user-defined binding */
+ attr = shProg->Attributes->Parameters[index].StateIndexes[0];
}
- if (attr == MAX_VERTEX_ATTRIBS) {
- /* too many! XXX record error log */
- return GL_FALSE;
+ else {
+ /* No user-defined binding, choose our own attribute number.
+ * Start at 1 since generic attribute 0 always aliases
+ * glVertex/position.
+ */
+ for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) {
+ if (((1 << attr) & usedAttributes) == 0)
+ break;
+ }
+ if (attr == MAX_VERTEX_ATTRIBS) {
+ link_error(shProg, "Too many vertex attributes");
+ return GL_FALSE;
+ }
+
+ /* mark this attribute as used */
+ usedAttributes |= (1 << attr);
}
- _mesa_add_attribute(shProg->Attributes, name, size, datatype,attr);
- /* set the attribute as used */
- usedAttributes |= 1<<attr;
+ attribMap[k] = attr;
+
+ /* Save the final name->attrib binding so it can be queried
+ * with glGetAttributeLocation().
+ */
+ _mesa_add_attribute(linkedProg->Attributes, name,
+ size, type, attr);
}
+ assert(attr >= 0);
+
+ /* update the instruction's src reg */
inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + attr;
}
}
}
+
return GL_TRUE;
}
@@ -325,6 +381,7 @@ static void
_slang_update_inputs_outputs(struct gl_program *prog)
{
GLuint i, j;
+ GLuint maxAddrReg = 0;
prog->InputsRead = 0x0;
prog->OutputsWritten = 0x0;
@@ -335,60 +392,34 @@ _slang_update_inputs_outputs(struct gl_program *prog)
for (j = 0; j < numSrc; j++) {
if (inst->SrcReg[j].File == PROGRAM_INPUT) {
prog->InputsRead |= 1 << inst->SrcReg[j].Index;
+ if (prog->Target == GL_FRAGMENT_PROGRAM_ARB &&
+ inst->SrcReg[j].Index == FRAG_ATTRIB_FOGC) {
+ /* The fragment shader FOGC input is used for fog,
+ * front-facing and sprite/point coord.
+ */
+ struct gl_fragment_program *fp = fragment_program(prog);
+ const GLint swz = GET_SWZ(inst->SrcReg[j].Swizzle, 0);
+ if (swz == SWIZZLE_X)
+ fp->UsesFogFragCoord = GL_TRUE;
+ else if (swz == SWIZZLE_Y)
+ fp->UsesFrontFacing = GL_TRUE;
+ else if (swz == SWIZZLE_Z || swz == SWIZZLE_W)
+ fp->UsesPointCoord = GL_TRUE;
+ }
+ }
+ else if (inst->SrcReg[j].File == PROGRAM_ADDRESS) {
+ maxAddrReg = MAX2(maxAddrReg, inst->SrcReg[j].Index + 1);
}
}
if (inst->DstReg.File == PROGRAM_OUTPUT) {
prog->OutputsWritten |= 1 << inst->DstReg.Index;
}
- }
-}
-
-
-/**
- * Scan a vertex program looking for instances of
- * (PROGRAM_INPUT, VERT_ATTRIB_GENERIC0 + oldAttrib) and replace with
- * (PROGRAM_INPUT, VERT_ATTRIB_GENERIC0 + newAttrib).
- * This is used when the user calls glBindAttribLocation on an already linked
- * shader program.
- */
-void
-_slang_remap_attribute(struct gl_program *prog, GLuint oldAttrib, GLuint newAttrib)
-{
- GLuint i, j;
-
- assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
-
- for (i = 0; i < prog->NumInstructions; i++) {
- struct prog_instruction *inst = prog->Instructions + i;
- for (j = 0; j < 3; j++) {
- if (inst->SrcReg[j].File == PROGRAM_INPUT) {
- if (inst->SrcReg[j].Index == VERT_ATTRIB_GENERIC0 + oldAttrib) {
- inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + newAttrib;
- }
- }
+ else if (inst->DstReg.File == PROGRAM_ADDRESS) {
+ maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1);
}
}
- _slang_update_inputs_outputs(prog);
-}
-
-
-
-/** cast wrapper */
-static struct gl_vertex_program *
-vertex_program(struct gl_program *prog)
-{
- assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
- return (struct gl_vertex_program *) prog;
-}
-
-
-/** cast wrapper */
-static struct gl_fragment_program *
-fragment_program(struct gl_program *prog)
-{
- assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
- return (struct gl_fragment_program *) prog;
+ prog->NumAddressRegs = maxAddrReg;
}
@@ -492,9 +523,8 @@ _slang_link(GLcontext *ctx,
/*_mesa_print_uniforms(shProg->Uniforms);*/
if (shProg->VertexProgram) {
- if (!_slang_resolve_attributes(shProg, &shProg->VertexProgram->Base)) {
- /*goto cleanup;*/
- _mesa_problem(ctx, "_slang_resolve_attributes() failed");
+ if (!_slang_resolve_attributes(shProg, &vertProg->Base,
+ &shProg->VertexProgram->Base)) {
return;
}
}
diff --git a/src/mesa/shader/slang/slang_link.h b/src/mesa/shader/slang/slang_link.h
index 8ef8a6b4b..2b44d2078 100644
--- a/src/mesa/shader/slang/slang_link.h
+++ b/src/mesa/shader/slang/slang_link.h
@@ -1,8 +1,8 @@
/*
* Mesa 3-D graphics library
- * Version: 6.5.3
+ * Version: 7.2
*
- * Copyright (C) 2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -32,10 +32,6 @@ extern void
_slang_link(GLcontext *ctx, GLhandleARB h,
struct gl_shader_program *shProg);
-extern void
-_slang_remap_attribute(struct gl_program *prog, GLuint oldAttrib,
- GLuint newAttrib);
-
#endif
diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c
index e286dc511..fc47896c2 100644
--- a/src/mesa/state_tracker/st_atom_rasterizer.c
+++ b/src/mesa/state_tracker/st_atom_rasterizer.c
@@ -254,7 +254,7 @@ static void update_raster_state( struct st_context *st )
raster->line_stipple_factor = ctx->Line.StippleFactor - 1;
/* _NEW_MULTISAMPLE */
- if (ctx->Multisample._Enabled)
+ if (ctx->Multisample._Enabled || st->force_msaa)
raster->multisample = 1;
/* _NEW_SCISSOR */
diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
index 8406bf247..00076f61e 100644
--- a/src/mesa/state_tracker/st_cb_fbo.c
+++ b/src/mesa/state_tracker/st_cb_fbo.c
@@ -170,6 +170,7 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
0, 0, 0,
surface_usage );
+ assert(strb->surface->texture);
assert(strb->surface->buffer);
assert(strb->surface->format);
assert(strb->surface->block.size);
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index a3e8fc992..2e1ad9394 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -455,6 +455,11 @@ st_TexImage(GLcontext * ctx,
_mesa_align_free(texImage->Data);
}
+ if (width == 0 || height == 0 || depth == 0) {
+ /* stop after freeing old image */
+ return;
+ }
+
/* If this is the only mipmap level in the texture, could call
* bmBufferData with NULL data to free the old block and avoid
* waiting on any outstanding fences.
@@ -1048,7 +1053,8 @@ st_copy_texsubimage(GLcontext *ctx,
GLboolean use_fallback = GL_TRUE;
GLboolean matching_base_formats;
- st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ /* any rendering in progress must complete before we grab the fb image */
+ st_finish(ctx->st);
/* determine if copying depth or color data */
if (texBaseFormat == GL_DEPTH_COMPONENT) {
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index 08d4db7f7..cca808d32 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -88,6 +88,19 @@ void st_invalidate_state(GLcontext * ctx, GLuint new_state)
}
+/**
+ * Check for multisample env var override.
+ */
+int
+st_get_msaa(void)
+{
+ const char *msaa = _mesa_getenv("__GL_FSAA_MODE");
+ if (msaa)
+ return atoi(msaa);
+ return 0;
+}
+
+
static struct st_context *
st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe )
{
@@ -141,6 +154,8 @@ st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe )
st->pixel_xfer.cache = _mesa_new_program_cache();
+ st->force_msaa = st_get_msaa();
+
/* GL limits and extensions */
st_init_limits(st);
st_init_extensions(st);
@@ -188,8 +203,6 @@ static void st_destroy_context_priv( struct st_context *st )
st_destroy_drawtex(st);
#endif
- _vbo_DestroyContext(st->ctx);
-
for (i = 0; i < Elements(st->state.sampler_texture); i++) {
pipe_texture_reference(&st->state.sampler_texture[i], NULL);
}
@@ -223,6 +236,8 @@ void st_destroy_context( struct st_context *st )
_mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache);
+ _vbo_DestroyContext(st->ctx);
+
_mesa_free_context_data(ctx);
st_destroy_context_priv(st);
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 4314d9af5..1d1aca311 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -181,6 +181,8 @@ struct st_context
struct blit_state *blit;
struct cso_context *cso_context;
+
+ int force_msaa;
};
@@ -238,4 +240,8 @@ st_fb_orientation(const struct gl_framebuffer *fb)
}
+extern int
+st_get_msaa(void);
+
+
#endif
diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c
index 0f4a03fa4..ec8928f20 100644
--- a/src/mesa/state_tracker/st_framebuffer.c
+++ b/src/mesa/state_tracker/st_framebuffer.c
@@ -51,13 +51,12 @@ st_create_framebuffer( const __GLcontextModes *visual,
{
struct st_framebuffer *stfb = CALLOC_STRUCT(st_framebuffer);
if (stfb) {
- int samples = 0;
- const char *msaa_override = _mesa_getenv("__GL_FSAA_MODE");
+ int samples = st_get_msaa();
+
+ if (visual->sampleBuffers)
+ samples = visual->samples;
+
_mesa_initialize_framebuffer(&stfb->Base, visual);
- if (visual->sampleBuffers) samples = visual->samples;
- if (msaa_override) {
- samples = _mesa_atoi(msaa_override);
- }
{
/* fake frontbuffer */
diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c
index 5ec9fddd7..b9807bb80 100644
--- a/src/mesa/state_tracker/st_mesa_to_tgsi.c
+++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c
@@ -35,10 +35,13 @@
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_build.h"
#include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_sanity.h"
#include "st_mesa_to_tgsi.h"
#include "shader/prog_instruction.h"
#include "shader/prog_parameter.h"
-
+#include "shader/prog_print.h"
+#include "pipe/p_debug.h"
/*
* Map mesa register file to TGSI register file.
@@ -239,6 +242,15 @@ compile_instruction(
immediateMapping,
indirectAccess );
+ /**
+ * This not at all the correct solution.
+ * FIXME: Roll this up in the above map functions
+ */
+ if (fullsrc->SrcRegister.File == TGSI_FILE_IMMEDIATE && fullsrc->SrcRegister.Index == ~0) {
+ fullsrc->SrcRegister.File = TGSI_FILE_CONSTANT;
+ fullsrc->SrcRegister.Index = inst->SrcReg[i].Index;
+ }
+
/* swizzle (ext swizzle also depends on negation) */
{
GLuint swz[4];
@@ -980,5 +992,17 @@ tgsi_translate_mesa_program(
maxTokens - ti );
}
+#if DEBUG
+ if(!tgsi_sanity_check(tokens)) {
+ debug_printf("Due to sanity check failure(s) above the following shader program is invalid:\n");
+ debug_printf("\nOriginal program:\n%s", program->String);
+ debug_printf("\nMesa program:\n");
+ _mesa_print_program(program);
+ debug_printf("\nTGSI program:\n");
+ tgsi_dump(tokens, 0);
+ assert(0);
+ }
+#endif
+
return ti;
}
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 936a6e32e..b2abf0286 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -409,7 +409,10 @@ st_translate_fragment_program(struct st_context *st,
interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
break;
case FRAG_ATTRIB_FOGC:
- stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ if (stfp->Base.UsesPointCoord)
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ else
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
stfp->input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
break;
diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c
index dc7c53425..b452ac8a3 100644
--- a/src/mesa/vbo/vbo_context.c
+++ b/src/mesa/vbo/vbo_context.c
@@ -246,12 +246,14 @@ void _vbo_DestroyContext( GLcontext *ctx )
ctx->aelt_context = NULL;
}
- vbo_exec_destroy(ctx);
+ if (vbo_context(ctx)) {
+ vbo_exec_destroy(ctx);
#if FEATURE_dlist
- vbo_save_destroy(ctx);
+ vbo_save_destroy(ctx);
#endif
- FREE(vbo_context(ctx));
- ctx->swtnl_im = NULL;
+ FREE(vbo_context(ctx));
+ ctx->swtnl_im = NULL;
+ }
}
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index 88d573f12..f69a33d81 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -1045,6 +1045,32 @@ void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode )
void vbo_save_EndList( GLcontext *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ /* EndList called inside a (saved) Begin/End pair?
+ */
+ if (ctx->Driver.CurrentSavePrimitive != PRIM_OUTSIDE_BEGIN_END) {
+
+ if (save->prim_count > 0) {
+ GLint i = save->prim_count - 1;
+ ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
+ save->prim[i].end = 0;
+ save->prim[i].count = (save->vert_count -
+ save->prim[i].start);
+ }
+
+ /* Make sure this vertex list gets replayed by the "loopback"
+ * mechanism:
+ */
+ save->dangling_attr_ref = 1;
+ vbo_save_SaveFlushVertices( ctx );
+
+ /* 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 );
+ }
+
unmap_vertex_store( ctx, save->vertex_store );
assert(save->vertex_size == 0);