Revert "cogl: Remove the generated array size for cogl_tex_coord_in"
This reverts commit 4cfe90bde2
.
GLSL 1.00 on GLES doesn't support unsized arrays so the whole idea
can't work.
Conflicts:
clutter/cogl/cogl/cogl-pipeline-glsl.c
This commit is contained in:
parent
f54cc7abd4
commit
f8449582c8
@ -262,7 +262,7 @@ cogl_create_context (void)
|
|||||||
default_texture_data);
|
default_texture_data);
|
||||||
|
|
||||||
cogl_push_source (_context->opaque_color_pipeline);
|
cogl_push_source (_context->opaque_color_pipeline);
|
||||||
_cogl_pipeline_flush_gl_state (_context->opaque_color_pipeline, FALSE);
|
_cogl_pipeline_flush_gl_state (_context->opaque_color_pipeline, FALSE, 0);
|
||||||
_cogl_enable (enable_flags);
|
_cogl_enable (enable_flags);
|
||||||
_cogl_flush_face_winding ();
|
_cogl_flush_face_winding ();
|
||||||
|
|
||||||
|
@ -184,7 +184,8 @@ get_arbfp_program_state (CoglPipeline *pipeline)
|
|||||||
static gboolean
|
static gboolean
|
||||||
_cogl_pipeline_backend_arbfp_start (CoglPipeline *pipeline,
|
_cogl_pipeline_backend_arbfp_start (CoglPipeline *pipeline,
|
||||||
int n_layers,
|
int n_layers,
|
||||||
unsigned long pipelines_difference)
|
unsigned long pipelines_difference,
|
||||||
|
int n_tex_coord_attribs)
|
||||||
{
|
{
|
||||||
CoglPipelineBackendARBfpPrivate *priv;
|
CoglPipelineBackendARBfpPrivate *priv;
|
||||||
CoglPipeline *authority;
|
CoglPipeline *authority;
|
||||||
|
@ -69,7 +69,8 @@ _cogl_pipeline_backend_fixed_get_max_texture_units (void)
|
|||||||
static gboolean
|
static gboolean
|
||||||
_cogl_pipeline_backend_fixed_start (CoglPipeline *pipeline,
|
_cogl_pipeline_backend_fixed_start (CoglPipeline *pipeline,
|
||||||
int n_layers,
|
int n_layers,
|
||||||
unsigned long pipelines_difference)
|
unsigned long pipelines_difference,
|
||||||
|
int n_tex_coord_attribs)
|
||||||
{
|
{
|
||||||
CoglHandle user_program;
|
CoglHandle user_program;
|
||||||
|
|
||||||
|
@ -102,6 +102,15 @@ typedef struct _GlslProgramState
|
|||||||
GString *header, *source;
|
GString *header, *source;
|
||||||
UnitState *unit_state;
|
UnitState *unit_state;
|
||||||
|
|
||||||
|
/* To allow writing shaders that are portable between GLES 2 and
|
||||||
|
* OpenGL Cogl prepends a number of boilerplate #defines and
|
||||||
|
* declarations to user shaders. One of those declarations is an
|
||||||
|
* array of texture coordinate varyings, but to know how to emit the
|
||||||
|
* declaration we need to know how many texture coordinate
|
||||||
|
* attributes are in use. The boilerplate also needs to be changed
|
||||||
|
* if this increases. */
|
||||||
|
int n_tex_coord_attribs;
|
||||||
|
|
||||||
#ifdef HAVE_COGL_GLES2
|
#ifdef HAVE_COGL_GLES2
|
||||||
/* The GLES2 generated program that was generated from the user
|
/* The GLES2 generated program that was generated from the user
|
||||||
program. This is used to detect when the GLES2 backend generates
|
program. This is used to detect when the GLES2 backend generates
|
||||||
@ -277,7 +286,8 @@ link_program (GLint gl_program)
|
|||||||
static gboolean
|
static gboolean
|
||||||
_cogl_pipeline_backend_glsl_start (CoglPipeline *pipeline,
|
_cogl_pipeline_backend_glsl_start (CoglPipeline *pipeline,
|
||||||
int n_layers,
|
int n_layers,
|
||||||
unsigned long pipelines_difference)
|
unsigned long pipelines_difference,
|
||||||
|
int n_tex_coord_attribs)
|
||||||
{
|
{
|
||||||
CoglPipelineBackendGlslPrivate *priv;
|
CoglPipelineBackendGlslPrivate *priv;
|
||||||
CoglPipeline *authority;
|
CoglPipeline *authority;
|
||||||
@ -345,13 +355,24 @@ _cogl_pipeline_backend_glsl_start (CoglPipeline *pipeline,
|
|||||||
if (priv->glsl_program_state->gl_program)
|
if (priv->glsl_program_state->gl_program)
|
||||||
{
|
{
|
||||||
/* If we already have a valid GLSL program then we don't need to
|
/* If we already have a valid GLSL program then we don't need to
|
||||||
relink a new one. However if the program has changed since
|
* relink a new one. However if the program has changed since
|
||||||
the last link then we do need to relink */
|
* the last link then we do need to relink
|
||||||
|
*
|
||||||
|
* Also if the number of texture coordinate attributes in use has
|
||||||
|
* increased, then delete the program so we can prepend a new
|
||||||
|
* _cogl_tex_coord[] varying array declaration. */
|
||||||
if (user_program == NULL ||
|
if (user_program == NULL ||
|
||||||
(priv->glsl_program_state->user_program_age == user_program->age))
|
(priv->glsl_program_state->user_program_age == user_program->age
|
||||||
|
#ifdef HAVE_COGL_GLES2
|
||||||
|
&& (priv->glsl_program_state->n_tex_coord_attribs >=
|
||||||
|
n_tex_coord_attribs)
|
||||||
|
#endif
|
||||||
|
))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* We need to recreate the program so destroy the existing one */
|
/* Destroy the existing program. We can't just dirty the whole
|
||||||
|
glsl state because otherwise if we are not the authority on
|
||||||
|
the user program then we'll just find the same state again */
|
||||||
delete_program (priv->glsl_program_state->gl_program);
|
delete_program (priv->glsl_program_state->gl_program);
|
||||||
priv->glsl_program_state->gl_program = 0;
|
priv->glsl_program_state->gl_program = 0;
|
||||||
}
|
}
|
||||||
@ -361,6 +382,21 @@ _cogl_pipeline_backend_glsl_start (CoglPipeline *pipeline,
|
|||||||
encountered it or because the user program has changed since it
|
encountered it or because the user program has changed since it
|
||||||
was last linked */
|
was last linked */
|
||||||
|
|
||||||
|
#ifdef HAVE_COGL_GLES2
|
||||||
|
/* Find the largest count of texture coordinate attributes
|
||||||
|
* associated with each of the shaders so we can ensure a consistent
|
||||||
|
* _cogl_tex_coord[] array declaration across all of the shaders.*/
|
||||||
|
if (user_program)
|
||||||
|
for (l = user_program->attached_shaders; l; l = l->next)
|
||||||
|
{
|
||||||
|
CoglShader *shader = l->data;
|
||||||
|
n_tex_coord_attribs = MAX (shader->n_tex_coord_attribs,
|
||||||
|
n_tex_coord_attribs);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
priv->glsl_program_state->n_tex_coord_attribs = n_tex_coord_attribs;
|
||||||
|
|
||||||
/* Check whether the user program contains a fragment
|
/* Check whether the user program contains a fragment
|
||||||
shader. Otherwise we need to generate one */
|
shader. Otherwise we need to generate one */
|
||||||
if (user_program)
|
if (user_program)
|
||||||
@ -991,7 +1027,9 @@ _cogl_pipeline_backend_glsl_end (CoglPipeline *pipeline,
|
|||||||
|
|
||||||
g_assert (shader->language == COGL_SHADER_LANGUAGE_GLSL);
|
g_assert (shader->language == COGL_SHADER_LANGUAGE_GLSL);
|
||||||
|
|
||||||
cogl_shader_compile (shader);
|
_cogl_shader_compile_real (shader,
|
||||||
|
glsl_program_state->
|
||||||
|
n_tex_coord_attribs);
|
||||||
|
|
||||||
GE( glAttachShader (gl_program, shader->gl_handle) );
|
GE( glAttachShader (gl_program, shader->gl_handle) );
|
||||||
}
|
}
|
||||||
@ -1032,6 +1070,8 @@ _cogl_pipeline_backend_glsl_end (CoglPipeline *pipeline,
|
|||||||
source_strings[1] = glsl_program_state->source->str;
|
source_strings[1] = glsl_program_state->source->str;
|
||||||
|
|
||||||
_cogl_shader_set_source_with_boilerplate (shader, GL_FRAGMENT_SHADER,
|
_cogl_shader_set_source_with_boilerplate (shader, GL_FRAGMENT_SHADER,
|
||||||
|
glsl_program_state->
|
||||||
|
n_tex_coord_attribs,
|
||||||
2, /* count */
|
2, /* count */
|
||||||
source_strings, lengths);
|
source_strings, lengths);
|
||||||
|
|
||||||
|
@ -150,7 +150,8 @@ _cogl_gl_use_program_wrapper (CoglHandle program);
|
|||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
|
_cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
|
||||||
gboolean skip_gl_state);
|
gboolean skip_gl_state,
|
||||||
|
int n_tex_coord_attribs);
|
||||||
|
|
||||||
#endif /* __COGL_PIPELINE_OPENGL_PRIVATE_H */
|
#endif /* __COGL_PIPELINE_OPENGL_PRIVATE_H */
|
||||||
|
|
||||||
|
@ -1031,7 +1031,8 @@ backend_add_layer_cb (CoglPipelineLayer *layer,
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
_cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
|
_cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
|
||||||
gboolean skip_gl_color)
|
gboolean skip_gl_color,
|
||||||
|
int n_tex_coord_attribs)
|
||||||
{
|
{
|
||||||
unsigned long pipelines_difference;
|
unsigned long pipelines_difference;
|
||||||
int n_layers;
|
int n_layers;
|
||||||
@ -1134,7 +1135,8 @@ _cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
|
|||||||
* scratch buffers here... */
|
* scratch buffers here... */
|
||||||
if (G_UNLIKELY (!backend->start (pipeline,
|
if (G_UNLIKELY (!backend->start (pipeline,
|
||||||
n_layers,
|
n_layers,
|
||||||
pipelines_difference)))
|
pipelines_difference,
|
||||||
|
n_tex_coord_attribs)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
state.backend = backend;
|
state.backend = backend;
|
||||||
|
@ -567,7 +567,8 @@ typedef struct _CoglPipelineBackend
|
|||||||
|
|
||||||
gboolean (*start) (CoglPipeline *pipeline,
|
gboolean (*start) (CoglPipeline *pipeline,
|
||||||
int n_layers,
|
int n_layers,
|
||||||
unsigned long pipelines_difference);
|
unsigned long pipelines_difference,
|
||||||
|
int n_tex_coord_attribs);
|
||||||
gboolean (*add_layer) (CoglPipeline *pipeline,
|
gboolean (*add_layer) (CoglPipeline *pipeline,
|
||||||
CoglPipelineLayer *layer,
|
CoglPipelineLayer *layer,
|
||||||
unsigned long layers_difference);
|
unsigned long layers_difference);
|
||||||
|
@ -92,7 +92,6 @@
|
|||||||
"#endif\n" \
|
"#endif\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"varying vec4 _cogl_color;\n" \
|
"varying vec4 _cogl_color;\n" \
|
||||||
"varying vec4 _cogl_tex_coord[];\n" \
|
|
||||||
"\n" \
|
"\n" \
|
||||||
"#define cogl_color_in _cogl_color\n" \
|
"#define cogl_color_in _cogl_color\n" \
|
||||||
"#define cogl_tex_coord_in _cogl_tex_coord\n" \
|
"#define cogl_tex_coord_in _cogl_tex_coord\n" \
|
||||||
|
@ -40,18 +40,24 @@ struct _CoglShader
|
|||||||
{
|
{
|
||||||
CoglHandleObject _parent;
|
CoglHandleObject _parent;
|
||||||
GLuint gl_handle;
|
GLuint gl_handle;
|
||||||
|
int n_tex_coord_attribs;
|
||||||
CoglShaderType type;
|
CoglShaderType type;
|
||||||
CoglShaderLanguage language;
|
CoglShaderLanguage language;
|
||||||
|
char *source;
|
||||||
};
|
};
|
||||||
|
|
||||||
CoglShader *_cogl_shader_pointer_from_handle (CoglHandle handle);
|
CoglShader *_cogl_shader_pointer_from_handle (CoglHandle handle);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_shader_compile_real (CoglHandle handle, int n_tex_coord_attribs);
|
||||||
|
|
||||||
CoglShaderLanguage
|
CoglShaderLanguage
|
||||||
_cogl_program_get_language (CoglHandle handle);
|
_cogl_program_get_language (CoglHandle handle);
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle,
|
_cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle,
|
||||||
GLenum shader_gl_type,
|
GLenum shader_gl_type,
|
||||||
|
int n_tex_coord_attribs,
|
||||||
GLsizei count_in,
|
GLsizei count_in,
|
||||||
const char **strings_in,
|
const char **strings_in,
|
||||||
const GLint *lengths_in);
|
const GLint *lengths_in);
|
||||||
|
@ -101,52 +101,33 @@ cogl_create_shader (CoglShaderType type)
|
|||||||
shader = g_slice_new (CoglShader);
|
shader = g_slice_new (CoglShader);
|
||||||
shader->language = COGL_SHADER_LANGUAGE_GLSL;
|
shader->language = COGL_SHADER_LANGUAGE_GLSL;
|
||||||
shader->gl_handle = 0;
|
shader->gl_handle = 0;
|
||||||
|
#ifdef HAVE_COGL_GLES2
|
||||||
|
shader->n_tex_coord_attribs = 0;
|
||||||
|
#endif
|
||||||
shader->type = type;
|
shader->type = type;
|
||||||
|
|
||||||
return _cogl_shader_handle_new (shader);
|
return _cogl_shader_handle_new (shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
_cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle,
|
delete_shader (CoglShader *shader)
|
||||||
GLenum shader_gl_type,
|
|
||||||
GLsizei count_in,
|
|
||||||
const char **strings_in,
|
|
||||||
const GLint *lengths_in)
|
|
||||||
{
|
{
|
||||||
static const char vertex_boilerplate[] = _COGL_VERTEX_SHADER_BOILERPLATE;
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
static const char fragment_boilerplate[] = _COGL_FRAGMENT_SHADER_BOILERPLATE;
|
|
||||||
|
|
||||||
const char **strings = g_alloca (sizeof (char *) * (count_in + 2));
|
#ifdef HAVE_COGL_GL
|
||||||
GLint *lengths = g_alloca (sizeof (GLint) * (count_in + 2));
|
if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
GET_CONTEXT (ctx, NO_RETVAL);
|
|
||||||
|
|
||||||
if (shader_gl_type == GL_VERTEX_SHADER)
|
|
||||||
{
|
{
|
||||||
strings[count] = vertex_boilerplate;
|
if (shader->gl_handle)
|
||||||
lengths[count++] = sizeof (vertex_boilerplate) - 1;
|
GE (glDeletePrograms (1, &shader->gl_handle));
|
||||||
}
|
}
|
||||||
else if (shader_gl_type == GL_FRAGMENT_SHADER)
|
|
||||||
{
|
|
||||||
strings[count] = fragment_boilerplate;
|
|
||||||
lengths[count++] = sizeof (fragment_boilerplate) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy (strings + count, strings_in, sizeof (char *) * count_in);
|
|
||||||
if (lengths_in)
|
|
||||||
memcpy (lengths + count, lengths_in, sizeof (GLint) * count_in);
|
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
int i;
|
if (shader->gl_handle)
|
||||||
|
GE (glDeleteShader (shader->gl_handle));
|
||||||
for (i = 0; i < count_in; i++)
|
|
||||||
lengths[count + i] = -1; /* null terminated */
|
|
||||||
}
|
}
|
||||||
count += count_in;
|
|
||||||
|
|
||||||
GE( glShaderSource (shader_gl_handle, count,
|
shader->gl_handle = 0;
|
||||||
(const char **) strings, lengths) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -171,30 +152,119 @@ cogl_shader_source (CoglHandle handle,
|
|||||||
language = COGL_SHADER_LANGUAGE_GLSL;
|
language = COGL_SHADER_LANGUAGE_GLSL;
|
||||||
|
|
||||||
/* Delete the old object if the language is changing... */
|
/* Delete the old object if the language is changing... */
|
||||||
if (G_UNLIKELY (language != shader->language))
|
if (G_UNLIKELY (language != shader->language) &&
|
||||||
{
|
shader->gl_handle)
|
||||||
|
delete_shader (shader);
|
||||||
|
|
||||||
|
shader->source = g_strdup (source);
|
||||||
|
|
||||||
|
shader->language = language;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_shader_compile (CoglHandle handle)
|
||||||
|
{
|
||||||
#ifdef HAVE_COGL_GL
|
#ifdef HAVE_COGL_GL
|
||||||
if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
|
CoglShader *shader = handle;
|
||||||
{
|
|
||||||
if (shader->gl_handle)
|
|
||||||
GE (glDeletePrograms (1, &shader->gl_handle));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
{
|
|
||||||
if (shader->gl_handle)
|
if (!cogl_is_shader (handle))
|
||||||
GE (glDeleteShader (shader->gl_handle));
|
return;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_COGL_GL
|
#ifdef HAVE_COGL_GL
|
||||||
if (language == COGL_SHADER_LANGUAGE_ARBFP)
|
_cogl_shader_compile_real (shader, 0 /* ignored */);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* XXX: For GLES2 we don't actually compile anything until the
|
||||||
|
* shader gets used so we have an opportunity to add some
|
||||||
|
* boilerplate to the shader.
|
||||||
|
*
|
||||||
|
* At the end of the day this is obviously a badly designed API
|
||||||
|
* given that we are having to lie to the user. It was a mistake to
|
||||||
|
* so thinly wrap the OpenGL shader API and the current plan is to
|
||||||
|
* replace it with a pipeline snippets API. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle,
|
||||||
|
GLenum shader_gl_type,
|
||||||
|
int n_tex_coord_attribs,
|
||||||
|
GLsizei count_in,
|
||||||
|
const char **strings_in,
|
||||||
|
const GLint *lengths_in)
|
||||||
|
{
|
||||||
|
static const char vertex_boilerplate[] = _COGL_VERTEX_SHADER_BOILERPLATE;
|
||||||
|
static const char fragment_boilerplate[] = _COGL_FRAGMENT_SHADER_BOILERPLATE;
|
||||||
|
|
||||||
|
const char **strings = g_alloca (sizeof (char *) * (count_in + 2));
|
||||||
|
GLint *lengths = g_alloca (sizeof (GLint) * (count_in + 2));
|
||||||
|
int count = 0;
|
||||||
|
#ifdef HAVE_COGL_GLES2
|
||||||
|
char *tex_coords_declaration = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
|
if (shader_gl_type == GL_VERTEX_SHADER)
|
||||||
|
{
|
||||||
|
strings[count] = vertex_boilerplate;
|
||||||
|
lengths[count++] = sizeof (vertex_boilerplate) - 1;
|
||||||
|
}
|
||||||
|
else if (shader_gl_type == GL_FRAGMENT_SHADER)
|
||||||
|
{
|
||||||
|
strings[count] = fragment_boilerplate;
|
||||||
|
lengths[count++] = sizeof (fragment_boilerplate) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_COGL_GLES2
|
||||||
|
if (n_tex_coord_attribs)
|
||||||
|
{
|
||||||
|
tex_coords_declaration =
|
||||||
|
g_strdup_printf ("varying vec2 _cogl_tex_coord[%d];\n",
|
||||||
|
n_tex_coord_attribs);
|
||||||
|
strings[count] = tex_coords_declaration;
|
||||||
|
lengths[count++] = -1; /* null terminated */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memcpy (strings + count, strings_in, sizeof (char *) * count_in);
|
||||||
|
if (lengths_in)
|
||||||
|
memcpy (lengths + count, lengths_in, sizeof (GLint) * count_in);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count_in; i++)
|
||||||
|
lengths[count + i] = -1; /* null terminated */
|
||||||
|
}
|
||||||
|
count += count_in;
|
||||||
|
|
||||||
|
GE( glShaderSource (shader_gl_handle, count,
|
||||||
|
(const char **) strings, lengths) );
|
||||||
|
|
||||||
|
#ifdef HAVE_COGL_GLES2
|
||||||
|
g_free (tex_coords_declaration);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_shader_compile_real (CoglHandle handle,
|
||||||
|
int n_tex_coord_attribs)
|
||||||
|
{
|
||||||
|
CoglShader *shader = handle;
|
||||||
|
|
||||||
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
|
#ifdef HAVE_COGL_GL
|
||||||
|
if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
|
||||||
{
|
{
|
||||||
#ifdef COGL_GL_DEBUG
|
#ifdef COGL_GL_DEBUG
|
||||||
GLenum gl_error;
|
GLenum gl_error;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (shader->gl_handle == 0)
|
if (shader->gl_handle)
|
||||||
|
return;
|
||||||
|
|
||||||
GE (glGenPrograms (1, &shader->gl_handle));
|
GE (glGenPrograms (1, &shader->gl_handle));
|
||||||
|
|
||||||
GE (glBindProgram (GL_FRAGMENT_PROGRAM_ARB, shader->gl_handle));
|
GE (glBindProgram (GL_FRAGMENT_PROGRAM_ARB, shader->gl_handle));
|
||||||
@ -205,8 +275,8 @@ cogl_shader_source (CoglHandle handle,
|
|||||||
#endif
|
#endif
|
||||||
glProgramString (GL_FRAGMENT_PROGRAM_ARB,
|
glProgramString (GL_FRAGMENT_PROGRAM_ARB,
|
||||||
GL_PROGRAM_FORMAT_ASCII_ARB,
|
GL_PROGRAM_FORMAT_ASCII_ARB,
|
||||||
strlen (source),
|
strlen (shader->source),
|
||||||
source);
|
shader->source);
|
||||||
#ifdef COGL_GL_DEBUG
|
#ifdef COGL_GL_DEBUG
|
||||||
gl_error = glGetError ();
|
gl_error = glGetError ();
|
||||||
if (gl_error != GL_NO_ERROR)
|
if (gl_error != GL_NO_ERROR)
|
||||||
@ -214,7 +284,7 @@ cogl_shader_source (CoglHandle handle,
|
|||||||
g_warning ("%s: GL error (%d): Failed to compile ARBfp:\n%s\n%s",
|
g_warning ("%s: GL error (%d): Failed to compile ARBfp:\n%s\n%s",
|
||||||
G_STRLOC,
|
G_STRLOC,
|
||||||
gl_error,
|
gl_error,
|
||||||
source,
|
shader->source,
|
||||||
glGetString (GL_PROGRAM_ERROR_STRING_ARB));
|
glGetString (GL_PROGRAM_ERROR_STRING_ARB));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -224,6 +294,16 @@ cogl_shader_source (CoglHandle handle,
|
|||||||
{
|
{
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
|
|
||||||
|
if (shader->gl_handle
|
||||||
|
#ifdef HAVE_COGL_GLES2
|
||||||
|
&& shader->n_tex_coord_attribs >= n_tex_coord_attribs
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (shader->gl_handle)
|
||||||
|
delete_shader (shader);
|
||||||
|
|
||||||
switch (shader->type)
|
switch (shader->type)
|
||||||
{
|
{
|
||||||
case COGL_SHADER_TYPE_VERTEX:
|
case COGL_SHADER_TYPE_VERTEX:
|
||||||
@ -237,30 +317,31 @@ cogl_shader_source (CoglHandle handle,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shader->gl_handle)
|
|
||||||
shader->gl_handle = glCreateShader (gl_type);
|
shader->gl_handle = glCreateShader (gl_type);
|
||||||
|
|
||||||
_cogl_shader_set_source_with_boilerplate (shader->gl_handle,
|
_cogl_shader_set_source_with_boilerplate (shader->gl_handle,
|
||||||
gl_type,
|
gl_type,
|
||||||
1, &source, NULL);
|
n_tex_coord_attribs,
|
||||||
}
|
1,
|
||||||
|
(const char **) &shader->source,
|
||||||
|
NULL);
|
||||||
|
|
||||||
shader->language = language;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
cogl_shader_compile (CoglHandle handle)
|
|
||||||
{
|
|
||||||
CoglShader *shader;
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
|
||||||
|
|
||||||
if (!cogl_is_shader (handle))
|
|
||||||
return;
|
|
||||||
|
|
||||||
shader = _cogl_shader_pointer_from_handle (handle);
|
|
||||||
|
|
||||||
if (shader->language == COGL_SHADER_LANGUAGE_GLSL)
|
|
||||||
GE (glCompileShader (shader->gl_handle));
|
GE (glCompileShader (shader->gl_handle));
|
||||||
|
|
||||||
|
#ifdef HAVE_COGL_GLES2
|
||||||
|
shader->n_tex_coord_attribs = n_tex_coord_attribs;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef COGL_GL_DEBUG
|
||||||
|
if (!cogl_shader_is_compiled (handle))
|
||||||
|
{
|
||||||
|
char *log = cogl_shader_get_info_log (handle);
|
||||||
|
g_warning ("Failed to compile GLSL program:\nsrc:\n%s\nerror:\n%s\n",
|
||||||
|
shader->source,
|
||||||
|
log);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
@ -288,6 +369,21 @@ cogl_shader_get_info_log (CoglHandle handle)
|
|||||||
{
|
{
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
|
/* We don't normally compile the shader when the user calls
|
||||||
|
* cogl_shader_compile() because we want to be able to add
|
||||||
|
* boilerplate code that depends on how it ends up finally being
|
||||||
|
* used.
|
||||||
|
*
|
||||||
|
* Here we force an early compile if the user is interested in
|
||||||
|
* log information to increase the chance that the log will be
|
||||||
|
* useful! We have to guess the number of texture coordinate
|
||||||
|
* attributes that may be used (normally less than 4) since that
|
||||||
|
* affects the boilerplate.
|
||||||
|
*/
|
||||||
|
if (!shader->gl_handle)
|
||||||
|
_cogl_shader_compile_real (handle, 4);
|
||||||
|
|
||||||
glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer);
|
glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer);
|
||||||
buffer[len] = '\0';
|
buffer[len] = '\0';
|
||||||
return g_strdup (buffer);
|
return g_strdup (buffer);
|
||||||
@ -330,6 +426,24 @@ cogl_shader_is_compiled (CoglHandle handle)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
/* FIXME: We currently have an arbitrary limit of 4 texture
|
||||||
|
* coordinate attributes since our API means we have to add
|
||||||
|
* some boilerplate to the users GLSL program (for GLES2)
|
||||||
|
* before we actually know how many attributes are in use.
|
||||||
|
*
|
||||||
|
* 4 will probably be enough (or at least that limitation should
|
||||||
|
* be enough until we can replace this API with the pipeline
|
||||||
|
* snippets API) but if it isn't then the shader won't compile,
|
||||||
|
* through no fault of the user.
|
||||||
|
*
|
||||||
|
* To some extent this is just a symptom of bad API design; it
|
||||||
|
* was a mistake for Cogl to so thinly wrap the OpenGL shader
|
||||||
|
* API. Eventually we plan for this whole API will be deprecated
|
||||||
|
* by the pipeline snippets framework.
|
||||||
|
*/
|
||||||
|
if (!shader->gl_handle)
|
||||||
|
_cogl_shader_compile_real (handle, 4);
|
||||||
|
|
||||||
GE (glGetShaderiv (shader->gl_handle, GL_COMPILE_STATUS, &status));
|
GE (glGetShaderiv (shader->gl_handle, GL_COMPILE_STATUS, &status));
|
||||||
if (status == GL_TRUE)
|
if (status == GL_TRUE)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -395,3 +509,4 @@ cogl_shader_is_compiled (CoglHandle handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_COGL_GLES */
|
#endif /* HAVE_COGL_GLES */
|
||||||
|
|
||||||
|
@ -435,6 +435,7 @@ enable_gl_state (CoglVertexAttribute **attributes,
|
|||||||
gboolean skip_gl_color = FALSE;
|
gboolean skip_gl_color = FALSE;
|
||||||
CoglPipeline *source;
|
CoglPipeline *source;
|
||||||
CoglPipeline *copy = NULL;
|
CoglPipeline *copy = NULL;
|
||||||
|
int n_tex_coord_attribs = 0;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
@ -490,6 +491,7 @@ enable_gl_state (CoglVertexAttribute **attributes,
|
|||||||
base + attribute->offset));
|
base + attribute->offset));
|
||||||
_cogl_bitmask_set (&ctx->temp_bitmask,
|
_cogl_bitmask_set (&ctx->temp_bitmask,
|
||||||
attribute->texture_unit, TRUE);
|
attribute->texture_unit, TRUE);
|
||||||
|
n_tex_coord_attribs++;
|
||||||
break;
|
break;
|
||||||
case COGL_VERTEX_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
|
case COGL_VERTEX_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
|
||||||
enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
|
enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
|
||||||
@ -578,7 +580,7 @@ enable_gl_state (CoglVertexAttribute **attributes,
|
|||||||
_cogl_pipeline_apply_legacy_state (source);
|
_cogl_pipeline_apply_legacy_state (source);
|
||||||
}
|
}
|
||||||
|
|
||||||
_cogl_pipeline_flush_gl_state (source, skip_gl_color);
|
_cogl_pipeline_flush_gl_state (source, skip_gl_color, n_tex_coord_attribs);
|
||||||
|
|
||||||
if (ctx->enable_backface_culling)
|
if (ctx->enable_backface_culling)
|
||||||
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
|
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
|
||||||
|
@ -770,13 +770,20 @@ cogl_begin_gl (void)
|
|||||||
* A user should instead call cogl_set_source_color4ub() before
|
* A user should instead call cogl_set_source_color4ub() before
|
||||||
* cogl_begin_gl() to simplify the state flushed.
|
* cogl_begin_gl() to simplify the state flushed.
|
||||||
*
|
*
|
||||||
|
* XXX: note defining n_tex_coord_attribs using
|
||||||
|
* cogl_pipeline_get_n_layers is a hack, but the problem is that
|
||||||
|
* n_tex_coord_attribs is usually defined when drawing a primitive
|
||||||
|
* which isn't happening here.
|
||||||
|
*
|
||||||
* Maybe it would be more useful if this code did flush the
|
* Maybe it would be more useful if this code did flush the
|
||||||
* opaque_color_pipeline and then call into cogl-pipeline-opengl.c to then
|
* opaque_color_pipeline and then call into cogl-pipeline-opengl.c to then
|
||||||
* restore all state for the material's backend back to default OpenGL
|
* restore all state for the material's backend back to default OpenGL
|
||||||
* values.
|
* values.
|
||||||
*/
|
*/
|
||||||
pipeline = cogl_get_source ();
|
pipeline = cogl_get_source ();
|
||||||
_cogl_pipeline_flush_gl_state (pipeline, FALSE);
|
_cogl_pipeline_flush_gl_state (pipeline,
|
||||||
|
FALSE,
|
||||||
|
cogl_pipeline_get_n_layers (pipeline));
|
||||||
|
|
||||||
if (ctx->enable_backface_culling)
|
if (ctx->enable_backface_culling)
|
||||||
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
|
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
|
||||||
|
@ -221,7 +221,7 @@ _cogl_path_stroke_nodes (CoglPath *path)
|
|||||||
|
|
||||||
cogl_push_source (source);
|
cogl_push_source (source);
|
||||||
|
|
||||||
_cogl_pipeline_flush_gl_state (source, FALSE);
|
_cogl_pipeline_flush_gl_state (source, FALSE, 0);
|
||||||
|
|
||||||
/* Disable all client texture coordinate arrays */
|
/* Disable all client texture coordinate arrays */
|
||||||
_cogl_bitmask_clear_all (&ctx->temp_bitmask);
|
_cogl_bitmask_clear_all (&ctx->temp_bitmask);
|
||||||
@ -365,7 +365,7 @@ _cogl_add_path_to_stencil_buffer (CoglPath *path,
|
|||||||
/* Just setup a simple pipeline that doesn't use texturing... */
|
/* Just setup a simple pipeline that doesn't use texturing... */
|
||||||
cogl_push_source (ctx->stencil_pipeline);
|
cogl_push_source (ctx->stencil_pipeline);
|
||||||
|
|
||||||
_cogl_pipeline_flush_gl_state (ctx->stencil_pipeline, FALSE);
|
_cogl_pipeline_flush_gl_state (ctx->stencil_pipeline, FALSE, 0);
|
||||||
|
|
||||||
_cogl_enable (enable_flags);
|
_cogl_enable (enable_flags);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user