texture = texture_target_state->texture_zero;
}
- // TEXTURE_EXTERNAL_OES is late bound, before drawing
- if (target != GL_TEXTURE_EXTERNAL_OES) {
- if (!yagl_gles_texture_bind(texture, target)) {
- YAGL_SET_ERR(GL_INVALID_OPERATION);
- return;
- }
+ if (!yagl_gles_texture_bind(texture, target)) {
+ YAGL_SET_ERR(GL_INVALID_OPERATION);
+ return;
}
yagl_gles_texture_acquire(texture);
// on host side. In order to not collide with what is bound there we'll
// store the texture for later on guest side and do the temporary bind
// on-demand, whenever app modifies TEXTURE_EXTERNAL_OES
- // target via other GL APIs.
- assert(target != GL_TEXTURE_EXTERNAL_OES);
-
- yagl_host_glBindTexture(target, texture->global_name);
+ // target via other GL APIs. See yagl_gles2_context_pre_draw().
+ if (target != GL_TEXTURE_EXTERNAL_OES) {
+ yagl_host_glBindTexture(target, texture->global_name);
+ }
texture->target = target;
&ctx->base.texture_units[samplers[i].value].target_states[yagl_gles_texture_target_external_oes];
if (texture_external_state->texture == texture_external_state->texture_zero) {
- YAGL_LOG_WARN(" #d: Trying to rebind unbound external texture at unit %d", i, samplers[i].value);
+ YAGL_LOG_WARN(" #%d: Trying to rebind unbound external texture at unit %d", i, samplers[i].value);
continue; // TODO error GL_INVALID_OPERATION?
}
if (samplers[i].location == YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN ||
samplers[i].value == YAGL_GLSL_SAMPLER_VALUE_UNKNOWN) {
- YAGL_LOG_WARN(" #d: Unknown location/value of uniform %s - skipping", i, samplers[i].name);
+ YAGL_LOG_WARN(" #%d: Unknown location/value of uniform %s - skipping", i, samplers[i].name);
continue;
}
%option prefix="yagl_glsl_lexer_"
%option extra-type="struct yagl_glsl_state *"
-%x COMMENT PP PP_IFDEF PP_IF PP_DEFINE PP_UNDEF UNIFORM
+%x COMMENT PP PP_IFDEF PP_IF PP_DEFINE PP_UNDEF UNIFORM PRECISION
WS [ \r\t\v\f]
-PRECISION "lowp"|"mediump"|"highp"|"precision"[^;\n]+;?
+PRECISION_QUAL "lowp"|"mediump"|"highp"
+PRECISION_ALL ${PRECISION_QUAL}|"precision"[^;\n]+;?
CONTROL [()\[\]{},;?:/%*&|^!+\-=<>\.]
STRING [^ \r\t\v\f\n()\[\]{},;?:/%*&|^!+\-=<>\.]+
return TOK_GLFRAGCOLOR;
}
-{PRECISION} {
+"precision" {
struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
+ BEGIN(PRECISION);
yagl_glsl_state_new_str_token(state, yylval, yytext);
return TOK_PRECISION;
}
+<PRECISION>{PRECISION_QUAL}[^;\n]+;? {
+ struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
+ BEGIN(INITIAL);
+ yagl_glsl_state_new_str_token(state, yylval, yytext);
+ return TOK_PRECISION_QUAL;
+}
+
{CONTROL} {
struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
yagl_glsl_state_new_pending(state, yytext);
return TOK_ES;
}
-<PP>{PRECISION} {
+<PP>{PRECISION_ALL} {
struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
yagl_glsl_state_new_str_token(state, yylval, yytext);
- return TOK_PRECISION;
+ return TOK_PRECISION_ALL;
}
<PP>{CONTROL} {
yagl_glsl_state_new_pending(state, yytext);
}
+<UNIFORM>{PRECISION_QUAL} {
+ struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
+ yagl_glsl_state_new_str_token(state, yylval, yytext);
+ return TOK_PRECISION_QUAL;
+}
+
<UNIFORM>{STRING} {
struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner);
yagl_glsl_state_new_str_token(state, yylval, yytext);
return num_read;
}
-//extern int yagl_glsl_debug;
+extern int yagl_glsl_debug;
int yagl_glsl_state_init(struct yagl_glsl_state *state,
GLenum shader_type,
memset(state, 0, sizeof(*state));
- //yagl_glsl_debug = 1;
+ yagl_glsl_debug = 1;
if (yagl_glsl_lexer_lex_init_extra(state, &scanner)) {
return 0;
%token <integer> TOK_INTEGER
%token <str> TOK_ES
%token <str> TOK_PRECISION
+%token <str> TOK_PRECISION_QUAL
+%token <str> TOK_PRECISION_ALL
%token <str> TOK_MAXVERTEXUNIFORMVECTORS
%token <str> TOK_MAXFRAGMENTUNIFORMVECTORS
%token <str> TOK_MAXVARYINGVECTORS
yagl_glsl_state_flush_pending(state, $1.index);
yagl_glsl_state_append_output(state, $1.value);
}
-| TOK_DEFINE TOK_PRECISION
+| TOK_DEFINE TOK_PRECISION_ALL
{
yagl_glsl_state_flush_pending(state, $1.index);
yagl_glsl_state_append_output(state, $1.value);
yagl_glsl_state_append_output_char(state, $1.c);
if (state->pp_condition_parse_started) {
- int condition_result = yagl_glsl_state_pp_condition_resolve(state);
- if (condition_result < 0) {
+ yagl_glsl_pp_condition_status status = yagl_glsl_state_pp_condition_resolve(state);
+ if (status == yagl_glsl_pp_condition_error) {
yyerror(state, "GLSL preprocessor condition resolution failure");
} else {
if (state->pp_elif_check) {
- yagl_glsl_state_pp_set_condition_status(state,
- (condition_result > 0) ? yagl_glsl_pp_condition_met : yagl_glsl_pp_condition_not_met);
+ yagl_glsl_state_pp_set_condition_status(state, status);
state->pp_elif_check = 0;
} else {
- yagl_glsl_state_pp_start_condition(state,
- (condition_result > 0) ? yagl_glsl_pp_condition_met : yagl_glsl_pp_condition_not_met);
+ yagl_glsl_state_pp_start_condition(state, status);
}
}
}
yagl_glsl_state_flush_pending(state, $1.index);
}
-| TOK_PRECISION
+| TOK_PRECISION TOK_PRECISION_QUAL
{
yagl_glsl_state_flush_pending(state, $1.index);
if (!state->patch_precision) {
yagl_glsl_state_append_output(state, $1.value);
}
+
+ yagl_glsl_state_flush_pending(state, $2.index);
+ if (!state->patch_precision) {
+ yagl_glsl_state_append_output(state, $2.value);
+ }
}
| TOK_ES
{
yagl_glsl_state_append_output(state, $1.value);
}
}
+| TOK_UNIFORM TOK_PRECISION_QUAL TOK_STRING TOK_STRING TOK_EOI
+{
+ yagl_glsl_state_flush_pending(state, $1.index);
+ yagl_glsl_state_append_output(state, $1.value);
+
+ // precision qualifier should only be flushed here, GLSL non-ES does not support it
+ yagl_glsl_state_flush_pending(state, $2.index);
+
+ 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_flush_pending(state, $5.index);
+ yagl_glsl_state_append_output(state, $5.value);
+
+ if (yagl_glsl_state_pp_is_condition_met(state)) {
+ // 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 = NULL;
+ int int_resolved = 0;
+ yagl_glsl_state_pp_resolve_define(state, $3.value, &type_resolved, &int_resolved);
+
+ if (type_resolved != NULL) {
+ 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, $4.value);
+ } else if (strcmp(type_resolved, "sampler2D") == 0) {
+ yagl_glsl_state_add_sampler_2D(state, $4.value);
+ }
+
+ free(type_resolved);
+ }
+ }
+}
| TOK_UNIFORM TOK_STRING TOK_STRING TOK_EOI
{
yagl_glsl_state_flush_pending(state, $1.index);
if (yagl_glsl_state_pp_is_condition_met(state)) {
// 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;
- int int_resolved;
+ char* type_resolved = NULL;
+ int int_resolved = 0;
yagl_glsl_state_pp_resolve_define(state, $2.value, &type_resolved, &int_resolved);
if (type_resolved != NULL) {
if (op == yagl_glsl_pp_op_par_close) {
// move ops from op stack to expr stack until we hit open parenthesis
while (state->pp_ops[state->pp_current_op - 1] != yagl_glsl_pp_op_par_open) {
- assert(state->pp_current_op > 0 && state->pp_curent_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE);
+ assert(state->pp_current_op > 0 && state->pp_current_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE);
state->pp_current_op--;
state->pp_exprs[state->pp_current_expr].op = state->pp_ops[state->pp_current_op];
state->pp_current_expr++;
// move higher or equal priority operations to expression stack
while (glsl_pp_op_prio[op] <= glsl_pp_op_prio[state->pp_ops[state->pp_current_op - 1]]) {
- assert(state->pp_current_op > 0 && state->pp_curent_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE);
+ assert(state->pp_current_op > 0 && state->pp_current_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE);
state->pp_current_op--;
state->pp_exprs[state->pp_current_expr].op = state->pp_ops[state->pp_current_op];
state->pp_current_expr++;
struct yagl_glsl_pp_token token,
int *result)
{
- char* tmp;
- int v;
+ char* tmp = NULL;
+ int v = 0;
assert(result != NULL);
struct yagl_glsl_pp_token tok_b,
int *result)
{
- char *tmp;
- int a, b;
+ char *tmp = NULL;
+ int a = 0, b = 0;
assert(result != NULL);
}
}
-int yagl_glsl_state_pp_condition_resolve(struct yagl_glsl_state *state)
+yagl_glsl_pp_condition_status yagl_glsl_state_pp_condition_resolve(struct yagl_glsl_state *state)
{
struct yagl_glsl_pp_token res_stack[YAGL_GLSL_PP_EXPRESSION_STACK_SIZE];
int res_cur = 0;
struct yagl_glsl_pp_token tok_a, tok_b;
int i, tmp_result;
- int result = 0;
+ yagl_glsl_pp_condition_status result = yagl_glsl_pp_condition_not_met;
+ YAGL_LOG_FUNC_SET(yagl_glsl_state_pp_condition_resolve);
// empty op stack into expression stack
while (state->pp_current_op > 0) {
- assert(state->pp_current_op > 0 && state->pp_curent_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE);
+ assert(state->pp_current_op > 0 && state->pp_current_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE);
state->pp_current_op--;
state->pp_exprs[state->pp_current_expr].op = state->pp_ops[state->pp_current_op];
state->pp_current_expr++;
assert(res_cur > 0);
if (!yagl_glsl_state_pp_solve_unary(state, state->pp_exprs[i].op, res_stack[res_cur - 1], &tmp_result)) {
- result = -1;
+ YAGL_LOG_ERROR("Expression #%d: Unary operator %d (%s) failed", i, state->pp_exprs[i].op, glsl_pp_op_dbgstr[state->pp_exprs[i].op]);
+ result = yagl_glsl_pp_condition_error;
goto clean;
}
} else {
res_cur--;
if (!yagl_glsl_state_pp_solve_binary(state, state->pp_exprs[i].op, tok_a, tok_b, &tmp_result)) {
- result = -1;
+ YAGL_LOG_ERROR("Expression #%d: Binary operator %d (%s) failed", i, state->pp_exprs[i].op, glsl_pp_op_dbgstr[state->pp_exprs[i].op]);
+ result = yagl_glsl_pp_condition_error;
goto clean;
}
}
// there should be only one resolution on stack remaining - the result
assert(res_cur == 1);
- result = res_stack[res_cur - 1].value;
+ result = (res_stack[res_cur - 1].value > 0 ? yagl_glsl_pp_condition_met : yagl_glsl_pp_condition_not_met);
clean:
// cleanup
typedef enum
{
+ yagl_glsl_pp_condition_error = -1,
yagl_glsl_pp_condition_not_met = 0,
yagl_glsl_pp_condition_met,
yagl_glsl_pp_condition_completed,
void yagl_glsl_state_pp_condition_parse_add_op(struct yagl_glsl_state *state, yagl_glsl_pp_expr_op op);
// resolve preprocessor condition parser; 1 if met, 0 if not met, -1 on error
-int yagl_glsl_state_pp_condition_resolve(struct yagl_glsl_state *state);
+yagl_glsl_pp_condition_status yagl_glsl_state_pp_condition_resolve(struct yagl_glsl_state *state);
/*
* @}
*/