diff options
author | Brian Paul <[email protected]> | 2002-01-06 03:54:12 +0000 |
---|---|---|
committer | Brian Paul <[email protected]> | 2002-01-06 03:54:12 +0000 |
commit | 363049160da54f4aafe88f99bb2140a9bfed142b (patch) | |
tree | f189ec97cdd323e6e38958d9dc4b62c778c9868e /src/mesa/tnl | |
parent | e2053d16901732f4947c702cdc5ef72993d8d130 (diff) |
Another vertex program checkpoint: clean-up of vertex attribute storage
in vertex_buffer. Improved vertex program pipeline stage such that
output registers can be processed in a loop. Getting closer to where
we need to be in order to implement performance optimizations...
Diffstat (limited to 'src/mesa/tnl')
-rw-r--r-- | src/mesa/tnl/t_array_import.c | 12 | ||||
-rw-r--r-- | src/mesa/tnl/t_context.h | 7 | ||||
-rw-r--r-- | src/mesa/tnl/t_imm_elt.c | 9 | ||||
-rw-r--r-- | src/mesa/tnl/t_imm_exec.c | 11 | ||||
-rw-r--r-- | src/mesa/tnl/t_imm_fixup.c | 5 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_fog.c | 14 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_points.c | 16 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_program.c | 138 |
8 files changed, 98 insertions, 114 deletions
diff --git a/src/mesa/tnl/t_array_import.c b/src/mesa/tnl/t_array_import.c index c9bb9d502c5..0b93cf91309 100644 --- a/src/mesa/tnl/t_array_import.c +++ b/src/mesa/tnl/t_array_import.c @@ -1,10 +1,10 @@ -/* $Id: t_array_import.c,v 1.20 2002/01/05 20:51:13 brianp Exp $ */ +/* $Id: t_array_import.c,v 1.21 2002/01/06 03:54:12 brianp Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2002 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"), @@ -277,8 +277,8 @@ static void _tnl_upgrade_client_data( GLcontext *ctx, } if ((required & VERT_FOG_BIT) - && (VB->AttribPtr[VERT_ATTRIB_FOG]->flags & flags)) { - ASSERT(VB->AttribPtr[VERT_ATTRIB_FOG] == &inputs->FogCoord); + && (VB->FogCoordPtr->flags & flags)) { + ASSERT(VB->FogCoordPtr == &inputs->FogCoord); _tnl_import_fogcoord( ctx, writeable, stride ); VB->importable_data &= ~VERT_FOG_BIT; } @@ -372,7 +372,7 @@ void _tnl_vb_bind_arrays( GLcontext *ctx, GLint start, GLsizei count ) if (inputs & VERT_FOG_BIT) { _tnl_import_fogcoord( ctx, 0, 0 ); tmp->FogCoord.count = VB->Count; - VB->AttribPtr[VERT_ATTRIB_FOG] = &tmp->FogCoord; + VB->FogCoordPtr = &tmp->FogCoord; } if (inputs & VERT_EDGEFLAG_BIT) { diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h index cd435d89c4e..64abe88bb7b 100644 --- a/src/mesa/tnl/t_context.h +++ b/src/mesa/tnl/t_context.h @@ -1,4 +1,4 @@ -/* $Id: t_context.h,v 1.35 2002/01/05 20:51:13 brianp Exp $ */ +/* $Id: t_context.h,v 1.36 2002/01/06 03:54:12 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -254,7 +254,6 @@ typedef struct vertex_buffer GLuint FirstPrimitive; /* usually zero */ /* Pointers to current data. - * XXX Replace ObjPtr, NormalPtr, TexCoordPtr, etc with AttribPtr[] arrays. */ GLuint *Elts; /* VERT_ELT */ GLvector4f *ObjPtr; /* VERT_OBJ_BIT */ @@ -270,13 +269,15 @@ typedef struct vertex_buffer GLvector1ui *IndexPtr[2]; /* VERT_INDEX_BIT */ struct gl_client_array *ColorPtr[2]; /* VERT_COLOR0_BIT */ struct gl_client_array *SecondaryColorPtr[2];/* VERT_COLOR1_BIT */ - GLvector1f *PointSizePtr; /* VERT_POINT_SIZE */ + GLvector4f *PointSizePtr; /* VERT_POINT_SIZE */ + GLvector4f *FogCoordPtr; /* VERT_FOG_BIT */ GLmaterial (*Material)[2]; /* VERT_MATERIAL, optional */ GLuint *MaterialMask; /* VERT_MATERIAL, optional */ GLuint *Flag; /* VERT_* flags, optional */ GLuint *Primitive; /* GL_(mode)|PRIM_* flags */ GLuint *PrimitiveLength; /* integers */ + /* Inputs to the vertex program stage */ GLvector4f *AttribPtr[VERT_ATTRIB_MAX]; /* GL_NV_vertex_program */ GLuint importable_data; diff --git a/src/mesa/tnl/t_imm_elt.c b/src/mesa/tnl/t_imm_elt.c index b127a9e4c3d..83765025ea2 100644 --- a/src/mesa/tnl/t_imm_elt.c +++ b/src/mesa/tnl/t_imm_elt.c @@ -1,10 +1,10 @@ -/* $Id: t_imm_elt.c,v 1.14 2002/01/05 20:51:13 brianp Exp $ */ +/* $Id: t_imm_elt.c,v 1.15 2002/01/06 03:54:12 brianp Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2002 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"), @@ -721,6 +721,7 @@ static void _tnl_trans_elt_4f(GLfloat (*to)[4], +#if 0 static void _tnl_trans_elt_3f(GLfloat (*to)[3], const struct gl_client_array *from, GLuint *flags, @@ -738,7 +739,7 @@ static void _tnl_trans_elt_3f(GLfloat (*to)[3], start, n ); } - +#endif diff --git a/src/mesa/tnl/t_imm_exec.c b/src/mesa/tnl/t_imm_exec.c index d02ec2ee212..8df863875ae 100644 --- a/src/mesa/tnl/t_imm_exec.c +++ b/src/mesa/tnl/t_imm_exec.c @@ -1,10 +1,10 @@ -/* $Id: t_imm_exec.c,v 1.33 2002/01/05 20:51:13 brianp Exp $ */ +/* $Id: t_imm_exec.c,v 1.34 2002/01/06 03:54:12 brianp Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2002 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"), @@ -232,7 +232,6 @@ static void _tnl_vb_bind_immediate( GLcontext *ctx, struct immediate *IM ) GLuint inputs = tnl->pipeline.inputs; /* for copy-to-current */ const GLuint start = IM->CopyStart; const GLuint count = IM->Count - start; - GLuint i; /* TODO: optimize the case where nothing has changed. (Just bind * tmp to vb). @@ -267,8 +266,6 @@ static void _tnl_vb_bind_immediate( GLcontext *ctx, struct immediate *IM ) VB->Elts = 0; VB->MaterialMask = 0; VB->Material = 0; - for (i = 0; i < 16; i++) - VB->AttribPtr[i] = NULL; /* _tnl_print_vert_flags("copy-orflag", IM->CopyOrFlag); */ /* _tnl_print_vert_flags("orflag", IM->OrFlag); */ @@ -309,7 +306,7 @@ static void _tnl_vb_bind_immediate( GLcontext *ctx, struct immediate *IM ) tmp->FogCoord.data = IM->Attrib[VERT_ATTRIB_FOG] + start; tmp->FogCoord.start = (GLfloat *) (IM->Attrib[VERT_ATTRIB_FOG] + start); tmp->FogCoord.count = count; - VB->AttribPtr[VERT_ATTRIB_FOG] = &tmp->FogCoord; + VB->FogCoordPtr = &tmp->FogCoord; } if (inputs & VERT_COLOR1_BIT) { diff --git a/src/mesa/tnl/t_imm_fixup.c b/src/mesa/tnl/t_imm_fixup.c index 6d6bfad83fc..6e52187a47d 100644 --- a/src/mesa/tnl/t_imm_fixup.c +++ b/src/mesa/tnl/t_imm_fixup.c @@ -1,4 +1,4 @@ -/* $Id: t_imm_fixup.c,v 1.31 2002/01/05 20:51:13 brianp Exp $ */ +/* $Id: t_imm_fixup.c,v 1.32 2002/01/06 03:54:12 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -145,6 +145,7 @@ fixup_first_4f( GLfloat data[][4], GLuint flag[], GLuint match, COPY_4FV(data[i], dflt); } +#if 0 static void fixup_first_3f( GLfloat data[][3], GLuint flag[], GLuint match, GLuint start, GLfloat *dflt ) @@ -158,7 +159,7 @@ fixup_first_3f( GLfloat data[][3], GLuint flag[], GLuint match, while ((flag[++i]&match) == 0) COPY_3FV(data[i], dflt); } - +#endif static void fixup_first_1ui( GLuint data[], GLuint flag[], GLuint match, diff --git a/src/mesa/tnl/t_vb_fog.c b/src/mesa/tnl/t_vb_fog.c index b7876a4db9d..d0e87cdbd8a 100644 --- a/src/mesa/tnl/t_vb_fog.c +++ b/src/mesa/tnl/t_vb_fog.c @@ -1,10 +1,10 @@ -/* $Id: t_vb_fog.c,v 1.15 2002/01/05 20:51:13 brianp Exp $ */ +/* $Id: t_vb_fog.c,v 1.16 2002/01/06 03:54:12 brianp Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2002 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"), @@ -142,7 +142,7 @@ static GLboolean run_fog_stage( GLcontext *ctx, /* fog computed from Z depth */ /* source = VB->ObjPtr or VB->EyePtr coords */ /* dest = VB->FogCoordPtr = fog stage private storage */ - VB->AttribPtr[VERT_ATTRIB_FOG] = &store->fogcoord; + VB->FogCoordPtr = &store->fogcoord; if (!ctx->_NeedEyeCoords) { const GLfloat *m = ctx->ModelviewMatrixStack.Top->m; @@ -181,12 +181,12 @@ static GLboolean run_fog_stage( GLcontext *ctx, else { /* use glFogCoord() coordinates */ /* source = VB->FogCoordPtr */ - input = VB->AttribPtr[VERT_ATTRIB_FOG]; + input = VB->FogCoordPtr; /* dest = fog stage private storage */ - VB->AttribPtr[VERT_ATTRIB_FOG] = &store->fogcoord; + VB->FogCoordPtr = &store->fogcoord; } - make_win_fog_coords( ctx, VB->AttribPtr[VERT_ATTRIB_FOG], input ); + make_win_fog_coords( ctx, VB->FogCoordPtr, input ); return GL_TRUE; } diff --git a/src/mesa/tnl/t_vb_points.c b/src/mesa/tnl/t_vb_points.c index c60a0f56b12..429a0ab7cb4 100644 --- a/src/mesa/tnl/t_vb_points.c +++ b/src/mesa/tnl/t_vb_points.c @@ -1,10 +1,10 @@ -/* $Id: t_vb_points.c,v 1.5 2001/12/14 02:51:45 brianp Exp $ */ +/* $Id: t_vb_points.c,v 1.6 2002/01/06 03:54:12 brianp Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2002 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"), @@ -34,7 +34,7 @@ struct point_stage_data { - GLvector1f PointSize; + GLvector4f PointSize; }; #define POINT_STAGE_DATA(stage) ((struct point_stage_data *)stage->privatePtr) @@ -53,7 +53,7 @@ static GLboolean run_point_stage( GLcontext *ctx, const GLfloat p1 = ctx->Point.Params[1]; const GLfloat p2 = ctx->Point.Params[2]; const GLfloat pointSize = ctx->Point._Size; - GLfloat *size = store->PointSize.data; + GLfloat (*size)[4] = store->PointSize.data; GLuint i; if (stage->changed_inputs) { @@ -61,7 +61,7 @@ static GLboolean run_point_stage( GLcontext *ctx, for (i = 0; i < VB->Count; i++) { const GLfloat dist = -eye[i][2]; /* GLfloat dist = GL_SQRT(pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2]);*/ - size[i] = pointSize / (p0 + dist * (p1 + dist * p2)); + size[i][0] = pointSize / (p0 + dist * (p1 + dist * p2)); } } @@ -89,7 +89,7 @@ static GLboolean alloc_point_data( GLcontext *ctx, if (!store) return GL_FALSE; - _mesa_vector1f_alloc( &store->PointSize, 0, VB->Size, 32 ); + _mesa_vector4f_alloc( &store->PointSize, 0, VB->Size, 32 ); /* Now run the stage. */ @@ -102,7 +102,7 @@ static void free_point_data( struct gl_pipeline_stage *stage ) { struct point_stage_data *store = POINT_STAGE_DATA(stage); if (store) { - _mesa_vector1f_free( &store->PointSize ); + _mesa_vector4f_free( &store->PointSize ); FREE( store ); stage->privatePtr = 0; } diff --git a/src/mesa/tnl/t_vb_program.c b/src/mesa/tnl/t_vb_program.c index a711c96c43e..cfa1397d70e 100644 --- a/src/mesa/tnl/t_vb_program.c +++ b/src/mesa/tnl/t_vb_program.c @@ -1,4 +1,4 @@ -/* $Id: t_vb_program.c,v 1.6 2002/01/05 20:51:13 brianp Exp $ */ +/* $Id: t_vb_program.c,v 1.7 2002/01/06 03:54:12 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -98,16 +98,36 @@ #include "t_imm_exec.h" +/* WARNING: these values _MUST_ match the values in the OutputRegisters[] + * array in vpparse.c!!! + */ +#define VERT_RESULT_HPOS 0 +#define VERT_RESULT_COL0 1 +#define VERT_RESULT_COL1 2 +#define VERT_RESULT_BFC0 3 +#define VERT_RESULT_BFC1 4 +#define VERT_RESULT_FOGC 5 +#define VERT_RESULT_PSIZ 6 +#define VERT_RESULT_TEX0 7 +#define VERT_RESULT_TEX1 8 +#define VERT_RESULT_TEX2 9 +#define VERT_RESULT_TEX3 10 +#define VERT_RESULT_TEX4 11 +#define VERT_RESULT_TEX5 12 +#define VERT_RESULT_TEX6 13 +#define VERT_RESULT_TEX7 14 + struct vp_stage_data { - GLvector4f clipCoords; /* post-modelview/projection coords */ - GLvector4f ndcCoords; /* normalized device coords */ + /* The results of running the vertex program go into these arrays. */ + GLvector4f attribs[15]; + + /* These point to the attribs[VERT_RESULT_COL0, COL1, BFC0, BFC1] arrays */ struct gl_client_array color0[2]; /* front and back */ struct gl_client_array color1[2]; /* front and back */ - GLvector4f texCoord[MAX_TEXTURE_UNITS]; - GLvector4f fogCoord; - GLvector1f pointSize; - GLubyte *clipmask; + + GLvector4f ndcCoords; /* normalized device coords */ + GLubyte *clipmask; /* clip flags */ GLubyte ormask, andmask; }; @@ -123,21 +143,8 @@ static GLboolean run_vp( GLcontext *ctx, struct gl_pipeline_stage *stage ) struct vp_machine *machine = &(ctx->VertexProgram.Machine); GLint i; - /* convenience pointers */ - GLfloat (*clip)[4] = (GLfloat (*)[4]) store->clipCoords.data; - GLfloat (*color0)[4] = (GLfloat (*)[4]) store->color0[0].Ptr; - GLfloat (*color1)[4] = (GLfloat (*)[4]) store->color1[0].Ptr; - GLfloat (*bfcolor0)[4] = (GLfloat (*)[4]) store->color0[1].Ptr; - GLfloat (*bfcolor1)[4] = (GLfloat (*)[4]) store->color1[1].Ptr; - GLfloat (*fog)[4] = (GLfloat (*)[4]) store->fogCoord.data; - GLfloat *pointSize = (GLfloat *) store->pointSize.data; - GLfloat (*texture0)[4] = (GLfloat (*)[4]) store->texCoord[0].data; - GLfloat (*texture1)[4] = (GLfloat (*)[4]) store->texCoord[1].data; - GLfloat (*texture2)[4] = (GLfloat (*)[4]) store->texCoord[2].data; - GLfloat (*texture3)[4] = (GLfloat (*)[4]) store->texCoord[3].data; - _mesa_init_tracked_matrices(ctx); - _mesa_init_vp_registers(ctx); /* sets temp regs to (0,0,0,1) */ + _mesa_init_vp_registers(ctx); /* init temp and result regs */ for (i = 0; i < VB->Count; i++) { GLuint attr; @@ -185,33 +192,28 @@ static GLboolean run_vp( GLcontext *ctx, struct gl_pipeline_stage *stage ) machine->Registers[VP_OUT_COL0][3]); #endif - /* store the attribute output registers into the VB arrays */ - COPY_4V(clip[i], machine->Registers[VP_OUT_HPOS]); - COPY_4V(color0[i], machine->Registers[VP_OUT_COL0]); - COPY_4V(color1[i], machine->Registers[VP_OUT_COL1]); - COPY_4V(bfcolor0[i], machine->Registers[VP_OUT_BFC0]); - COPY_4V(bfcolor1[i], machine->Registers[VP_OUT_BFC1]); - fog[i][0] = machine->Registers[VP_OUT_FOGC][0]; - pointSize[i] = machine->Registers[VP_OUT_PSIZ][0]; - COPY_4V(texture0[i], machine->Registers[VP_OUT_TEX0]); - COPY_4V(texture1[i], machine->Registers[VP_OUT_TEX0]); - COPY_4V(texture2[i], machine->Registers[VP_OUT_TEX0]); - COPY_4V(texture3[i], machine->Registers[VP_OUT_TEX0]); + /* copy the output registers into the VB->attribs arrays */ + /* XXX (optimize) could use a conditional and smaller loop limit here */ + for (attr = 0; attr < 15; attr++) { + COPY_4V( store->attribs[attr].data[i], + machine->Registers[VP_OUTPUT_REG_START + attr] ); + } } - VB->ClipPtr = &store->clipCoords; + /* Setup the VB pointers so that the next pipeline stages get + * their data from the right place (the program output arrays). + */ + VB->ClipPtr = &store->attribs[VERT_RESULT_HPOS]; VB->ClipPtr->size = 4; VB->ClipPtr->count = VB->Count; VB->ColorPtr[0] = &store->color0[0]; VB->ColorPtr[1] = &store->color0[1]; VB->SecondaryColorPtr[0] = &store->color1[0]; VB->SecondaryColorPtr[1] = &store->color1[1]; - VB->AttribPtr[VERT_ATTRIB_FOG] = &store->fogCoord; - VB->PointSizePtr = &store->pointSize; - VB->TexCoordPtr[0] = &store->texCoord[0]; - VB->TexCoordPtr[1] = &store->texCoord[1]; - VB->TexCoordPtr[2] = &store->texCoord[2]; - VB->TexCoordPtr[3] = &store->texCoord[3]; + VB->FogCoordPtr = &store->attribs[VERT_RESULT_FOGC]; + VB->PointSizePtr = &store->attribs[VERT_RESULT_PSIZ]; + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) + VB->TexCoordPtr[i] = &store->attribs[VERT_RESULT_TEX0 + i]; /* Cliptest and perspective divide. Clip functions must clear * the clipmask. @@ -304,23 +306,9 @@ static GLboolean run_validate_program( GLcontext *ctx, } - -#if 0 -static void alloc_4chan( struct gl_client_array *a, GLuint sz ) -{ - a->Ptr = ALIGN_MALLOC( sz * sizeof(GLchan) * 4, 32 ); - a->Size = 4; - a->Type = CHAN_TYPE; - a->Stride = 0; - a->StrideB = sizeof(GLchan) * 4; - a->Enabled = 0; - a->Flags = 0; -} -#endif - -static void alloc_4float( struct gl_client_array *a, GLuint sz ) +static void init_client_array( struct gl_client_array *a, GLvector4f *vec ) { - a->Ptr = ALIGN_MALLOC( sz * sizeof(GLfloat) * 4, 32 ); + a->Ptr = vec->data; a->Size = 4; a->Type = GL_FLOAT; a->Stride = 0; @@ -347,20 +335,20 @@ static GLboolean run_init_vp( GLcontext *ctx, if (!store) return GL_FALSE; - /* The output of a vertex program is: */ - _mesa_vector4f_alloc( &store->clipCoords, 0, size, 32 ); + /* Allocate arrays of vertex output values */ + for (i = 0; i < 15; i++) + _mesa_vector4f_alloc( &store->attribs[i], 0, size, 32 ); + + /* Make the color0[] and color1[] arrays point into the attribs[] arrays */ + init_client_array( &store->color0[0], &store->attribs[VERT_RESULT_COL0] ); + init_client_array( &store->color0[1], &store->attribs[VERT_RESULT_COL1] ); + init_client_array( &store->color1[0], &store->attribs[VERT_RESULT_BFC0] ); + init_client_array( &store->color1[1], &store->attribs[VERT_RESULT_BFC1] ); + + /* a few other misc allocations */ _mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 ); - alloc_4float( &store->color0[0], size ); - alloc_4float( &store->color0[1], size ); - alloc_4float( &store->color1[0], size ); - alloc_4float( &store->color1[1], size ); - for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) - _mesa_vector4f_alloc( &store->texCoord[i], 0, VB->Size, 32 ); - _mesa_vector4f_alloc( &store->fogCoord, 0, size, 32 ); - _mesa_vector1f_alloc( &store->pointSize, 0, size, 32 ); store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 ); - /* Now validate the stage derived data... */ stage->run = run_validate_program; @@ -401,17 +389,13 @@ static void dtr( struct gl_pipeline_stage *stage ) if (store) { GLuint i; - _mesa_vector4f_free( &store->clipCoords ); + + /* free the vertex program result arrays */ + for (i = 0; i < 15; i++) + _mesa_vector4f_free( &store->attribs[i] ); + + /* free misc arrays */ _mesa_vector4f_free( &store->ndcCoords ); - ALIGN_FREE( store->color0[0].Ptr ); - ALIGN_FREE( store->color0[1].Ptr ); - ALIGN_FREE( store->color1[0].Ptr ); - ALIGN_FREE( store->color1[1].Ptr ); - for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) - if (store->texCoord[i].data) - _mesa_vector4f_free( &store->texCoord[i] ); - _mesa_vector4f_free( &store->fogCoord ); - _mesa_vector1f_free( &store->pointSize ); ALIGN_FREE( store->clipmask ); FREE( store ); |