diff options
Diffstat (limited to 'src/glsl/cl/sl_cl_parse.c')
-rw-r--r-- | src/glsl/cl/sl_cl_parse.c | 153 |
1 files changed, 148 insertions, 5 deletions
diff --git a/src/glsl/cl/sl_cl_parse.c b/src/glsl/cl/sl_cl_parse.c index e256ab8213..8106ff6f61 100644 --- a/src/glsl/cl/sl_cl_parse.c +++ b/src/glsl/cl/sl_cl_parse.c @@ -120,6 +120,11 @@ #define TYPE_CENTER 95 #define TYPE_CENTROID 96 +/* layout qualifiers */ +#define LAYOUT_QUALIFIER_NONE 0 +#define LAYOUT_QUALIFIER_UPPER_LEFT 1 +#define LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER 2 + /* type specifier */ #define TYPE_SPECIFIER_VOID 0 #define TYPE_SPECIFIER_BOOL 1 @@ -297,6 +302,10 @@ struct parse_dict { int out; int inout; + int layout; + int origin_upper_left; + int pixel_center_integer; + int _struct; int __constructor; @@ -316,6 +325,9 @@ struct parse_dict { int _false; int _true; + + int all; + int _GL_ARB_fragment_coord_conventions; }; @@ -334,6 +346,8 @@ struct parse_context { unsigned int shader_type; unsigned int parsing_builtin; + unsigned int fragment_coord_conventions:1; + char error[256]; int process_error; }; @@ -451,6 +465,10 @@ _fetch_token(struct parse_context *ctx, case SL_PP_IDENTIFIER: case SL_PP_UINT: case SL_PP_FLOAT: + case SL_PP_EXTENSION_REQUIRE: + case SL_PP_EXTENSION_ENABLE: + case SL_PP_EXTENSION_WARN: + case SL_PP_EXTENSION_DISABLE: case SL_PP_EOF: ctx->tokens_read++; break; @@ -462,6 +480,10 @@ _fetch_token(struct parse_context *ctx, } +/** + * Try to parse/match a particular token. + * \return 0 for success, -1 for error. + */ static int _parse_token(struct parse_context *ctx, enum sl_pp_token token, @@ -477,6 +499,10 @@ _parse_token(struct parse_context *ctx, } +/** + * Try to parse an identifer. + * \return 0 for success, -1 for error + */ static int _parse_id(struct parse_context *ctx, int id, @@ -707,8 +733,65 @@ _parse_centroid_qualifier(struct parse_context *ctx, static int -_parse_type_qualifier(struct parse_context *ctx, - struct parse_state *ps) +_parse_layout_qualifier(struct parse_context *ctx, + struct parse_state *ps) +{ + if (_parse_id(ctx, ctx->dict.layout, ps) == 0) { + if (!ctx->fragment_coord_conventions) { + _error(ctx, "GL_ARB_fragment_coord_conventions extension must be enabled " + "in order to use a layout qualifier"); + return -1; + } + + /* Layout qualifiers are only defined for fragment shaders, + * so do an early check. + */ + if (ctx->shader_type != 1) { + _error(ctx, "layout qualifiers are only valid for fragment shaders"); + return -1; + } + + /* start of a parenthesised list of layout qualifiers */ + + if (_parse_token(ctx, SL_PP_LPAREN, ps)) { + _error(ctx, "expected `('"); + return -1; + } + + /* parse comma-separated ID list */ + while (1) { + if (_parse_id(ctx, ctx->dict.origin_upper_left, ps) == 0) { + _emit(ctx, &ps->out, LAYOUT_QUALIFIER_UPPER_LEFT); + } + else if (_parse_id(ctx, ctx->dict.pixel_center_integer, ps) == 0) { + _emit(ctx, &ps->out, LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER); + } + else { + _error(ctx, "expected a layout qualifier name"); + return -1; + } + + if (_parse_token(ctx, SL_PP_RPAREN, ps) == 0) { + /* all done */ + break; + } + else if (_parse_token(ctx, SL_PP_COMMA, ps) == 0) { + /* another layout qualifier is coming */ + } + else { + _error(ctx, "expected `,' or `)'"); + return -1; + } + } + } + + return 0; +} + + +static int +_parse_storage_qualifier(struct parse_context *ctx, + struct parse_state *ps) { struct parse_state p = *ps; const struct sl_pp_token_info *input = _fetch_token(ctx, p.in); @@ -1006,13 +1089,19 @@ _parse_fully_specified_type(struct parse_context *ctx, { struct parse_state p = *ps; + if (_parse_layout_qualifier(ctx, &p)) { + return -1; + } + _emit(ctx, &p.out, LAYOUT_QUALIFIER_NONE); + if (_parse_invariant_qualifier(ctx, &p)) { _emit(ctx, &p.out, TYPE_VARIANT); } + if (_parse_centroid_qualifier(ctx, &p)) { _emit(ctx, &p.out, TYPE_CENTER); } - if (_parse_type_qualifier(ctx, &p)) { + if (_parse_storage_qualifier(ctx, &p)) { _emit(ctx, &p.out, TYPE_QUALIFIER_NONE); } if (_parse_precision(ctx, &p)) { @@ -1698,7 +1787,7 @@ _parse_parameter_declaration(struct parse_context *ctx, (void) e; - if (_parse_type_qualifier(ctx, &p)) { + if (_parse_storage_qualifier(ctx, &p)) { _emit(ctx, &p.out, TYPE_QUALIFIER_NONE); } _parse_parameter_qualifier(ctx, &p); @@ -2679,14 +2768,59 @@ _parse_external_declaration(struct parse_context *ctx, static int +_parse_extensions(struct parse_context *ctx, + struct parse_state *ps) +{ + for (;;) { + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); + unsigned int enable; + + if (!input) { + return -1; + } + + switch (input->token) { + case SL_PP_EXTENSION_REQUIRE: + case SL_PP_EXTENSION_ENABLE: + case SL_PP_EXTENSION_WARN: + enable = 1; + break; + case SL_PP_EXTENSION_DISABLE: + enable = 0; + break; + default: + return 0; + } + + ps->in++; + if (input->data.extension == ctx->dict.all) { + ctx->fragment_coord_conventions = enable; + } + else if (input->data.extension == ctx->dict._GL_ARB_fragment_coord_conventions) { + ctx->fragment_coord_conventions = enable; + } + } +} + + +static int _parse_translation_unit(struct parse_context *ctx, struct parse_state *ps) { _emit(ctx, &ps->out, REVISION); + if (_parse_extensions(ctx, ps)) { + return -1; + } if (_parse_external_declaration(ctx, ps)) { return -1; } - while (_parse_external_declaration(ctx, ps) == 0) { + for (;;) { + if (_parse_extensions(ctx, ps)) { + return -1; + } + if (_parse_external_declaration(ctx, ps)) { + break; + } } _emit(ctx, &ps->out, EXTERNAL_NULL); if (_parse_token(ctx, SL_PP_EOF, ps)) { @@ -2772,6 +2906,10 @@ sl_cl_compile(struct sl_pp_context *context, ADD_NAME(ctx, out); ADD_NAME(ctx, inout); + ADD_NAME(ctx, layout); + ADD_NAME(ctx, origin_upper_left); + ADD_NAME(ctx, pixel_center_integer); + ADD_NAME_STR(ctx, _struct, "struct"); ADD_NAME(ctx, __constructor); @@ -2792,12 +2930,17 @@ sl_cl_compile(struct sl_pp_context *context, ADD_NAME_STR(ctx, _false, "false"); ADD_NAME_STR(ctx, _true, "true"); + ADD_NAME(ctx, all); + ADD_NAME_STR(ctx, _GL_ARB_fragment_coord_conventions, "GL_ARB_fragment_coord_conventions"); + ctx.out_buf = NULL; ctx.out_cap = 0; ctx.shader_type = shader_type; ctx.parsing_builtin = 1; + ctx.fragment_coord_conventions = 0; + ctx.error[0] = '\0'; ctx.process_error = 0; |