tex_target_state->texture->mag_filter = param;
}
- yagl_host_glTexParameteri(target, pname, param);
+ if (target == GL_TEXTURE_EXTERNAL_OES) {
+ struct yagl_gles_texture_target_state *tex2d_target_state =
+ yagl_gles_context_get_active_texture_target_state(ctx, yagl_gles_texture_target_2d);
+
+ yagl_host_glBindTexture(GL_TEXTURE_2D, tex_target_state->texture->global_name);
+ yagl_host_glTexParameteri(GL_TEXTURE_2D, pname, param);
+ yagl_host_glBindTexture(GL_TEXTURE_2D, tex2d_target_state->texture->global_name);
+ } else {
+ yagl_host_glTexParameteri(target, pname, param);
+ }
out:
YAGL_LOG_FUNC_EXIT(NULL);
tex_target_state->texture->mag_filter = params[0];
}
- yagl_host_glTexParameteriv(target, pname, params, 1);
+ if (target == GL_TEXTURE_EXTERNAL_OES) {
+ struct yagl_gles_texture_target_state *tex2d_target_state =
+ yagl_gles_context_get_active_texture_target_state(ctx, yagl_gles_texture_target_2d);
+
+ yagl_host_glBindTexture(GL_TEXTURE_2D, tex_target_state->texture->global_name);
+ yagl_host_glTexParameteriv(GL_TEXTURE_2D, pname, params, 1);
+ yagl_host_glBindTexture(GL_TEXTURE_2D, tex2d_target_state->texture->global_name);
+ } else {
+ yagl_host_glTexParameteriv(target, pname, params, 1);
+ }
out:
YAGL_LOG_FUNC_EXIT(NULL);
tex_target_state->texture->mag_filter = param;
}
- yagl_host_glTexParameterf(target, pname, param);
+ if (target == GL_TEXTURE_EXTERNAL_OES) {
+ struct yagl_gles_texture_target_state *tex2d_target_state =
+ yagl_gles_context_get_active_texture_target_state(ctx, yagl_gles_texture_target_2d);
+
+ yagl_host_glBindTexture(GL_TEXTURE_2D, tex_target_state->texture->global_name);
+ yagl_host_glTexParameterf(GL_TEXTURE_2D, pname, param);
+ yagl_host_glBindTexture(GL_TEXTURE_2D, tex2d_target_state->texture->global_name);
+ } else {
+ yagl_host_glTexParameterf(target, pname, param);
+ }
}
void yagl_gles_context_tex_parameterfv(struct yagl_gles_context *ctx,
tex_target_state->texture->mag_filter = params[0];
}
- yagl_host_glTexParameterfv(target, pname, params, 1);
+ if (target == GL_TEXTURE_EXTERNAL_OES) {
+ struct yagl_gles_texture_target_state *tex2d_target_state =
+ yagl_gles_context_get_active_texture_target_state(ctx, yagl_gles_texture_target_2d);
+
+ yagl_host_glBindTexture(GL_TEXTURE_2D, tex_target_state->texture->global_name);
+ yagl_host_glTexParameterfv(GL_TEXTURE_2D, pname, params, 1);
+ yagl_host_glBindTexture(GL_TEXTURE_2D, tex2d_target_state->texture->global_name);
+ } else {
+ yagl_host_glTexParameterfv(target, pname, params, 1);
+ }
+
}
int yagl_gles_context_get_tex_parameterfv(struct yagl_gles_context *ctx,
break;
}
- yagl_host_glGetTexParameterfv(target, pname, params);
+ if (target == GL_TEXTURE_EXTERNAL_OES) {
+ struct yagl_gles_texture_target_state *tex2d_target_state =
+ yagl_gles_context_get_active_texture_target_state(ctx, yagl_gles_texture_target_2d);
+
+ yagl_host_glBindTexture(GL_TEXTURE_2D, texture_obj->global_name);
+ yagl_host_glGetTexParameterfv(GL_TEXTURE_2D, pname, params);
+ yagl_host_glBindTexture(GL_TEXTURE_2D, tex2d_target_state->texture->global_name);
+ } else {
+ yagl_host_glGetTexParameterfv(target, pname, params);
+ }
return 1;
}
break;
}
- yagl_host_glGetTexParameteriv(target, pname, params);
+ if (target == GL_TEXTURE_EXTERNAL_OES) {
+ struct yagl_gles_texture_target_state *tex2d_target_state =
+ yagl_gles_context_get_active_texture_target_state(ctx, yagl_gles_texture_target_2d);
+
+ yagl_host_glBindTexture(GL_TEXTURE_2D, texture_obj->global_name);
+ yagl_host_glGetTexParameteriv(GL_TEXTURE_2D, pname, params);
+ yagl_host_glBindTexture(GL_TEXTURE_2D, tex2d_target_state->texture->global_name);
+ } else {
+ yagl_host_glGetTexParameteriv(target, pname, params);
+ }
return 1;
}
}
static void yagl_gles2_context_bind_externaloes(struct yagl_gles2_context *ctx,
- struct yagl_gles2_shader *shader)
+ struct yagl_gles2_program_sampler_info *sampler_info)
{
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:");
+ 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(&shader->state.samplers_ExternalOES);
- samplers_size = yagl_vector_size(&shader->state.samplers_ExternalOES);
+ samplers = yagl_vector_data(&sampler_info->samplers_ExternalOES);
+ samplers_size = yagl_vector_size(&sampler_info->samplers_ExternalOES);
for (i = 0; i < samplers_size; ++i) {
struct yagl_gles_texture_target_state *texture_2d_state, *texture_external_state;
//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,
+ YAGL_LOG_TRACE(" #%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
}
}
-static void yagl_gles2_context_restore_externaloes_binds(struct yagl_gles2_shader *shader)
+static void yagl_gles2_context_restore_externaloes_binds(struct yagl_gles2_program_sampler_info *sampler_info)
{
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);
+ YAGL_LOG_TRACE("Restoring TEXTURE_2D bindings:");
+ samplers = yagl_vector_data(&sampler_info->samplers_ExternalOES);
+ samplers_size = yagl_vector_size(&sampler_info->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_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;
* 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 *vertex_shader = ctx->program->vertex_shader;
- if (vertex_shader && vertex_shader->state.have_samplerexternaloes) {
+ if (ctx->program->vertex_shader_sampler_info.fetched &&
+ ctx->program->vertex_shader_sampler_info.have_samplerexternaloes) {
ctx->have_externaloes_rebinds_vs = 1;
- YAGL_LOG_DEBUG("======= Vertex shader has samplerExternalOES ========");
- yagl_gles2_context_bind_externaloes(ctx, vertex_shader);
+ YAGL_LOG_TRACE("======= Vertex shader has samplerExternalOES ========");
+ yagl_gles2_context_bind_externaloes(ctx, &ctx->program->vertex_shader_sampler_info);
}
- struct yagl_gles2_shader *fragment_shader = ctx->program->fragment_shader;
- if (fragment_shader && fragment_shader->state.have_samplerexternaloes) {
+ if (ctx->program->fragment_shader_sampler_info.fetched &&
+ ctx->program->fragment_shader_sampler_info.have_samplerexternaloes) {
ctx->have_externaloes_rebinds_fs = 1;
- YAGL_LOG_DEBUG("======= Fragment shader has samplerExternalOES ========");
- yagl_gles2_context_bind_externaloes(ctx, fragment_shader);
+ YAGL_LOG_TRACE("======= Fragment shader has samplerExternalOES ========");
+ yagl_gles2_context_bind_externaloes(ctx, &ctx->program->fragment_shader_sampler_info);
}
}
* Restore original TEXTURE_2D bindings
*/
if (ctx->have_externaloes_rebinds_vs) {
- yagl_gles2_context_restore_externaloes_binds(ctx->program->vertex_shader);
+ yagl_gles2_context_restore_externaloes_binds(&ctx->program->vertex_shader_sampler_info);
}
if (ctx->have_externaloes_rebinds_fs) {
- yagl_gles2_context_restore_externaloes_binds(ctx->program->fragment_shader);
+ yagl_gles2_context_restore_externaloes_binds(&ctx->program->fragment_shader_sampler_info);
}
/*
#include "yagl_log.h"
#include "yagl_utils.h"
#include "yagl_host_gles_calls.h"
+#include "yagl_glsl_state.h"
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
*/
#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+/*
+ * GL_OES_EGL_image_external extension
+ */
+#define GL_SAMPLER_EXTERNAL_OES 0x8D66
+
struct yagl_gles2_location_v
{
GLchar *name;
}
}
+static void yagl_gles2_program_sampler_info_copy_from_shader(struct yagl_gles2_program_sampler_info *info,
+ struct yagl_gles2_shader *shader)
+{
+ struct yagl_glsl_sampler *samplers_src;
+ int i = 0, samplers_size = 0;
+ YAGL_LOG_FUNC_SET(yagl_gles2_program_sampler_info_copy_from_shader);
+
+ if (!shader) {
+ YAGL_LOG_TRACE("No shader info available for copy");
+ return;
+ }
+
+ if (shader->state.have_error) {
+ YAGL_LOG_TRACE("Shader's GLSL state is invalid/has error");
+ return;
+ }
+
+ info->have_samplerexternaloes = shader->state.have_samplerexternaloes;
+
+ samplers_size = yagl_vector_size(&shader->state.samplers_ExternalOES);
+ samplers_src = yagl_vector_data(&shader->state.samplers_ExternalOES);
+
+ yagl_vector_init(&info->samplers_ExternalOES, sizeof(struct yagl_glsl_sampler), samplers_size);
+
+ for (i = 0; i < samplers_size; ++i) {
+ struct yagl_glsl_sampler s;
+ s.name = strdup(samplers_src[i].name);
+ s.location = samplers_src[i].location;
+ s.replaced_tex2d = samplers_src[i].replaced_tex2d;
+ s.value = samplers_src[i].value;
+
+ yagl_vector_push_back(&info->samplers_ExternalOES, &s);
+ }
+
+ samplers_size = yagl_vector_size(&shader->state.samplers_2D);
+ samplers_src = yagl_vector_data(&shader->state.samplers_2D);
+
+ yagl_vector_init(&info->samplers_2D, sizeof(struct yagl_glsl_sampler), samplers_size);
+
+ for (i = 0; i < samplers_size; ++i) {
+ struct yagl_glsl_sampler s;
+ s.name = strdup(samplers_src[i].name);
+ s.location = samplers_src[i].location;
+ s.replaced_tex2d = samplers_src[i].replaced_tex2d;
+ s.value = samplers_src[i].value;
+
+ yagl_vector_push_back(&info->samplers_2D, &s);
+ }
+
+ info->fetched = 1;
+}
+
+static void yagl_gles2_program_sampler_info_init(struct yagl_gles2_program_sampler_info *info)
+{
+ info->fetched = 0;
+ info->have_samplerexternaloes = 0;
+}
+
+static void yagl_gles2_program_sampler_info_reset(struct yagl_gles2_program_sampler_info *info)
+{
+ struct yagl_glsl_sampler *samplers;
+ int i = 0, samplers_size = 0;
+
+ info->fetched = 0;
+ info->have_samplerexternaloes = 0;
+
+ samplers_size = yagl_vector_size(&info->samplers_ExternalOES);
+ samplers = yagl_vector_data(&info->samplers_ExternalOES);
+ for (i = 0; i < samplers_size; ++i) {
+ yagl_free(samplers[i].name);
+ }
+
+ samplers_size = yagl_vector_size(&info->samplers_2D);
+ samplers = yagl_vector_data(&info->samplers_2D);
+ for (i = 0; i < samplers_size; ++i) {
+ yagl_free(samplers[i].name);
+ }
+
+ yagl_vector_cleanup(&info->samplers_ExternalOES);
+ yagl_vector_cleanup(&info->samplers_2D);
+}
+
static void yagl_gles2_program_reset_cached(struct yagl_gles2_program *program)
{
int i;
yagl_free(location_l);
}
}
+
+ yagl_gles2_program_sampler_info_reset(&program->vertex_shader_sampler_info);
+ yagl_gles2_program_sampler_info_reset(&program->fragment_shader_sampler_info);
}
static void yagl_gles2_program_destroy(struct yagl_ref *ref)
program->transform_feedback_info.buffer_mode = GL_INTERLEAVED_ATTRIBS;
+ yagl_gles2_program_sampler_info_init(&program->vertex_shader_sampler_info);
+ yagl_gles2_program_sampler_info_init(&program->fragment_shader_sampler_info);
+
yagl_host_glCreateProgram(program->global_name);
return program;
yagl_gles2_transform_feedback_info_copy(
&program->transform_feedback_info,
&program->linked_transform_feedback_info);
+
+ /*
+ * There is a possibility (and even a GLES spec recommendation) to call
+ * glDetachShader/glDeleteShader after this call. Thus, program->vertex_shader
+ * and program->fragment_shader pointers become NULL and we could have no access
+ * to shader info. Copy necessary for us info to program-local space for further use.
+ */
+ yagl_gles2_program_sampler_info_copy_from_shader(&program->vertex_shader_sampler_info, program->vertex_shader);
+ yagl_gles2_program_sampler_info_copy_from_shader(&program->fragment_shader_sampler_info, program->fragment_shader);
}
int yagl_gles2_program_get_uniform_location(struct yagl_gles2_program *program,
* Luckily, uniform location does not change so it has to be done
* only once.
*/
- if (program->vertex_shader &&
- program->vertex_shader->state.have_samplerexternaloes) {
+ if (program->vertex_shader_sampler_info.fetched &&
+ program->vertex_shader_sampler_info.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);
+ data = yagl_vector_data(&program->vertex_shader_sampler_info.samplers_ExternalOES);
+ data_size = yagl_vector_size(&program->vertex_shader_sampler_info.samplers_ExternalOES);
for (i = 0; i < data_size; ++i) {
if (strcmp(data[i].name, name) == 0) {
data[i].location = ret;
}
}
- if (program->fragment_shader &&
- program->fragment_shader->state.have_samplerexternaloes) {
+ if (program->fragment_shader_sampler_info.fetched &&
+ program->fragment_shader_sampler_info.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);
+ data = yagl_vector_data(&program->fragment_shader_sampler_info.samplers_ExternalOES);
+ data_size = yagl_vector_size(&program->fragment_shader_sampler_info.samplers_ExternalOES);
for (i = 0; i < data_size; ++i) {
if (strcmp(data[i].name, name) == 0) {
data[i].location = ret;
if (!var->generic_fetched) {
yagl_free(var->name);
- var->name = yagl_malloc(program->max_active_uniform_bufsize);
+ var->name = yagl_malloc(program->max_active_uniform_bufsize + 1);
var->name[0] = '\0';
yagl_host_glGetActiveUniform(program->global_name,
var->name_fetched = 1;
var->generic_fetched = 1;
+
+ var->name[var->name_size] = 0;
+
+ // It is possible that our sampler2D could actually be samplerExternalOES
+ // Host doesn't know about this. In case we encounter a GL_SAMPLER_2D type
+ // of uniform, go through GLSL program state and see if we should "replace"
+ // it with GL_SAMPLER_EXTERNAL_OES.
+ if (var->type == GL_SAMPLER_2D) {
+ if (program->fragment_shader_sampler_info.fetched) {
+ struct yagl_glsl_sampler *samplers = yagl_vector_data(&program->fragment_shader_sampler_info.samplers_ExternalOES);
+ int i = 0, samplers_size = yagl_vector_size(&program->fragment_shader_sampler_info.samplers_ExternalOES);
+
+ for (i = 0; i < samplers_size; ++i) {
+ if (strcmp(samplers[i].name, var->name) == 0) {
+ // also store location because we're here anyway
+ samplers[i].location = index;
+ var->type = GL_SAMPLER_EXTERNAL_OES;
+ break;
+ }
+ }
+ }
+ }
}
yagl_gles2_set_name(var->name, var->name_size,
/*
* Update shader state for pre_draw/post_draw analysis
*/
- if (program->vertex_shader &&
- program->vertex_shader->state.have_samplerexternaloes) {
+ if (program->vertex_shader_sampler_info.fetched &&
+ program->vertex_shader_sampler_info.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);
+ data = yagl_vector_data(&program->vertex_shader_sampler_info.samplers_ExternalOES);
+ data_size = yagl_vector_size(&program->vertex_shader_sampler_info.samplers_ExternalOES);
for (i = 0; i < data_size; ++i) {
if (data[i].location == location) {
data[i].value = x;
}
}
- if (program->fragment_shader &&
- program->fragment_shader->state.have_samplerexternaloes) {
+ if (program->fragment_shader_sampler_info.fetched &&
+ program->fragment_shader_sampler_info.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);
+ data = yagl_vector_data(&program->fragment_shader_sampler_info.samplers_ExternalOES);
+ data_size = yagl_vector_size(&program->fragment_shader_sampler_info.samplers_ExternalOES);
for (i = 0; i < data_size; ++i) {
if (data[i].location == location) {
data[i].value = x;
GLint max_varying_bufsize;
};
+struct yagl_gles2_program_sampler_info
+{
+ int fetched;
+
+ int have_samplerexternaloes;
+ struct yagl_vector samplers_ExternalOES;
+ struct yagl_vector samplers_2D;
+};
+
struct yagl_gles2_program
{
/*
struct yagl_gles2_shader *fragment_shader;
+ struct yagl_gles2_program_sampler_info vertex_shader_sampler_info;
+
+ struct yagl_gles2_program_sampler_info fragment_shader_sampler_info;
+
union
{
struct yagl_list uniform_locations_l;
struct yagl_glsl_sampler sampler;
sampler.name = strdup(str);
sampler.location = YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN;
- sampler.value = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
+ sampler.value = 0; // GL spec predefines uniform value as 0
sampler.replaced_tex2d = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
yagl_vector_push_back(&state->samplers_ExternalOES, &sampler);
}
struct yagl_glsl_sampler sampler;
sampler.name = strdup(str);
sampler.location = YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN;
- sampler.value = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
+ sampler.value = 0; // GL spec predefines uniform value as 0
sampler.replaced_tex2d = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
yagl_vector_push_back(&state->samplers_2D, &sampler);
}