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:
Jonas Ådahl 2018-05-17 13:45:16 +02:00
parent 8f58ad02fb
commit 97004e6114
24 changed files with 65 additions and 1781 deletions

View File

@ -70,8 +70,6 @@ struct _ClutterShaderPrivate
{ {
guint compiled : 1; /* Shader is bound to the GL context */ guint compiled : 1; /* Shader is bound to the GL context */
guint is_enabled : 1; guint is_enabled : 1;
guint vertex_is_glsl : 1;
guint fragment_is_glsl : 1;
gchar *vertex_source; /* GLSL source for vertex shader */ gchar *vertex_source; /* GLSL source for vertex shader */
gchar *fragment_source; /* GLSL source for fragment 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); 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); 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); cogl_handle_unref (priv->fragment_shader);
if (priv->program != COGL_INVALID_HANDLE) if (priv->program != COGL_INVALID_HANDLE)
@ -350,7 +348,6 @@ clutter_shader_set_source (ClutterShader *shader,
gssize length) gssize length)
{ {
ClutterShaderPrivate *priv = shader->priv; ClutterShaderPrivate *priv = shader->priv;
gboolean is_glsl = FALSE;
if (length < 0) if (length < 0)
length = strlen (data); length = strlen (data);
@ -363,12 +360,9 @@ clutter_shader_set_source (ClutterShader *shader,
if (clutter_shader_is_compiled (shader)) if (clutter_shader_is_compiled (shader))
clutter_shader_release (shader); clutter_shader_release (shader);
is_glsl = !g_str_has_prefix (data, "!!ARBfp");
CLUTTER_NOTE (SHADER, 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", shader_type == CLUTTER_VERTEX_SHADER ? "vertex" : "fragment",
is_glsl ? "yes" : "no",
length); length);
switch (shader_type) switch (shader_type)
@ -377,7 +371,6 @@ clutter_shader_set_source (ClutterShader *shader,
g_free (priv->fragment_source); g_free (priv->fragment_source);
priv->fragment_source = g_strndup (data, length); 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]); g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_FRAGMENT_SOURCE]);
break; break;
@ -385,7 +378,6 @@ clutter_shader_set_source (ClutterShader *shader,
g_free (priv->vertex_source); g_free (priv->vertex_source);
priv->vertex_source = g_strndup (data, length); 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]); g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_VERTEX_SOURCE]);
break; break;
} }
@ -538,7 +530,7 @@ bind_glsl_shader (ClutterShader *self,
priv->program = cogl_create_program (); 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, res = clutter_shader_glsl_bind (self,
CLUTTER_VERTEX_SHADER, 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, res = clutter_shader_glsl_bind (self,
CLUTTER_FRAGMENT_SHADER, CLUTTER_FRAGMENT_SHADER,
@ -597,18 +589,6 @@ clutter_shader_compile (ClutterShader *shader,
if (priv->compiled) if (priv->compiled)
return 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)) if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
{ {
g_set_error (error, CLUTTER_SHADER_ERROR, g_set_error (error, CLUTTER_SHADER_ERROR,

View File

@ -12,7 +12,6 @@
/test-cogl-offscreen /test-cogl-offscreen
/test-cogl-point-sprites /test-cogl-point-sprites
/test-cogl-primitives /test-cogl-primitives
/test-cogl-shader-arbfp
/test-cogl-shader-glsl /test-cogl-shader-glsl
/test-cogl-tex-convert /test-cogl-tex-convert
/test-cogl-tex-foreign /test-cogl-tex-foreign

View File

@ -8,7 +8,6 @@ UNIT_TESTS = \
test-shader-effects.c \ test-shader-effects.c \
test-script.c \ test-script.c \
test-grab.c \ test-grab.c \
test-cogl-shader-arbfp.c \
test-cogl-shader-glsl.c \ test-cogl-shader-glsl.c \
test-animator.c \ test-animator.c \
test-state.c \ test-state.c \

View File

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

View File

@ -171,8 +171,6 @@ cogl_driver_sources += \
driver/gl/cogl-pipeline-opengl-private.h \ driver/gl/cogl-pipeline-opengl-private.h \
driver/gl/cogl-pipeline-fragend-glsl.c \ driver/gl/cogl-pipeline-fragend-glsl.c \
driver/gl/cogl-pipeline-fragend-glsl-private.h \ 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.c \
driver/gl/cogl-pipeline-vertend-glsl-private.h \ driver/gl/cogl-pipeline-vertend-glsl-private.h \
driver/gl/cogl-pipeline-progend-glsl.c \ driver/gl/cogl-pipeline-progend-glsl.c \

View File

@ -63,10 +63,6 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_COGL_GL
#include "cogl-pipeline-fragend-arbfp-private.h"
#endif
/* These aren't defined in the GLES headers */ /* These aren't defined in the GLES headers */
#ifndef GL_POINT_SPRITE #ifndef GL_POINT_SPRITE
#define GL_POINT_SPRITE 0x8861 #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))) if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PBOS)))
COGL_FLAGS_SET (ctx->private_features, COGL_PRIVATE_FEATURE_PBOS, FALSE); 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))) if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_GLSL)))
{ {
ctx->feature_flags &= ~COGL_FEATURE_SHADERS_GLSL; ctx->feature_flags &= ~COGL_FEATURE_SHADERS_GLSL;

View File

@ -201,7 +201,6 @@ cogl_is_context (void *object);
* @COGL_FEATURE_ID_ONSCREEN_MULTIPLE: Multiple onscreen framebuffers * @COGL_FEATURE_ID_ONSCREEN_MULTIPLE: Multiple onscreen framebuffers
* supported. * supported.
* @COGL_FEATURE_ID_GLSL: GLSL support * @COGL_FEATURE_ID_GLSL: GLSL support
* @COGL_FEATURE_ID_ARBFP: ARBFP support
* @COGL_FEATURE_ID_UNSIGNED_INT_INDICES: Set if * @COGL_FEATURE_ID_UNSIGNED_INT_INDICES: Set if
* %COGL_INDICES_TYPE_UNSIGNED_INT is supported in * %COGL_INDICES_TYPE_UNSIGNED_INT is supported in
* cogl_indices_new(). * cogl_indices_new().
@ -244,7 +243,6 @@ typedef enum _CoglFeatureID
COGL_FEATURE_ID_TEXTURE_RECTANGLE, COGL_FEATURE_ID_TEXTURE_RECTANGLE,
COGL_FEATURE_ID_TEXTURE_3D, COGL_FEATURE_ID_TEXTURE_3D,
COGL_FEATURE_ID_GLSL, COGL_FEATURE_ID_GLSL,
COGL_FEATURE_ID_ARBFP,
COGL_FEATURE_ID_OFFSCREEN, COGL_FEATURE_ID_OFFSCREEN,
COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE, COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE,
COGL_FEATURE_ID_ONSCREEN_MULTIPLE, COGL_FEATURE_ID_ONSCREEN_MULTIPLE,

View File

@ -130,11 +130,6 @@ OPT (DISABLE_TEXTURING,
"disable-texturing", "disable-texturing",
N_("Disable texturing"), N_("Disable texturing"),
N_("Disable texturing any primitives")) 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, OPT (DISABLE_GLSL,
N_("Root Cause"), N_("Root Cause"),
"disable-glsl", "disable-glsl",
@ -160,7 +155,7 @@ OPT (SHOW_SOURCE,
N_("Cogl Tracing"), N_("Cogl Tracing"),
"show-source", "show-source",
N_("Show source"), N_("Show source"),
N_("Show generated ARBfp/GLSL source code")) N_("Show generated GLSL source code"))
OPT (OPENGL, OPT (OPENGL,
N_("Cogl Tracing"), N_("Cogl Tracing"),
"opengl", "opengl",
@ -175,7 +170,7 @@ OPT (DISABLE_BLENDING,
N_("Root Cause"), N_("Root Cause"),
"disable-program-caches", "disable-program-caches",
N_("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, OPT (DISABLE_FAST_READ_PIXEL,
N_("Root Cause"), N_("Root Cause"),
"disable-fast-read-pixel", "disable-fast-read-pixel",

View File

@ -79,7 +79,6 @@ static const GDebugKey cogl_behavioural_debug_keys[] = {
{ "disable-atlas", COGL_DEBUG_DISABLE_ATLAS }, { "disable-atlas", COGL_DEBUG_DISABLE_ATLAS },
{ "disable-shared-atlas", COGL_DEBUG_DISABLE_SHARED_ATLAS }, { "disable-shared-atlas", COGL_DEBUG_DISABLE_SHARED_ATLAS },
{ "disable-texturing", COGL_DEBUG_DISABLE_TEXTURING}, { "disable-texturing", COGL_DEBUG_DISABLE_TEXTURING},
{ "disable-arbfp", COGL_DEBUG_DISABLE_ARBFP},
{ "disable-glsl", COGL_DEBUG_DISABLE_GLSL}, { "disable-glsl", COGL_DEBUG_DISABLE_GLSL},
{ "disable-blending", COGL_DEBUG_DISABLE_BLENDING}, { "disable-blending", COGL_DEBUG_DISABLE_BLENDING},
{ "disable-npot-textures", COGL_DEBUG_DISABLE_NPOT_TEXTURES}, { "disable-npot-textures", COGL_DEBUG_DISABLE_NPOT_TEXTURES},

View File

@ -60,7 +60,6 @@ typedef enum {
COGL_DEBUG_DISABLE_SHARED_ATLAS, COGL_DEBUG_DISABLE_SHARED_ATLAS,
COGL_DEBUG_OPENGL, COGL_DEBUG_OPENGL,
COGL_DEBUG_DISABLE_TEXTURING, COGL_DEBUG_DISABLE_TEXTURING,
COGL_DEBUG_DISABLE_ARBFP,
COGL_DEBUG_DISABLE_GLSL, COGL_DEBUG_DISABLE_GLSL,
COGL_DEBUG_SHOW_SOURCE, COGL_DEBUG_SHOW_SOURCE,
COGL_DEBUG_DISABLE_BLENDING, COGL_DEBUG_DISABLE_BLENDING,

View File

@ -49,21 +49,7 @@
#include <glib.h> #include <glib.h>
#ifdef HAVE_COGL_GL #if defined(HAVE_COGL_GL) || defined(HAVE_COGL_GLES2)
#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
#define COGL_PIPELINE_PROGEND_GLSL 0 #define COGL_PIPELINE_PROGEND_GLSL 0
#define COGL_PIPELINE_VERTEND_GLSL 0 #define COGL_PIPELINE_VERTEND_GLSL 0
@ -73,13 +59,11 @@
#define COGL_PIPELINE_N_VERTENDS 1 #define COGL_PIPELINE_N_VERTENDS 1
#define COGL_PIPELINE_N_FRAGENDS 1 #define COGL_PIPELINE_N_FRAGENDS 1
#else /* HAVE_COGL_GLES2 */ #else /* defined(HAVE_COGL_GL) || defined(HAVE_COGL_GLES2) */
#error No drivers defined #error No drivers defined
#endif /* HAVE_COGL_GLES2 */ #endif /* defined(HAVE_COGL_GL) || defined(HAVE_COGL_GLES2) */
#endif /* HAVE_COGL_GL */
#define COGL_PIPELINE_PROGEND_DEFAULT 0 #define COGL_PIPELINE_PROGEND_DEFAULT 0
#define COGL_PIPELINE_PROGEND_UNDEFINED 3 #define COGL_PIPELINE_PROGEND_UNDEFINED 3
@ -553,7 +537,6 @@ typedef struct
typedef enum typedef enum
{ {
COGL_PIPELINE_PROGRAM_TYPE_GLSL = 1, COGL_PIPELINE_PROGRAM_TYPE_GLSL = 1,
COGL_PIPELINE_PROGRAM_TYPE_ARBFP,
} CoglPipelineProgramType; } CoglPipelineProgramType;
extern const CoglPipelineFragend * extern const CoglPipelineFragend *

View File

@ -71,9 +71,6 @@ _cogl_pipeline_progends[MAX (COGL_PIPELINE_N_PROGENDS, 1)];
#ifdef COGL_PIPELINE_FRAGEND_GLSL #ifdef COGL_PIPELINE_FRAGEND_GLSL
#include "cogl-pipeline-fragend-glsl-private.h" #include "cogl-pipeline-fragend-glsl-private.h"
#endif #endif
#ifdef COGL_PIPELINE_FRAGEND_ARBFP
#include "cogl-pipeline-fragend-arbfp-private.h"
#endif
#ifdef COGL_PIPELINE_VERTEND_GLSL #ifdef COGL_PIPELINE_VERTEND_GLSL
#include "cogl-pipeline-vertend-glsl-private.h" #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_fragends[COGL_PIPELINE_FRAGEND_GLSL] =
&_cogl_pipeline_glsl_fragend; &_cogl_pipeline_glsl_fragend;
#endif #endif
#ifdef COGL_PIPELINE_FRAGEND_ARBFP
_cogl_pipeline_fragends[COGL_PIPELINE_FRAGEND_ARBFP] =
&_cogl_pipeline_arbfp_fragend;
#endif
#ifdef COGL_PIPELINE_PROGEND_GLSL #ifdef COGL_PIPELINE_PROGEND_GLSL
_cogl_pipeline_progends[COGL_PIPELINE_PROGEND_GLSL] = _cogl_pipeline_progends[COGL_PIPELINE_PROGEND_GLSL] =
&_cogl_pipeline_glsl_progend; &_cogl_pipeline_glsl_progend;

View File

@ -62,7 +62,6 @@ typedef enum
COGL_PRIVATE_FEATURE_ALPHA_TEXTURES, COGL_PRIVATE_FEATURE_ALPHA_TEXTURES,
COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE, COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE,
COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL, COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL,
COGL_PRIVATE_FEATURE_ARBFP,
COGL_PRIVATE_FEATURE_OES_EGL_SYNC, COGL_PRIVATE_FEATURE_OES_EGL_SYNC,
/* If this is set then the winsys is responsible for queueing dirty /* If this is set then the winsys is responsible for queueing dirty
* events. Otherwise a dirty event will be queued when the onscreen * events. Otherwise a dirty event will be queued when the onscreen

View File

@ -787,8 +787,7 @@ cogl_renderer_get_n_fragment_texture_units (CoglRenderer *renderer)
_COGL_GET_CONTEXT (ctx, 0); _COGL_GET_CONTEXT (ctx, 0);
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2) #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2)
if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL) || if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL))
cogl_has_feature (ctx, COGL_FEATURE_ID_ARBFP))
GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &n)); GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &n));
#endif #endif

View File

@ -366,7 +366,6 @@ typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
* @COGL_FEATURE_TEXTURE_YUV: ycbcr conversion support * @COGL_FEATURE_TEXTURE_YUV: ycbcr conversion support
* @COGL_FEATURE_TEXTURE_READ_PIXELS: glReadPixels() support * @COGL_FEATURE_TEXTURE_READ_PIXELS: glReadPixels() support
* @COGL_FEATURE_SHADERS_GLSL: GLSL support * @COGL_FEATURE_SHADERS_GLSL: GLSL support
* @COGL_FEATURE_SHADERS_ARBFP: ARBFP support
* @COGL_FEATURE_OFFSCREEN: FBO support * @COGL_FEATURE_OFFSCREEN: FBO support
* @COGL_FEATURE_OFFSCREEN_MULTISAMPLE: Multisample support on FBOs * @COGL_FEATURE_OFFSCREEN_MULTISAMPLE: Multisample support on FBOs
* @COGL_FEATURE_OFFSCREEN_BLIT: Blit 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_TEXTURE_NPOT_REPEAT = (1 << 17),
COGL_FEATURE_POINT_SPRITE = (1 << 18), COGL_FEATURE_POINT_SPRITE = (1 << 18),
COGL_FEATURE_TEXTURE_3D = (1 << 19), 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_READ = (1 << 21),
COGL_FEATURE_MAP_BUFFER_FOR_WRITE = (1 << 22), COGL_FEATURE_MAP_BUFFER_FOR_WRITE = (1 << 22),
COGL_FEATURE_ONSCREEN_MULTIPLE = (1 << 23), COGL_FEATURE_ONSCREEN_MULTIPLE = (1 << 23),

View File

@ -112,10 +112,7 @@ cogl_program_attach_shader (CoglHandle program_handle,
program = program_handle; program = program_handle;
shader = shader_handle; shader = shader_handle;
/* Only one shader is allowed if the type is ARBfp */ if (shader->language == COGL_SHADER_LANGUAGE_GLSL)
if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
_COGL_RETURN_IF_FAIL (program->attached_shaders == NULL);
else if (shader->language == COGL_SHADER_LANGUAGE_GLSL)
_COGL_RETURN_IF_FAIL (_cogl_program_get_language (program) == _COGL_RETURN_IF_FAIL (_cogl_program_get_language (program) ==
COGL_SHADER_LANGUAGE_GLSL); 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); _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 void
_cogl_program_flush_uniforms (CoglProgram *program, _cogl_program_flush_uniforms (CoglProgram *program,
GLuint gl_program, GLuint gl_program,
@ -422,9 +366,6 @@ _cogl_program_flush_uniforms (CoglProgram *program,
COGL_SHADER_LANGUAGE_GLSL) COGL_SHADER_LANGUAGE_GLSL)
uniform->location = uniform->location =
ctx->glGetUniformLocation (gl_program, uniform->name); ctx->glGetUniformLocation (gl_program, uniform->name);
else
uniform->location =
get_local_param_index (uniform->name);
uniform->location_valid = TRUE; uniform->location_valid = TRUE;
} }
@ -440,13 +381,6 @@ _cogl_program_flush_uniforms (CoglProgram *program,
uniform->location, uniform->location,
&uniform->value); &uniform->value);
break; break;
case COGL_SHADER_LANGUAGE_ARBFP:
#ifdef HAVE_COGL_GL
_cogl_program_flush_uniform_arbfp (uniform->location,
&uniform->value);
#endif
break;
} }
} }

View File

@ -41,7 +41,6 @@ typedef struct _CoglShader CoglShader;
typedef enum typedef enum
{ {
COGL_SHADER_LANGUAGE_GLSL, COGL_SHADER_LANGUAGE_GLSL,
COGL_SHADER_LANGUAGE_ARBFP
} CoglShaderLanguage; } CoglShaderLanguage;
struct _CoglShader struct _CoglShader

View File

@ -62,14 +62,6 @@ _cogl_shader_free (CoglShader *shader)
released! Do that separately before this! */ released! Do that separately before this! */
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _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) if (shader->gl_handle)
GE (ctx, glDeleteShader (shader->gl_handle)); GE (ctx, glDeleteShader (shader->gl_handle));
@ -108,18 +100,8 @@ delete_shader (CoglShader *shader)
{ {
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _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) if (shader->gl_handle)
GE (ctx, glDeleteShader (shader->gl_handle)); GE (ctx, glDeleteShader (shader->gl_handle));
}
shader->gl_handle = 0; shader->gl_handle = 0;
@ -143,12 +125,6 @@ cogl_shader_source (CoglHandle handle,
return; return;
shader = handle; 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... */ /* Delete the old object if the language is changing... */
@ -164,19 +140,6 @@ cogl_shader_source (CoglHandle handle,
void void
cogl_shader_compile (CoglHandle handle) 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 /* XXX: For GLSL we don't actually compile anything until the shader
* gets used so we have an opportunity to add some boilerplate to * gets used so we have an opportunity to add some boilerplate to
* the shader. * the shader.
@ -192,51 +155,11 @@ _cogl_shader_compile_real (CoglHandle handle,
CoglPipeline *pipeline) CoglPipeline *pipeline)
{ {
CoglShader *shader = handle; CoglShader *shader = handle;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
#ifdef HAVE_COGL_GL
if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
{
#ifdef COGL_GL_DEBUG
GLenum gl_error;
#endif
if (shader->gl_handle)
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
{
GLenum gl_type; GLenum gl_type;
GLint status; GLint status;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (shader->gl_handle) if (shader->gl_handle)
{ {
CoglPipeline *prev = shader->compilation_pipeline; CoglPipeline *prev = shader->compilation_pipeline;
@ -296,7 +219,6 @@ _cogl_shader_compile_real (CoglHandle handle,
shader->source, shader->source,
buffer); buffer);
} }
}
} }
char * char *

View File

@ -283,23 +283,11 @@ _cogl_use_fragment_program (GLuint gl_program, CoglPipelineProgramType type)
COGL_PIPELINE_PROGRAM_TYPE_GLSL) COGL_PIPELINE_PROGRAM_TYPE_GLSL)
set_glsl_program (0); set_glsl_program (0);
break; 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 */ /* ... and enable the new type */
switch (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: case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
/* don't need to to anything */ /* don't need to to anything */
break; break;
@ -317,10 +305,6 @@ _cogl_use_fragment_program (GLuint gl_program, CoglPipelineProgramType type)
#endif /* COGL_PIPELINE_FRAGEND_GLSL */ #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; ctx->current_fragment_program_type = type;
} }
@ -343,21 +327,11 @@ _cogl_use_vertex_program (GLuint gl_program, CoglPipelineProgramType type)
COGL_PIPELINE_PROGRAM_TYPE_GLSL) COGL_PIPELINE_PROGRAM_TYPE_GLSL)
set_glsl_program (0); set_glsl_program (0);
break; 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 */ /* ... and enable the new type */
switch (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: case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
/* don't need to to anything */ /* don't need to to anything */
break; break;
@ -375,10 +349,6 @@ _cogl_use_vertex_program (GLuint gl_program, CoglPipelineProgramType type)
#endif /* COGL_PIPELINE_VERTEND_GLSL */ #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; 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 defines the number of texture coordinates that can be
uploaded (but doesn't necessarily relate to how many texture uploaded (but doesn't necessarily relate to how many texture
images can be sampled) */ images can be sampled) */
if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL) || if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL))
cogl_has_feature (ctx, COGL_FEATURE_ID_ARBFP))
/* Previously this code subtracted the value by one but there /* Previously this code subtracted the value by one but there
was no explanation for why it did this and it doesn't seem was no explanation for why it did this and it doesn't seem
to make sense so it has been removed */ to make sense so it has been removed */

View File

@ -518,12 +518,6 @@ _cogl_driver_update_features (CoglContext *ctx,
COGL_FLAGS_SET (private_features, COGL_FLAGS_SET (private_features,
COGL_PRIVATE_FEATURE_BLEND_CONSTANT, TRUE); 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) if (ctx->glCreateProgram)
{ {
flags |= COGL_FEATURE_SHADERS_GLSL; flags |= COGL_FEATURE_SHADERS_GLSL;

View File

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

View File

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

View File

@ -148,31 +148,6 @@ COGL_EXT_FUNCTION (void, glBlitFramebuffer,
GLenum filter)) GLenum filter))
COGL_EXT_END () 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, COGL_EXT_BEGIN (EGL_image, 255, 255,
0, /* not in either GLES */ 0, /* not in either GLES */
"OES\0", "OES\0",

View File

@ -88,7 +88,7 @@ printf $TITLE_FORMAT "Test"
if test $HAVE_GL -eq 1; then if test $HAVE_GL -eq 1; then
GL_FORMAT=" %6s %8s %7s %6s %6s" 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 fi
if test $HAVE_GLES2 -eq 1; then if test $HAVE_GLES2 -eq 1; then
GLES2_FORMAT=" %6s %7s" GLES2_FORMAT=" %6s %7s"
@ -136,7 +136,6 @@ do
printf $TITLE_FORMAT "$test:" printf $TITLE_FORMAT "$test:"
if test $HAVE_GL -eq 1; then if test $HAVE_GL -eq 1; then
printf "$GL_FORMAT" \ printf "$GL_FORMAT" \
"`get_status $gl_arbfp_result`" \
"`get_status $gl_glsl_result`" \ "`get_status $gl_glsl_result`" \
"`get_status $gl_npot_result`" \ "`get_status $gl_npot_result`" \
"`get_status $gl3_result`" "`get_status $gl3_result`"