diff options
author | Lukasz Kostyra <l.kostyra@samsung.com> | 2020-12-29 12:08:05 +0100 |
---|---|---|
committer | Lukasz Kostyra <l.kostyra@samsung.com> | 2021-01-07 17:40:54 +0100 |
commit | 2c7783b1fef54254001594636906eb27baeebd2e (patch) | |
tree | f6f019e391f4e654935420ec498cf725f327c59f | |
parent | 680bb1745b92ed22b4325f170f338cf21e63f507 (diff) | |
download | emulator-yagl-2c7783b1fef54254001594636906eb27baeebd2e.tar.gz emulator-yagl-2c7783b1fef54254001594636906eb27baeebd2e.tar.bz2 emulator-yagl-2c7783b1fef54254001594636906eb27baeebd2e.zip |
Parse GLSL #define preprocessor macros
GLSL lexer/parser now handles #define macros in order to properly
discover samplerExternalOES/sampler2D type.
Change-Id: I77f01bb722d31f980bf8a1d6b00a717c108a15b0
-rw-r--r-- | GLESv2/yagl_gles2_calls.c | 19 | ||||
-rw-r--r-- | GLESv2/yagl_gles2_context.c | 7 | ||||
-rw-r--r-- | GLESv2/yagl_glsl_lexer.l | 17 | ||||
-rw-r--r-- | GLESv2/yagl_glsl_parser.y | 57 | ||||
-rw-r--r-- | GLESv2/yagl_glsl_state.c | 40 | ||||
-rw-r--r-- | GLESv2/yagl_glsl_state.h | 15 |
6 files changed, 119 insertions, 36 deletions
diff --git a/GLESv2/yagl_gles2_calls.c b/GLESv2/yagl_gles2_calls.c index fec51f5..029a680 100644 --- a/GLESv2/yagl_gles2_calls.c +++ b/GLESv2/yagl_gles2_calls.c @@ -1438,11 +1438,30 @@ YAGL_API void glShaderSource(GLuint shader, GLsizei count, const GLchar * const ret = yagl_glsl_parse(&shader_obj->state); if ((ret == 0) && !shader_obj->state.have_error) { + struct yagl_glsl_sampler *samplers = NULL; + struct yagl_glsl_define *defines = NULL; + int i = 0, size = 0; + patched_source = yagl_glsl_state_get_output(&shader_obj->state, &patched_len); YAGL_LOG_TRACE("patched source = %s", patched_source); + YAGL_LOG_DEBUG("extract summary:"); + YAGL_LOG_DEBUG(" defines extracted from source:"); + defines = yagl_vector_data(&shader_obj->state.defines); + size = yagl_vector_size(&shader_obj->state.defines); + for (i = 0; i < size; ++i) { + YAGL_LOG_DEBUG(" -> %s => %s", defines[i].name_orig, defines[i].name_new); + } + + YAGL_LOG_DEBUG(" samplersExternalOES extracted from source:"); + samplers = yagl_vector_data(&shader_obj->state.samplers_ExternalOES); + size = yagl_vector_size(&shader_obj->state.samplers_ExternalOES); + for (i = 0; i < size; ++i) { + YAGL_LOG_DEBUG(" -> %s: at %d unit %d", samplers[i].name, samplers[i].location, samplers[i].value); + } + yagl_gles2_shader_source(shader_obj, (GLchar*)tmp_buff, patched_source, diff --git a/GLESv2/yagl_gles2_context.c b/GLESv2/yagl_gles2_context.c index b3018e2..928d900 100644 --- a/GLESv2/yagl_gles2_context.c +++ b/GLESv2/yagl_gles2_context.c @@ -641,6 +641,13 @@ void yagl_gles2_context_pre_draw(struct yagl_gles2_context *ctx, struct yagl_glsl_sampler *samplers = NULL; int i = 0, samplers_size = 0; + YAGL_LOG_DEBUG("samplersExternalOES extracted from source:"); + samplers = yagl_vector_data(&fragment_shader->state.samplers_ExternalOES); + samplers_size = yagl_vector_size(&fragment_shader->state.samplers_ExternalOES); + for (i = 0; i < samplers_size; ++i) { + YAGL_LOG_DEBUG(" -> %s: at %d unit %d", samplers[i].name, samplers[i].location, samplers[i].value); + } + ctx->base.have_externaloes_rebinds = 1; // FIXME for now assume user is always right and there is no error cases. diff --git a/GLESv2/yagl_glsl_lexer.l b/GLESv2/yagl_glsl_lexer.l index 84be821..8ec6599 100644 --- a/GLESv2/yagl_glsl_lexer.l +++ b/GLESv2/yagl_glsl_lexer.l @@ -264,26 +264,20 @@ STRING [^ \r\t\v\f\n()\[\]{},;?:/%*&|^!+\-=<>\.]+ return TOK_STRING; } -<UNIFORM>{WS}+ { - struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); - yagl_glsl_state_new_pending(state, yytext); -} - -<UNIFORM>"samplerExternalOES" { +<UNIFORM>{WS}*; { struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + BEGIN(INITIAL); yagl_glsl_state_new_str_token(state, yylval, yytext); - return TOK_SAMPLEREXTERNALOES; + return TOK_EOI; } -<UNIFORM>"sampler2D" { +<UNIFORM>{WS}+ { struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); - yagl_glsl_state_new_str_token(state, yylval, yytext); - return TOK_SAMPLER2D; + yagl_glsl_state_new_pending(state, yytext); } <UNIFORM>{STRING} { struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); - BEGIN(INITIAL); yagl_glsl_state_new_str_token(state, yylval, yytext); return TOK_STRING; } @@ -365,6 +359,7 @@ int yagl_glsl_state_init(struct yagl_glsl_state *state, yagl_vector_init(&state->strings, sizeof(char*), 0); yagl_vector_init(&state->samplers_ExternalOES, sizeof(struct yagl_glsl_sampler), 0); yagl_vector_init(&state->samplers_2D, sizeof(struct yagl_glsl_sampler), 0); + yagl_vector_init(&state->defines, sizeof(struct yagl_glsl_define), 0); return 1; } diff --git a/GLESv2/yagl_glsl_parser.y b/GLESv2/yagl_glsl_parser.y index d42aafb..d6ae2b1 100644 --- a/GLESv2/yagl_glsl_parser.y +++ b/GLESv2/yagl_glsl_parser.y @@ -41,6 +41,7 @@ static int yagl_glsl_lex(union YYSTYPE *val, struct yagl_glsl_state *state) } %token <str> TOK_EOL +%token <str> TOK_EOI %token <str> TOK_VERSION %token <str> TOK_DEFINE %token <str> TOK_EXTENSION @@ -55,8 +56,6 @@ static int yagl_glsl_lex(union YYSTYPE *val, struct yagl_glsl_state *state) %token <str> TOK_ATTRIBUTE %token <str> TOK_VARYING %token <str> TOK_UNIFORM -%token <str> TOK_SAMPLEREXTERNALOES -%token <str> TOK_SAMPLER2D %token <str> TOK_TEXTURE1D %token <str> TOK_TEXTURE1DPROJ %token <str> TOK_TEXTURE1DLOD @@ -187,6 +186,19 @@ expression yagl_glsl_state_flush_pending(state, $2.index); yagl_glsl_state_append_output(state, $2.value); } +| TOK_DEFINE TOK_STRING TOK_STRING TOK_EOL +{ + yagl_glsl_state_flush_pending(state, $1.index); + yagl_glsl_state_append_output(state, $1.value); + yagl_glsl_state_flush_pending(state, $2.index); + yagl_glsl_state_append_output(state, $2.value); + yagl_glsl_state_flush_pending(state, $3.index); + yagl_glsl_state_append_output(state, $3.value); + yagl_glsl_state_flush_pending(state, $4.index); + yagl_glsl_state_append_output(state, $4.value); + + yagl_glsl_state_add_define(state, $2.value, $3.value); +} | TOK_DEFINE { yagl_glsl_state_flush_pending(state, $1.index); @@ -330,14 +342,7 @@ expression yagl_glsl_state_append_output(state, $1.value); } } -| TOK_UNIFORM TOK_STRING -{ - yagl_glsl_state_flush_pending(state, $1.index); - yagl_glsl_state_append_output(state, $1.value); - yagl_glsl_state_flush_pending(state, $2.index); - yagl_glsl_state_append_output(state, $2.value); -} -| TOK_UNIFORM TOK_SAMPLEREXTERNALOES TOK_STRING +| TOK_UNIFORM TOK_STRING TOK_STRING TOK_EOI { yagl_glsl_state_flush_pending(state, $1.index); yagl_glsl_state_append_output(state, $1.value); @@ -345,24 +350,26 @@ expression yagl_glsl_state_append_output(state, $2.value); yagl_glsl_state_flush_pending(state, $3.index); yagl_glsl_state_append_output(state, $3.value); + yagl_glsl_state_flush_pending(state, $4.index); + yagl_glsl_state_append_output(state, $4.value); - if (!state->have_samplerexternaloes) { - yagl_glsl_state_append_header(state, "#define samplerExternalOES sampler2D\n"); - state->have_samplerexternaloes = 1; - } + // locally try to resolve the define based on current knowledge + // it won't matter if our type is not a macro but an actual sampler type + char* type_resolved; + yagl_glsl_state_resolve_define(state, $2.value, &type_resolved); - yagl_glsl_state_add_sampler_ExternalOES(state, $3.value); -} -| TOK_UNIFORM TOK_SAMPLER2D TOK_STRING -{ - yagl_glsl_state_flush_pending(state, $1.index); - yagl_glsl_state_append_output(state, $1.value); - yagl_glsl_state_flush_pending(state, $2.index); - yagl_glsl_state_append_output(state, $2.value); - yagl_glsl_state_flush_pending(state, $3.index); - yagl_glsl_state_append_output(state, $3.value); + if (strcmp(type_resolved, "samplerExternalOES") == 0) { + if (!state->have_samplerexternaloes) { + yagl_glsl_state_append_header(state, "#define samplerExternalOES sampler2D\n"); + state->have_samplerexternaloes = 1; + } + + yagl_glsl_state_add_sampler_ExternalOES(state, $3.value); + } else if (strcmp(type_resolved, "sampler2D") == 0) { + yagl_glsl_state_add_sampler_2D(state, $3.value); + } - yagl_glsl_state_add_sampler_2D(state, $3.value); + free(type_resolved); } | TOK_TEXTURE1D { diff --git a/GLESv2/yagl_glsl_state.c b/GLESv2/yagl_glsl_state.c index c1c3a5d..ee7f33f 100644 --- a/GLESv2/yagl_glsl_state.c +++ b/GLESv2/yagl_glsl_state.c @@ -38,6 +38,7 @@ #include "yagl_state.h" #include <string.h> #include <stdio.h> +#include <assert.h> static void yagl_glsl_state_flush_version(struct yagl_glsl_state *state) { @@ -324,3 +325,42 @@ void yagl_glsl_state_add_sampler_2D(struct yagl_glsl_state *state, sampler.replaced_tex2d = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN; yagl_vector_push_back(&state->samplers_2D, &sampler); } + +void yagl_glsl_state_add_define(struct yagl_glsl_state *state, + const char *tok_orig, const char *tok_new) +{ + struct yagl_glsl_define define; + define.name_orig = strdup(tok_orig); + define.name_new = strdup(tok_new); + yagl_vector_push_back(&state->defines, &define); +} + +void yagl_glsl_state_resolve_define(struct yagl_glsl_state *state, + const char *token, char **resolved) +{ + struct yagl_glsl_define *defines = yagl_vector_data(&state->defines); + int i = 0, defines_size = yagl_vector_size(&state->defines); + const char* to_resolve = token; + YAGL_LOG_FUNC_SET(yagl_glsl_state_resolve_define); + + assert(resolved != NULL); + + YAGL_LOG_DEBUG("LKDEBUG resolving define %s", to_resolve); + while (1) { + for (i = 0; i < defines_size; ++i) { + if (strcmp(to_resolve, defines[i].name_orig) == 0) { + YAGL_LOG_DEBUG(" * %s -> %s", to_resolve, defines[i].name_new); + to_resolve = defines[i].name_new; + break; + } + } + + if (i == defines_size) + // we went through everything we know and name did not appear + // assume this is the end + break; + } + + *resolved = strdup(to_resolve); + YAGL_LOG_DEBUG("resolved as %s", *resolved); +} diff --git a/GLESv2/yagl_glsl_state.h b/GLESv2/yagl_glsl_state.h index 2f9184f..4091339 100644 --- a/GLESv2/yagl_glsl_state.h +++ b/GLESv2/yagl_glsl_state.h @@ -52,6 +52,12 @@ struct yagl_glsl_pending #define YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN (-1) #define YAGL_GLSL_SAMPLER_VALUE_UNKNOWN (-1) +struct yagl_glsl_define +{ + char* name_orig; + char* name_new; +}; + struct yagl_glsl_sampler { char* name; @@ -134,6 +140,9 @@ struct yagl_glsl_state // strdup'ed strings. struct yagl_vector strings; + // preprocessor defines + struct yagl_vector defines; + // names of samplerExternalOES uniforms struct yagl_vector samplers_ExternalOES; @@ -196,6 +205,12 @@ void yagl_glsl_state_add_sampler_ExternalOES(struct yagl_glsl_state *state, void yagl_glsl_state_add_sampler_2D(struct yagl_glsl_state *state, const char *str); +void yagl_glsl_state_add_define(struct yagl_glsl_state *state, + const char *tok_orig, const char *tok_new); + +void yagl_glsl_state_resolve_define(struct yagl_glsl_state *state, + const char *token, char **resolved); + int yagl_glsl_parse(struct yagl_glsl_state *state); #endif |