From 92f77e9c01085c6babe6ce80dfe4e0e7abab61a1 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Wed, 19 Oct 2016 11:59:12 +1100 Subject: [PATCH] i965/mesa/st: eliminate gl_geometry_program We now get all the gs metadata from shader_info. Reviewed-by: Jason Ekstrand --- src/mesa/drivers/dri/i965/brw_context.h | 6 +++--- src/mesa/drivers/dri/i965/brw_draw.c | 2 +- src/mesa/drivers/dri/i965/brw_gs.c | 19 ++++++++----------- src/mesa/drivers/dri/i965/brw_gs_surface_state.c | 2 +- src/mesa/drivers/dri/i965/brw_program.c | 2 +- src/mesa/drivers/dri/i965/gen6_gs_state.c | 4 ++-- src/mesa/main/context.c | 2 +- src/mesa/main/mtypes.h | 22 +++------------------- src/mesa/main/state.c | 10 +++++----- src/mesa/program/program.c | 5 +---- src/mesa/program/program.h | 23 ----------------------- src/mesa/state_tracker/st_atom.c | 2 +- src/mesa/state_tracker/st_atom_constbuf.c | 2 +- src/mesa/state_tracker/st_atom_rasterizer.c | 2 +- src/mesa/state_tracker/st_atom_sampler.c | 2 +- src/mesa/state_tracker/st_atom_shader.c | 2 +- src/mesa/state_tracker/st_atom_texture.c | 2 +- src/mesa/state_tracker/st_cb_program.c | 10 +++++----- src/mesa/state_tracker/st_program.c | 10 +++++----- src/mesa/state_tracker/st_program.h | 6 +++--- 20 files changed, 45 insertions(+), 90 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index db48aa1..5e68c50 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -351,7 +351,7 @@ struct brw_tess_eval_program { /** Subclass of Mesa geometry program */ struct brw_geometry_program { - struct gl_geometry_program program; + struct gl_program program; unsigned id; /**< serial no. to identify geom progs, never re-used */ }; @@ -1007,7 +1007,7 @@ struct brw_context /* Active vertex program: */ const struct gl_vertex_program *vertex_program; - const struct gl_geometry_program *geometry_program; + const struct gl_program *geometry_program; const struct gl_program *tess_ctrl_program; const struct gl_program *tess_eval_program; const struct gl_fragment_program *fragment_program; @@ -1742,7 +1742,7 @@ brw_tess_eval_program(struct gl_program *p) } static inline struct brw_geometry_program * -brw_geometry_program(struct gl_geometry_program *p) +brw_geometry_program(struct gl_program *p) { return (struct brw_geometry_program *) p; } diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index 2dbaddd8..a2e0442 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -454,7 +454,7 @@ brw_try_draw_prims(struct gl_context *ctx, brw->wm.base.sampler_count = util_last_bit(ctx->FragmentProgram._Current->Base.SamplersUsed); brw->gs.base.sampler_count = ctx->GeometryProgram._Current ? - util_last_bit(ctx->GeometryProgram._Current->Base.SamplersUsed) : 0; + util_last_bit(ctx->GeometryProgram._Current->SamplersUsed) : 0; brw->tes.base.sampler_count = ctx->TessEvalProgram._Current ? util_last_bit(ctx->TessEvalProgram._Current->SamplersUsed) : 0; brw->tcs.base.sampler_count = ctx->TessCtrlProgram._Current ? diff --git a/src/mesa/drivers/dri/i965/brw_gs.c b/src/mesa/drivers/dri/i965/brw_gs.c index b493e6c..8fba6fa 100644 --- a/src/mesa/drivers/dri/i965/brw_gs.c +++ b/src/mesa/drivers/dri/i965/brw_gs.c @@ -106,8 +106,7 @@ brw_codegen_gs_prog(struct brw_context *brw, memset(&prog_data, 0, sizeof(prog_data)); - assign_gs_binding_table_offsets(devinfo, prog, - &gp->program.Base, &prog_data); + assign_gs_binding_table_offsets(devinfo, prog, &gp->program, &prog_data); /* Allocate the references to the uniforms that will end up in the * prog_data associated with the compiled program, and which will be freed @@ -119,7 +118,7 @@ brw_codegen_gs_prog(struct brw_context *brw, */ struct gl_linked_shader *gs = prog->_LinkedShaders[MESA_SHADER_GEOMETRY]; struct brw_shader *bgs = (struct brw_shader *) gs; - int param_count = gp->program.Base.nir->num_uniforms / 4; + int param_count = gp->program.nir->num_uniforms / 4; prog_data.base.base.param = rzalloc_array(NULL, const gl_constant_value *, param_count); @@ -130,15 +129,15 @@ brw_codegen_gs_prog(struct brw_context *brw, prog_data.base.base.nr_params = param_count; prog_data.base.base.nr_image_params = gs->NumImages; - brw_nir_setup_glsl_uniforms(gp->program.Base.nir, prog, &gp->program.Base, + brw_nir_setup_glsl_uniforms(gp->program.nir, prog, &gp->program, &prog_data.base.base, compiler->scalar_stage[MESA_SHADER_GEOMETRY]); - uint64_t outputs_written = gp->program.Base.info.outputs_written; + uint64_t outputs_written = gp->program.info.outputs_written; prog_data.base.cull_distance_mask = - ((1 << gp->program.Base.CullDistanceArraySize) - 1) << - gp->program.Base.ClipDistanceArraySize; + ((1 << gp->program.CullDistanceArraySize) - 1) << + gp->program.ClipDistanceArraySize; brw_compute_vue_map(devinfo, &prog_data.base.vue_map, outputs_written, @@ -213,14 +212,13 @@ brw_gs_populate_key(struct brw_context *brw, struct gl_context *ctx = &brw->ctx; struct brw_geometry_program *gp = (struct brw_geometry_program *) brw->geometry_program; - struct gl_program *prog = &gp->program.Base; memset(key, 0, sizeof(*key)); key->program_string_id = gp->id; /* _NEW_TEXTURE */ - brw_populate_sampler_prog_key_data(ctx, prog, &key->tex); + brw_populate_sampler_prog_key_data(ctx, &gp->program, &key->tex); } void @@ -277,8 +275,7 @@ brw_gs_precompile(struct gl_context *ctx, struct brw_stage_prog_data *old_prog_data = brw->gs.base.prog_data; bool success; - struct gl_geometry_program *gp = (struct gl_geometry_program *) prog; - struct brw_geometry_program *bgp = brw_geometry_program(gp); + struct brw_geometry_program *bgp = brw_geometry_program(prog); memset(&key, 0, sizeof(key)); diff --git a/src/mesa/drivers/dri/i965/brw_gs_surface_state.c b/src/mesa/drivers/dri/i965/brw_gs_surface_state.c index 371255c..686ddb4 100644 --- a/src/mesa/drivers/dri/i965/brw_gs_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_gs_surface_state.c @@ -52,7 +52,7 @@ brw_upload_gs_pull_constants(struct brw_context *brw) _mesa_shader_write_subroutine_indices(&brw->ctx, MESA_SHADER_GEOMETRY); /* _NEW_PROGRAM_CONSTANTS */ - brw_upload_pull_constants(brw, BRW_NEW_GS_CONSTBUF, &gp->program.Base, + brw_upload_pull_constants(brw, BRW_NEW_GS_CONSTBUF, &gp->program, stage_state, prog_data); } diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c index 7c553c8..7151558 100644 --- a/src/mesa/drivers/dri/i965/brw_program.c +++ b/src/mesa/drivers/dri/i965/brw_program.c @@ -157,7 +157,7 @@ static struct gl_program *brwNewProgram( struct gl_context *ctx, if (prog) { prog->id = get_new_program_id(brw->screen); - return _mesa_init_gl_program(&prog->program.Base, target, id); + return _mesa_init_gl_program(&prog->program, target, id); } else { return NULL; } diff --git a/src/mesa/drivers/dri/i965/gen6_gs_state.c b/src/mesa/drivers/dri/i965/gen6_gs_state.c index ca212c8..4923764 100644 --- a/src/mesa/drivers/dri/i965/gen6_gs_state.c +++ b/src/mesa/drivers/dri/i965/gen6_gs_state.c @@ -45,8 +45,8 @@ gen6_upload_gs_push_constants(struct brw_context *brw) struct brw_stage_prog_data *prog_data = brw->gs.base.prog_data; _mesa_shader_write_subroutine_indices(&brw->ctx, MESA_SHADER_GEOMETRY); - gen6_upload_push_constants(brw, &gp->program.Base, prog_data, - stage_state, AUB_TRACE_VS_CONSTANTS); + gen6_upload_push_constants(brw, &gp->program, prog_data, stage_state, + AUB_TRACE_VS_CONSTANTS); } if (brw->gen >= 7) diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 5f00365..757dbfc 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -1299,7 +1299,7 @@ _mesa_free_context_data( struct gl_context *ctx ) _mesa_reference_program(ctx, &ctx->TessCtrlProgram._Current, NULL); _mesa_reference_program(ctx, &ctx->TessEvalProgram._Current, NULL); - _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, NULL); + _mesa_reference_program(ctx, &ctx->GeometryProgram._Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index c0984f1..65f73f4 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1998,22 +1998,6 @@ struct gl_vertex_program }; -/** Geometry program object */ -struct gl_geometry_program -{ - struct gl_program Base; /**< base class */ - - GLint VerticesIn; - GLint VerticesOut; - GLint Invocations; - GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB, - GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */ - GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */ - bool UsesEndPrimitive; - bool UsesStreams; -}; - - /** Fragment program object */ struct gl_fragment_program { @@ -2134,7 +2118,7 @@ struct gl_geometry_program_state /** Currently enabled and valid program (including internal programs * and compiled shader programs). */ - struct gl_geometry_program *_Current; + struct gl_program *_Current; }; /** @@ -2770,7 +2754,7 @@ struct gl_shader_program } TessEval; /** - * Geometry shader state - copied into gl_geometry_program by + * Geometry shader state - copied into gl_program by * _mesa_copy_linked_program_data(). */ struct { @@ -2778,7 +2762,7 @@ struct gl_shader_program /** * True if gl_ClipDistance is written to. Copied into - * gl_geometry_program by _mesa_copy_linked_program_data(). + * gl_program by _mesa_copy_linked_program_data(). */ GLuint ClipDistanceArraySize; /**< Size of the gl_ClipDistance array, or 0 if not present. */ diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index 10194a9..407ff38 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -109,7 +109,7 @@ update_program(struct gl_context *ctx) ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current; const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current; - const struct gl_geometry_program *prevGP = ctx->GeometryProgram._Current; + const struct gl_program *prevGP = ctx->GeometryProgram._Current; const struct gl_program *prevTCP = ctx->TessCtrlProgram._Current; const struct gl_program *prevTEP = ctx->TessEvalProgram._Current; const struct gl_compute_program *prevCP = ctx->ComputeProgram._Current; @@ -186,11 +186,11 @@ update_program(struct gl_context *ctx) if (gsProg && gsProg->LinkStatus && gsProg->_LinkedShaders[MESA_SHADER_GEOMETRY]) { /* Use GLSL geometry shader */ - _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, - gl_geometry_program(gsProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program)); + _mesa_reference_program(ctx, &ctx->GeometryProgram._Current, + gsProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program); } else { /* No geometry program */ - _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, NULL); + _mesa_reference_program(ctx, &ctx->GeometryProgram._Current, NULL); } if (tesProg && tesProg->LinkStatus @@ -266,7 +266,7 @@ update_program(struct gl_context *ctx) new_state |= _NEW_PROGRAM; if (ctx->Driver.BindProgram) { ctx->Driver.BindProgram(ctx, GL_GEOMETRY_PROGRAM_NV, - (struct gl_program *) ctx->GeometryProgram._Current); + ctx->GeometryProgram._Current); } } diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c index 85c9b7b..28af5b5 100644 --- a/src/mesa/program/program.c +++ b/src/mesa/program/program.c @@ -223,10 +223,7 @@ _mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id) struct gl_fragment_program *prog = CALLOC_STRUCT(gl_fragment_program); return _mesa_init_gl_program(&prog->Base, target, id); } - case GL_GEOMETRY_PROGRAM_NV: { - struct gl_geometry_program *prog = CALLOC_STRUCT(gl_geometry_program); - return _mesa_init_gl_program(&prog->Base, target, id); - } + case GL_GEOMETRY_PROGRAM_NV: case GL_TESS_CONTROL_PROGRAM_NV: case GL_TESS_EVALUATION_PROGRAM_NV: { struct gl_program *prog = CALLOC_STRUCT(gl_program); diff --git a/src/mesa/program/program.h b/src/mesa/program/program.h index 41806c2..a909dcc 100644 --- a/src/mesa/program/program.h +++ b/src/mesa/program/program.h @@ -108,15 +108,6 @@ _mesa_reference_fragprog(struct gl_context *ctx, } static inline void -_mesa_reference_geomprog(struct gl_context *ctx, - struct gl_geometry_program **ptr, - struct gl_geometry_program *prog) -{ - _mesa_reference_program(ctx, (struct gl_program **) ptr, - (struct gl_program *) prog); -} - -static inline void _mesa_reference_compprog(struct gl_context *ctx, struct gl_compute_program **ptr, struct gl_compute_program *prog) @@ -222,20 +213,6 @@ gl_vertex_program_const(const struct gl_program *prog) return (const struct gl_vertex_program *) prog; } - -static inline struct gl_geometry_program * -gl_geometry_program(struct gl_program *prog) -{ - return (struct gl_geometry_program *) prog; -} - -static inline const struct gl_geometry_program * -gl_geometry_program_const(const struct gl_program *prog) -{ - return (const struct gl_geometry_program *) prog; -} - - static inline struct gl_compute_program * gl_compute_program(struct gl_program *prog) { diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index 231bdd9..dc4e143 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -72,7 +72,7 @@ static void check_program_state( struct st_context *st ) struct gl_vertex_program *new_vp = ctx->VertexProgram._Current; struct gl_program *new_tcp = ctx->TessCtrlProgram._Current; struct gl_program *new_tep = ctx->TessEvalProgram._Current; - struct gl_geometry_program *new_gp = ctx->GeometryProgram._Current; + struct gl_program *new_gp = ctx->GeometryProgram._Current; struct gl_fragment_program *new_fp = ctx->FragmentProgram._Current; uint64_t dirty = 0; diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c index 77232f2..74d18e3 100644 --- a/src/mesa/state_tracker/st_atom_constbuf.c +++ b/src/mesa/state_tracker/st_atom_constbuf.c @@ -178,7 +178,7 @@ static void update_gs_constants(struct st_context *st ) struct gl_program_parameter_list *params; if (gp) { - params = gp->Base.Base.Parameters; + params = gp->Base.Parameters; st_upload_constants( st, params, MESA_SHADER_GEOMETRY ); } } diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c index 8d22bfc..1598f5e 100644 --- a/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/src/mesa/state_tracker/st_atom_rasterizer.c @@ -209,7 +209,7 @@ static void update_raster_state( struct st_context *st ) /* We have to check the last bound stage and see if it writes psize */ struct gl_program *last = NULL; if (ctx->GeometryProgram._Current) - last = &ctx->GeometryProgram._Current->Base; + last = ctx->GeometryProgram._Current; else if (ctx->TessEvalProgram._Current) last = ctx->TessEvalProgram._Current; else if (ctx->VertexProgram._Current) diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index c802ad5..f170298 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -336,7 +336,7 @@ update_samplers(struct st_context *st) if (ctx->GeometryProgram._Current) { update_shader_samplers(st, PIPE_SHADER_GEOMETRY, - &ctx->GeometryProgram._Current->Base, + ctx->GeometryProgram._Current, ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits, st->state.samplers[PIPE_SHADER_GEOMETRY], &st->state.num_samplers[PIPE_SHADER_GEOMETRY]); diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 235303c..02f789c 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -225,7 +225,7 @@ update_gp( struct st_context *st ) } stgp = st_geometry_program(st->ctx->GeometryProgram._Current); - assert(stgp->Base.Base.Target == GL_GEOMETRY_PROGRAM_NV); + assert(stgp->Base.Target == GL_GEOMETRY_PROGRAM_NV); st->gp_variant = st_get_basic_variant(st, PIPE_SHADER_GEOMETRY, &stgp->tgsi, &stgp->variants); diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index 613886e..df77a38 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -237,7 +237,7 @@ update_geometry_textures(struct st_context *st) if (ctx->GeometryProgram._Current) { update_textures(st, MESA_SHADER_GEOMETRY, - &ctx->GeometryProgram._Current->Base, + ctx->GeometryProgram._Current, ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits, st->state.sampler_views[PIPE_SHADER_GEOMETRY], &st->state.num_sampler_views[PIPE_SHADER_GEOMETRY]); diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c index 9878e9c..6dce2f6 100644 --- a/src/mesa/state_tracker/st_cb_program.c +++ b/src/mesa/state_tracker/st_cb_program.c @@ -67,7 +67,7 @@ st_new_program(struct gl_context *ctx, GLenum target, GLuint id) } case GL_GEOMETRY_PROGRAM_NV: { struct st_geometry_program *prog = ST_CALLOC_STRUCT(st_geometry_program); - return _mesa_init_gl_program(&prog->Base.Base, target, id); + return _mesa_init_gl_program(&prog->Base, target, id); } case GL_TESS_CONTROL_PROGRAM_NV: { struct st_tessctrl_program *prog = ST_CALLOC_STRUCT(st_tessctrl_program); @@ -111,8 +111,8 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) struct st_geometry_program *stgp = (struct st_geometry_program *) prog; - st_release_basic_variants(st, stgp->Base.Base.Target, - &stgp->variants, &stgp->tgsi); + st_release_basic_variants(st, stgp->Base.Target, &stgp->variants, + &stgp->tgsi); if (stgp->glsl_to_tgsi) free_glsl_to_tgsi_visitor(stgp->glsl_to_tgsi); @@ -199,8 +199,8 @@ st_program_string_notify( struct gl_context *ctx, else if (target == GL_GEOMETRY_PROGRAM_NV) { struct st_geometry_program *stgp = (struct st_geometry_program *) prog; - st_release_basic_variants(st, stgp->Base.Base.Target, - &stgp->variants, &stgp->tgsi); + st_release_basic_variants(st, stgp->Base.Target, &stgp->variants, + &stgp->tgsi); if (!st_translate_geometry_program(st, stgp)) return false; diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 0a80568..9f90f6b 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -1521,15 +1521,15 @@ st_translate_geometry_program(struct st_context *st, return false; ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, - stgp->Base.Base.info.gs.input_primitive); + stgp->Base.info.gs.input_primitive); ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, - stgp->Base.Base.info.gs.output_primitive); + stgp->Base.info.gs.output_primitive); ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, - stgp->Base.Base.info.gs.vertices_out); + stgp->Base.info.gs.vertices_out); ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS, - stgp->Base.Base.info.gs.invocations); + stgp->Base.info.gs.invocations); - st_translate_program_common(st, &stgp->Base.Base, stgp->glsl_to_tgsi, ureg, + st_translate_program_common(st, &stgp->Base, stgp->glsl_to_tgsi, ureg, PIPE_SHADER_GEOMETRY, &stgp->tgsi); free_glsl_to_tgsi_visitor(stgp->glsl_to_tgsi); diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index daea781..ab01d7b 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -246,11 +246,11 @@ struct st_basic_variant /** - * Derived from Mesa gl_geometry_program: + * Derived from Mesa gl_program: */ struct st_geometry_program { - struct gl_geometry_program Base; /**< The Mesa geometry program */ + struct gl_program Base; /**< The Mesa geometry program */ struct pipe_shader_state tgsi; struct glsl_to_tgsi_visitor* glsl_to_tgsi; uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */ @@ -315,7 +315,7 @@ st_vertex_program( struct gl_vertex_program *vp ) } static inline struct st_geometry_program * -st_geometry_program( struct gl_geometry_program *gp ) +st_geometry_program( struct gl_program *gp ) { return (struct st_geometry_program *)gp; } -- 2.7.4