mirror of
https://github.com/brl/mutter.git
synced 2024-11-24 17:10:40 -05:00
cogl: Remove ARBfp pipeline support
As with fixed pipelines, we require the use of the GLSL pipeline in mutter, and no point in supporting ARBfp anyway.
This commit is contained in:
parent
8f58ad02fb
commit
97004e6114
@ -70,8 +70,6 @@ struct _ClutterShaderPrivate
|
||||
{
|
||||
guint compiled : 1; /* Shader is bound to the GL context */
|
||||
guint is_enabled : 1;
|
||||
guint vertex_is_glsl : 1;
|
||||
guint fragment_is_glsl : 1;
|
||||
|
||||
gchar *vertex_source; /* GLSL source for vertex shader */
|
||||
gchar *fragment_source; /* GLSL source for fragment shader */
|
||||
@ -108,10 +106,10 @@ clutter_shader_release_internal (ClutterShader *shader)
|
||||
|
||||
g_assert (priv->program != COGL_INVALID_HANDLE);
|
||||
|
||||
if (priv->vertex_is_glsl && priv->vertex_shader != COGL_INVALID_HANDLE)
|
||||
if (priv->vertex_shader != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (priv->vertex_shader);
|
||||
|
||||
if (priv->fragment_is_glsl && priv->fragment_shader != COGL_INVALID_HANDLE)
|
||||
if (priv->fragment_shader != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (priv->fragment_shader);
|
||||
|
||||
if (priv->program != COGL_INVALID_HANDLE)
|
||||
@ -350,7 +348,6 @@ clutter_shader_set_source (ClutterShader *shader,
|
||||
gssize length)
|
||||
{
|
||||
ClutterShaderPrivate *priv = shader->priv;
|
||||
gboolean is_glsl = FALSE;
|
||||
|
||||
if (length < 0)
|
||||
length = strlen (data);
|
||||
@ -363,12 +360,9 @@ clutter_shader_set_source (ClutterShader *shader,
|
||||
if (clutter_shader_is_compiled (shader))
|
||||
clutter_shader_release (shader);
|
||||
|
||||
is_glsl = !g_str_has_prefix (data, "!!ARBfp");
|
||||
|
||||
CLUTTER_NOTE (SHADER,
|
||||
"setting %s shader (GLSL:%s, len:%" G_GSSIZE_FORMAT ")",
|
||||
"setting %s shader (len:%" G_GSSIZE_FORMAT ")",
|
||||
shader_type == CLUTTER_VERTEX_SHADER ? "vertex" : "fragment",
|
||||
is_glsl ? "yes" : "no",
|
||||
length);
|
||||
|
||||
switch (shader_type)
|
||||
@ -377,7 +371,6 @@ clutter_shader_set_source (ClutterShader *shader,
|
||||
g_free (priv->fragment_source);
|
||||
|
||||
priv->fragment_source = g_strndup (data, length);
|
||||
priv->fragment_is_glsl = is_glsl;
|
||||
g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_FRAGMENT_SOURCE]);
|
||||
break;
|
||||
|
||||
@ -385,7 +378,6 @@ clutter_shader_set_source (ClutterShader *shader,
|
||||
g_free (priv->vertex_source);
|
||||
|
||||
priv->vertex_source = g_strndup (data, length);
|
||||
priv->vertex_is_glsl = is_glsl;
|
||||
g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_VERTEX_SOURCE]);
|
||||
break;
|
||||
}
|
||||
@ -538,7 +530,7 @@ bind_glsl_shader (ClutterShader *self,
|
||||
|
||||
priv->program = cogl_create_program ();
|
||||
|
||||
if (priv->vertex_is_glsl && priv->vertex_source != COGL_INVALID_HANDLE)
|
||||
if (priv->vertex_source != COGL_INVALID_HANDLE)
|
||||
{
|
||||
res = clutter_shader_glsl_bind (self,
|
||||
CLUTTER_VERTEX_SHADER,
|
||||
@ -551,7 +543,7 @@ bind_glsl_shader (ClutterShader *self,
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->fragment_is_glsl && priv->fragment_source != COGL_INVALID_HANDLE)
|
||||
if (priv->fragment_source != COGL_INVALID_HANDLE)
|
||||
{
|
||||
res = clutter_shader_glsl_bind (self,
|
||||
CLUTTER_FRAGMENT_SHADER,
|
||||
@ -597,18 +589,6 @@ clutter_shader_compile (ClutterShader *shader,
|
||||
if (priv->compiled)
|
||||
return priv->compiled;
|
||||
|
||||
if ((priv->vertex_source != COGL_INVALID_HANDLE && !priv->vertex_is_glsl) ||
|
||||
(priv->fragment_source != COGL_INVALID_HANDLE && !priv->fragment_is_glsl))
|
||||
{
|
||||
/* XXX: Could remove this check, since we only advertise support for GLSL
|
||||
* shaders anyways. */
|
||||
g_set_error (error, CLUTTER_SHADER_ERROR,
|
||||
CLUTTER_SHADER_ERROR_NO_ASM,
|
||||
"ASM shaders not supported");
|
||||
priv->compiled = FALSE;
|
||||
return priv->compiled;
|
||||
}
|
||||
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
{
|
||||
g_set_error (error, CLUTTER_SHADER_ERROR,
|
||||
|
1
clutter/tests/interactive/.gitignore
vendored
1
clutter/tests/interactive/.gitignore
vendored
@ -12,7 +12,6 @@
|
||||
/test-cogl-offscreen
|
||||
/test-cogl-point-sprites
|
||||
/test-cogl-primitives
|
||||
/test-cogl-shader-arbfp
|
||||
/test-cogl-shader-glsl
|
||||
/test-cogl-tex-convert
|
||||
/test-cogl-tex-foreign
|
||||
|
@ -8,7 +8,6 @@ UNIT_TESTS = \
|
||||
test-shader-effects.c \
|
||||
test-script.c \
|
||||
test-grab.c \
|
||||
test-cogl-shader-arbfp.c \
|
||||
test-cogl-shader-glsl.c \
|
||||
test-animator.c \
|
||||
test-state.c \
|
||||
|
@ -1,407 +0,0 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
char *source;
|
||||
} ShaderSource;
|
||||
|
||||
static ShaderSource shaders[]=
|
||||
{
|
||||
/*{"brightness-contrast",
|
||||
FRAGMENT_SHADER_VARS
|
||||
"uniform float brightness, contrast;"
|
||||
FRAGMENT_SHADER_BEGIN
|
||||
" color.rgb = (color.rgb - vec3(0.5, 0.5, 0.5)) * contrast + "
|
||||
"vec3 (brightness + 0.5, brightness + 0.5, brightness + 0.5);"
|
||||
FRAGMENT_SHADER_END
|
||||
},*/
|
||||
{"brightness-contrast",
|
||||
"!!ARBfp1.0\n"
|
||||
"PARAM bc = program.local[0];"
|
||||
"TEMP color;"
|
||||
"TEMP color2;"
|
||||
"TEX color.rgba, fragment.texcoord[0], texture[0], 2D;"
|
||||
"SUB color.rgb, color, 0.5;"
|
||||
"MUL color2, color, bc.w;"
|
||||
"ADD color.rgb, color2, bc.z;"
|
||||
"MOV result.color, color;"
|
||||
"END"
|
||||
},
|
||||
|
||||
/*{"box-blur",
|
||||
FRAGMENT_SHADER_VARS
|
||||
|
||||
"vec4 get_rgba_rel(sampler2D tex, float dx, float dy)"
|
||||
"{"
|
||||
" return texture2D (tex, " TEX_COORD ".st "
|
||||
" + vec2(dx, dy) * 2.0);"
|
||||
"}"
|
||||
|
||||
FRAGMENT_SHADER_BEGIN
|
||||
" float count = 1.0;"
|
||||
" color += get_rgba_rel (tex, -x_step, -y_step); count++;"
|
||||
" color += get_rgba_rel (tex, -x_step, 0.0); count++;"
|
||||
" color += get_rgba_rel (tex, -x_step, y_step); count++;"
|
||||
" color += get_rgba_rel (tex, 0.0, -y_step); count++;"
|
||||
" color += get_rgba_rel (tex, 0.0, 0.0); count++;"
|
||||
" color += get_rgba_rel (tex, 0.0, y_step); count++;"
|
||||
" color += get_rgba_rel (tex, x_step, -y_step); count++;"
|
||||
" color += get_rgba_rel (tex, x_step, 0.0); count++;"
|
||||
" color += get_rgba_rel (tex, x_step, y_step); count++;"
|
||||
" color = color / count;"
|
||||
FRAGMENT_SHADER_END
|
||||
},*/
|
||||
{"box-blur",
|
||||
"!!ARBfp1.0\n"
|
||||
"PARAM params = program.local[0];"
|
||||
"TEMP accum;"
|
||||
"TEMP color;"
|
||||
"TEMP coord;"
|
||||
"TEMP step;"
|
||||
|
||||
"MUL step, params, 2.0;"
|
||||
|
||||
"SUB coord, fragment.texcoord[0], step;"
|
||||
"TEX color.rgba, coord, texture[0], 2D;"
|
||||
"MOV accum, color;"
|
||||
|
||||
"MOV coord, fragment.texcoord[0];"
|
||||
"SUB coord.x, coord.x, step.x;"
|
||||
"TEX color.rgba, coord, texture[0], 2D;"
|
||||
"ADD accum, accum, color;"
|
||||
|
||||
"MOV coord, fragment.texcoord[0];"
|
||||
"SUB coord.x, coord.x, step.x;"
|
||||
"ADD coord.y, coord.y, step.y;"
|
||||
"TEX color.rgba, coord, texture[0], 2D;"
|
||||
"ADD accum, accum, color;"
|
||||
|
||||
"MOV coord, fragment.texcoord[0];"
|
||||
"SUB coord.y, coord.y, step.y;"
|
||||
"TEX color.rgba, coord, texture[0], 2D;"
|
||||
"ADD accum, accum, color;"
|
||||
|
||||
"MOV coord, fragment.texcoord[0];"
|
||||
"TEX color.rgba, coord, texture[0], 2D;"
|
||||
"ADD accum, accum, color;"
|
||||
|
||||
"MOV coord, fragment.texcoord[0];"
|
||||
"ADD coord.y, coord.y, step.y;"
|
||||
"TEX color.rgba, coord, texture[0], 2D;"
|
||||
"ADD accum, accum, color;"
|
||||
|
||||
"MOV coord, fragment.texcoord[0];"
|
||||
"ADD coord.x, coord.x, step.x;"
|
||||
"SUB coord.y, coord.y, step.y;"
|
||||
"TEX color.rgba, coord, texture[0], 2D;"
|
||||
"ADD accum, accum, color;"
|
||||
|
||||
"MOV coord, fragment.texcoord[0];"
|
||||
"ADD coord.x, coord.x, step.x;"
|
||||
"TEX color.rgba, coord, texture[0], 2D;"
|
||||
"ADD accum, accum, color;"
|
||||
|
||||
"MOV coord, fragment.texcoord[0];"
|
||||
"ADD coord.x, coord.x, step.x;"
|
||||
"ADD coord.y, coord.y, step.y;"
|
||||
"TEX color.rgba, coord, texture[0], 2D;"
|
||||
"ADD accum, accum, color;"
|
||||
|
||||
"MUL color, accum, 0.11111111;"
|
||||
"MOV result.color, color;"
|
||||
"END"
|
||||
},
|
||||
|
||||
/*{"invert",
|
||||
FRAGMENT_SHADER_VARS
|
||||
FRAGMENT_SHADER_BEGIN
|
||||
" color.rgb = vec3(1.0, 1.0, 1.0) - color.rgb;\n"
|
||||
FRAGMENT_SHADER_END
|
||||
},*/
|
||||
{"invert",
|
||||
"!!ARBfp1.0\n"
|
||||
"TEMP color;"
|
||||
"TEX color.rgba, fragment.texcoord[0], texture[0], 2D;"
|
||||
"ADD color.rgb, 1.0, -color;"
|
||||
"MOV result.color, color;"
|
||||
"END"
|
||||
},
|
||||
|
||||
/*{"gray",
|
||||
FRAGMENT_SHADER_VARS
|
||||
FRAGMENT_SHADER_BEGIN
|
||||
" float avg = (color.r + color.g + color.b) / 3.0;"
|
||||
" color.r = avg;"
|
||||
" color.g = avg;"
|
||||
" color.b = avg;"
|
||||
FRAGMENT_SHADER_END
|
||||
},*/
|
||||
{"gray",
|
||||
"!!ARBfp1.0\n"
|
||||
"TEMP color;"
|
||||
"TEMP grey;"
|
||||
"TEX color.rgba, fragment.texcoord[0], texture[0], 2D;"
|
||||
"ADD grey, color.r, color.g;"
|
||||
"ADD grey, grey, color.b;"
|
||||
"MUL grey, grey, 0.33333333;"
|
||||
"MOV color.rgb, grey;"
|
||||
"MOV result.color, color;"
|
||||
"END"
|
||||
},
|
||||
|
||||
/* {"combined-mirror",
|
||||
FRAGMENT_SHADER_VARS
|
||||
FRAGMENT_SHADER_BEGIN
|
||||
" vec4 colorB = texture2D (tex, vec2(" TEX_COORD ".ts));"
|
||||
" float avg = (color.r + color.g + color.b) / 3.0;"
|
||||
" color.r = avg;"
|
||||
" color.g = avg;"
|
||||
" color.b = avg;"
|
||||
" color = (color + colorB)/2.0;"
|
||||
FRAGMENT_SHADER_END
|
||||
},*/
|
||||
{"combined-mirror",
|
||||
"!!ARBfp1.0\n"
|
||||
"TEMP color1;"
|
||||
"TEMP color2;"
|
||||
"TEMP coord;"
|
||||
"MOV coord.x, fragment.texcoord[0].y;"
|
||||
"MOV coord.y, fragment.texcoord[0].x;"
|
||||
"TEX color1.rgba, fragment.texcoord[0], texture[0], 2D;"
|
||||
"TEX color2.rgba, coord, texture[0], 2D;"
|
||||
"MUL color1, color1, 0.5;"
|
||||
"MUL color2, color2, 0.5;"
|
||||
"ADD result.color, color1, color2;"
|
||||
"END"
|
||||
},
|
||||
|
||||
/* {"edge-detect",
|
||||
FRAGMENT_SHADER_VARS
|
||||
"float get_avg_rel(sampler2D texB, float dx, float dy)"
|
||||
"{"
|
||||
" vec4 colorB = texture2D (texB, " TEX_COORD ".st + vec2(dx, dy));"
|
||||
" return (colorB.r + colorB.g + colorB.b) / 3.0;"
|
||||
"}"
|
||||
FRAGMENT_SHADER_BEGIN
|
||||
" mat3 sobel_h = mat3( 1.0, 2.0, 1.0,"
|
||||
" 0.0, 0.0, 0.0,"
|
||||
" -1.0, -2.0, -1.0);"
|
||||
" mat3 sobel_v = mat3( 1.0, 0.0, -1.0,"
|
||||
" 2.0, 0.0, -2.0,"
|
||||
" 1.0, 0.0, -1.0);"
|
||||
" mat3 map = mat3( get_avg_rel(tex, -x_step, -y_step),"
|
||||
" get_avg_rel(tex, -x_step, 0.0),"
|
||||
" get_avg_rel(tex, -x_step, y_step),"
|
||||
" get_avg_rel(tex, 0.0, -y_step),"
|
||||
" get_avg_rel(tex, 0.0, 0.0),"
|
||||
" get_avg_rel(tex, 0.0, y_step),"
|
||||
" get_avg_rel(tex, x_step, -y_step),"
|
||||
" get_avg_rel(tex, x_step, 0.0),"
|
||||
" get_avg_rel(tex, x_step, y_step) );"
|
||||
" mat3 gh = sobel_h * map;"
|
||||
" mat3 gv = map * sobel_v;"
|
||||
" float avgh = (gh[0][0] + gh[0][1] + gh[0][2] +"
|
||||
" gh[1][0] + gh[1][1] + gh[1][2] +"
|
||||
" gh[2][0] + gh[2][1] + gh[2][2]) / 18.0 + 0.5;"
|
||||
" float avgv = (gv[0][0] + gv[0][1] + gv[0][2] +"
|
||||
" gv[1][0] + gv[1][1] + gv[1][2] +"
|
||||
" gv[2][0] + gv[2][1] + gv[2][2]) / 18.0 + 0.5;"
|
||||
" float avg = (avgh + avgv) / 2.0;"
|
||||
" color.r = avg * color.r;"
|
||||
" color.g = avg * color.g;"
|
||||
" color.b = avg * color.b;"
|
||||
FRAGMENT_SHADER_END
|
||||
},*/
|
||||
|
||||
/* Don't really fancy doing this one in assembly :) */
|
||||
};
|
||||
|
||||
static CoglHandle redhand;
|
||||
static CoglMaterial *material;
|
||||
static unsigned int timeout_id = 0;
|
||||
static int shader_no = 0;
|
||||
|
||||
static void
|
||||
paint_cb (ClutterActor *actor)
|
||||
{
|
||||
int stage_width = clutter_actor_get_width (actor);
|
||||
int stage_height = clutter_actor_get_height (actor);
|
||||
int image_width = cogl_texture_get_width (redhand);
|
||||
int image_height = cogl_texture_get_height (redhand);
|
||||
|
||||
cogl_set_source (material);
|
||||
cogl_rectangle (stage_width/2.0f - image_width/2.0f,
|
||||
stage_height/2.0f - image_height/2.0f,
|
||||
stage_width/2.0f + image_width/2.0f,
|
||||
stage_height/2.0f + image_height/2.0f);
|
||||
}
|
||||
|
||||
static void
|
||||
set_shader_num (int new_no)
|
||||
{
|
||||
CoglHandle shader;
|
||||
CoglHandle program;
|
||||
int image_width = cogl_texture_get_width (redhand);
|
||||
int image_height = cogl_texture_get_height (redhand);
|
||||
float param0[4];
|
||||
int uniform_no;
|
||||
|
||||
g_print ("setting shaders[%i] named '%s'\n",
|
||||
new_no,
|
||||
shaders[new_no].name);
|
||||
|
||||
shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
|
||||
cogl_shader_source (shader, shaders[new_no].source);
|
||||
cogl_shader_compile (shader);
|
||||
|
||||
program = cogl_create_program ();
|
||||
cogl_program_attach_shader (program, shader);
|
||||
cogl_handle_unref (shader);
|
||||
cogl_program_link (program);
|
||||
|
||||
param0[0] = 1.0f/image_width; /* texel x step delta */
|
||||
param0[1] = 1.0f/image_height; /* texel y step delta */
|
||||
param0[2] = 0.4; /* brightness */
|
||||
param0[3] = -1.9; /* contrast */
|
||||
|
||||
uniform_no = cogl_program_get_uniform_location (program, "program.local[0]");
|
||||
cogl_program_set_uniform_float (program, uniform_no, 4, 1, param0);
|
||||
|
||||
cogl_material_set_user_program (material, program);
|
||||
cogl_handle_unref (program);
|
||||
|
||||
shader_no = new_no;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
button_release_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
void *data)
|
||||
{
|
||||
int new_no;
|
||||
|
||||
/* Stop the automatic cycling if the user want to manually control
|
||||
* which shader to display */
|
||||
if (timeout_id)
|
||||
{
|
||||
g_source_remove (timeout_id);
|
||||
timeout_id = 0;
|
||||
}
|
||||
|
||||
if (event->button.button == 1)
|
||||
{
|
||||
new_no = shader_no - 1;
|
||||
if (new_no < 0)
|
||||
new_no = G_N_ELEMENTS (shaders) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_no = shader_no + 1;
|
||||
if (new_no >= G_N_ELEMENTS (shaders))
|
||||
new_no = 0;
|
||||
}
|
||||
|
||||
set_shader_num (new_no);
|
||||
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
key_release_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
guint keysym = clutter_event_get_key_symbol (event);
|
||||
ClutterModifierType mods = clutter_event_get_state (event);
|
||||
|
||||
if (keysym == CLUTTER_KEY_q ||
|
||||
((mods & CLUTTER_SHIFT_MASK) && keysym == CLUTTER_KEY_q))
|
||||
clutter_main_quit ();
|
||||
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
timeout_cb (gpointer user_data)
|
||||
{
|
||||
shader_no++;
|
||||
if (shader_no > (G_N_ELEMENTS (shaders) - 1))
|
||||
shader_no = 0;
|
||||
|
||||
set_shader_num (shader_no);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_cb (gpointer data)
|
||||
{
|
||||
clutter_actor_queue_redraw (data);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
destroy_window_cb (ClutterStage *stage,
|
||||
ClutterEvent *event,
|
||||
void *user_data)
|
||||
{
|
||||
clutter_main_quit ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_shader_arbfp_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
char *file;
|
||||
GError *error;
|
||||
ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Assembly Shader Test");
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
|
||||
file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
||||
error = NULL;
|
||||
redhand = cogl_texture_new_from_file (file, 0, COGL_PIXEL_FORMAT_ANY,
|
||||
&error);
|
||||
if (redhand == COGL_INVALID_HANDLE)
|
||||
g_error ("image load failed: %s", error->message);
|
||||
|
||||
material = cogl_material_new ();
|
||||
cogl_material_set_layer (material, 0, redhand);
|
||||
|
||||
set_shader_num (0);
|
||||
g_signal_connect_after (stage, "paint", G_CALLBACK (paint_cb), NULL);
|
||||
|
||||
clutter_actor_set_reactive (stage, TRUE);
|
||||
g_signal_connect (stage, "button-release-event",
|
||||
G_CALLBACK (button_release_cb), NULL);
|
||||
g_signal_connect (stage, "key-release-event",
|
||||
G_CALLBACK (key_release_cb), NULL);
|
||||
|
||||
g_signal_connect (stage, "delete-event",
|
||||
G_CALLBACK (destroy_window_cb), NULL);
|
||||
|
||||
timeout_id = clutter_threads_add_timeout (1000, timeout_cb, NULL);
|
||||
|
||||
clutter_threads_add_idle (idle_cb, stage);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -171,8 +171,6 @@ cogl_driver_sources += \
|
||||
driver/gl/cogl-pipeline-opengl-private.h \
|
||||
driver/gl/cogl-pipeline-fragend-glsl.c \
|
||||
driver/gl/cogl-pipeline-fragend-glsl-private.h \
|
||||
driver/gl/gl/cogl-pipeline-fragend-arbfp.c \
|
||||
driver/gl/gl/cogl-pipeline-fragend-arbfp-private.h \
|
||||
driver/gl/cogl-pipeline-vertend-glsl.c \
|
||||
driver/gl/cogl-pipeline-vertend-glsl-private.h \
|
||||
driver/gl/cogl-pipeline-progend-glsl.c \
|
||||
|
@ -63,10 +63,6 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_COGL_GL
|
||||
#include "cogl-pipeline-fragend-arbfp-private.h"
|
||||
#endif
|
||||
|
||||
/* These aren't defined in the GLES headers */
|
||||
#ifndef GL_POINT_SPRITE
|
||||
#define GL_POINT_SPRITE 0x8861
|
||||
@ -113,12 +109,6 @@ _cogl_init_feature_overrides (CoglContext *ctx)
|
||||
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PBOS)))
|
||||
COGL_FLAGS_SET (ctx->private_features, COGL_PRIVATE_FEATURE_PBOS, FALSE);
|
||||
|
||||
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_ARBFP)))
|
||||
{
|
||||
ctx->feature_flags &= ~COGL_FEATURE_SHADERS_ARBFP;
|
||||
COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_ARBFP, FALSE);
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_GLSL)))
|
||||
{
|
||||
ctx->feature_flags &= ~COGL_FEATURE_SHADERS_GLSL;
|
||||
|
@ -201,7 +201,6 @@ cogl_is_context (void *object);
|
||||
* @COGL_FEATURE_ID_ONSCREEN_MULTIPLE: Multiple onscreen framebuffers
|
||||
* supported.
|
||||
* @COGL_FEATURE_ID_GLSL: GLSL support
|
||||
* @COGL_FEATURE_ID_ARBFP: ARBFP support
|
||||
* @COGL_FEATURE_ID_UNSIGNED_INT_INDICES: Set if
|
||||
* %COGL_INDICES_TYPE_UNSIGNED_INT is supported in
|
||||
* cogl_indices_new().
|
||||
@ -244,7 +243,6 @@ typedef enum _CoglFeatureID
|
||||
COGL_FEATURE_ID_TEXTURE_RECTANGLE,
|
||||
COGL_FEATURE_ID_TEXTURE_3D,
|
||||
COGL_FEATURE_ID_GLSL,
|
||||
COGL_FEATURE_ID_ARBFP,
|
||||
COGL_FEATURE_ID_OFFSCREEN,
|
||||
COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE,
|
||||
COGL_FEATURE_ID_ONSCREEN_MULTIPLE,
|
||||
|
@ -130,11 +130,6 @@ OPT (DISABLE_TEXTURING,
|
||||
"disable-texturing",
|
||||
N_("Disable texturing"),
|
||||
N_("Disable texturing any primitives"))
|
||||
OPT (DISABLE_ARBFP,
|
||||
N_("Root Cause"),
|
||||
"disable-arbfp",
|
||||
N_("Disable arbfp"),
|
||||
N_("Disable use of ARB fragment programs"))
|
||||
OPT (DISABLE_GLSL,
|
||||
N_("Root Cause"),
|
||||
"disable-glsl",
|
||||
@ -160,7 +155,7 @@ OPT (SHOW_SOURCE,
|
||||
N_("Cogl Tracing"),
|
||||
"show-source",
|
||||
N_("Show source"),
|
||||
N_("Show generated ARBfp/GLSL source code"))
|
||||
N_("Show generated GLSL source code"))
|
||||
OPT (OPENGL,
|
||||
N_("Cogl Tracing"),
|
||||
"opengl",
|
||||
@ -175,7 +170,7 @@ OPT (DISABLE_BLENDING,
|
||||
N_("Root Cause"),
|
||||
"disable-program-caches",
|
||||
N_("Disable program caches"),
|
||||
N_("Disable fallback caches for arbfp and glsl programs"))
|
||||
N_("Disable fallback caches for glsl programs"))
|
||||
OPT (DISABLE_FAST_READ_PIXEL,
|
||||
N_("Root Cause"),
|
||||
"disable-fast-read-pixel",
|
||||
|
@ -79,7 +79,6 @@ static const GDebugKey cogl_behavioural_debug_keys[] = {
|
||||
{ "disable-atlas", COGL_DEBUG_DISABLE_ATLAS },
|
||||
{ "disable-shared-atlas", COGL_DEBUG_DISABLE_SHARED_ATLAS },
|
||||
{ "disable-texturing", COGL_DEBUG_DISABLE_TEXTURING},
|
||||
{ "disable-arbfp", COGL_DEBUG_DISABLE_ARBFP},
|
||||
{ "disable-glsl", COGL_DEBUG_DISABLE_GLSL},
|
||||
{ "disable-blending", COGL_DEBUG_DISABLE_BLENDING},
|
||||
{ "disable-npot-textures", COGL_DEBUG_DISABLE_NPOT_TEXTURES},
|
||||
|
@ -60,7 +60,6 @@ typedef enum {
|
||||
COGL_DEBUG_DISABLE_SHARED_ATLAS,
|
||||
COGL_DEBUG_OPENGL,
|
||||
COGL_DEBUG_DISABLE_TEXTURING,
|
||||
COGL_DEBUG_DISABLE_ARBFP,
|
||||
COGL_DEBUG_DISABLE_GLSL,
|
||||
COGL_DEBUG_SHOW_SOURCE,
|
||||
COGL_DEBUG_DISABLE_BLENDING,
|
||||
|
@ -49,21 +49,7 @@
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#ifdef HAVE_COGL_GL
|
||||
|
||||
#define COGL_PIPELINE_PROGEND_GLSL 0
|
||||
#define COGL_PIPELINE_N_PROGENDS 1
|
||||
|
||||
#define COGL_PIPELINE_VERTEND_GLSL 0
|
||||
#define COGL_PIPELINE_N_VERTENDS 1
|
||||
|
||||
#define COGL_PIPELINE_FRAGEND_ARBFP 0
|
||||
#define COGL_PIPELINE_FRAGEND_GLSL 1
|
||||
#define COGL_PIPELINE_N_FRAGENDS 2
|
||||
|
||||
#else /* HAVE_COGL_GL */
|
||||
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
#if defined(HAVE_COGL_GL) || defined(HAVE_COGL_GLES2)
|
||||
|
||||
#define COGL_PIPELINE_PROGEND_GLSL 0
|
||||
#define COGL_PIPELINE_VERTEND_GLSL 0
|
||||
@ -73,13 +59,11 @@
|
||||
#define COGL_PIPELINE_N_VERTENDS 1
|
||||
#define COGL_PIPELINE_N_FRAGENDS 1
|
||||
|
||||
#else /* HAVE_COGL_GLES2 */
|
||||
#else /* defined(HAVE_COGL_GL) || defined(HAVE_COGL_GLES2) */
|
||||
|
||||
#error No drivers defined
|
||||
|
||||
#endif /* HAVE_COGL_GLES2 */
|
||||
|
||||
#endif /* HAVE_COGL_GL */
|
||||
#endif /* defined(HAVE_COGL_GL) || defined(HAVE_COGL_GLES2) */
|
||||
|
||||
#define COGL_PIPELINE_PROGEND_DEFAULT 0
|
||||
#define COGL_PIPELINE_PROGEND_UNDEFINED 3
|
||||
@ -553,7 +537,6 @@ typedef struct
|
||||
typedef enum
|
||||
{
|
||||
COGL_PIPELINE_PROGRAM_TYPE_GLSL = 1,
|
||||
COGL_PIPELINE_PROGRAM_TYPE_ARBFP,
|
||||
} CoglPipelineProgramType;
|
||||
|
||||
extern const CoglPipelineFragend *
|
||||
|
@ -71,9 +71,6 @@ _cogl_pipeline_progends[MAX (COGL_PIPELINE_N_PROGENDS, 1)];
|
||||
#ifdef COGL_PIPELINE_FRAGEND_GLSL
|
||||
#include "cogl-pipeline-fragend-glsl-private.h"
|
||||
#endif
|
||||
#ifdef COGL_PIPELINE_FRAGEND_ARBFP
|
||||
#include "cogl-pipeline-fragend-arbfp-private.h"
|
||||
#endif
|
||||
|
||||
#ifdef COGL_PIPELINE_VERTEND_GLSL
|
||||
#include "cogl-pipeline-vertend-glsl-private.h"
|
||||
@ -115,10 +112,6 @@ _cogl_pipeline_init_default_pipeline (void)
|
||||
_cogl_pipeline_fragends[COGL_PIPELINE_FRAGEND_GLSL] =
|
||||
&_cogl_pipeline_glsl_fragend;
|
||||
#endif
|
||||
#ifdef COGL_PIPELINE_FRAGEND_ARBFP
|
||||
_cogl_pipeline_fragends[COGL_PIPELINE_FRAGEND_ARBFP] =
|
||||
&_cogl_pipeline_arbfp_fragend;
|
||||
#endif
|
||||
#ifdef COGL_PIPELINE_PROGEND_GLSL
|
||||
_cogl_pipeline_progends[COGL_PIPELINE_PROGEND_GLSL] =
|
||||
&_cogl_pipeline_glsl_progend;
|
||||
|
@ -62,7 +62,6 @@ typedef enum
|
||||
COGL_PRIVATE_FEATURE_ALPHA_TEXTURES,
|
||||
COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE,
|
||||
COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL,
|
||||
COGL_PRIVATE_FEATURE_ARBFP,
|
||||
COGL_PRIVATE_FEATURE_OES_EGL_SYNC,
|
||||
/* If this is set then the winsys is responsible for queueing dirty
|
||||
* events. Otherwise a dirty event will be queued when the onscreen
|
||||
|
@ -787,8 +787,7 @@ cogl_renderer_get_n_fragment_texture_units (CoglRenderer *renderer)
|
||||
_COGL_GET_CONTEXT (ctx, 0);
|
||||
|
||||
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2)
|
||||
if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL) ||
|
||||
cogl_has_feature (ctx, COGL_FEATURE_ID_ARBFP))
|
||||
if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL))
|
||||
GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &n));
|
||||
#endif
|
||||
|
||||
|
@ -366,7 +366,6 @@ typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
|
||||
* @COGL_FEATURE_TEXTURE_YUV: ycbcr conversion support
|
||||
* @COGL_FEATURE_TEXTURE_READ_PIXELS: glReadPixels() support
|
||||
* @COGL_FEATURE_SHADERS_GLSL: GLSL support
|
||||
* @COGL_FEATURE_SHADERS_ARBFP: ARBFP support
|
||||
* @COGL_FEATURE_OFFSCREEN: FBO support
|
||||
* @COGL_FEATURE_OFFSCREEN_MULTISAMPLE: Multisample support on FBOs
|
||||
* @COGL_FEATURE_OFFSCREEN_BLIT: Blit support on FBOs
|
||||
@ -424,7 +423,6 @@ typedef enum
|
||||
COGL_FEATURE_TEXTURE_NPOT_REPEAT = (1 << 17),
|
||||
COGL_FEATURE_POINT_SPRITE = (1 << 18),
|
||||
COGL_FEATURE_TEXTURE_3D = (1 << 19),
|
||||
COGL_FEATURE_SHADERS_ARBFP = (1 << 20),
|
||||
COGL_FEATURE_MAP_BUFFER_FOR_READ = (1 << 21),
|
||||
COGL_FEATURE_MAP_BUFFER_FOR_WRITE = (1 << 22),
|
||||
COGL_FEATURE_ONSCREEN_MULTIPLE = (1 << 23),
|
||||
|
@ -112,10 +112,7 @@ cogl_program_attach_shader (CoglHandle program_handle,
|
||||
program = program_handle;
|
||||
shader = shader_handle;
|
||||
|
||||
/* Only one shader is allowed if the type is ARBfp */
|
||||
if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
|
||||
_COGL_RETURN_IF_FAIL (program->attached_shaders == NULL);
|
||||
else if (shader->language == COGL_SHADER_LANGUAGE_GLSL)
|
||||
if (shader->language == COGL_SHADER_LANGUAGE_GLSL)
|
||||
_COGL_RETURN_IF_FAIL (_cogl_program_get_language (program) ==
|
||||
COGL_SHADER_LANGUAGE_GLSL);
|
||||
|
||||
@ -346,59 +343,6 @@ cogl_program_uniform_matrix (int uniform_no,
|
||||
_cogl_boxed_value_set_matrix (&uniform->value, size, count, transpose, value);
|
||||
}
|
||||
|
||||
/* ARBfp local parameters can be referenced like:
|
||||
*
|
||||
* "program.local[5]"
|
||||
* ^14char offset (after whitespace is stripped)
|
||||
*/
|
||||
static int
|
||||
get_local_param_index (const char *uniform_name)
|
||||
{
|
||||
char *input = g_strdup (uniform_name);
|
||||
int i;
|
||||
char *p = input;
|
||||
char *endptr;
|
||||
int _index;
|
||||
|
||||
for (i = 0; input[i] != '\0'; i++)
|
||||
if (input[i] != '_' && input[i] != '\t')
|
||||
*p++ = input[i];
|
||||
input[i] = '\0';
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (strncmp ("program.local[", input, 14) == 0, -1);
|
||||
|
||||
_index = g_ascii_strtoull (input + 14, &endptr, 10);
|
||||
_COGL_RETURN_VAL_IF_FAIL (endptr != input + 14, -1);
|
||||
_COGL_RETURN_VAL_IF_FAIL (*endptr == ']', -1);
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (_index >= 0, -1);
|
||||
|
||||
g_free (input);
|
||||
|
||||
return _index;
|
||||
}
|
||||
|
||||
#ifdef HAVE_COGL_GL
|
||||
|
||||
static void
|
||||
_cogl_program_flush_uniform_arbfp (GLint location,
|
||||
CoglBoxedValue *value)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
if (value->type != COGL_BOXED_NONE)
|
||||
{
|
||||
_COGL_RETURN_IF_FAIL (value->type == COGL_BOXED_FLOAT);
|
||||
_COGL_RETURN_IF_FAIL (value->size == 4);
|
||||
_COGL_RETURN_IF_FAIL (value->count == 1);
|
||||
|
||||
GE( ctx, glProgramLocalParameter4fv (GL_FRAGMENT_PROGRAM_ARB, location,
|
||||
value->v.float_value) );
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_COGL_GL */
|
||||
|
||||
void
|
||||
_cogl_program_flush_uniforms (CoglProgram *program,
|
||||
GLuint gl_program,
|
||||
@ -422,9 +366,6 @@ _cogl_program_flush_uniforms (CoglProgram *program,
|
||||
COGL_SHADER_LANGUAGE_GLSL)
|
||||
uniform->location =
|
||||
ctx->glGetUniformLocation (gl_program, uniform->name);
|
||||
else
|
||||
uniform->location =
|
||||
get_local_param_index (uniform->name);
|
||||
|
||||
uniform->location_valid = TRUE;
|
||||
}
|
||||
@ -440,13 +381,6 @@ _cogl_program_flush_uniforms (CoglProgram *program,
|
||||
uniform->location,
|
||||
&uniform->value);
|
||||
break;
|
||||
|
||||
case COGL_SHADER_LANGUAGE_ARBFP:
|
||||
#ifdef HAVE_COGL_GL
|
||||
_cogl_program_flush_uniform_arbfp (uniform->location,
|
||||
&uniform->value);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,6 @@ typedef struct _CoglShader CoglShader;
|
||||
typedef enum
|
||||
{
|
||||
COGL_SHADER_LANGUAGE_GLSL,
|
||||
COGL_SHADER_LANGUAGE_ARBFP
|
||||
} CoglShaderLanguage;
|
||||
|
||||
struct _CoglShader
|
||||
|
@ -62,14 +62,6 @@ _cogl_shader_free (CoglShader *shader)
|
||||
released! Do that separately before this! */
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
#ifdef HAVE_COGL_GL
|
||||
if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
|
||||
{
|
||||
if (shader->gl_handle)
|
||||
GE (ctx, glDeletePrograms (1, &shader->gl_handle));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (shader->gl_handle)
|
||||
GE (ctx, glDeleteShader (shader->gl_handle));
|
||||
|
||||
@ -108,18 +100,8 @@ 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 (ctx, glDeletePrograms (1, &shader->gl_handle));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (shader->gl_handle)
|
||||
GE (ctx, glDeleteShader (shader->gl_handle));
|
||||
}
|
||||
if (shader->gl_handle)
|
||||
GE (ctx, glDeleteShader (shader->gl_handle));
|
||||
|
||||
shader->gl_handle = 0;
|
||||
|
||||
@ -143,13 +125,7 @@ cogl_shader_source (CoglHandle handle,
|
||||
return;
|
||||
|
||||
shader = handle;
|
||||
|
||||
#ifdef HAVE_COGL_GL
|
||||
if (strncmp (source, "!!ARBfp1.0", 10) == 0)
|
||||
language = COGL_SHADER_LANGUAGE_ARBFP;
|
||||
else
|
||||
#endif
|
||||
language = COGL_SHADER_LANGUAGE_GLSL;
|
||||
language = COGL_SHADER_LANGUAGE_GLSL;
|
||||
|
||||
/* Delete the old object if the language is changing... */
|
||||
if (G_UNLIKELY (language != shader->language) &&
|
||||
@ -164,19 +140,6 @@ cogl_shader_source (CoglHandle handle,
|
||||
void
|
||||
cogl_shader_compile (CoglHandle handle)
|
||||
{
|
||||
CoglShader *shader;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
if (!cogl_is_shader (handle))
|
||||
return;
|
||||
|
||||
#ifdef HAVE_COGL_GL
|
||||
shader = handle;
|
||||
if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
|
||||
_cogl_shader_compile_real (handle, NULL);
|
||||
#endif
|
||||
|
||||
/* XXX: For GLSL we don't actually compile anything until the shader
|
||||
* gets used so we have an opportunity to add some boilerplate to
|
||||
* the shader.
|
||||
@ -192,110 +155,69 @@ _cogl_shader_compile_real (CoglHandle handle,
|
||||
CoglPipeline *pipeline)
|
||||
{
|
||||
CoglShader *shader = handle;
|
||||
GLenum gl_type;
|
||||
GLint status;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
#ifdef HAVE_COGL_GL
|
||||
if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
|
||||
if (shader->gl_handle)
|
||||
{
|
||||
#ifdef COGL_GL_DEBUG
|
||||
GLenum gl_error;
|
||||
#endif
|
||||
CoglPipeline *prev = shader->compilation_pipeline;
|
||||
|
||||
if (shader->gl_handle)
|
||||
/* XXX: currently the only things that will affect the
|
||||
* boilerplate for user shaders, apart from driver features,
|
||||
* are the pipeline layer-indices and texture-unit-indices
|
||||
*/
|
||||
if (pipeline == prev ||
|
||||
_cogl_pipeline_layer_and_unit_numbers_equal (prev, pipeline))
|
||||
return;
|
||||
|
||||
GE (ctx, glGenPrograms (1, &shader->gl_handle));
|
||||
|
||||
GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB, shader->gl_handle));
|
||||
|
||||
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
|
||||
g_message ("user ARBfp program:\n%s", shader->source);
|
||||
|
||||
#ifdef COGL_GL_DEBUG
|
||||
_cogl_gl_util_clear_gl_errors (ctx);
|
||||
#endif
|
||||
ctx->glProgramString (GL_FRAGMENT_PROGRAM_ARB,
|
||||
GL_PROGRAM_FORMAT_ASCII_ARB,
|
||||
strlen (shader->source),
|
||||
shader->source);
|
||||
#ifdef COGL_GL_DEBUG
|
||||
gl_error = _cogl_gl_util_get_error (ctx);
|
||||
if (gl_error != GL_NO_ERROR)
|
||||
{
|
||||
g_warning ("%s: GL error (%d): Failed to compile ARBfp:\n%s\n%s",
|
||||
G_STRLOC,
|
||||
gl_error,
|
||||
shader->source,
|
||||
ctx->glGetString (GL_PROGRAM_ERROR_STRING_ARB));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if (shader->gl_handle)
|
||||
delete_shader (shader);
|
||||
|
||||
switch (shader->type)
|
||||
{
|
||||
GLenum gl_type;
|
||||
GLint status;
|
||||
case COGL_SHADER_TYPE_VERTEX:
|
||||
gl_type = GL_VERTEX_SHADER;
|
||||
break;
|
||||
case COGL_SHADER_TYPE_FRAGMENT:
|
||||
gl_type = GL_FRAGMENT_SHADER;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
if (shader->gl_handle)
|
||||
{
|
||||
CoglPipeline *prev = shader->compilation_pipeline;
|
||||
shader->gl_handle = ctx->glCreateShader (gl_type);
|
||||
|
||||
/* XXX: currently the only things that will affect the
|
||||
* boilerplate for user shaders, apart from driver features,
|
||||
* are the pipeline layer-indices and texture-unit-indices
|
||||
*/
|
||||
if (pipeline == prev ||
|
||||
_cogl_pipeline_layer_and_unit_numbers_equal (prev, pipeline))
|
||||
return;
|
||||
}
|
||||
_cogl_glsl_shader_set_source_with_boilerplate (ctx,
|
||||
shader->gl_handle,
|
||||
gl_type,
|
||||
pipeline,
|
||||
1,
|
||||
(const char **)
|
||||
&shader->source,
|
||||
NULL);
|
||||
|
||||
if (shader->gl_handle)
|
||||
delete_shader (shader);
|
||||
GE (ctx, glCompileShader (shader->gl_handle));
|
||||
|
||||
switch (shader->type)
|
||||
{
|
||||
case COGL_SHADER_TYPE_VERTEX:
|
||||
gl_type = GL_VERTEX_SHADER;
|
||||
break;
|
||||
case COGL_SHADER_TYPE_FRAGMENT:
|
||||
gl_type = GL_FRAGMENT_SHADER;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
shader->compilation_pipeline = cogl_object_ref (pipeline);
|
||||
|
||||
shader->gl_handle = ctx->glCreateShader (gl_type);
|
||||
GE (ctx, glGetShaderiv (shader->gl_handle, GL_COMPILE_STATUS, &status));
|
||||
if (!status)
|
||||
{
|
||||
char buffer[512];
|
||||
int len = 0;
|
||||
|
||||
_cogl_glsl_shader_set_source_with_boilerplate (ctx,
|
||||
shader->gl_handle,
|
||||
gl_type,
|
||||
pipeline,
|
||||
1,
|
||||
(const char **)
|
||||
&shader->source,
|
||||
NULL);
|
||||
ctx->glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer);
|
||||
buffer[len] = '\0';
|
||||
|
||||
GE (ctx, glCompileShader (shader->gl_handle));
|
||||
|
||||
shader->compilation_pipeline = cogl_object_ref (pipeline);
|
||||
|
||||
GE (ctx, glGetShaderiv (shader->gl_handle, GL_COMPILE_STATUS, &status));
|
||||
if (!status)
|
||||
{
|
||||
char buffer[512];
|
||||
int len = 0;
|
||||
|
||||
ctx->glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer);
|
||||
buffer[len] = '\0';
|
||||
|
||||
g_warning ("Failed to compile GLSL program:\n"
|
||||
"src:\n%s\n"
|
||||
"error:\n%s\n",
|
||||
shader->source,
|
||||
buffer);
|
||||
}
|
||||
g_warning ("Failed to compile GLSL program:\n"
|
||||
"src:\n%s\n"
|
||||
"error:\n%s\n",
|
||||
shader->source,
|
||||
buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,23 +283,11 @@ _cogl_use_fragment_program (GLuint gl_program, CoglPipelineProgramType type)
|
||||
COGL_PIPELINE_PROGRAM_TYPE_GLSL)
|
||||
set_glsl_program (0);
|
||||
break;
|
||||
|
||||
case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
|
||||
#ifdef HAVE_COGL_GL
|
||||
GE( ctx, glDisable (GL_FRAGMENT_PROGRAM_ARB) );
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
/* ... and enable the new type */
|
||||
switch (type)
|
||||
{
|
||||
case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
|
||||
#ifdef HAVE_COGL_GL
|
||||
GE( ctx, glEnable (GL_FRAGMENT_PROGRAM_ARB) );
|
||||
#endif
|
||||
break;
|
||||
|
||||
case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
|
||||
/* don't need to to anything */
|
||||
break;
|
||||
@ -317,10 +305,6 @@ _cogl_use_fragment_program (GLuint gl_program, CoglPipelineProgramType type)
|
||||
|
||||
#endif /* COGL_PIPELINE_FRAGEND_GLSL */
|
||||
}
|
||||
#ifndef COGL_PIPELINE_FRAGEND_ARBFP
|
||||
else if (type == COGL_PIPELINE_PROGRAM_TYPE_ARBFP)
|
||||
g_warning ("Unexpected use of ARBFP fragend!");
|
||||
#endif /* COGL_PIPELINE_FRAGEND_ARBFP */
|
||||
|
||||
ctx->current_fragment_program_type = type;
|
||||
}
|
||||
@ -343,21 +327,11 @@ _cogl_use_vertex_program (GLuint gl_program, CoglPipelineProgramType type)
|
||||
COGL_PIPELINE_PROGRAM_TYPE_GLSL)
|
||||
set_glsl_program (0);
|
||||
break;
|
||||
|
||||
case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
|
||||
/* It doesn't make sense to enable ARBfp for the vertex program */
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
/* ... and enable the new type */
|
||||
switch (type)
|
||||
{
|
||||
case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
|
||||
/* It doesn't make sense to enable ARBfp for the vertex program */
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
|
||||
case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
|
||||
/* don't need to to anything */
|
||||
break;
|
||||
@ -375,10 +349,6 @@ _cogl_use_vertex_program (GLuint gl_program, CoglPipelineProgramType type)
|
||||
|
||||
#endif /* COGL_PIPELINE_VERTEND_GLSL */
|
||||
}
|
||||
#ifndef COGL_PIPELINE_VERTEND_ARBFP
|
||||
else if (type == COGL_PIPELINE_PROGRAM_TYPE_ARBFP)
|
||||
g_warning ("Unexpected use of ARBFP vertend!");
|
||||
#endif /* COGL_PIPELINE_VERTEND_ARBFP */
|
||||
|
||||
ctx->current_vertex_program_type = type;
|
||||
}
|
||||
@ -720,8 +690,7 @@ get_max_activateable_texture_units (void)
|
||||
defines the number of texture coordinates that can be
|
||||
uploaded (but doesn't necessarily relate to how many texture
|
||||
images can be sampled) */
|
||||
if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL) ||
|
||||
cogl_has_feature (ctx, COGL_FEATURE_ID_ARBFP))
|
||||
if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL))
|
||||
/* Previously this code subtracted the value by one but there
|
||||
was no explanation for why it did this and it doesn't seem
|
||||
to make sense so it has been removed */
|
||||
|
@ -518,12 +518,6 @@ _cogl_driver_update_features (CoglContext *ctx,
|
||||
COGL_FLAGS_SET (private_features,
|
||||
COGL_PRIVATE_FEATURE_BLEND_CONSTANT, TRUE);
|
||||
|
||||
if (ctx->glGenPrograms)
|
||||
{
|
||||
flags |= COGL_FEATURE_SHADERS_ARBFP;
|
||||
COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_ARBFP, TRUE);
|
||||
}
|
||||
|
||||
if (ctx->glCreateProgram)
|
||||
{
|
||||
flags |= COGL_FEATURE_SHADERS_GLSL;
|
||||
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* A Low Level GPU Graphics and Utilities API
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors:
|
||||
* Robert Bragg <robert@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifndef __COGL_PIPELINE_FRAGEND_ARBFP_PRIVATE_H
|
||||
#define __COGL_PIPELINE_FRAGEND_ARBFP_PRIVATE_H
|
||||
|
||||
#include "cogl-pipeline-private.h"
|
||||
|
||||
extern const CoglPipelineFragend _cogl_pipeline_arbfp_fragend;
|
||||
|
||||
#endif /* __COGL_PIPELINE_ARBFP_PRIVATE_H */
|
||||
|
@ -1,988 +0,0 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* A Low Level GPU Graphics and Utilities API
|
||||
*
|
||||
* Copyright (C) 2008,2009,2010 Intel Corporation.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors:
|
||||
* Robert Bragg <robert@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "cogl-config.h"
|
||||
#endif
|
||||
|
||||
#include "cogl-debug.h"
|
||||
#include "cogl-context-private.h"
|
||||
#include "cogl-util-gl-private.h"
|
||||
#include "cogl-pipeline-private.h"
|
||||
#include "cogl-pipeline-state-private.h"
|
||||
#include "cogl-pipeline-layer-private.h"
|
||||
|
||||
#ifdef COGL_PIPELINE_FRAGEND_ARBFP
|
||||
|
||||
#include "cogl-context-private.h"
|
||||
#include "cogl-object-private.h"
|
||||
|
||||
#include "cogl-texture-private.h"
|
||||
#include "cogl-blend-string.h"
|
||||
#include "cogl-journal-private.h"
|
||||
#include "cogl-color-private.h"
|
||||
#include "cogl-profile.h"
|
||||
#include "cogl-program-private.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
#include <string.h>
|
||||
|
||||
/* This might not be defined on GLES */
|
||||
#ifndef GL_TEXTURE_3D
|
||||
#define GL_TEXTURE_3D 0x806F
|
||||
#endif
|
||||
|
||||
const CoglPipelineFragend _cogl_pipeline_arbfp_fragend;
|
||||
|
||||
typedef struct _UnitState
|
||||
{
|
||||
int constant_id; /* The program.local[] index */
|
||||
unsigned int dirty_combine_constant:1;
|
||||
unsigned int has_combine_constant:1;
|
||||
|
||||
unsigned int sampled:1;
|
||||
} UnitState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int ref_count;
|
||||
|
||||
CoglHandle user_program;
|
||||
/* XXX: only valid during codegen */
|
||||
GString *source;
|
||||
GLuint gl_program;
|
||||
UnitState *unit_state;
|
||||
int next_constant_id;
|
||||
|
||||
/* Age of the program the last time the uniforms were flushed. This
|
||||
is used to detect when we need to flush all of the uniforms */
|
||||
unsigned int user_program_age;
|
||||
|
||||
/* We need to track the last pipeline that an ARBfp program was used
|
||||
* with so know if we need to update any program.local parameters. */
|
||||
CoglPipeline *last_used_for_pipeline;
|
||||
|
||||
CoglPipelineCacheEntry *cache_entry;
|
||||
} CoglPipelineShaderState;
|
||||
|
||||
static CoglUserDataKey shader_state_key;
|
||||
|
||||
static CoglPipelineShaderState *
|
||||
shader_state_new (int n_layers,
|
||||
CoglPipelineCacheEntry *cache_entry)
|
||||
{
|
||||
CoglPipelineShaderState *shader_state;
|
||||
|
||||
shader_state = g_slice_new0 (CoglPipelineShaderState);
|
||||
shader_state->ref_count = 1;
|
||||
shader_state->unit_state = g_new0 (UnitState, n_layers);
|
||||
shader_state->cache_entry = cache_entry;
|
||||
|
||||
return shader_state;
|
||||
}
|
||||
|
||||
static CoglPipelineShaderState *
|
||||
get_shader_state (CoglPipeline *pipeline)
|
||||
{
|
||||
return cogl_object_get_user_data (COGL_OBJECT (pipeline), &shader_state_key);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_shader_state (void *user_data,
|
||||
void *instance)
|
||||
{
|
||||
CoglPipelineShaderState *shader_state = user_data;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* If the shader state was last used for this pipeline then clear it
|
||||
so that if same address gets used again for a new pipeline then
|
||||
we won't think it's the same pipeline and avoid updating the
|
||||
constants */
|
||||
if (shader_state->last_used_for_pipeline == instance)
|
||||
shader_state->last_used_for_pipeline = NULL;
|
||||
|
||||
if (shader_state->cache_entry &&
|
||||
shader_state->cache_entry->pipeline != instance)
|
||||
shader_state->cache_entry->usage_count--;
|
||||
|
||||
if (--shader_state->ref_count == 0)
|
||||
{
|
||||
if (shader_state->gl_program)
|
||||
{
|
||||
GE (ctx, glDeletePrograms (1, &shader_state->gl_program));
|
||||
shader_state->gl_program = 0;
|
||||
}
|
||||
|
||||
g_free (shader_state->unit_state);
|
||||
|
||||
g_slice_free (CoglPipelineShaderState, shader_state);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_shader_state (CoglPipeline *pipeline, CoglPipelineShaderState *shader_state)
|
||||
{
|
||||
if (shader_state)
|
||||
{
|
||||
shader_state->ref_count++;
|
||||
|
||||
/* If we're not setting the state on the template pipeline then
|
||||
* mark it as a usage of the pipeline cache entry */
|
||||
if (shader_state->cache_entry &&
|
||||
shader_state->cache_entry->pipeline != pipeline)
|
||||
shader_state->cache_entry->usage_count++;
|
||||
}
|
||||
|
||||
_cogl_object_set_user_data (COGL_OBJECT (pipeline),
|
||||
&shader_state_key,
|
||||
shader_state,
|
||||
destroy_shader_state);
|
||||
}
|
||||
|
||||
static void
|
||||
dirty_shader_state (CoglPipeline *pipeline)
|
||||
{
|
||||
cogl_object_set_user_data (COGL_OBJECT (pipeline),
|
||||
&shader_state_key,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline,
|
||||
int n_layers,
|
||||
unsigned long pipelines_difference)
|
||||
{
|
||||
CoglPipelineShaderState *shader_state;
|
||||
CoglPipeline *authority;
|
||||
CoglPipelineCacheEntry *cache_entry = NULL;
|
||||
CoglProgram *user_program = cogl_pipeline_get_user_program (pipeline);
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Now lookup our ARBfp backend private state */
|
||||
shader_state = get_shader_state (pipeline);
|
||||
|
||||
/* If we have a valid shader_state then we are all set and don't
|
||||
* need to generate a new program. */
|
||||
if (shader_state)
|
||||
return;
|
||||
|
||||
/* If we don't have an associated arbfp program yet then find the
|
||||
* arbfp-authority (the oldest ancestor whose state will result in
|
||||
* the same program being generated as for this pipeline).
|
||||
*
|
||||
* We always make sure to associate new programs with the
|
||||
* arbfp-authority to maximize the chance that other pipelines can
|
||||
* share it.
|
||||
*/
|
||||
authority = _cogl_pipeline_find_equivalent_parent
|
||||
(pipeline,
|
||||
_cogl_pipeline_get_state_for_fragment_codegen (ctx) &
|
||||
~COGL_PIPELINE_STATE_LAYERS,
|
||||
_cogl_pipeline_get_layer_state_for_fragment_codegen (ctx));
|
||||
shader_state = get_shader_state (authority);
|
||||
if (shader_state)
|
||||
{
|
||||
/* If we are going to share our program state with an arbfp-authority
|
||||
* then add a reference to the program state associated with that
|
||||
* arbfp-authority... */
|
||||
set_shader_state (pipeline, shader_state);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we haven't yet found an existing program then before we resort to
|
||||
* generating a new arbfp program we see if we can find a suitable
|
||||
* program in the pipeline_cache. */
|
||||
if (G_LIKELY (!(COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PROGRAM_CACHES))))
|
||||
{
|
||||
cache_entry =
|
||||
_cogl_pipeline_cache_get_fragment_template (ctx->pipeline_cache,
|
||||
authority);
|
||||
|
||||
shader_state = get_shader_state (cache_entry->pipeline);
|
||||
|
||||
if (shader_state)
|
||||
shader_state->ref_count++;
|
||||
}
|
||||
|
||||
/* If we still haven't got a shader state then we'll have to create
|
||||
a new one */
|
||||
if (shader_state == NULL)
|
||||
{
|
||||
shader_state = shader_state_new (n_layers, cache_entry);
|
||||
|
||||
shader_state->user_program = user_program;
|
||||
if (user_program == COGL_INVALID_HANDLE)
|
||||
{
|
||||
/* We reuse a single grow-only GString for code-gen */
|
||||
g_string_set_size (ctx->codegen_source_buffer, 0);
|
||||
shader_state->source = ctx->codegen_source_buffer;
|
||||
g_string_append (shader_state->source,
|
||||
"!!ARBfp1.0\n"
|
||||
"TEMP output;\n"
|
||||
"TEMP tmp0, tmp1, tmp2, tmp3, tmp4;\n"
|
||||
"PARAM half = {.5, .5, .5, .5};\n"
|
||||
"PARAM one = {1, 1, 1, 1};\n"
|
||||
"PARAM two = {2, 2, 2, 2};\n"
|
||||
"PARAM minus_one = {-1, -1, -1, -1};\n");
|
||||
}
|
||||
}
|
||||
|
||||
set_shader_state (pipeline, shader_state);
|
||||
|
||||
shader_state->ref_count--;
|
||||
|
||||
/* Since we have already resolved the arbfp-authority at this point
|
||||
* we might as well also associate any program we find from the cache
|
||||
* with the authority too... */
|
||||
if (authority != pipeline)
|
||||
set_shader_state (authority, shader_state);
|
||||
|
||||
/* If we found a template then we'll attach it to that too so that
|
||||
next time a similar pipeline is used it can use the same state */
|
||||
if (cache_entry)
|
||||
set_shader_state (cache_entry->pipeline, shader_state);
|
||||
}
|
||||
|
||||
static const char *
|
||||
texture_type_to_arbfp_string (CoglTextureType texture_type)
|
||||
{
|
||||
switch (texture_type)
|
||||
{
|
||||
#if 0 /* TODO */
|
||||
case COGL_TEXTURE_TYPE_1D:
|
||||
return "1D";
|
||||
#endif
|
||||
case COGL_TEXTURE_TYPE_2D:
|
||||
return "2D";
|
||||
case COGL_TEXTURE_TYPE_3D:
|
||||
return "3D";
|
||||
case COGL_TEXTURE_TYPE_RECTANGLE:
|
||||
return "RECT";
|
||||
}
|
||||
|
||||
g_warn_if_reached ();
|
||||
|
||||
return "2D";
|
||||
}
|
||||
|
||||
static void
|
||||
setup_texture_source (CoglPipelineShaderState *shader_state,
|
||||
int unit_index,
|
||||
CoglTextureType texture_type)
|
||||
{
|
||||
if (!shader_state->unit_state[unit_index].sampled)
|
||||
{
|
||||
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING)))
|
||||
g_string_append_printf (shader_state->source,
|
||||
"TEMP texel%d;\n"
|
||||
"MOV texel%d, one;\n",
|
||||
unit_index,
|
||||
unit_index);
|
||||
else
|
||||
g_string_append_printf (shader_state->source,
|
||||
"TEMP texel%d;\n"
|
||||
"TEX texel%d,fragment.texcoord[%d],"
|
||||
"texture[%d],%s;\n",
|
||||
unit_index,
|
||||
unit_index,
|
||||
unit_index,
|
||||
unit_index,
|
||||
texture_type_to_arbfp_string (texture_type));
|
||||
shader_state->unit_state[unit_index].sampled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum _CoglPipelineFragendARBfpArgType
|
||||
{
|
||||
COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE,
|
||||
COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT,
|
||||
COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE
|
||||
} CoglPipelineFragendARBfpArgType;
|
||||
|
||||
typedef struct _CoglPipelineFragendARBfpArg
|
||||
{
|
||||
const char *name;
|
||||
|
||||
CoglPipelineFragendARBfpArgType type;
|
||||
|
||||
/* for type = TEXTURE */
|
||||
int texture_unit;
|
||||
CoglTextureType texture_type;
|
||||
|
||||
/* for type = CONSTANT */
|
||||
int constant_id;
|
||||
|
||||
const char *swizzle;
|
||||
|
||||
} CoglPipelineFragendARBfpArg;
|
||||
|
||||
static void
|
||||
append_arg (GString *source, const CoglPipelineFragendARBfpArg *arg)
|
||||
{
|
||||
switch (arg->type)
|
||||
{
|
||||
case COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE:
|
||||
g_string_append_printf (source, "texel%d%s",
|
||||
arg->texture_unit, arg->swizzle);
|
||||
break;
|
||||
case COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT:
|
||||
g_string_append_printf (source, "program.local[%d]%s",
|
||||
arg->constant_id, arg->swizzle);
|
||||
break;
|
||||
case COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE:
|
||||
g_string_append_printf (source, "%s%s",
|
||||
arg->name, arg->swizzle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: we are trying to avoid duplicating strings during codegen
|
||||
* which is why we have the slightly awkward
|
||||
* CoglPipelineFragendARBfpArg mechanism. */
|
||||
static void
|
||||
setup_arg (CoglPipeline *pipeline,
|
||||
CoglPipelineLayer *layer,
|
||||
CoglBlendStringChannelMask mask,
|
||||
int arg_index,
|
||||
CoglPipelineCombineSource src,
|
||||
GLint op,
|
||||
CoglPipelineFragendARBfpArg *arg)
|
||||
{
|
||||
CoglPipelineShaderState *shader_state = get_shader_state (pipeline);
|
||||
static const char *tmp_name[3] = { "tmp0", "tmp1", "tmp2" };
|
||||
|
||||
switch (src)
|
||||
{
|
||||
case COGL_PIPELINE_COMBINE_SOURCE_TEXTURE:
|
||||
arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE;
|
||||
arg->name = "texel%d";
|
||||
arg->texture_unit = _cogl_pipeline_layer_get_unit_index (layer);
|
||||
setup_texture_source (shader_state,
|
||||
arg->texture_unit,
|
||||
_cogl_pipeline_layer_get_texture_type (layer));
|
||||
break;
|
||||
case COGL_PIPELINE_COMBINE_SOURCE_CONSTANT:
|
||||
{
|
||||
int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
|
||||
UnitState *unit_state = &shader_state->unit_state[unit_index];
|
||||
|
||||
unit_state->constant_id = shader_state->next_constant_id++;
|
||||
unit_state->has_combine_constant = TRUE;
|
||||
unit_state->dirty_combine_constant = TRUE;
|
||||
|
||||
arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT;
|
||||
arg->name = "program.local[%d]";
|
||||
arg->constant_id = unit_state->constant_id;
|
||||
break;
|
||||
}
|
||||
case COGL_PIPELINE_COMBINE_SOURCE_PRIMARY_COLOR:
|
||||
arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE;
|
||||
arg->name = "fragment.color.primary";
|
||||
break;
|
||||
case COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS:
|
||||
arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE;
|
||||
if (_cogl_pipeline_layer_get_unit_index (layer) == 0)
|
||||
arg->name = "fragment.color.primary";
|
||||
else
|
||||
arg->name = "output";
|
||||
break;
|
||||
default: /* Sample the texture attached to a specific layer */
|
||||
{
|
||||
int layer_num = src - COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0;
|
||||
CoglPipelineGetLayerFlags flags = COGL_PIPELINE_GET_LAYER_NO_CREATE;
|
||||
CoglPipelineLayer *other_layer =
|
||||
_cogl_pipeline_get_layer_with_flags (pipeline, layer_num, flags);
|
||||
|
||||
if (other_layer == NULL)
|
||||
{
|
||||
static CoglBool warning_seen = FALSE;
|
||||
if (!warning_seen)
|
||||
{
|
||||
g_warning ("The application is trying to use a texture "
|
||||
"combine with a layer number that does not exist");
|
||||
warning_seen = TRUE;
|
||||
}
|
||||
arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE;
|
||||
arg->name = "output";
|
||||
}
|
||||
else
|
||||
{
|
||||
CoglTextureType texture_type;
|
||||
|
||||
arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE;
|
||||
arg->name = "texture[%d]";
|
||||
arg->texture_unit =
|
||||
_cogl_pipeline_layer_get_unit_index (other_layer);
|
||||
texture_type = _cogl_pipeline_layer_get_texture_type (other_layer);
|
||||
setup_texture_source (shader_state,
|
||||
arg->texture_unit,
|
||||
texture_type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
arg->swizzle = "";
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case COGL_PIPELINE_COMBINE_OP_SRC_COLOR:
|
||||
break;
|
||||
case COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_COLOR:
|
||||
g_string_append_printf (shader_state->source,
|
||||
"SUB tmp%d, one, ",
|
||||
arg_index);
|
||||
append_arg (shader_state->source, arg);
|
||||
g_string_append_printf (shader_state->source, ";\n");
|
||||
arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE;
|
||||
arg->name = tmp_name[arg_index];
|
||||
arg->swizzle = "";
|
||||
break;
|
||||
case COGL_PIPELINE_COMBINE_OP_SRC_ALPHA:
|
||||
/* avoid a swizzle if we know RGB are going to be masked
|
||||
* in the end anyway */
|
||||
if (mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
|
||||
arg->swizzle = ".a";
|
||||
break;
|
||||
case COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_ALPHA:
|
||||
g_string_append_printf (shader_state->source,
|
||||
"SUB tmp%d, one, ",
|
||||
arg_index);
|
||||
append_arg (shader_state->source, arg);
|
||||
/* avoid a swizzle if we know RGB are going to be masked
|
||||
* in the end anyway */
|
||||
if (mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
|
||||
g_string_append_printf (shader_state->source, ".a;\n");
|
||||
else
|
||||
g_string_append_printf (shader_state->source, ";\n");
|
||||
arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE;
|
||||
arg->name = tmp_name[arg_index];
|
||||
break;
|
||||
default:
|
||||
g_error ("Unknown texture combine operator %d", op);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
fragend_arbfp_args_equal (CoglPipelineFragendARBfpArg *arg0,
|
||||
CoglPipelineFragendARBfpArg *arg1)
|
||||
{
|
||||
if (arg0->type != arg1->type)
|
||||
return FALSE;
|
||||
|
||||
if (arg0->name != arg1->name &&
|
||||
strcmp (arg0->name, arg1->name) != 0)
|
||||
return FALSE;
|
||||
|
||||
if (arg0->type == COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE &&
|
||||
arg0->texture_unit != arg1->texture_unit)
|
||||
return FALSE;
|
||||
/* Note we don't have to check the target; a texture unit can only
|
||||
* have one target enabled at a time. */
|
||||
|
||||
if (arg0->type == COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT &&
|
||||
arg0->constant_id != arg1->constant_id)
|
||||
return FALSE;
|
||||
|
||||
if (arg0->swizzle != arg1->swizzle &&
|
||||
strcmp (arg0->swizzle, arg1->swizzle) != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
append_function (CoglPipeline *pipeline,
|
||||
CoglBlendStringChannelMask mask,
|
||||
GLint function,
|
||||
CoglPipelineFragendARBfpArg *args,
|
||||
int n_args)
|
||||
{
|
||||
CoglPipelineShaderState *shader_state = get_shader_state (pipeline);
|
||||
const char *mask_name;
|
||||
|
||||
switch (mask)
|
||||
{
|
||||
case COGL_BLEND_STRING_CHANNEL_MASK_RGB:
|
||||
mask_name = ".rgb";
|
||||
break;
|
||||
case COGL_BLEND_STRING_CHANNEL_MASK_ALPHA:
|
||||
mask_name = ".a";
|
||||
break;
|
||||
case COGL_BLEND_STRING_CHANNEL_MASK_RGBA:
|
||||
mask_name = "";
|
||||
break;
|
||||
default:
|
||||
g_error ("Unknown channel mask %d", mask);
|
||||
mask_name = "";
|
||||
}
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case COGL_PIPELINE_COMBINE_FUNC_ADD:
|
||||
g_string_append_printf (shader_state->source,
|
||||
"ADD_SAT output%s, ",
|
||||
mask_name);
|
||||
break;
|
||||
case COGL_PIPELINE_COMBINE_FUNC_MODULATE:
|
||||
/* Note: no need to saturate since we can assume operands
|
||||
* have values in the range [0,1] */
|
||||
g_string_append_printf (shader_state->source, "MUL output%s, ",
|
||||
mask_name);
|
||||
break;
|
||||
case COGL_PIPELINE_COMBINE_FUNC_REPLACE:
|
||||
/* Note: no need to saturate since we can assume operand
|
||||
* has a value in the range [0,1] */
|
||||
g_string_append_printf (shader_state->source, "MOV output%s, ",
|
||||
mask_name);
|
||||
break;
|
||||
case COGL_PIPELINE_COMBINE_FUNC_SUBTRACT:
|
||||
g_string_append_printf (shader_state->source,
|
||||
"SUB_SAT output%s, ",
|
||||
mask_name);
|
||||
break;
|
||||
case COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED:
|
||||
g_string_append_printf (shader_state->source, "ADD tmp3%s, ",
|
||||
mask_name);
|
||||
append_arg (shader_state->source, &args[0]);
|
||||
g_string_append (shader_state->source, ", ");
|
||||
append_arg (shader_state->source, &args[1]);
|
||||
g_string_append (shader_state->source, ";\n");
|
||||
g_string_append_printf (shader_state->source,
|
||||
"SUB_SAT output%s, tmp3, half",
|
||||
mask_name);
|
||||
n_args = 0;
|
||||
break;
|
||||
case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGB:
|
||||
/* These functions are the same except that GL_DOT3_RGB never
|
||||
* updates the alpha channel.
|
||||
*
|
||||
* NB: GL_DOT3_RGBA is a bit special because it effectively forces
|
||||
* an RGBA mask and we end up ignoring any separate alpha channel
|
||||
* function.
|
||||
*/
|
||||
case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA:
|
||||
{
|
||||
const char *tmp4 = "tmp4";
|
||||
|
||||
/* The maths for this was taken from Mesa;
|
||||
* apparently:
|
||||
*
|
||||
* tmp3 = 2*src0 - 1
|
||||
* tmp4 = 2*src1 - 1
|
||||
* output = DP3 (tmp3, tmp4)
|
||||
*
|
||||
* is the same as:
|
||||
*
|
||||
* output = 4 * DP3 (src0 - 0.5, src1 - 0.5)
|
||||
*/
|
||||
|
||||
g_string_append (shader_state->source, "MAD tmp3, two, ");
|
||||
append_arg (shader_state->source, &args[0]);
|
||||
g_string_append (shader_state->source, ", minus_one;\n");
|
||||
|
||||
if (!fragend_arbfp_args_equal (&args[0], &args[1]))
|
||||
{
|
||||
g_string_append (shader_state->source, "MAD tmp4, two, ");
|
||||
append_arg (shader_state->source, &args[1]);
|
||||
g_string_append (shader_state->source, ", minus_one;\n");
|
||||
}
|
||||
else
|
||||
tmp4 = "tmp3";
|
||||
|
||||
g_string_append_printf (shader_state->source,
|
||||
"DP3_SAT output%s, tmp3, %s",
|
||||
mask_name, tmp4);
|
||||
n_args = 0;
|
||||
}
|
||||
break;
|
||||
case COGL_PIPELINE_COMBINE_FUNC_INTERPOLATE:
|
||||
/* Note: no need to saturate since we can assume operands
|
||||
* have values in the range [0,1] */
|
||||
|
||||
/* NB: GL_INTERPOLATE = arg0*arg2 + arg1*(1-arg2)
|
||||
* but LRP dst, a, b, c = b*a + c*(1-a) */
|
||||
g_string_append_printf (shader_state->source, "LRP output%s, ",
|
||||
mask_name);
|
||||
append_arg (shader_state->source, &args[2]);
|
||||
g_string_append (shader_state->source, ", ");
|
||||
append_arg (shader_state->source, &args[0]);
|
||||
g_string_append (shader_state->source, ", ");
|
||||
append_arg (shader_state->source, &args[1]);
|
||||
n_args = 0;
|
||||
break;
|
||||
default:
|
||||
g_error ("Unknown texture combine function %d", function);
|
||||
g_string_append_printf (shader_state->source, "MUL_SAT output%s, ",
|
||||
mask_name);
|
||||
n_args = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (n_args > 0)
|
||||
append_arg (shader_state->source, &args[0]);
|
||||
if (n_args > 1)
|
||||
{
|
||||
g_string_append (shader_state->source, ", ");
|
||||
append_arg (shader_state->source, &args[1]);
|
||||
}
|
||||
g_string_append (shader_state->source, ";\n");
|
||||
}
|
||||
|
||||
static void
|
||||
append_masked_combine (CoglPipeline *arbfp_authority,
|
||||
CoglPipelineLayer *layer,
|
||||
CoglBlendStringChannelMask mask,
|
||||
CoglPipelineCombineFunc function,
|
||||
CoglPipelineCombineSource *src,
|
||||
CoglPipelineCombineOp *op)
|
||||
{
|
||||
int i;
|
||||
int n_args;
|
||||
CoglPipelineFragendARBfpArg args[3];
|
||||
|
||||
n_args = _cogl_get_n_args_for_combine_func (function);
|
||||
|
||||
for (i = 0; i < n_args; i++)
|
||||
{
|
||||
setup_arg (arbfp_authority,
|
||||
layer,
|
||||
mask,
|
||||
i,
|
||||
src[i],
|
||||
op[i],
|
||||
&args[i]);
|
||||
}
|
||||
|
||||
append_function (arbfp_authority,
|
||||
mask,
|
||||
function,
|
||||
args,
|
||||
n_args);
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
_cogl_pipeline_fragend_arbfp_add_layer (CoglPipeline *pipeline,
|
||||
CoglPipelineLayer *layer,
|
||||
unsigned long layers_difference)
|
||||
{
|
||||
CoglPipelineShaderState *shader_state = get_shader_state (pipeline);
|
||||
CoglPipelineLayer *combine_authority =
|
||||
_cogl_pipeline_layer_get_authority (layer,
|
||||
COGL_PIPELINE_LAYER_STATE_COMBINE);
|
||||
CoglPipelineLayerBigState *big_state = combine_authority->big_state;
|
||||
|
||||
/* Notes...
|
||||
*
|
||||
* We are ignoring the issue of texture indirection limits until
|
||||
* someone complains (Ref Section 3.11.6 in the ARB_fragment_program
|
||||
* spec)
|
||||
*
|
||||
* There always five TEMPs named tmp0, tmp1 and tmp2, tmp3 and tmp4
|
||||
* available and these constants: 'one' = {1, 1, 1, 1}, 'half'
|
||||
* {.5, .5, .5, .5}, 'two' = {2, 2, 2, 2}, 'minus_one' = {-1, -1,
|
||||
* -1, -1}
|
||||
*
|
||||
* tmp0-2 are intended for dealing with some of the texture combine
|
||||
* operands (e.g. GL_ONE_MINUS_SRC_COLOR) tmp3/4 are for dealing
|
||||
* with the GL_ADD_SIGNED texture combine and the GL_DOT3_RGB[A]
|
||||
* functions.
|
||||
*
|
||||
* Each layer outputs to the TEMP called "output", and reads from
|
||||
* output if it needs to refer to GL_PREVIOUS. (we detect if we are
|
||||
* layer0 so we will read fragment.color for GL_PREVIOUS in that
|
||||
* case)
|
||||
*
|
||||
* We aim to do all the channels together if the same function is
|
||||
* used for RGB as for A.
|
||||
*
|
||||
* We aim to avoid string duplication / allocations during codegen.
|
||||
*
|
||||
* We are careful to only saturate when writing to output.
|
||||
*/
|
||||
|
||||
if (!shader_state->source)
|
||||
return TRUE;
|
||||
|
||||
if (!_cogl_pipeline_layer_needs_combine_separate (combine_authority))
|
||||
{
|
||||
append_masked_combine (pipeline,
|
||||
layer,
|
||||
COGL_BLEND_STRING_CHANNEL_MASK_RGBA,
|
||||
big_state->texture_combine_rgb_func,
|
||||
big_state->texture_combine_rgb_src,
|
||||
big_state->texture_combine_rgb_op);
|
||||
}
|
||||
else if (big_state->texture_combine_rgb_func ==
|
||||
COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA)
|
||||
{
|
||||
/* GL_DOT3_RGBA Is a bit weird as a GL_COMBINE_RGB function
|
||||
* since if you use it, it overrides your ALPHA function...
|
||||
*/
|
||||
append_masked_combine (pipeline,
|
||||
layer,
|
||||
COGL_BLEND_STRING_CHANNEL_MASK_RGBA,
|
||||
big_state->texture_combine_rgb_func,
|
||||
big_state->texture_combine_rgb_src,
|
||||
big_state->texture_combine_rgb_op);
|
||||
}
|
||||
else
|
||||
{
|
||||
append_masked_combine (pipeline,
|
||||
layer,
|
||||
COGL_BLEND_STRING_CHANNEL_MASK_RGB,
|
||||
big_state->texture_combine_rgb_func,
|
||||
big_state->texture_combine_rgb_src,
|
||||
big_state->texture_combine_rgb_op);
|
||||
append_masked_combine (pipeline,
|
||||
layer,
|
||||
COGL_BLEND_STRING_CHANNEL_MASK_ALPHA,
|
||||
big_state->texture_combine_alpha_func,
|
||||
big_state->texture_combine_alpha_src,
|
||||
big_state->texture_combine_alpha_op);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
_cogl_pipeline_fragend_arbfp_passthrough (CoglPipeline *pipeline)
|
||||
{
|
||||
CoglPipelineShaderState *shader_state = get_shader_state (pipeline);
|
||||
|
||||
if (!shader_state->source)
|
||||
return TRUE;
|
||||
|
||||
g_string_append (shader_state->source,
|
||||
"MOV output, fragment.color.primary;\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct _UpdateConstantsState
|
||||
{
|
||||
int unit;
|
||||
CoglBool update_all;
|
||||
CoglPipelineShaderState *shader_state;
|
||||
} UpdateConstantsState;
|
||||
|
||||
static CoglBool
|
||||
update_constants_cb (CoglPipeline *pipeline,
|
||||
int layer_index,
|
||||
void *user_data)
|
||||
{
|
||||
UpdateConstantsState *state = user_data;
|
||||
CoglPipelineShaderState *shader_state = state->shader_state;
|
||||
UnitState *unit_state = &shader_state->unit_state[state->unit++];
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
if (unit_state->has_combine_constant &&
|
||||
(state->update_all || unit_state->dirty_combine_constant))
|
||||
{
|
||||
float constant[4];
|
||||
_cogl_pipeline_get_layer_combine_constant (pipeline,
|
||||
layer_index,
|
||||
constant);
|
||||
GE (ctx, glProgramLocalParameter4fv (GL_FRAGMENT_PROGRAM_ARB,
|
||||
unit_state->constant_id,
|
||||
constant));
|
||||
unit_state->dirty_combine_constant = FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
_cogl_pipeline_fragend_arbfp_end (CoglPipeline *pipeline,
|
||||
unsigned long pipelines_difference)
|
||||
{
|
||||
CoglPipelineShaderState *shader_state = get_shader_state (pipeline);
|
||||
GLuint gl_program;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
if (shader_state->source)
|
||||
{
|
||||
COGL_STATIC_COUNTER (fragend_arbfp_compile_counter,
|
||||
"arbfp compile counter",
|
||||
"Increments each time a new ARBfp "
|
||||
"program is compiled",
|
||||
0 /* no application private data */);
|
||||
|
||||
COGL_COUNTER_INC (_cogl_uprof_context, fragend_arbfp_compile_counter);
|
||||
|
||||
g_string_append (shader_state->source,
|
||||
"MOV result.color,output;\n");
|
||||
g_string_append (shader_state->source, "END\n");
|
||||
|
||||
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
|
||||
g_message ("pipeline program:\n%s", shader_state->source->str);
|
||||
|
||||
GE (ctx, glGenPrograms (1, &shader_state->gl_program));
|
||||
|
||||
GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB,
|
||||
shader_state->gl_program));
|
||||
_cogl_gl_util_clear_gl_errors (ctx);
|
||||
|
||||
ctx->glProgramString (GL_FRAGMENT_PROGRAM_ARB,
|
||||
GL_PROGRAM_FORMAT_ASCII_ARB,
|
||||
shader_state->source->len,
|
||||
shader_state->source->str);
|
||||
if (_cogl_gl_util_get_error (ctx) != GL_NO_ERROR)
|
||||
{
|
||||
g_warning ("\n%s\n%s",
|
||||
shader_state->source->str,
|
||||
ctx->glGetString (GL_PROGRAM_ERROR_STRING_ARB));
|
||||
}
|
||||
|
||||
shader_state->source = NULL;
|
||||
}
|
||||
|
||||
if (shader_state->user_program != COGL_INVALID_HANDLE)
|
||||
{
|
||||
/* An arbfp program should contain exactly one shader which we
|
||||
can use directly */
|
||||
CoglProgram *program = shader_state->user_program;
|
||||
CoglShader *shader = program->attached_shaders->data;
|
||||
|
||||
gl_program = shader->gl_handle;
|
||||
}
|
||||
else
|
||||
gl_program = shader_state->gl_program;
|
||||
|
||||
GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB, gl_program));
|
||||
_cogl_use_fragment_program (0, COGL_PIPELINE_PROGRAM_TYPE_ARBFP);
|
||||
|
||||
if (shader_state->user_program == COGL_INVALID_HANDLE)
|
||||
{
|
||||
UpdateConstantsState state;
|
||||
state.unit = 0;
|
||||
state.shader_state = shader_state;
|
||||
/* If this arbfp program was last used with a different pipeline
|
||||
* then we need to ensure we update all program.local params */
|
||||
state.update_all =
|
||||
pipeline != shader_state->last_used_for_pipeline;
|
||||
cogl_pipeline_foreach_layer (pipeline,
|
||||
update_constants_cb,
|
||||
&state);
|
||||
}
|
||||
else
|
||||
{
|
||||
CoglProgram *program = shader_state->user_program;
|
||||
CoglBool program_changed;
|
||||
|
||||
/* If the shader has changed since it was last flushed then we
|
||||
need to update all uniforms */
|
||||
program_changed = program->age != shader_state->user_program_age;
|
||||
|
||||
_cogl_program_flush_uniforms (program, gl_program, program_changed);
|
||||
|
||||
shader_state->user_program_age = program->age;
|
||||
}
|
||||
|
||||
/* We need to track what pipeline used this arbfp program last since
|
||||
* we will need to update program.local params when switching
|
||||
* between different pipelines. */
|
||||
shader_state->last_used_for_pipeline = pipeline;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_pipeline_fragend_arbfp_pipeline_pre_change_notify (
|
||||
CoglPipeline *pipeline,
|
||||
CoglPipelineState change,
|
||||
const CoglColor *new_color)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx)))
|
||||
dirty_shader_state (pipeline);
|
||||
}
|
||||
|
||||
/* NB: layers are considered immutable once they have any dependants
|
||||
* so although multiple pipelines can end up depending on a single
|
||||
* static layer, we can guarantee that if a layer is being *changed*
|
||||
* then it can only have one pipeline depending on it.
|
||||
*
|
||||
* XXX: Don't forget this is *pre* change, we can't read the new value
|
||||
* yet!
|
||||
*/
|
||||
static void
|
||||
_cogl_pipeline_fragend_arbfp_layer_pre_change_notify (
|
||||
CoglPipeline *owner,
|
||||
CoglPipelineLayer *layer,
|
||||
CoglPipelineLayerState change)
|
||||
{
|
||||
CoglPipelineShaderState *shader_state = get_shader_state (owner);
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
if (!shader_state)
|
||||
return;
|
||||
|
||||
if ((change & _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx)))
|
||||
{
|
||||
dirty_shader_state (owner);
|
||||
return;
|
||||
}
|
||||
|
||||
if (change & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT)
|
||||
{
|
||||
int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
|
||||
shader_state->unit_state[unit_index].dirty_combine_constant = TRUE;
|
||||
}
|
||||
|
||||
/* TODO: we could be saving snippets of texture combine code along
|
||||
* with each layer and then when a layer changes we would just free
|
||||
* the snippet. */
|
||||
return;
|
||||
}
|
||||
|
||||
const CoglPipelineFragend _cogl_pipeline_arbfp_fragend =
|
||||
{
|
||||
_cogl_pipeline_fragend_arbfp_start,
|
||||
_cogl_pipeline_fragend_arbfp_add_layer,
|
||||
_cogl_pipeline_fragend_arbfp_passthrough,
|
||||
_cogl_pipeline_fragend_arbfp_end,
|
||||
_cogl_pipeline_fragend_arbfp_pipeline_pre_change_notify,
|
||||
NULL,
|
||||
_cogl_pipeline_fragend_arbfp_layer_pre_change_notify
|
||||
};
|
||||
|
||||
#endif /* COGL_PIPELINE_FRAGEND_ARBFP */
|
||||
|
@ -148,31 +148,6 @@ COGL_EXT_FUNCTION (void, glBlitFramebuffer,
|
||||
GLenum filter))
|
||||
COGL_EXT_END ()
|
||||
|
||||
/* ARB_fragment_program */
|
||||
COGL_EXT_BEGIN (arbfp, 255, 255,
|
||||
0, /* not in either GLES */
|
||||
"ARB\0",
|
||||
"fragment_program\0")
|
||||
COGL_EXT_FUNCTION (void, glGenPrograms,
|
||||
(GLsizei n,
|
||||
GLuint *programs))
|
||||
COGL_EXT_FUNCTION (void, glDeletePrograms,
|
||||
(GLsizei n,
|
||||
GLuint *programs))
|
||||
COGL_EXT_FUNCTION (void, glBindProgram,
|
||||
(GLenum target,
|
||||
GLuint program))
|
||||
COGL_EXT_FUNCTION (void, glProgramString,
|
||||
(GLenum target,
|
||||
GLenum format,
|
||||
GLsizei len,
|
||||
const void *program))
|
||||
COGL_EXT_FUNCTION (void, glProgramLocalParameter4fv,
|
||||
(GLenum target,
|
||||
GLuint index,
|
||||
GLfloat *params))
|
||||
COGL_EXT_END ()
|
||||
|
||||
COGL_EXT_BEGIN (EGL_image, 255, 255,
|
||||
0, /* not in either GLES */
|
||||
"OES\0",
|
||||
|
@ -88,7 +88,7 @@ printf $TITLE_FORMAT "Test"
|
||||
|
||||
if test $HAVE_GL -eq 1; then
|
||||
GL_FORMAT=" %6s %8s %7s %6s %6s"
|
||||
printf "$GL_FORMAT" GL+ARBFP" "GL+GLSL" "GL-NPT" "GL3"
|
||||
printf "$GL_FORMAT" "GL+GLSL" "GL-NPT" "GL3"
|
||||
fi
|
||||
if test $HAVE_GLES2 -eq 1; then
|
||||
GLES2_FORMAT=" %6s %7s"
|
||||
@ -136,7 +136,6 @@ do
|
||||
printf $TITLE_FORMAT "$test:"
|
||||
if test $HAVE_GL -eq 1; then
|
||||
printf "$GL_FORMAT" \
|
||||
"`get_status $gl_arbfp_result`" \
|
||||
"`get_status $gl_glsl_result`" \
|
||||
"`get_status $gl_npot_result`" \
|
||||
"`get_status $gl3_result`"
|
||||
|
Loading…
Reference in New Issue
Block a user