cogl-shader: Prepend boilerplate for portable shaders

We now prepend a set of defines to any given GLSL shader so that we can
define builtin uniforms/attributes within the "cogl" namespace that we
can use to provide compatibility across a range of the earlier versions
of GLSL.

This updates test-cogl-shader-glsl.c and test-shader.c so they no longer
needs to special case GLES vs GL when splicing together its shaders as
well as the blur, colorize and desaturate effects.

To get a feel for the new, portable uniform/attribute names here are the
defines for OpenGL vertex shaders:

 #define cogl_position_in gl_Vertex
 #define cogl_color_in gl_Color
 #define cogl_tex_coord_in  gl_MultiTexCoord0
 #define cogl_tex_coord0_in gl_MultiTexCoord0
 #define cogl_tex_coord1_in gl_MultiTexCoord1
 #define cogl_tex_coord2_in gl_MultiTexCoord2
 #define cogl_tex_coord3_in gl_MultiTexCoord3
 #define cogl_tex_coord4_in gl_MultiTexCoord4
 #define cogl_tex_coord5_in gl_MultiTexCoord5
 #define cogl_tex_coord6_in gl_MultiTexCoord6
 #define cogl_tex_coord7_in gl_MultiTexCoord7
 #define cogl_normal_in gl_Normal

 #define cogl_position_out gl_Position
 #define cogl_point_size_out gl_PointSize
 #define cogl_color_out gl_FrontColor
 #define cogl_tex_coord_out gl_TexCoord

 #define cogl_modelview_matrix gl_ModelViewMatrix
 #define cogl_modelview_projection_matrix gl_ModelViewProjectionMatrix
 #define cogl_projection_matrix gl_ProjectionMatrix
 #define cogl_texture_matrix gl_TextureMatrix

And for fragment shaders we have:

 #define cogl_color_in gl_Color
 #define cogl_tex_coord_in gl_TexCoord

 #define cogl_color_out gl_FragColor
 #define cogl_depth_out gl_FragDepth

 #define cogl_front_facing gl_FrontFacing
This commit is contained in:
Robert Bragg 2010-07-23 17:46:41 +01:00
parent a4b984186c
commit 5f30835eae
22 changed files with 523 additions and 196 deletions

View File

@ -57,18 +57,17 @@ typedef struct _ClutterBlurEffectClass ClutterBlurEffectClass;
* horizontal/vertical two pass shader for the gaussian blur * horizontal/vertical two pass shader for the gaussian blur
*/ */
static const gchar *box_blur_glsl_shader = static const gchar *box_blur_glsl_shader =
"#version 110\n"
"uniform sampler2D tex;\n" "uniform sampler2D tex;\n"
"uniform float x_step, y_step;\n" "uniform float x_step, y_step;\n"
"\n" "\n"
"vec4 get_rgba_rel (sampler2D source, float dx, float dy)\n" "vec4 get_rgba_rel (sampler2D source, float dx, float dy)\n"
"{\n" "{\n"
" return texture2D (tex, gl_TexCoord[0].st + vec2 (dx, dy) * 2.0);\n" " return texture2D (tex, cogl_tex_coord[0].st + vec2 (dx, dy) * 2.0);\n"
"}\n" "}\n"
"\n" "\n"
"void main ()\n" "void main ()\n"
"{\n" "{\n"
" vec4 color = gl_Color * texture2D (tex, vec2 (gl_TexCoord[0].xy));\n" " vec4 color = cogl_color_in * texture2D (tex, vec2 (cogl_tex_coord[0].xy));\n"
" color += get_rgba_rel (tex, -x_step, -y_step);\n" " color += get_rgba_rel (tex, -x_step, -y_step);\n"
" color += get_rgba_rel (tex, 0.0, -y_step);\n" " color += get_rgba_rel (tex, 0.0, -y_step);\n"
" color += get_rgba_rel (tex, x_step, -y_step);\n" " color += get_rgba_rel (tex, x_step, -y_step);\n"
@ -78,7 +77,7 @@ static const gchar *box_blur_glsl_shader =
" color += get_rgba_rel (tex, -x_step, y_step);\n" " color += get_rgba_rel (tex, -x_step, y_step);\n"
" color += get_rgba_rel (tex, 0.0, y_step);\n" " color += get_rgba_rel (tex, 0.0, y_step);\n"
" color += get_rgba_rel (tex, x_step, y_step);\n" " color += get_rgba_rel (tex, x_step, y_step);\n"
" gl_FragColor = color / 9.0;\n" " cogl_color_out = color / 9.0;\n"
"}"; "}";
struct _ClutterBlurEffect struct _ClutterBlurEffect

View File

@ -84,15 +84,14 @@ struct _ClutterColorizeEffectClass
* Addison-Wesley * Addison-Wesley
*/ */
static const gchar *colorize_glsl_shader = static const gchar *colorize_glsl_shader =
"#version 110\n"
"uniform sampler2D tex;\n" "uniform sampler2D tex;\n"
"uniform vec3 tint;\n" "uniform vec3 tint;\n"
"\n" "\n"
"void main ()\n" "void main ()\n"
"{\n" "{\n"
" vec4 color = gl_Color * texture2D (tex, vec2 (gl_TexCoord[0].xy));\n" " vec4 color = cogl_color_in * texture2D (tex, vec2 (cogl_tex_coord[0].xy));\n"
" float gray = dot (color.rgb, vec3 (0.299, 0.587, 0.114));\n" " float gray = dot (color.rgb, vec3 (0.299, 0.587, 0.114));\n"
" gl_FragColor = vec4 (gray * tint, color.a);\n" " cogl_color_out = vec4 (gray * tint, color.a);\n"
"}\n"; "}\n";
/* a lame sepia */ /* a lame sepia */

View File

@ -88,7 +88,6 @@ struct _ClutterDesaturateEffectClass
* Addison-Wesley * Addison-Wesley
*/ */
static const gchar *desaturate_glsl_shader = static const gchar *desaturate_glsl_shader =
"#version 110\n"
"uniform sampler2D tex;\n" "uniform sampler2D tex;\n"
"uniform float factor;\n" "uniform float factor;\n"
"\n" "\n"
@ -101,9 +100,9 @@ static const gchar *desaturate_glsl_shader =
"\n" "\n"
"void main ()\n" "void main ()\n"
"{\n" "{\n"
" vec4 color = gl_Color * texture2D (tex, vec2 (gl_TexCoord[0].xy));\n" " vec4 color = cogl_color_in * texture2D (tex, vec2 (cogl_tex_coord[0].xy));\n"
" color.rgb = desaturate (color.rgb, factor);\n" " color.rgb = desaturate (color.rgb, factor);\n"
" gl_FragColor = color;\n" " cogl_color_out = color;\n"
"}\n"; "}\n";
enum enum

View File

@ -239,7 +239,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 ();

View File

@ -230,7 +230,7 @@ _cogl_path_stroke_nodes (void)
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);
@ -376,7 +376,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);

View File

@ -327,7 +327,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;

View File

@ -73,7 +73,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)
{ {
_cogl_use_program (0, COGL_PIPELINE_PROGRAM_TYPE_FIXED); _cogl_use_program (0, COGL_PIPELINE_PROGRAM_TYPE_FIXED);
return TRUE; return TRUE;

View File

@ -73,6 +73,17 @@ typedef struct _GlslProgramState
unsigned int user_program_age; unsigned int user_program_age;
GLuint gl_program; GLuint gl_program;
#ifdef HAVE_COGL_GLES2
/* 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;
#endif
/* This is set to TRUE if the program has changed since we last /* This is set to TRUE if the program has changed since we last
flushed the uniforms */ flushed the uniforms */
gboolean gl_program_changed; gboolean gl_program_changed;
@ -252,7 +263,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;
@ -285,8 +297,17 @@ _cogl_pipeline_backend_glsl_start (CoglPipeline *pipeline,
if (priv->glsl_program_state) if (priv->glsl_program_state)
{ {
/* However if the program has changed since the last link then we do /* However if the program has changed since the last link then we do
need to relink */ * need to relink
if (priv->glsl_program_state->user_program_age == user_program->age) *
* 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 (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;
/* Destroy the existing program. We can't just dirty the whole /* Destroy the existing program. We can't just dirty the whole
@ -340,6 +361,18 @@ _cogl_pipeline_backend_glsl_start (CoglPipeline *pipeline,
GE_RET( gl_program, glCreateProgram () ); GE_RET( gl_program, glCreateProgram () );
#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.*/
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
/* Add all of the shaders from the user program */ /* Add all of the shaders from the user program */
for (l = user_program->attached_shaders; l; l = l->next) for (l = user_program->attached_shaders; l; l = l->next)
{ {
@ -347,11 +380,16 @@ _cogl_pipeline_backend_glsl_start (CoglPipeline *pipeline,
g_assert (shader->language == COGL_SHADER_LANGUAGE_GLSL); g_assert (shader->language == COGL_SHADER_LANGUAGE_GLSL);
_cogl_shader_compile_real (shader, n_tex_coord_attribs);
GE( glAttachShader (gl_program, shader->gl_handle) ); GE( glAttachShader (gl_program, shader->gl_handle) );
} }
priv->glsl_program_state->gl_program = gl_program; priv->glsl_program_state->gl_program = gl_program;
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
link_program (gl_program); link_program (gl_program);

View File

@ -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 */

View File

@ -1036,7 +1036,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;
@ -1139,7 +1140,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;

View File

@ -552,7 +552,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);

View File

@ -0,0 +1,107 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2010 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
*
* Authors:
* Robert Bragg <robert@linux.intel.com>
*/
#ifndef __COGL_SHADER_BOILERPLATE_H
#define __COGL_SHADER_BOILERPLATE_H
#include "cogl.h"
#define _COGL_COMMON_SHADER_BOILERPLATE \
"#define COGL_VERSION 100\n" \
"\n"
#ifndef HAVE_COGL_GLES2
#define _COGL_VERTEX_SHADER_BOILERPLATE \
_COGL_COMMON_SHADER_BOILERPLATE \
"#define cogl_position_in gl_Vertex\n" \
"#define cogl_color_in gl_Color\n" \
"#define cogl_tex_coord_in gl_MultiTexCoord0\n" \
"#define cogl_tex_coord0_in gl_MultiTexCoord0\n" \
"#define cogl_tex_coord1_in gl_MultiTexCoord1\n" \
"#define cogl_tex_coord2_in gl_MultiTexCoord2\n" \
"#define cogl_tex_coord3_in gl_MultiTexCoord3\n" \
"#define cogl_tex_coord4_in gl_MultiTexCoord4\n" \
"#define cogl_tex_coord5_in gl_MultiTexCoord5\n" \
"#define cogl_tex_coord6_in gl_MultiTexCoord6\n" \
"#define cogl_tex_coord7_in gl_MultiTexCoord7\n" \
"#define cogl_normal_in gl_Normal\n" \
"\n" \
"#define cogl_position_out gl_Position\n" \
"#define cogl_point_size_out gl_PointSize\n" \
"#define cogl_color_out gl_FrontColor\n" \
"#define cogl_tex_coord_out gl_TexCoord\n" \
"\n" \
"#define cogl_modelview_matrix gl_ModelViewMatrix\n" \
"#define cogl_modelview_projection_matrix gl_ModelViewProjectionMatrix\n" \
"#define cogl_projection_matrix gl_ProjectionMatrix\n" \
"#define cogl_texture_matrix gl_TextureMatrix\n" \
#define _COGL_FRAGMENT_SHADER_BOILERPLATE \
_COGL_COMMON_SHADER_BOILERPLATE \
"#define cogl_color_in gl_Color\n" \
"#define cogl_tex_coord_in gl_TexCoord\n" \
"\n" \
"#define cogl_color_out gl_FragColor\n" \
"#define cogl_depth_out gl_FragDepth\n" \
"\n" \
"#define cogl_front_facing gl_FrontFacing\n"
#if 0
/* GLSL 1.2 has a bottom left origin, though later versions
* allow use of an origin_upper_left keyword which would be
* more appropriate for Cogl. */
"#define coglFragCoord gl_FragCoord\n"
#endif
#else /* HAVE_COGL_GLES2 */
#define _COGL_VERTEX_SHADER_BOILERPLATE \
_COGL_COMMON_SHADER_BOILERPLATE \
"#define cogl_color_out _cogl_color\n" \
"#define cogl_point_coord_out _cogl_point_coord\n" \
"#define cogl_tex_coord_out _cogl_tex_coord\n"
#define _COGL_FRAGMENT_SHADER_BOILERPLATE \
_COGL_COMMON_SHADER_BOILERPLATE \
"#if __VERSION__ == 100\n" \
"precision highp float;\n" \
"#endif\n" \
"\n" \
"varying vec4 _cogl_color;\n" \
"\n" \
"#define cogl_color_in _cogl_color\n" \
"#define cogl_tex_coord_in _cogl_tex_coord\n" \
"\n" \
"#define cogl_color_out gl_FragColor\n" \
"#define cogl_depth_out gl_FragDepth\n" \
"\n" \
"#define cogl_front_facing gl_FrontFacing\n"
#endif /* HAVE_COGL_GLES2 */
#endif /* __COGL_SHADER_BOILERPLATE_H */

View File

@ -40,12 +40,17 @@ 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);

View File

@ -27,6 +27,7 @@
#include "cogl.h" #include "cogl.h"
#include "cogl-shader-private.h" #include "cogl-shader-private.h"
#include "cogl-shader-boilerplate.h"
#include "cogl-internal.h" #include "cogl-internal.h"
#include "cogl-context.h" #include "cogl-context.h"
#include "cogl-handle.h" #include "cogl-handle.h"
@ -100,11 +101,35 @@ 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);
} }
static void
delete_shader (CoglShader *shader)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
#ifdef HAVE_COGL_GL
if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
{
if (shader->gl_handle)
GE (glDeletePrograms (1, &shader->gl_handle));
}
else
#endif
{
if (shader->gl_handle)
GE (glDeleteShader (shader->gl_handle));
}
shader->gl_handle = 0;
}
void void
cogl_shader_source (CoglHandle handle, cogl_shader_source (CoglHandle handle,
const char *source) const char *source)
@ -127,29 +152,55 @@ 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)
#ifdef HAVE_COGL_GL delete_shader (shader);
if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
{ shader->source = g_strdup (source);
if (shader->gl_handle)
GE (glDeletePrograms (1, &shader->gl_handle)); shader->language = language;
} }
else
#endif void
{ cogl_shader_compile (CoglHandle handle)
if (shader->gl_handle) {
GE (glDeleteShader (shader->gl_handle)); CoglShader *shader = handle;
}
} if (!cogl_is_shader (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_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)
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));
@ -160,8 +211,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)
@ -169,7 +220,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
@ -177,44 +228,70 @@ cogl_shader_source (CoglHandle handle,
else else
#endif #endif
{ {
if (!shader->gl_handle) char *sourcev[4];
int count = 0;
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)
{ {
GLenum gl_type; case COGL_SHADER_TYPE_VERTEX:
gl_type = GL_VERTEX_SHADER;
switch (shader->type) break;
{ case COGL_SHADER_TYPE_FRAGMENT:
case COGL_SHADER_TYPE_VERTEX: gl_type = GL_FRAGMENT_SHADER;
gl_type = GL_VERTEX_SHADER; break;
break; default:
case COGL_SHADER_TYPE_FRAGMENT: g_assert_not_reached ();
gl_type = GL_FRAGMENT_SHADER; break;
break;
default:
g_assert_not_reached ();
break;
}
shader->gl_handle = glCreateShader (gl_type);
} }
glShaderSource (shader->gl_handle, 1, &source, NULL);
shader->gl_handle = glCreateShader (gl_type);
sourcev[count++] = _COGL_COMMON_SHADER_BOILERPLATE;
if (shader->type == COGL_SHADER_TYPE_VERTEX)
sourcev[count++] = _COGL_VERTEX_SHADER_BOILERPLATE;
else
sourcev[count++] = _COGL_FRAGMENT_SHADER_BOILERPLATE;
#ifdef HAVE_COGL_GLES2
if (n_tex_coord_attribs)
sourcev[count++] =
g_strdup_printf ("varying vec2 _cogl_tex_coord[%d];\n",
n_tex_coord_attribs);
shader->n_tex_coord_attribs = n_tex_coord_attribs;
#endif
sourcev[count++] = shader->source;
glShaderSource (shader->gl_handle, count, (const char **)sourcev, NULL);
#ifdef HAVE_COGL_GLES2
if (count == 4)
g_free (sourcev[2]);
#endif
GE (glCompileShader (shader->gl_handle));
#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
} }
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));
} }
char * char *
@ -242,6 +319,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);
@ -284,6 +376,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;

View File

@ -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;

View File

@ -218,6 +218,79 @@ validate_gl_attribute (const char *gl_attribute,
return type; return type;
} }
/* There are a number of standard OpenGL attributes that we deal with
* specially. These attributes are all namespaced with a "gl_" prefix
* so we should catch any typos instead of silently adding a custom
* attribute.
*/
static CoglVertexBufferAttribFlags
validate_cogl_attribute (const char *cogl_attribute,
guint8 n_components,
guint8 *texture_unit)
{
CoglVertexBufferAttribFlags type;
char *detail_seperator = NULL;
int name_len;
detail_seperator = strstr (cogl_attribute, "::");
if (detail_seperator)
name_len = detail_seperator - cogl_attribute;
else
name_len = strlen (cogl_attribute);
if (strncmp (cogl_attribute, "position_in", name_len) == 0)
{
if (G_UNLIKELY (n_components == 1))
g_critical ("glVertexPointer doesn't allow 1 component vertex "
"positions so we currently only support "
"\"cogl_position_in\" attributes where "
"n_components == 2, 3 or 4");
type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY;
}
else if (strncmp (cogl_attribute, "color_in", name_len) == 0)
{
if (G_UNLIKELY (n_components != 3 && n_components != 4))
g_critical ("glColorPointer expects 3 or 4 component colors so we "
"currently only support \"cogl_color_in\" attributes "
"where n_components == 3 or 4");
type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_COLOR_ARRAY;
}
else if (strncmp (cogl_attribute,
"cogl_tex_coord",
strlen ("cogl_tex_coord")) == 0)
{
unsigned int unit;
if (strcmp (cogl_attribute, "cogl_tex_coord_in") == 0)
unit = 0;
else if (sscanf (cogl_attribute, "cogl_tex_coord%u_in", &unit) != 1)
{
g_warning ("texture coordinate attributes should either be "
"referenced as \"cogl_tex_coord_in\" or with a"
"texture unit number like \"cogl_tex_coord1_in\"");
unit = 0;
}
/* FIXME: validate any '::' delimiter for this case */
*texture_unit = unit;
type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY;
}
else if (strncmp (cogl_attribute, "normal_in", name_len) == 0)
{
if (G_UNLIKELY (n_components != 3))
g_critical ("glNormalPointer expects 3 component normals so we "
"currently only support \"cogl_normal_in\" attributes "
"where n_components == 3");
type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMAL_ARRAY;
}
else
{
g_warning ("Unknown cogl_* attribute name cogl_%s\n", cogl_attribute);
type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID;
}
return type;
}
/* This validates that a custom attribute name is a valid GLSL variable name /* This validates that a custom attribute name is a valid GLSL variable name
* *
* NB: attribute names may have a detail component delimited using '::' E.g. * NB: attribute names may have a detail component delimited using '::' E.g.
@ -402,8 +475,9 @@ cogl_vertex_buffer_add (CoglHandle handle,
attribute = submitted_attribute; attribute = submitted_attribute;
/* since we will skip validate_gl_attribute in this case, we need /* since we will skip validate_gl/cogl_attribute in this case, we
* to pluck out the attribute type before overwriting the flags: */ * need to pluck out the attribute type before overwriting the
* flags: */
flags |= flags |=
attribute->flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_TYPE_MASK; attribute->flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_TYPE_MASK;
break; break;
@ -424,6 +498,14 @@ cogl_vertex_buffer_add (CoglHandle handle,
if (flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID) if (flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID)
return; return;
} }
else if (strncmp (attribute_name, "cogl_", 5) == 0)
{
flags |= validate_cogl_attribute (attribute_name + 5,
n_components,
&texture_unit);
if (flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID)
return;
}
else else
{ {
flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_CUSTOM_ARRAY; flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_CUSTOM_ARRAY;

View File

@ -745,6 +745,7 @@ void
cogl_begin_gl (void) cogl_begin_gl (void)
{ {
unsigned long enable_flags = 0; unsigned long enable_flags = 0;
CoglPipeline *pipeline;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -777,8 +778,21 @@ 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
* 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
* values.
*/ */
_cogl_pipeline_flush_gl_state (cogl_get_source (), FALSE); pipeline = cogl_get_source ();
_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;

View File

@ -7,8 +7,8 @@ precision highp float;
/*** _cogl_fixed_fragment_shader_inputs ***/ /*** _cogl_fixed_fragment_shader_inputs ***/
/* Inputs from the vertex shader */ /* Inputs from the vertex shader */
varying vec4 frag_color; varying vec4 _cogl_color;
varying float fog_amount; varying float _cogl_fog_amount;
/*** _cogl_fixed_fragment_shader_texturing_options ***/ /*** _cogl_fixed_fragment_shader_texturing_options ***/
@ -17,10 +17,10 @@ varying float fog_amount;
/*** _cogl_fixed_fragment_shader_fogging_options ***/ /*** _cogl_fixed_fragment_shader_fogging_options ***/
/* Fogging options */ /* Fogging options */
uniform vec4 fog_color; uniform vec4 _cogl_fog_color;
/* Alpha test options */ /* Alpha test options */
uniform float alpha_test_ref; uniform float _cogl_alpha_test_ref;
/*** _cogl_fixed_fragment_shader_main_declare ***/ /*** _cogl_fixed_fragment_shader_main_declare ***/
@ -33,30 +33,32 @@ main (void)
/*** _cogl_fixed_fragment_shader_fog ***/ /*** _cogl_fixed_fragment_shader_fog ***/
/* Mix the calculated color with the fog color */ /* Mix the calculated color with the fog color */
gl_FragColor.rgb = mix (fog_color.rgb, gl_FragColor.rgb, fog_amount); gl_FragColor.rgb = mix (_cogl_fog_color.rgb, gl_FragColor.rgb,
_cogl_fog_amount);
/* Alpha testing */ /* Alpha testing */
/*** _cogl_fixed_fragment_shader_alpha_never ***/ /*** _cogl_fixed_fragment_shader_alpha_never ***/
discard; discard;
/*** _cogl_fixed_fragment_shader_alpha_less ***/ /*** _cogl_fixed_fragment_shader_alpha_less ***/
if (gl_FragColor.a >= alpha_test_ref) if (gl_FragColor.a >= _cogl_alpha_test_ref)
discard; discard;
/*** _cogl_fixed_fragment_shader_alpha_equal ***/ /*** _cogl_fixed_fragment_shader_alpha_equal ***/
if (gl_FragColor.a != alpha_test_ref) if (gl_FragColor.a != _cogl_alpha_test_ref)
discard; discard;
/*** _cogl_fixed_fragment_shader_alpha_lequal ***/ /*** _cogl_fixed_fragment_shader_alpha_lequal ***/
if (gl_FragColor.a > alpha_test_ref) if (gl_FragColor.a > _cogl_alpha_test_ref)
discard; discard;
/*** _cogl_fixed_fragment_shader_alpha_greater ***/ /*** _cogl_fixed_fragment_shader_alpha_greater ***/
if (gl_FragColor.a <= alpha_test_ref) if (gl_FragColor.a <= _cogl_alpha_test_ref)
discard; discard;
/*** _cogl_fixed_fragment_shader_alpha_notequal ***/ /*** _cogl_fixed_fragment_shader_alpha_notequal ***/
if (gl_FragColor.a == alpha_test_ref) if (gl_FragColor.a == _cogl_alpha_test_ref)
discard; discard;
/*** _cogl_fixed_fragment_shader_alpha_gequal ***/ /*** _cogl_fixed_fragment_shader_alpha_gequal ***/
if (gl_FragColor.a < alpha_test_ref) if (gl_FragColor.a < _cogl_alpha_test_ref)
discard; discard;
/*** _cogl_fixed_fragment_shader_end ***/ /*** _cogl_fixed_fragment_shader_end ***/
} }

View File

@ -1,30 +1,30 @@
/*** _cogl_fixed_vertex_shader_per_vertex_attribs ***/ /*** _cogl_fixed_vertex_shader_per_vertex_attribs ***/
/* Per vertex attributes */ /* Per vertex attributes */
attribute vec4 vertex_attrib; attribute vec4 cogl_position_in;
attribute vec4 color_attrib; attribute vec4 cogl_color_in;
/*** _cogl_fixed_vertex_shader_transform_matrices ***/ /*** _cogl_fixed_vertex_shader_transform_matrices ***/
/* Transformation matrices */ /* Transformation matrices */
uniform mat4 modelview_matrix; uniform mat4 cogl_modelview_matrix;
uniform mat4 mvp_matrix; /* combined modelview and projection matrix */ uniform mat4 cogl_modelview_projection_matrix; /* combined modelview and projection matrix */
/*** _cogl_fixed_vertex_shader_output_variables ***/ /*** _cogl_fixed_vertex_shader_output_variables ***/
/* Outputs to the fragment shader */ /* Outputs to the fragment shader */
varying vec4 frag_color; varying vec4 _cogl_color;
varying float fog_amount; varying float _cogl_fog_amount;
/*** _cogl_fixed_vertex_shader_fogging_options ***/ /*** _cogl_fixed_vertex_shader_fogging_options ***/
/* Fogging options */ /* Fogging options */
uniform float fog_density; uniform float _cogl_fog_density;
uniform float fog_start; uniform float _cogl_fog_start;
uniform float fog_end; uniform float _cogl_fog_end;
/* Point options */ /* Point options */
uniform float point_size; uniform float cogl_point_size_in;
/*** _cogl_fixed_vertex_shader_main_start ***/ /*** _cogl_fixed_vertex_shader_main_start ***/
@ -34,38 +34,40 @@ main (void)
vec4 transformed_tex_coord; vec4 transformed_tex_coord;
/* Calculate the transformed position */ /* Calculate the transformed position */
gl_Position = mvp_matrix * vertex_attrib; gl_Position = cogl_modelview_projection_matrix * cogl_position_in;
/* Copy across the point size from the uniform */ /* Copy across the point size from the uniform */
gl_PointSize = point_size; gl_PointSize = cogl_point_size_in;
/* Calculate the transformed texture coordinate */ /* Calculate the transformed texture coordinate */
/*** _cogl_fixed_vertex_shader_frag_color_start ***/ /*** _cogl_fixed_vertex_shader_frag_color_start ***/
/* Pass the interpolated vertex color on to the fragment shader */ /* Pass the interpolated vertex color on to the fragment shader */
frag_color = color_attrib; _cogl_color = cogl_color_in;
/*** _cogl_fixed_vertex_shader_fog_start ***/ /*** _cogl_fixed_vertex_shader_fog_start ***/
/* Estimate the distance from the eye using just the z-coordinate to /* Estimate the distance from the eye using just the z-coordinate to
use as the fog coord */ use as the fog coord */
vec4 eye_coord = modelview_matrix * vertex_attrib; vec4 eye_coord = cogl_modelview_matrix * cogl_position_in;
float fog_coord = abs (eye_coord.z / eye_coord.w); float fog_coord = abs (eye_coord.z / eye_coord.w);
/* Calculate the fog amount per-vertex and interpolate it for the /* Calculate the fog amount per-vertex and interpolate it for the
fragment shader */ fragment shader */
/*** _cogl_fixed_vertex_shader_fog_exp ***/ /*** _cogl_fixed_vertex_shader_fog_exp ***/
fog_amount = exp (-fog_density * fog_coord); _cogl_fog_amount = exp (-fog_density * fog_coord);
/*** _cogl_fixed_vertex_shader_fog_exp2 ***/ /*** _cogl_fixed_vertex_shader_fog_exp2 ***/
fog_amount = exp (-fog_density * fog_coord _cogl_fog_amount = exp (-_cogl_fog_density * fog_coord
* fog_density * fog_coord); * _cogl_fog_density * fog_coord);
/*** _cogl_fixed_vertex_shader_fog_linear ***/ /*** _cogl_fixed_vertex_shader_fog_linear ***/
fog_amount = (fog_end - fog_coord) / (fog_end - fog_start); _cogl_fog_amount = (_cogl_fog_end - fog_coord) /
(_cogl_fog_end - _cogl_fog_start);
/*** _cogl_fixed_vertex_shader_fog_end ***/ /*** _cogl_fixed_vertex_shader_fog_end ***/
fog_amount = clamp (fog_amount, 0.0, 1.0); _cogl_fog_amount = clamp (_cogl_fog_amount, 0.0, 1.0);
/*** _cogl_fixed_vertex_shader_end ***/ /*** _cogl_fixed_vertex_shader_end ***/
} }

View File

@ -318,7 +318,7 @@ cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings)
for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++) for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i)) if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
g_string_append_printf (shader_source, g_string_append_printf (shader_source,
"attribute vec4 multi_tex_coord_attrib%d;\n", "attribute vec4 cogl_tex_coord%d_in;\n",
i); i);
/* Find the biggest enabled texture unit index */ /* Find the biggest enabled texture unit index */
@ -332,11 +332,11 @@ cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings)
if (n_texture_units > 0) if (n_texture_units > 0)
{ {
g_string_append_printf (shader_source, g_string_append_printf (shader_source,
"uniform mat4 texture_matrix[%d];\n", "uniform mat4 cogl_texture_matrix[%d];\n",
n_texture_units); n_texture_units);
g_string_append_printf (shader_source, g_string_append_printf (shader_source,
"varying vec2 tex_coord[%d];", "varying vec2 _cogl_tex_coord[%d];",
n_texture_units); n_texture_units);
} }
@ -349,11 +349,11 @@ cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings)
{ {
g_string_append_printf (shader_source, g_string_append_printf (shader_source,
"transformed_tex_coord = " "transformed_tex_coord = "
"texture_matrix[%d] " "cogl_texture_matrix[%d] "
" * multi_tex_coord_attrib%d;\n", " * cogl_tex_coord%d_in;\n",
i, i); i, i);
g_string_append_printf (shader_source, g_string_append_printf (shader_source,
"tex_coord[%d] = transformed_tex_coord.st " "_cogl_tex_coord[%d] = transformed_tex_coord.st "
" / transformed_tex_coord.q;\n", " / transformed_tex_coord.q;\n",
i); i);
} }
@ -410,19 +410,21 @@ cogl_gles2_add_texture_lookup (int unit,
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
if (w->settings.tex_env[unit].texture_target == GL_TEXTURE_3D_OES) if (w->settings.tex_env[unit].texture_target == GL_TEXTURE_3D_OES)
g_string_append_printf (shader_source, "texture3D (texture_unit[%d], ", g_string_append_printf (shader_source,
"texture3D (_cogl_texture_unit[%d], ",
unit); unit);
else else
g_string_append_printf (shader_source, "texture2D (texture_unit[%d], ", g_string_append_printf (shader_source,
"texture2D (_cogl_texture_unit[%d], ",
unit); unit);
/* If point sprite coord generation is being used then divert to the /* If point sprite coord generation is being used then divert to the
built-in varying var for that instead of the texture built-in varying var for that instead of the texture
coordinates */ coordinates */
if (w->settings.tex_env[unit].point_sprite_coords) if (w->settings.tex_env[unit].point_sprite_coords)
g_string_append (shader_source, "gl_PointCoord"); g_string_append (shader_source, "_cogl_point_coord");
else else
g_string_append_printf (shader_source, "tex_coord[%d]", unit); g_string_append_printf (shader_source, "_cogl_tex_coord[%d]", unit);
g_string_append_printf (shader_source, ").%s", swizzle); g_string_append_printf (shader_source, ").%s", swizzle);
} }
@ -458,7 +460,7 @@ cogl_gles2_add_arg (int unit,
break; break;
case GL_CONSTANT: case GL_CONSTANT:
g_string_append_printf (shader_source, "combine_constant[%d].%s", g_string_append_printf (shader_source, "_cogl_combine_constant[%d].%s",
unit, swizzle); unit, swizzle);
break; break;
@ -470,7 +472,7 @@ cogl_gles2_add_arg (int unit,
} }
/* flow through */ /* flow through */
case GL_PRIMARY_COLOR: case GL_PRIMARY_COLOR:
g_string_append_printf (shader_source, "frag_color.%s", swizzle); g_string_append_printf (shader_source, "_cogl_color.%s", swizzle);
break; break;
default: default:
@ -635,13 +637,13 @@ cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings)
if (n_texture_units > 0) if (n_texture_units > 0)
{ {
g_string_append_printf (shader_source, g_string_append_printf (shader_source,
"varying vec2 tex_coord[%d];\n", "varying vec2 _cogl_tex_coord[%d];\n",
n_texture_units); n_texture_units);
g_string_append (shader_source, g_string_append (shader_source,
_cogl_fixed_fragment_shader_texturing_options); _cogl_fixed_fragment_shader_texturing_options);
g_string_append_printf (shader_source, g_string_append_printf (shader_source,
"uniform sampler2D texture_unit[%d];\n", "uniform sampler2D _cogl_texture_unit[%d];\n",
n_texture_units); n_texture_units);
} }
@ -655,12 +657,12 @@ cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings)
apparent bug in the PowerVR drivers. Without it the alpha apparent bug in the PowerVR drivers. Without it the alpha
blending seems to stop working */ blending seems to stop working */
g_string_append (shader_source, g_string_append (shader_source,
"vec4 frag_color_copy = frag_color;\n"); "vec4 frag_color_copy = _cogl_color;\n");
/* If there are no textures units enabled then we can just directly /* If there are no textures units enabled then we can just directly
use the color from the vertex shader */ use the color from the vertex shader */
if (n_texture_units == 0) if (n_texture_units == 0)
g_string_append (shader_source, "gl_FragColor = frag_color;\n"); g_string_append (shader_source, "gl_FragColor = _cogl_color;\n");
else else
/* Otherwise we need to calculate the value based on the layer /* Otherwise we need to calculate the value based on the layer
combine settings */ combine settings */
@ -769,17 +771,17 @@ cogl_gles2_wrapper_get_locations (GLuint program,
int i; int i;
uniforms->mvp_matrix_uniform uniforms->mvp_matrix_uniform
= glGetUniformLocation (program, "mvp_matrix"); = glGetUniformLocation (program, "cogl_modelview_projection_matrix");
uniforms->modelview_matrix_uniform uniforms->modelview_matrix_uniform
= glGetUniformLocation (program, "modelview_matrix"); = glGetUniformLocation (program, "cogl_modelview_matrix");
for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++) for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i)) if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
{ {
char *matrix_var_name = g_strdup_printf ("texture_matrix[%d]", i); char *matrix_var_name = g_strdup_printf ("cogl_texture_matrix[%d]", i);
char *sampler_var_name = g_strdup_printf ("texture_unit[%d]", i); char *sampler_var_name = g_strdup_printf ("_cogl_texture_unit[%d]", i);
char *tex_coord_var_name = char *tex_coord_var_name =
g_strdup_printf ("multi_tex_coord_attrib%d", i); g_strdup_printf ("cogl_tex_coord%d_in", i);
uniforms->texture_matrix_uniforms[i] uniforms->texture_matrix_uniforms[i]
= glGetUniformLocation (program, matrix_var_name); = glGetUniformLocation (program, matrix_var_name);
@ -800,30 +802,30 @@ cogl_gles2_wrapper_get_locations (GLuint program,
} }
uniforms->fog_density_uniform uniforms->fog_density_uniform
= glGetUniformLocation (program, "fog_density"); = glGetUniformLocation (program, "_cogl_fog_density");
uniforms->fog_start_uniform uniforms->fog_start_uniform
= glGetUniformLocation (program, "fog_start"); = glGetUniformLocation (program, "_cogl_fog_start");
uniforms->fog_end_uniform uniforms->fog_end_uniform
= glGetUniformLocation (program, "fog_end"); = glGetUniformLocation (program, "_cogl_fog_end");
uniforms->fog_color_uniform uniforms->fog_color_uniform
= glGetUniformLocation (program, "fog_color"); = glGetUniformLocation (program, "_cogl_fog_color");
uniforms->alpha_test_ref_uniform uniforms->alpha_test_ref_uniform
= glGetUniformLocation (program, "alpha_test_ref"); = glGetUniformLocation (program, "_cogl_alpha_test_ref");
uniforms->point_size_uniform uniforms->point_size_uniform
= glGetUniformLocation (program, "point_size"); = glGetUniformLocation (program, "cogl_point_size_in");
} }
static void static void
cogl_gles2_wrapper_bind_attributes (GLuint program) cogl_gles2_wrapper_bind_attributes (GLuint program)
{ {
glBindAttribLocation (program, COGL_GLES2_WRAPPER_VERTEX_ATTRIB, glBindAttribLocation (program, COGL_GLES2_WRAPPER_VERTEX_ATTRIB,
"vertex_attrib"); "cogl_position_in");
glBindAttribLocation (program, COGL_GLES2_WRAPPER_COLOR_ATTRIB, glBindAttribLocation (program, COGL_GLES2_WRAPPER_COLOR_ATTRIB,
"color_attrib"); "cogl_color_in");
glBindAttribLocation (program, COGL_GLES2_WRAPPER_NORMAL_ATTRIB, glBindAttribLocation (program, COGL_GLES2_WRAPPER_NORMAL_ATTRIB,
"normal_attrib"); "cogl_normal_in");
} }
static CoglGles2WrapperProgram * static CoglGles2WrapperProgram *

View File

@ -11,25 +11,6 @@ typedef struct
char *source; char *source;
} ShaderSource; } ShaderSource;
/* These variables are used instead of the standard GLSL variables on
GLES 2 */
#ifdef COGL_HAS_GLES2
#define GLES2_VARS \
"precision mediump float;\n" \
"varying vec2 tex_coord[1];\n" \
"varying vec4 frag_color;\n"
#define TEX_COORD "tex_coord[0]"
#define COLOR_VAR "frag_color"
#else /* COGL_HAS_GLES2 */
#define GLES2_VARS ""
#define TEX_COORD "gl_TexCoord[0]"
#define COLOR_VAR "gl_Color"
#endif /* COGL_HAS_GLES2 */
/* a couple of boilerplate defines that are common amongst all the /* a couple of boilerplate defines that are common amongst all the
* sample shaders * sample shaders
*/ */
@ -38,21 +19,20 @@ typedef struct
* initialized, from a sampler2D in a variable tex. * initialized, from a sampler2D in a variable tex.
*/ */
#define FRAGMENT_SHADER_VARS \ #define FRAGMENT_SHADER_VARS \
GLES2_VARS \
"uniform sampler2D tex;" \ "uniform sampler2D tex;" \
"uniform float x_step, y_step;" \ "uniform float x_step, y_step;"
#define FRAGMENT_SHADER_BEGIN \ #define FRAGMENT_SHADER_BEGIN \
"void main (){" \ "void main (){" \
" vec4 color = texture2D (tex, vec2(" TEX_COORD "));" " vec4 color = texture2D (tex, vec2(cogl_tex_coord_in[0]));"
/* FRAGMENT_SHADER_END: apply the changed color to the output buffer correctly /* FRAGMENT_SHADER_END: apply the changed color to the output buffer correctly
* blended with the gl specified color (makes the opacity of actors work * blended with the gl specified color (makes the opacity of actors work
* correctly). * correctly).
*/ */
#define FRAGMENT_SHADER_END \ #define FRAGMENT_SHADER_END \
" gl_FragColor = color;" \ " cogl_color_out = color;" \
" gl_FragColor = gl_FragColor * " COLOR_VAR ";" \ " cogl_color_out = cogl_color_out * cogl_color_in;" \
"}" "}"
static ShaderSource shaders[]= static ShaderSource shaders[]=
@ -80,8 +60,8 @@ static ShaderSource shaders[]=
" for (v=-radius;v<radius;v++)" " for (v=-radius;v<radius;v++)"
" {" " {"
" color += texture2D(tex, " " color += texture2D(tex, "
" vec2(" TEX_COORD ".s + u * 2.0 * x_step, " " vec2(cogl_tex_coord_in[0].s + u * 2.0 * x_step, "
" " TEX_COORD ".t + v * 2.0 * y_step));" " cogl_tex_coord_in[0].t + v * 2.0 * y_step));"
" count ++;" " count ++;"
" }" " }"
"color = color / float(count);" "color = color / float(count);"
@ -89,7 +69,7 @@ static ShaderSource shaders[]=
#else #else
"vec4 get_rgba_rel(sampler2D tex, float dx, float dy)" "vec4 get_rgba_rel(sampler2D tex, float dx, float dy)"
"{" "{"
" return texture2D (tex, " TEX_COORD ".st " " return texture2D (tex, cogl_tex_coord_in[0].st "
" + vec2(dx, dy) * 2.0);" " + vec2(dx, dy) * 2.0);"
"}" "}"
@ -144,7 +124,7 @@ static ShaderSource shaders[]=
{"combined-mirror", {"combined-mirror",
FRAGMENT_SHADER_VARS FRAGMENT_SHADER_VARS
FRAGMENT_SHADER_BEGIN FRAGMENT_SHADER_BEGIN
" vec4 colorB = texture2D (tex, vec2(" TEX_COORD ".ts));" " vec4 colorB = texture2D (tex, vec2(cogl_tex_coord_in[0].ts));"
" float avg = (color.r + color.g + color.b) / 3.0;" " float avg = (color.r + color.g + color.b) / 3.0;"
" color.r = avg;" " color.r = avg;"
" color.g = avg;" " color.g = avg;"
@ -157,7 +137,7 @@ static ShaderSource shaders[]=
FRAGMENT_SHADER_VARS FRAGMENT_SHADER_VARS
"float get_avg_rel(sampler2D texB, float dx, float dy)" "float get_avg_rel(sampler2D texB, float dx, float dy)"
"{" "{"
" vec4 colorB = texture2D (texB, " TEX_COORD ".st + vec2(dx, dy));" " vec4 colorB = texture2D (texB, cogl_tex_coord_in[0].st + vec2(dx, dy));"
" return (colorB.r + colorB.g + colorB.b) / 3.0;" " return (colorB.r + colorB.g + colorB.b) / 3.0;"
"}" "}"
FRAGMENT_SHADER_BEGIN FRAGMENT_SHADER_BEGIN

View File

@ -18,25 +18,6 @@ typedef struct
gchar *source; gchar *source;
} ShaderSource; } ShaderSource;
/* These variables are used instead of the standard GLSL variables on
GLES 2 */
#ifdef COGL_HAS_GLES2
#define GLES2_VARS \
"precision mediump float;\n" \
"varying vec2 tex_coord[1];\n" \
"varying vec4 frag_color;\n"
#define TEX_COORD "tex_coord[0]"
#define COLOR_VAR "frag_color"
#else /* COGL_HAS_GLES2 */
#define GLES2_VARS ""
#define TEX_COORD "gl_TexCoord[0]"
#define COLOR_VAR "gl_Color"
#endif /* COGL_HAS_GLES2 */
/* a couple of boilerplate defines that are common amongst all the /* a couple of boilerplate defines that are common amongst all the
* sample shaders * sample shaders
*/ */
@ -45,13 +26,12 @@ typedef struct
* initialized, from a sampler2D in a variable tex. * initialized, from a sampler2D in a variable tex.
*/ */
#define FRAGMENT_SHADER_VARS \ #define FRAGMENT_SHADER_VARS \
GLES2_VARS \
"uniform sampler2D tex;" \ "uniform sampler2D tex;" \
"uniform float x_step, y_step;" \ "uniform float x_step, y_step;" \
#define FRAGMENT_SHADER_BEGIN \ #define FRAGMENT_SHADER_BEGIN \
"void main (){" \ "void main (){" \
" vec4 color = texture2D (tex, vec2(" TEX_COORD "));" " vec4 color = texture2D (tex, vec2(cogl_tex_coord_in[0]));"
/* FRAGMENT_SHADER_END: apply the changed color to the output buffer correctly /* FRAGMENT_SHADER_END: apply the changed color to the output buffer correctly
* blended with the gl specified color (makes the opacity of actors work * blended with the gl specified color (makes the opacity of actors work
@ -59,7 +39,7 @@ typedef struct
*/ */
#define FRAGMENT_SHADER_END \ #define FRAGMENT_SHADER_END \
" gl_FragColor = color;" \ " gl_FragColor = color;" \
" gl_FragColor = gl_FragColor * " COLOR_VAR ";" \ " gl_FragColor = gl_FragColor * cogl_color_in;" \
"}" "}"
static ShaderSource shaders[]= static ShaderSource shaders[]=
@ -87,8 +67,8 @@ static ShaderSource shaders[]=
" for (v=-radius;v<radius;v++)" " for (v=-radius;v<radius;v++)"
" {" " {"
" color += texture2D(tex, " " color += texture2D(tex, "
" vec2(" TEX_COORD ".s + u * 2.0 * x_step, " " vec2(cogl_tex_coord_in[0].s + u * 2.0 * x_step, "
" " TEX_COORD ".t + v * 2.0 * y_step));" " cogl_tex_coord_in[0].t + v * 2.0 * y_step));"
" count ++;" " count ++;"
" }" " }"
"color = color / float(count);" "color = color / float(count);"
@ -96,7 +76,7 @@ static ShaderSource shaders[]=
#else #else
"vec4 get_rgba_rel(sampler2D tex, float dx, float dy)" "vec4 get_rgba_rel(sampler2D tex, float dx, float dy)"
"{" "{"
" return texture2D (tex, " TEX_COORD ".st " " return texture2D (tex, cogl_tex_coord_in[0].st "
" + vec2(dx, dy) * 2.0);" " + vec2(dx, dy) * 2.0);"
"}" "}"
@ -151,7 +131,7 @@ static ShaderSource shaders[]=
{"combined-mirror", {"combined-mirror",
FRAGMENT_SHADER_VARS FRAGMENT_SHADER_VARS
FRAGMENT_SHADER_BEGIN FRAGMENT_SHADER_BEGIN
" vec4 colorB = texture2D (tex, vec2(" TEX_COORD ".ts));" " vec4 colorB = texture2D (tex, vec2(cogl_tex_coord_in[0].ts));"
" float avg = (color.r + color.g + color.b) / 3.0;" " float avg = (color.r + color.g + color.b) / 3.0;"
" color.r = avg;" " color.r = avg;"
" color.g = avg;" " color.g = avg;"
@ -164,7 +144,7 @@ static ShaderSource shaders[]=
FRAGMENT_SHADER_VARS FRAGMENT_SHADER_VARS
"float get_avg_rel(sampler2D texB, float dx, float dy)" "float get_avg_rel(sampler2D texB, float dx, float dy)"
"{" "{"
" vec4 colorB = texture2D (texB, " TEX_COORD ".st + vec2(dx, dy));" " vec4 colorB = texture2D (texB, cogl_tex_coord_in.st + vec2(dx, dy));"
" return (colorB.r + colorB.g + colorB.b) / 3.0;" " return (colorB.r + colorB.g + colorB.b) / 3.0;"
"}" "}"
FRAGMENT_SHADER_BEGIN FRAGMENT_SHADER_BEGIN