return arrays;
}
+static void yagl_gles2_context_bind_externaloes(struct yagl_gles2_context *ctx,
+ struct yagl_gles2_shader *shader)
+{
+ struct yagl_glsl_sampler *samplers;
+ int i = 0, samplers_size = 0;
+ YAGL_LOG_FUNC_SET(yagl_gles2_context_bind_externaloes);
+
+ YAGL_LOG_DEBUG("Binding samplerExternalOES units into GL_TEXTURE_2D slots:");
+ // FIXME for now assume user is always right and there is no error cases.
+ // Errors to consider:
+ // * samplerExternalOES and sampler2D attempting to access same unit
+ // * samplerExternalOES points at unit having no texture bound
+ samplers = yagl_vector_data(&shader->state.samplers_ExternalOES);
+ samplers_size = yagl_vector_size(&shader->state.samplers_ExternalOES);
+ for (i = 0; i < samplers_size; ++i) {
+ struct yagl_gles_texture_target_state *texture_2d_state, *texture_external_state;
+
+ texture_2d_state =
+ &ctx->base.texture_units[samplers[i].value].target_states[yagl_gles_texture_target_2d];
+ texture_external_state =
+ &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);
+ //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);
+ continue;
+ }
+
+ // we could have currently bound either an actual texture 2d or a "zero texture" (for binding = 0)
+ // store whatever is bound from cached info, we'll restore it post-draw
+ if (texture_2d_state->texture != texture_2d_state->texture_zero) {
+ samplers[i].replaced_tex2d = texture_2d_state->texture->global_name;
+ YAGL_LOG_DEBUG(" -> Binding in place of existing texture");
+ } else {
+ samplers[i].replaced_tex2d = texture_2d_state->texture_zero->global_name;
+ YAGL_LOG_DEBUG(" -> Binding in place of zero texture");
+ }
+ YAGL_LOG_DEBUG(" #%d: slot %d texture2D %d => textureExternal %d", i, samplers[i].value, samplers[i].replaced_tex2d,
+ texture_external_state->texture->global_name);
+
+ // samplers[i].value is unit requested by app from shader - replace it
+ yagl_host_glActiveTexture(GL_TEXTURE0 + samplers[i].value);
+ yagl_host_glBindTexture(GL_TEXTURE_2D, texture_external_state->texture->global_name);
+ }
+}
+
+static void yagl_gles2_context_restore_externaloes_binds(struct yagl_gles2_shader *shader)
+{
+ struct yagl_glsl_sampler *samplers;
+ int i = 0, samplers_size = 0;
+ YAGL_LOG_FUNC_SET(yagl_gles2_context_restore_externaloes_binds);
+
+ YAGL_LOG_DEBUG("Restoring TEXTURE_2D bindings:");
+ samplers = yagl_vector_data(&shader->state.samplers_ExternalOES);
+ samplers_size = yagl_vector_size(&shader->state.samplers_ExternalOES);
+ for (i = 0; i < samplers_size; ++i) {
+ if (samplers[i].location == YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN ||
+ samplers[i].value == YAGL_GLSL_SAMPLER_VALUE_UNKNOWN) {
+ continue;
+ }
+
+ YAGL_LOG_DEBUG(" #%d: %d unit => %d texture", i, samplers[i].value, samplers[i].replaced_tex2d);
+ yagl_host_glActiveTexture(GL_TEXTURE0 + samplers[i].value);
+ yagl_host_glBindTexture(GL_TEXTURE_2D, samplers[i].replaced_tex2d);
+ samplers[i].replaced_tex2d = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
+ }
+}
+
void yagl_gles2_context_pre_draw(struct yagl_gles2_context *ctx,
GLenum mode,
GLint count)
* Check for currently bound shaders if any samplers are of samplerExternalOES type.
* If they are, do some extra checks and bind some textures temporarily.
*/
- struct yagl_gles2_shader *fragment_shader = ctx->program->fragment_shader;
- if (fragment_shader->state.have_samplerexternaloes) {
- struct yagl_glsl_sampler *samplers = NULL;
- int i = 0, samplers_size = 0;
-
- ctx->base.have_externaloes_rebinds = 1;
-
- YAGL_LOG_TRACE("Binding samplerExternalOES units into GL_TEXTURE_2D slots:");
- // FIXME for now assume user is always right and there is no error cases.
- // Errors to consider:
- // * samplerExternalOES and sampler2D attempting to access same unit
- // * samplerExternalOES points at unit having no texture bound
- 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) {
- struct yagl_gles_texture_target_state *texture_2d_state, *texture_external_state;
-
- texture_2d_state =
- &ctx->base.texture_units[samplers[i].value].target_states[yagl_gles_texture_target_2d];
- texture_external_state =
- &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);
- 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);
- continue;
- }
-
- // we could have currently bound either an actual texture 2d or a "zero texture" (for binding = 0)
- // store whatever is bound from cached info, we'll restore it post-draw
- if (texture_2d_state->texture != texture_2d_state->texture_zero) {
- samplers[i].replaced_tex2d = texture_2d_state->texture->global_name;
- } else {
- samplers[i].replaced_tex2d = texture_2d_state->texture_zero->global_name;
- }
- YAGL_LOG_TRACE(" #%d: slot %d texture2D %d => textureExternal %d", i, samplers[i].value, samplers[i].replaced_tex2d,
- texture_external_state->texture->global_name);
+ struct yagl_gles2_shader *vertex_shader = ctx->program->vertex_shader;
+ if (vertex_shader && vertex_shader->state.have_samplerexternaloes) {
+ ctx->have_externaloes_rebinds_vs = 1;
+ YAGL_LOG_DEBUG("======= Vertex shader has samplerExternalOES ========");
+ yagl_gles2_context_bind_externaloes(ctx, vertex_shader);
+ }
- // samplers[i].value is unit requested by app from shader - replace it
- yagl_host_glActiveTexture(GL_TEXTURE0 + samplers[i].value);
- yagl_host_glBindTexture(GL_TEXTURE_2D, texture_external_state->texture->global_name);
- }
+ struct yagl_gles2_shader *fragment_shader = ctx->program->fragment_shader;
+ if (fragment_shader && fragment_shader->state.have_samplerexternaloes) {
+ ctx->have_externaloes_rebinds_fs = 1;
+ YAGL_LOG_DEBUG("======= Fragment shader has samplerExternalOES ========");
+ yagl_gles2_context_bind_externaloes(ctx, fragment_shader);
}
}
GLenum mode,
GLint count)
{
- YAGL_LOG_FUNC_SET(yagl_gles2_context_post_draw);
-
if (mode == GL_POINTS) {
yagl_host_glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
if (yagl_get_host_gl_version() <= yagl_gl_3_2) {
/*
* Restore original TEXTURE_2D bindings
*/
- if (ctx->base.have_externaloes_rebinds) {
- struct yagl_gles2_shader *fragment_shader = ctx->program->fragment_shader;
- struct yagl_glsl_sampler *samplers;
- int i = 0, samplers_size = 0;
-
- YAGL_LOG_TRACE("Restoring TEXTURE_2D bindings:");
- 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) {
- if (samplers[i].location == YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN ||
- samplers[i].value == YAGL_GLSL_SAMPLER_VALUE_UNKNOWN) {
- continue;
- }
+ if (ctx->have_externaloes_rebinds_vs) {
+ yagl_gles2_context_restore_externaloes_binds(ctx->program->vertex_shader);
+ }
- YAGL_LOG_TRACE(" #%d: %d unit => %d texture", i, samplers[i].value, samplers[i].replaced_tex2d);
- yagl_host_glActiveTexture(GL_TEXTURE0 + samplers[i].value);
- yagl_host_glBindTexture(GL_TEXTURE_2D, samplers[i].replaced_tex2d);
- samplers[i].replaced_tex2d = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
- }
+ if (ctx->have_externaloes_rebinds_fs) {
+ yagl_gles2_context_restore_externaloes_binds(ctx->program->fragment_shader);
+ }
- yagl_host_glActiveTexture(ctx->base.active_texture_unit);
- ctx->base.have_externaloes_rebinds = 0;
+ /*
+ * Reactivate texture unit which was active before draw and zero flags
+ */
+ if (ctx->have_externaloes_rebinds_vs || ctx->have_externaloes_rebinds_fs) {
+ yagl_host_glActiveTexture(GL_TEXTURE0 + ctx->base.active_texture_unit);
+ ctx->have_externaloes_rebinds_vs = 0;
+ ctx->have_externaloes_rebinds_fs = 0;
}
}
* Luckily, uniform location does not change so it has to be done
* only once.
*/
- if (program->fragment_shader->state.have_samplerexternaloes) {
- struct yagl_glsl_sampler *data = NULL, *it = NULL;
+ if (program->vertex_shader &&
+ program->vertex_shader->state.have_samplerexternaloes) {
+ struct yagl_glsl_sampler *data = NULL;
+ int i = 0, data_size = 0;
+
+ data = yagl_vector_data(&program->vertex_shader->state.samplers_ExternalOES);
+ data_size = yagl_vector_size(&program->vertex_shader->state.samplers_ExternalOES);
+ for (i = 0; i < data_size; ++i) {
+ if (strcmp(data[i].name, name) == 0) {
+ data[i].location = ret;
+ break;
+ }
+ }
+ }
+
+ if (program->fragment_shader &&
+ program->fragment_shader->state.have_samplerexternaloes) {
+ struct yagl_glsl_sampler *data = NULL;
int i = 0, data_size = 0;
data = yagl_vector_data(&program->fragment_shader->state.samplers_ExternalOES);
data_size = yagl_vector_size(&program->fragment_shader->state.samplers_ExternalOES);
for (i = 0; i < data_size; ++i) {
- it = data + i;
- if (strcmp(it->name, name) == 0) {
- it->location = ret;
+ if (strcmp(data[i].name, name) == 0) {
+ data[i].location = ret;
break;
}
}
yagl_host_glUniform1i(program->gen_locations, global_location, x);
/*
- * Update fragment shader state for pre_draw/post_draw analysis
+ * Update shader state for pre_draw/post_draw analysis
*/
- if (program->fragment_shader->state.have_samplerexternaloes) {
- struct yagl_glsl_sampler *data = NULL, *it = NULL;
+ if (program->vertex_shader &&
+ program->vertex_shader->state.have_samplerexternaloes) {
+ struct yagl_glsl_sampler *data = NULL;
+ int i = 0, data_size = 0;
+
+ data = yagl_vector_data(&program->vertex_shader->state.samplers_ExternalOES);
+ data_size = yagl_vector_size(&program->vertex_shader->state.samplers_ExternalOES);
+ for (i = 0; i < data_size; ++i) {
+ if (data[i].location == location) {
+ data[i].value = x;
+ break;
+ }
+ }
+ }
+
+ if (program->fragment_shader &&
+ program->fragment_shader->state.have_samplerexternaloes) {
+ struct yagl_glsl_sampler *data = NULL;
int i = 0, data_size = 0;
data = yagl_vector_data(&program->fragment_shader->state.samplers_ExternalOES);
data_size = yagl_vector_size(&program->fragment_shader->state.samplers_ExternalOES);
for (i = 0; i < data_size; ++i) {
- it = data + i;
- if (it->location == location) {
- it->value = x;
+ if (data[i].location == location) {
+ data[i].value = x;
break;
}
}
// TODO
// Might require switching state->defines into yagl_list
}
+/*
+static void yagl_glsl_state_pp_dbg_print_expr_stack(struct yagl_glsl_state *state, const char* func_name)
+{
+ int i = 0;
+ const char* _yagl_log_current_func = func_name ? func_name : "yagl_glsl_state_pp_dbg_print_expr_stack";
+ pid_t _yagl_log_current_pid = getpid();
+ pid_t _yagl_log_current_tid = syscall(SYS_gettid);
+
+
+ YAGL_LOG_TRACE(" Expression stack state:");
+ for (i = state->pp_current_expr - 1; i >= 0; --i) {
+ if (state->pp_exprs[i].op == yagl_glsl_pp_op_token) {
+ if (state->pp_exprs[i].token.macro) {
+ YAGL_LOG_TRACE(" #%d: macro %s", i, state->pp_exprs[i].token.macro);
+ } else {
+ YAGL_LOG_TRACE(" #%d: const %d", i, state->pp_exprs[i].token.value);
+ }
+ } else {
+ YAGL_LOG_TRACE(" #%d: oper %d (%s) prio %d", i,
+ state->pp_exprs[i].op, glsl_pp_op_dbgstr[state->pp_exprs[i].op],
+ glsl_pp_op_prio[state->pp_exprs[i].op]
+ );
+ }
+ }
+ YAGL_LOG_TRACE(" ");
+}
+static void yagl_glsl_state_pp_dbg_print_op_stack(struct yagl_glsl_state *state, const char* func_name)
+{
+ int i = 0;
+ const char* _yagl_log_current_func = func_name ? func_name : "yagl_glsl_state_pp_dbg_print_op_stack";
+ pid_t _yagl_log_current_pid = getpid();
+ pid_t _yagl_log_current_tid = syscall(SYS_gettid);
+
+ YAGL_LOG_TRACE(" Operation stack state:");
+ for (i = state->pp_current_op - 1; i >= 0; --i) {
+ YAGL_LOG_TRACE(" #%d: op %d (%s) prio %d", i,
+ state->pp_ops[i], glsl_pp_op_dbgstr[state->pp_ops[i]],
+ glsl_pp_op_prio[state->pp_ops[i]]
+ );
+ }
+ YAGL_LOG_TRACE(" ");
+}
+*/
void yagl_glsl_state_pp_resolve_define(struct yagl_glsl_state *state,
const char *token, char **resolved, int *resolved_int)
{
int yagl_glsl_state_pp_is_condition_met(struct yagl_glsl_state *state)
{
- if (state->pp_current_condition)
- // we are in a condition scope, check if it's met
- return (state->pp_conditions[state->pp_current_condition - 1] == yagl_glsl_pp_condition_met);
- else
- // outside of any condition scope, we don't need to exclude any preprocessor code
- // so assume preprocessor condition is met anyway
- return 1;
+ int result = 1;
+ int i = 0;
+
+ // for current condition to be met all conditions on the stack must be met
+ // if there is no conditions on stack, result is always true (we're not in condition scope)
+ for (i = 0; i < state->pp_current_condition; ++i) {
+ result &= (state->pp_conditions[i] == yagl_glsl_pp_condition_met);
+ }
+
+ return result;
}
int yagl_glsl_state_pp_is_condition_completed(struct yagl_glsl_state *state)
{
- if (state->pp_current_condition)
- return (state->pp_conditions[state->pp_current_condition - 1] == yagl_glsl_pp_condition_completed);
- else
- return 1;
+ assert(state->pp_current_condition > 0);
+ return (state->pp_conditions[state->pp_current_condition - 1] == yagl_glsl_pp_condition_completed);
}
void yagl_glsl_state_pp_condition_parse_start(struct yagl_glsl_state *state)
return;
assert(state->pp_current_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE);
-
state->pp_exprs[state->pp_current_expr].op = yagl_glsl_pp_op_token;
state->pp_exprs[state->pp_current_expr].token.macro = token ? strdup(token) : NULL;
state->pp_exprs[state->pp_current_expr].token.value = value;
}
// 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_current_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE);
+ while (glsl_pp_op_prio[op] <= glsl_pp_op_prio[state->pp_ops[state->pp_current_op - 1]] &&
+ state->pp_current_op > 0) {
+ assert(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++;
if (token.macro != NULL) {
yagl_glsl_state_pp_resolve_define(state, token.macro, &tmp, &v);
if (tmp != NULL) {
+ yagl_free(tmp);
return 0;
}
} else {
if (tok_a.macro != NULL) {
yagl_glsl_state_pp_resolve_define(state, tok_a.macro, &tmp, &a);
if (tmp != NULL) {
+ yagl_free(tmp);
return 0;
}
} else {
if (tok_b.macro != NULL) {
yagl_glsl_state_pp_resolve_define(state, tok_b.macro, &tmp, &b);
if (tmp != NULL) {
+ yagl_free(tmp);
return 0;
}
} else {
// empty op stack into expression stack
while (state->pp_current_op > 0) {
- assert(state->pp_current_op > 0 && state->pp_current_expr < YAGL_GLSL_PP_EXPRESSION_STACK_SIZE);
+ assert(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++;