mirror of
https://github.com/brl/mutter.git
synced 2024-12-24 12:02:04 +00:00
Clearly define 3 progends that own the frag+vertends
This adds a new "fixed-arbfp" progend so we now have 3 distinct ways of setting up the state of a pipeline: » fixed; where the vertex and fragment processing are implemented using fixed function opengl apis. » fixed-arbfp; where vertex processing is implemented using fixed function opengl apis but fragment processing is implemented using the ARB Fragment Processing language. » glsl; there vertex and fragment processing are both implemented using glsl. This means we avoid unusual, combinations such as glsl for vertex processing and arbfp for fragment processing, and also avoid pairing fixed-function vertex processing with glsl fragment processing which we happen to know hits some awkward code paths in Mesa that lead to poor performance. As part of this change, the progend now implies specific vertend and fragend choices so instead of associating a vertend and fragend with a pipeline we now just associate a progend choice. When flushing a pipeline and choosing what progend to use, we now call a progend->start() method that is able to determine if the vertend and fragend together will be able to handle the given pipeline so the vertend and fragend ->start() methods no longer need to return a boolean status. Since we now don't need to support glsl used in conjunction with fixed function this will allow us to avoid ever using OpenGL builtin attribute names, though this patch doesn't change that yet. Reviewed-by: Neil Roberts <neil@linux.intel.com> (cherry picked from commit cec381f50c7a2f2186bd4a8c5f38fecd5f099075)
This commit is contained in:
parent
f05a1a62f4
commit
8f3380adc3
@ -175,6 +175,8 @@ cogl_driver_sources += \
|
||||
$(srcdir)/driver/gl/cogl-pipeline-fragend-glsl-private.h \
|
||||
$(srcdir)/driver/gl/gl/cogl-pipeline-fragend-arbfp.c \
|
||||
$(srcdir)/driver/gl/gl/cogl-pipeline-fragend-arbfp-private.h \
|
||||
$(srcdir)/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c \
|
||||
$(srcdir)/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp-private.h \
|
||||
$(srcdir)/driver/gl/cogl-pipeline-fragend-fixed.c \
|
||||
$(srcdir)/driver/gl/cogl-pipeline-fragend-fixed-private.h \
|
||||
$(srcdir)/driver/gl/cogl-pipeline-vertend-glsl.c \
|
||||
|
@ -45,9 +45,10 @@
|
||||
|
||||
#ifdef HAVE_COGL_GL
|
||||
|
||||
#define COGL_PIPELINE_PROGEND_FIXED 0
|
||||
#define COGL_PIPELINE_PROGEND_GLSL 1
|
||||
#define COGL_PIPELINE_N_PROGENDS 2
|
||||
#define COGL_PIPELINE_PROGEND_FIXED_ARBFP 0
|
||||
#define COGL_PIPELINE_PROGEND_FIXED 1
|
||||
#define COGL_PIPELINE_PROGEND_GLSL 2
|
||||
#define COGL_PIPELINE_N_PROGENDS 3
|
||||
|
||||
#define COGL_PIPELINE_VERTEND_FIXED 0
|
||||
#define COGL_PIPELINE_VERTEND_GLSL 1
|
||||
@ -97,11 +98,8 @@
|
||||
|
||||
#endif /* HAVE_COGL_GL */
|
||||
|
||||
#define COGL_PIPELINE_FRAGEND_DEFAULT 0
|
||||
#define COGL_PIPELINE_FRAGEND_UNDEFINED 3
|
||||
|
||||
#define COGL_PIPELINE_VERTEND_DEFAULT 0
|
||||
#define COGL_PIPELINE_VERTEND_UNDEFINED 3
|
||||
#define COGL_PIPELINE_PROGEND_DEFAULT 0
|
||||
#define COGL_PIPELINE_PROGEND_UNDEFINED 3
|
||||
|
||||
/* XXX: should I rename these as
|
||||
* COGL_PIPELINE_STATE_INDEX_XYZ... ?
|
||||
@ -480,20 +478,19 @@ struct _CoglPipeline
|
||||
* where the pipeline originates from */
|
||||
unsigned int has_static_breadcrumb:1;
|
||||
|
||||
/* There are multiple fragment processing backends for CoglPipeline,
|
||||
* glsl, arbfp and fixed. This identifies the backend being used for
|
||||
* the pipeline and any private state the backend has associated
|
||||
* with the pipeline. */
|
||||
unsigned int fragend:3;
|
||||
unsigned int vertend:3;
|
||||
/* There are multiple fragment and vertex processing backends for
|
||||
* CoglPipeline, glsl, arbfp and fixed that are bundled under a
|
||||
* "progend". This identifies the backend being used for the
|
||||
* pipeline. */
|
||||
unsigned int progend:3;
|
||||
};
|
||||
|
||||
typedef struct _CoglPipelineFragend
|
||||
{
|
||||
CoglBool (*start) (CoglPipeline *pipeline,
|
||||
int n_layers,
|
||||
unsigned long pipelines_difference,
|
||||
int n_tex_coord_attribs);
|
||||
void (*start) (CoglPipeline *pipeline,
|
||||
int n_layers,
|
||||
unsigned long pipelines_difference,
|
||||
int n_tex_coord_attribs);
|
||||
CoglBool (*add_layer) (CoglPipeline *pipeline,
|
||||
CoglPipelineLayer *layer,
|
||||
unsigned long layers_difference);
|
||||
@ -512,10 +509,10 @@ typedef struct _CoglPipelineFragend
|
||||
|
||||
typedef struct _CoglPipelineVertend
|
||||
{
|
||||
CoglBool (*start) (CoglPipeline *pipeline,
|
||||
int n_layers,
|
||||
unsigned long pipelines_difference,
|
||||
int n_tex_coord_attribs);
|
||||
void (*start) (CoglPipeline *pipeline,
|
||||
int n_layers,
|
||||
unsigned long pipelines_difference,
|
||||
int n_tex_coord_attribs);
|
||||
CoglBool (*add_layer) (CoglPipeline *pipeline,
|
||||
CoglPipelineLayer *layer,
|
||||
unsigned long layers_difference,
|
||||
@ -533,6 +530,9 @@ typedef struct _CoglPipelineVertend
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int vertend;
|
||||
int fragend;
|
||||
CoglBool (*start) (CoglPipeline *pipeline);
|
||||
void (*end) (CoglPipeline *pipeline,
|
||||
unsigned long pipelines_difference,
|
||||
int n_tex_coord_attribs);
|
||||
@ -818,10 +818,7 @@ _cogl_pipeline_weak_copy (CoglPipeline *pipeline,
|
||||
void *user_data);
|
||||
|
||||
void
|
||||
_cogl_pipeline_set_fragend (CoglPipeline *pipeline, int fragend);
|
||||
|
||||
void
|
||||
_cogl_pipeline_set_vertend (CoglPipeline *pipeline, int vertend);
|
||||
_cogl_pipeline_set_progend (CoglPipeline *pipeline, int progend);
|
||||
|
||||
CoglPipeline *
|
||||
_cogl_pipeline_get_parent (CoglPipeline *pipeline);
|
||||
|
@ -1111,10 +1111,7 @@ cogl_pipeline_set_user_program (CoglPipeline *pipeline,
|
||||
_cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
|
||||
|
||||
if (program != COGL_INVALID_HANDLE)
|
||||
{
|
||||
_cogl_pipeline_set_fragend (pipeline, COGL_PIPELINE_FRAGEND_DEFAULT);
|
||||
_cogl_pipeline_set_vertend (pipeline, COGL_PIPELINE_VERTEND_DEFAULT);
|
||||
}
|
||||
_cogl_pipeline_set_progend (pipeline, COGL_PIPELINE_PROGEND_UNDEFINED);
|
||||
|
||||
/* If we are the current authority see if we can revert to one of our
|
||||
* ancestors being the authority */
|
||||
|
@ -79,6 +79,9 @@ _cogl_pipeline_progends[MAX (COGL_PIPELINE_N_PROGENDS, 1)];
|
||||
#include "cogl-pipeline-vertend-fixed-private.h"
|
||||
#endif
|
||||
|
||||
#ifdef COGL_PIPELINE_PROGEND_FIXED_ARBFP
|
||||
#include "cogl-pipeline-progend-fixed-arbfp-private.h"
|
||||
#endif
|
||||
#ifdef COGL_PIPELINE_PROGEND_FIXED
|
||||
#include "cogl-pipeline-progend-fixed-private.h"
|
||||
#endif
|
||||
@ -125,6 +128,10 @@ _cogl_pipeline_init_default_pipeline (void)
|
||||
_cogl_pipeline_fragends[COGL_PIPELINE_FRAGEND_FIXED] =
|
||||
&_cogl_pipeline_fixed_fragend;
|
||||
#endif
|
||||
#ifdef COGL_PIPELINE_PROGEND_FIXED
|
||||
_cogl_pipeline_progends[COGL_PIPELINE_PROGEND_FIXED_ARBFP] =
|
||||
&_cogl_pipeline_fixed_arbfp_progend;
|
||||
#endif
|
||||
#ifdef COGL_PIPELINE_PROGEND_FIXED
|
||||
_cogl_pipeline_progends[COGL_PIPELINE_PROGEND_FIXED] =
|
||||
&_cogl_pipeline_fixed_progend;
|
||||
@ -147,8 +154,7 @@ _cogl_pipeline_init_default_pipeline (void)
|
||||
|
||||
pipeline->is_weak = FALSE;
|
||||
pipeline->journal_ref_count = 0;
|
||||
pipeline->fragend = COGL_PIPELINE_FRAGEND_UNDEFINED;
|
||||
pipeline->vertend = COGL_PIPELINE_VERTEND_UNDEFINED;
|
||||
pipeline->progend = COGL_PIPELINE_PROGEND_UNDEFINED;
|
||||
pipeline->differences = COGL_PIPELINE_STATE_ALL_SPARSE;
|
||||
|
||||
pipeline->real_blend_enable = FALSE;
|
||||
@ -284,12 +290,17 @@ _cogl_pipeline_set_parent (CoglPipeline *pipeline,
|
||||
* that depends on the pipeline's ancestry then it may be notified
|
||||
* here...
|
||||
*/
|
||||
if (pipeline->fragend != COGL_PIPELINE_FRAGEND_UNDEFINED &&
|
||||
_cogl_pipeline_fragends[pipeline->fragend]->pipeline_set_parent_notify)
|
||||
if (pipeline->progend != COGL_PIPELINE_PROGEND_UNDEFINED)
|
||||
{
|
||||
const CoglPipelineProgend *progend =
|
||||
_cogl_pipeline_progends[pipeline->progend];
|
||||
const CoglPipelineFragend *fragend =
|
||||
_cogl_pipeline_fragends[pipeline->fragend];
|
||||
fragend->pipeline_set_parent_notify (pipeline);
|
||||
_cogl_pipeline_fragends[progend->fragend];
|
||||
|
||||
/* Currently only the fragends ever care about reparenting of
|
||||
* pipelines... */
|
||||
if (fragend->pipeline_set_parent_notify)
|
||||
fragend->pipeline_set_parent_notify (pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
@ -368,9 +379,7 @@ _cogl_pipeline_copy (CoglPipeline *src, CoglBool is_weak)
|
||||
pipeline->deprecated_get_layers_list = NULL;
|
||||
pipeline->deprecated_get_layers_list_dirty = TRUE;
|
||||
|
||||
pipeline->fragend = src->fragend;
|
||||
|
||||
pipeline->vertend = src->vertend;
|
||||
pipeline->progend = src->progend;
|
||||
|
||||
pipeline->has_static_breadcrumb = FALSE;
|
||||
|
||||
@ -831,15 +840,9 @@ _cogl_pipeline_needs_blending_enabled (CoglPipeline *pipeline,
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_pipeline_set_fragend (CoglPipeline *pipeline, int fragend)
|
||||
_cogl_pipeline_set_progend (CoglPipeline *pipeline, int progend)
|
||||
{
|
||||
pipeline->fragend = fragend;
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_pipeline_set_vertend (CoglPipeline *pipeline, int vertend)
|
||||
{
|
||||
pipeline->vertend = vertend;
|
||||
pipeline->progend = progend;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1191,46 +1194,37 @@ _cogl_pipeline_pre_change_notify (CoglPipeline *pipeline,
|
||||
*
|
||||
* All STATE_LAYERS change notification with the exception of
|
||||
* ->n_layers will also result in layer_pre_change_notifications.
|
||||
* For backends that perform code generation for fragment
|
||||
* processing they typically need to understand the details of how
|
||||
* layers get changed to determine if they need to repeat codegen.
|
||||
* It doesn't help them to
|
||||
* report a pipeline STATE_LAYERS change for all layer changes since
|
||||
* it's so broad, they really need to wait for the specific layer
|
||||
* change to be notified. What does help though is to report a
|
||||
* STATE_LAYERS change for a change in
|
||||
* ->n_layers because they typically do need to repeat codegen in
|
||||
* that case.
|
||||
* For backends that perform code generation for fragment processing
|
||||
* they typically need to understand the details of how layers get
|
||||
* changed to determine if they need to repeat codegen. It doesn't
|
||||
* help them to report a pipeline STATE_LAYERS change for all layer
|
||||
* changes since it's so broad, they really need to wait for the
|
||||
* specific layer change to be notified. What does help though is
|
||||
* to report a STATE_LAYERS change for a change in ->n_layers
|
||||
* because they typically do need to repeat codegen in that case.
|
||||
*
|
||||
* Here we ensure that change notifications against a pipeline or
|
||||
* against a layer are mutually exclusive as far as fragment, vertex
|
||||
* and program backends are concerned.
|
||||
*/
|
||||
if (!from_layer_change)
|
||||
if (!from_layer_change &&
|
||||
pipeline->progend != COGL_PIPELINE_PROGEND_UNDEFINED)
|
||||
{
|
||||
int i;
|
||||
const CoglPipelineProgend *progend =
|
||||
_cogl_pipeline_progends[pipeline->progend];
|
||||
const CoglPipelineVertend *vertend =
|
||||
_cogl_pipeline_vertends[progend->vertend];
|
||||
const CoglPipelineFragend *fragend =
|
||||
_cogl_pipeline_fragends[progend->fragend];
|
||||
|
||||
if (pipeline->fragend != COGL_PIPELINE_FRAGEND_UNDEFINED &&
|
||||
_cogl_pipeline_fragends[pipeline->fragend]->pipeline_pre_change_notify)
|
||||
{
|
||||
const CoglPipelineFragend *fragend =
|
||||
_cogl_pipeline_fragends[pipeline->fragend];
|
||||
fragend->pipeline_pre_change_notify (pipeline, change, new_color);
|
||||
}
|
||||
if (vertend->pipeline_pre_change_notify)
|
||||
vertend->pipeline_pre_change_notify (pipeline, change, new_color);
|
||||
|
||||
if (pipeline->vertend != COGL_PIPELINE_VERTEND_UNDEFINED &&
|
||||
_cogl_pipeline_vertends[pipeline->vertend]->pipeline_pre_change_notify)
|
||||
{
|
||||
const CoglPipelineVertend *vertend =
|
||||
_cogl_pipeline_vertends[pipeline->vertend];
|
||||
vertend->pipeline_pre_change_notify (pipeline, change, new_color);
|
||||
}
|
||||
if (fragend->pipeline_pre_change_notify)
|
||||
fragend->pipeline_pre_change_notify (pipeline, change, new_color);
|
||||
|
||||
for (i = 0; i < COGL_PIPELINE_N_PROGENDS; i++)
|
||||
if (_cogl_pipeline_progends[i]->pipeline_pre_change_notify)
|
||||
_cogl_pipeline_progends[i]->pipeline_pre_change_notify (pipeline,
|
||||
change,
|
||||
new_color);
|
||||
if (progend->pipeline_pre_change_notify)
|
||||
progend->pipeline_pre_change_notify (pipeline, change, new_color);
|
||||
}
|
||||
|
||||
/* There may be an arbitrary tree of descendants of this pipeline;
|
||||
@ -1546,12 +1540,15 @@ _cogl_pipeline_fragend_layer_change_notify (CoglPipeline *owner,
|
||||
* have a single owner and can only be associated with a single
|
||||
* backend that needs to be notified of the layer change...
|
||||
*/
|
||||
if (owner->fragend != COGL_PIPELINE_FRAGEND_UNDEFINED &&
|
||||
_cogl_pipeline_fragends[owner->fragend]->layer_pre_change_notify)
|
||||
if (owner->progend != COGL_PIPELINE_PROGEND_UNDEFINED)
|
||||
{
|
||||
const CoglPipelineProgend *progend =
|
||||
_cogl_pipeline_progends[owner->progend];
|
||||
const CoglPipelineFragend *fragend =
|
||||
_cogl_pipeline_fragends[owner->fragend];
|
||||
fragend->layer_pre_change_notify (owner, layer, change);
|
||||
_cogl_pipeline_fragends[progend->fragend];
|
||||
|
||||
if (fragend->layer_pre_change_notify)
|
||||
fragend->layer_pre_change_notify (owner, layer, change);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1561,12 +1558,15 @@ _cogl_pipeline_vertend_layer_change_notify (CoglPipeline *owner,
|
||||
CoglPipelineLayerState change)
|
||||
{
|
||||
/* NB: The comment in fragend_layer_change_notify applies here too */
|
||||
if (owner->vertend != COGL_PIPELINE_VERTEND_UNDEFINED &&
|
||||
_cogl_pipeline_vertends[owner->vertend]->layer_pre_change_notify)
|
||||
if (owner->progend != COGL_PIPELINE_PROGEND_UNDEFINED)
|
||||
{
|
||||
const CoglPipelineProgend *progend =
|
||||
_cogl_pipeline_progends[owner->progend];
|
||||
const CoglPipelineVertend *vertend =
|
||||
_cogl_pipeline_vertends[owner->vertend];
|
||||
vertend->layer_pre_change_notify (owner, layer, change);
|
||||
_cogl_pipeline_vertends[progend->vertend];
|
||||
|
||||
if (vertend->layer_pre_change_notify)
|
||||
vertend->layer_pre_change_notify (owner, layer, change);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1575,15 +1575,11 @@ _cogl_pipeline_progend_layer_change_notify (CoglPipeline *owner,
|
||||
CoglPipelineLayer *layer,
|
||||
CoglPipelineLayerState change)
|
||||
{
|
||||
int i;
|
||||
const CoglPipelineProgend *progend =
|
||||
_cogl_pipeline_progends[owner->progend];
|
||||
|
||||
/* Give all of the progends a chance to notice that the layer has
|
||||
changed */
|
||||
for (i = 0; i < COGL_PIPELINE_N_PROGENDS; i++)
|
||||
if (_cogl_pipeline_progends[i]->layer_pre_change_notify)
|
||||
_cogl_pipeline_progends[i]->layer_pre_change_notify (owner,
|
||||
layer,
|
||||
change);
|
||||
if (progend->layer_pre_change_notify)
|
||||
progend->layer_pre_change_notify (owner, layer, change);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
|
@ -89,37 +89,13 @@ get_max_texture_units (void)
|
||||
return ctx->max_texture_units;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
static void
|
||||
_cogl_pipeline_fragend_fixed_start (CoglPipeline *pipeline,
|
||||
int n_layers,
|
||||
unsigned long pipelines_difference,
|
||||
int n_tex_coord_attribs)
|
||||
{
|
||||
CoglHandle user_program;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED)))
|
||||
return FALSE;
|
||||
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
return FALSE;
|
||||
|
||||
/* Fragment snippets are only supported in the GLSL fragend */
|
||||
if (_cogl_pipeline_has_fragment_snippets (pipeline))
|
||||
return FALSE;
|
||||
|
||||
/* If there is a user program with a fragment shader then the
|
||||
appropriate backend for that language should handle it. We can
|
||||
still use the fixed fragment backend if the program only contains
|
||||
a vertex shader */
|
||||
user_program = cogl_pipeline_get_user_program (pipeline);
|
||||
if (user_program != COGL_INVALID_HANDLE &&
|
||||
_cogl_program_has_fragment_shader (user_program))
|
||||
return FALSE;
|
||||
|
||||
_cogl_use_fragment_program (0, COGL_PIPELINE_PROGRAM_TYPE_FIXED);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -213,7 +213,7 @@ has_replace_hook (CoglPipelineLayer *layer,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
static void
|
||||
_cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
|
||||
int n_layers,
|
||||
unsigned long pipelines_difference,
|
||||
@ -222,22 +222,10 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
|
||||
CoglPipelineShaderState *shader_state;
|
||||
CoglPipeline *authority;
|
||||
CoglPipeline *template_pipeline = NULL;
|
||||
CoglProgram *user_program;
|
||||
CoglProgram *user_program = cogl_pipeline_get_user_program (pipeline);
|
||||
int i;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL))
|
||||
return FALSE;
|
||||
|
||||
user_program = cogl_pipeline_get_user_program (pipeline);
|
||||
|
||||
/* If the user fragment shader isn't GLSL then we should let
|
||||
another backend handle it */
|
||||
if (user_program &&
|
||||
_cogl_program_has_fragment_shader (user_program) &&
|
||||
_cogl_program_get_language (user_program) != COGL_SHADER_LANGUAGE_GLSL)
|
||||
return FALSE;
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Now lookup our glsl backend private state */
|
||||
shader_state = get_shader_state (pipeline);
|
||||
@ -313,7 +301,7 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
|
||||
shader_state->user_program_age == user_program->age)
|
||||
&& (ctx->driver != COGL_DRIVER_GLES2 ||
|
||||
shader_state->n_tex_coord_attribs == n_tex_coord_attribs))
|
||||
return TRUE;
|
||||
return;
|
||||
|
||||
/* We need to recreate the shader so destroy the existing one */
|
||||
GE( ctx, glDeleteShader (shader_state->gl_shader) );
|
||||
@ -333,7 +321,7 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
|
||||
to generate one */
|
||||
if (user_program &&
|
||||
_cogl_program_has_fragment_shader (user_program))
|
||||
return TRUE;
|
||||
return;
|
||||
|
||||
/* We reuse two grow-only GStrings for code-gen. One string
|
||||
contains the uniform and attribute declarations while the
|
||||
@ -356,8 +344,6 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
|
||||
shader_state->unit_state[i].sampled = FALSE;
|
||||
shader_state->unit_state[i].combine_constant_used = FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1035,28 +1035,30 @@ compare_layer_differences_cb (CoglPipelineLayer *layer, void *user_data)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CoglFramebuffer *framebuffer;
|
||||
const CoglPipelineVertend *vertend;
|
||||
const CoglPipelineFragend *fragend;
|
||||
CoglPipeline *pipeline;
|
||||
unsigned long *layer_differences;
|
||||
CoglBool error_adding_layer;
|
||||
CoglBool added_layer;
|
||||
} CoglPipelineFragendAddLayerState;
|
||||
|
||||
} CoglPipelineAddLayerState;
|
||||
|
||||
static CoglBool
|
||||
fragend_add_layer_cb (CoglPipelineLayer *layer,
|
||||
vertend_add_layer_cb (CoglPipelineLayer *layer,
|
||||
void *user_data)
|
||||
{
|
||||
CoglPipelineFragendAddLayerState *state = user_data;
|
||||
const CoglPipelineFragend *fragend = state->fragend;
|
||||
CoglPipelineAddLayerState *state = user_data;
|
||||
const CoglPipelineVertend *vertend = state->vertend;
|
||||
CoglPipeline *pipeline = state->pipeline;
|
||||
int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
|
||||
|
||||
/* Either generate per layer code snippets or setup the
|
||||
* fixed function glTexEnv for each layer... */
|
||||
if (G_LIKELY (fragend->add_layer (pipeline,
|
||||
if (G_LIKELY (vertend->add_layer (pipeline,
|
||||
layer,
|
||||
state->layer_differences[unit_index])))
|
||||
state->layer_differences[unit_index],
|
||||
state->framebuffer)))
|
||||
state->added_layer = TRUE;
|
||||
else
|
||||
{
|
||||
@ -1067,32 +1069,20 @@ fragend_add_layer_cb (CoglPipelineLayer *layer,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CoglFramebuffer *framebuffer;
|
||||
const CoglPipelineVertend *vertend;
|
||||
CoglPipeline *pipeline;
|
||||
unsigned long *layer_differences;
|
||||
CoglBool error_adding_layer;
|
||||
CoglBool added_layer;
|
||||
} CoglPipelineVertendAddLayerState;
|
||||
|
||||
|
||||
static CoglBool
|
||||
vertend_add_layer_cb (CoglPipelineLayer *layer,
|
||||
fragend_add_layer_cb (CoglPipelineLayer *layer,
|
||||
void *user_data)
|
||||
{
|
||||
CoglPipelineVertendAddLayerState *state = user_data;
|
||||
const CoglPipelineVertend *vertend = state->vertend;
|
||||
CoglPipelineAddLayerState *state = user_data;
|
||||
const CoglPipelineFragend *fragend = state->fragend;
|
||||
CoglPipeline *pipeline = state->pipeline;
|
||||
int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
|
||||
|
||||
/* Either enerate per layer code snippets or setup the
|
||||
* fixed function matrix uniforms for each layer... */
|
||||
if (G_LIKELY (vertend->add_layer (pipeline,
|
||||
/* Either generate per layer code snippets or setup the
|
||||
* fixed function glTexEnv for each layer... */
|
||||
if (G_LIKELY (fragend->add_layer (pipeline,
|
||||
layer,
|
||||
state->layer_differences[unit_index],
|
||||
state->framebuffer)))
|
||||
state->layer_differences[unit_index])))
|
||||
state->added_layer = TRUE;
|
||||
else
|
||||
{
|
||||
@ -1159,11 +1149,12 @@ _cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
|
||||
CoglBool skip_gl_color,
|
||||
int n_tex_coord_attribs)
|
||||
{
|
||||
unsigned long pipelines_difference;
|
||||
int n_layers;
|
||||
unsigned long *layer_differences;
|
||||
int i;
|
||||
unsigned long pipelines_difference;
|
||||
int n_layers;
|
||||
unsigned long *layer_differences;
|
||||
int i;
|
||||
CoglTextureUnit *unit1;
|
||||
const CoglPipelineProgend *progend;
|
||||
|
||||
COGL_STATIC_TIMER (pipeline_flush_timer,
|
||||
"Mainloop", /* parent */
|
||||
@ -1242,88 +1233,40 @@ _cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
|
||||
layer_differences,
|
||||
skip_gl_color);
|
||||
|
||||
/* Now flush the fragment processing state according to the current
|
||||
* fragment processing backend.
|
||||
/* Now flush the fragment, vertex and program state according to the
|
||||
* current progend backend.
|
||||
*
|
||||
* Note: Some of the backends may not support the current pipeline
|
||||
* configuration and in that case it will report an error and we
|
||||
* will fallback to a different backend.
|
||||
* Note: Some backends may not support the current pipeline
|
||||
* configuration and in that case it will report and error and we
|
||||
* will look for a different backend.
|
||||
*
|
||||
* NB: if pipeline->backend != COGL_PIPELINE_FRAGEND_UNDEFINED then
|
||||
* NB: if pipeline->progend != COGL_PIPELINE_PROGEND_UNDEFINED then
|
||||
* we have previously managed to successfully flush this pipeline
|
||||
* with the given backend so we will simply use that to avoid
|
||||
* with the given progend so we will simply use that to avoid
|
||||
* fallback code paths.
|
||||
*/
|
||||
if (pipeline->progend == COGL_PIPELINE_PROGEND_UNDEFINED)
|
||||
_cogl_pipeline_set_progend (pipeline, COGL_PIPELINE_PROGEND_DEFAULT);
|
||||
|
||||
if (pipeline->fragend == COGL_PIPELINE_FRAGEND_UNDEFINED)
|
||||
_cogl_pipeline_set_fragend (pipeline, COGL_PIPELINE_FRAGEND_DEFAULT);
|
||||
|
||||
for (i = pipeline->fragend;
|
||||
i < G_N_ELEMENTS (_cogl_pipeline_fragends);
|
||||
i++, _cogl_pipeline_set_fragend (pipeline, i))
|
||||
for (i = pipeline->progend;
|
||||
i < COGL_PIPELINE_N_PROGENDS;
|
||||
i++, _cogl_pipeline_set_progend (pipeline, i))
|
||||
{
|
||||
const CoglPipelineFragend *fragend = _cogl_pipeline_fragends[i];
|
||||
CoglPipelineFragendAddLayerState state;
|
||||
const CoglPipelineVertend *vertend;
|
||||
const CoglPipelineFragend *fragend;
|
||||
CoglPipelineAddLayerState state;
|
||||
|
||||
/* E.g. For fragends generating code they can setup their
|
||||
* scratch buffers here... */
|
||||
if (G_UNLIKELY (!fragend->start (pipeline,
|
||||
n_layers,
|
||||
pipelines_difference,
|
||||
n_tex_coord_attribs)))
|
||||
progend = _cogl_pipeline_progends[i];
|
||||
|
||||
if (G_UNLIKELY (!progend->start (pipeline)))
|
||||
continue;
|
||||
|
||||
state.fragend = fragend;
|
||||
state.pipeline = pipeline;
|
||||
state.layer_differences = layer_differences;
|
||||
state.error_adding_layer = FALSE;
|
||||
state.added_layer = FALSE;
|
||||
_cogl_pipeline_foreach_layer_internal (pipeline,
|
||||
fragend_add_layer_cb,
|
||||
&state);
|
||||
vertend = _cogl_pipeline_vertends[progend->vertend];
|
||||
|
||||
if (G_UNLIKELY (state.error_adding_layer))
|
||||
continue;
|
||||
|
||||
if (!state.added_layer &&
|
||||
fragend->passthrough &&
|
||||
G_UNLIKELY (!fragend->passthrough (pipeline)))
|
||||
continue;
|
||||
|
||||
/* For fragends generating code they may compile and link their
|
||||
* programs here, update any uniforms and tell OpenGL to use
|
||||
* that program.
|
||||
*/
|
||||
if (G_UNLIKELY (!fragend->end (pipeline, pipelines_difference)))
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (i >= G_N_ELEMENTS (_cogl_pipeline_fragends)))
|
||||
g_warning ("No usable pipeline fragment backend was found!");
|
||||
|
||||
/* Now flush the vertex processing state according to the current
|
||||
* vertex processing backend.
|
||||
*/
|
||||
|
||||
if (pipeline->vertend == COGL_PIPELINE_VERTEND_UNDEFINED)
|
||||
_cogl_pipeline_set_vertend (pipeline, COGL_PIPELINE_VERTEND_DEFAULT);
|
||||
|
||||
for (i = pipeline->vertend;
|
||||
i < G_N_ELEMENTS (_cogl_pipeline_vertends);
|
||||
i++, _cogl_pipeline_set_vertend (pipeline, i))
|
||||
{
|
||||
const CoglPipelineVertend *vertend = _cogl_pipeline_vertends[i];
|
||||
CoglPipelineVertendAddLayerState state;
|
||||
|
||||
/* E.g. For vertends generating code they can setup their
|
||||
* scratch buffers here... */
|
||||
if (G_UNLIKELY (!vertend->start (pipeline,
|
||||
n_layers,
|
||||
pipelines_difference,
|
||||
n_tex_coord_attribs)))
|
||||
continue;
|
||||
vertend->start (pipeline,
|
||||
n_layers,
|
||||
pipelines_difference,
|
||||
n_tex_coord_attribs);
|
||||
|
||||
state.framebuffer = framebuffer;
|
||||
state.vertend = vertend;
|
||||
@ -1331,6 +1274,7 @@ _cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
|
||||
state.layer_differences = layer_differences;
|
||||
state.error_adding_layer = FALSE;
|
||||
state.added_layer = FALSE;
|
||||
|
||||
_cogl_pipeline_foreach_layer_internal (pipeline,
|
||||
vertend_add_layer_cb,
|
||||
&state);
|
||||
@ -1338,24 +1282,46 @@ _cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
|
||||
if (G_UNLIKELY (state.error_adding_layer))
|
||||
continue;
|
||||
|
||||
/* For vertends generating code they may compile and link their
|
||||
* programs here, update any uniforms and tell OpenGL to use
|
||||
* that program.
|
||||
*/
|
||||
if (G_UNLIKELY (!vertend->end (pipeline, pipelines_difference)))
|
||||
continue;
|
||||
|
||||
/* Now prepare the fragment processing state (fragend)
|
||||
*
|
||||
* NB: We can't combine the setup of the vertend and fragend
|
||||
* since the backends that do code generation share
|
||||
* ctx->codegen_source_buffer as a scratch buffer.
|
||||
*/
|
||||
|
||||
fragend = _cogl_pipeline_fragends[progend->fragend];
|
||||
state.fragend = fragend;
|
||||
|
||||
fragend->start (pipeline,
|
||||
n_layers,
|
||||
pipelines_difference,
|
||||
n_tex_coord_attribs);
|
||||
|
||||
_cogl_pipeline_foreach_layer_internal (pipeline,
|
||||
fragend_add_layer_cb,
|
||||
&state);
|
||||
|
||||
if (G_UNLIKELY (state.error_adding_layer))
|
||||
continue;
|
||||
|
||||
if (!state.added_layer)
|
||||
{
|
||||
if (fragend->passthrough &&
|
||||
G_UNLIKELY (!fragend->passthrough (pipeline)))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (!fragend->end (pipeline, pipelines_difference)))
|
||||
continue;
|
||||
|
||||
if (progend->end)
|
||||
progend->end (pipeline, pipelines_difference, n_tex_coord_attribs);
|
||||
break;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (i >= G_N_ELEMENTS (_cogl_pipeline_vertends)))
|
||||
g_warning ("No usable pipeline vertex backend was found!");
|
||||
|
||||
for (i = 0; i < COGL_PIPELINE_N_PROGENDS; i++)
|
||||
if (_cogl_pipeline_progends[i]->end)
|
||||
_cogl_pipeline_progends[i]->end (pipeline, pipelines_difference,
|
||||
n_tex_coord_attribs);
|
||||
|
||||
/* FIXME: This reference is actually resulting in lots of
|
||||
* copy-on-write reparenting because one-shot pipelines end up
|
||||
* living for longer than necessary and so any later modification of
|
||||
@ -1374,6 +1340,8 @@ _cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
|
||||
|
||||
done:
|
||||
|
||||
progend = _cogl_pipeline_progends[pipeline->progend];
|
||||
|
||||
/* We can't assume the color will be retained between flushes on
|
||||
GLES2 because the generic attribute values are not stored as part
|
||||
of the program object so they could be overridden by any
|
||||
@ -1398,12 +1366,11 @@ done:
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Give any progends a chance to update any uniforms that might not
|
||||
depend on the material state. This is used on GLES2 to update the
|
||||
matrices */
|
||||
for (i = 0; i < COGL_PIPELINE_N_PROGENDS; i++)
|
||||
if (_cogl_pipeline_progends[i]->pre_paint)
|
||||
_cogl_pipeline_progends[i]->pre_paint (pipeline, framebuffer);
|
||||
/* Give the progend a chance to update any uniforms that might not
|
||||
* depend on the material state. This is used on GLES2 to update the
|
||||
* matrices */
|
||||
if (progend->pre_paint)
|
||||
progend->pre_paint (pipeline, framebuffer);
|
||||
|
||||
/* Handle the fact that OpenGL associates texture filter and wrap
|
||||
* modes with the texture objects not the texture units... */
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "cogl-pipeline-private.h"
|
||||
#include "cogl-pipeline-state-private.h"
|
||||
|
||||
#ifdef COGL_PIPELINE_PROGEND_FIXED
|
||||
|
||||
@ -39,15 +40,39 @@
|
||||
#include "cogl-context-private.h"
|
||||
#include "cogl-framebuffer-private.h"
|
||||
|
||||
static CoglBool
|
||||
_cogl_pipeline_progend_fixed_start (CoglPipeline *pipeline)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED)))
|
||||
return FALSE;
|
||||
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
return FALSE;
|
||||
|
||||
/* Vertex snippets are only supported in the GLSL fragend */
|
||||
if (_cogl_pipeline_has_vertex_snippets (pipeline))
|
||||
return FALSE;
|
||||
|
||||
/* Fragment snippets are only supported in the GLSL fragend */
|
||||
if (_cogl_pipeline_has_fragment_snippets (pipeline))
|
||||
return FALSE;
|
||||
|
||||
/* If there is a user program then the appropriate backend for that
|
||||
* language should handle it. */
|
||||
if (cogl_pipeline_get_user_program (pipeline))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_pipeline_progend_fixed_pre_paint (CoglPipeline *pipeline,
|
||||
CoglFramebuffer *framebuffer)
|
||||
{
|
||||
CoglContext *ctx = framebuffer->context;
|
||||
|
||||
if (pipeline->vertend != COGL_PIPELINE_VERTEND_FIXED)
|
||||
return;
|
||||
|
||||
if (ctx->current_projection_entry)
|
||||
_cogl_matrix_entry_flush_to_gl_builtins (ctx,
|
||||
ctx->current_projection_entry,
|
||||
@ -64,6 +89,9 @@ _cogl_pipeline_progend_fixed_pre_paint (CoglPipeline *pipeline,
|
||||
|
||||
const CoglPipelineProgend _cogl_pipeline_fixed_progend =
|
||||
{
|
||||
COGL_PIPELINE_VERTEND_FIXED,
|
||||
COGL_PIPELINE_FRAGEND_FIXED,
|
||||
_cogl_pipeline_progend_fixed_start,
|
||||
NULL, /* end */
|
||||
NULL, /* pre_change_notify */
|
||||
NULL, /* layer_pre_change_notify */
|
||||
|
@ -645,6 +645,24 @@ _cogl_pipeline_progend_glsl_flush_uniforms (CoglPipeline *pipeline,
|
||||
_cogl_bitmask_clear_all (&uniforms_state->changed_mask);
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
_cogl_pipeline_progend_glsl_start (CoglPipeline *pipeline)
|
||||
{
|
||||
CoglHandle user_program;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL))
|
||||
return FALSE;
|
||||
|
||||
user_program = cogl_pipeline_get_user_program (pipeline);
|
||||
if (user_program &&
|
||||
_cogl_program_get_language (user_program) != COGL_SHADER_LANGUAGE_GLSL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
|
||||
unsigned long pipelines_difference,
|
||||
@ -659,12 +677,6 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* If neither of the glsl fragend or vertends are used then we don't
|
||||
need to do anything */
|
||||
if (pipeline->fragend != COGL_PIPELINE_FRAGEND_GLSL &&
|
||||
pipeline->vertend != COGL_PIPELINE_VERTEND_GLSL)
|
||||
return;
|
||||
|
||||
program_state = get_program_state (pipeline);
|
||||
|
||||
user_program = cogl_pipeline_get_user_program (pipeline);
|
||||
@ -763,11 +775,9 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
|
||||
}
|
||||
|
||||
/* Attach any shaders from the GLSL backends */
|
||||
if (pipeline->fragend == COGL_PIPELINE_FRAGEND_GLSL &&
|
||||
(backend_shader = _cogl_pipeline_fragend_glsl_get_shader (pipeline)))
|
||||
if ((backend_shader = _cogl_pipeline_fragend_glsl_get_shader (pipeline)))
|
||||
GE( ctx, glAttachShader (program_state->program, backend_shader) );
|
||||
if (pipeline->vertend == COGL_PIPELINE_VERTEND_GLSL &&
|
||||
(backend_shader = _cogl_pipeline_vertend_glsl_get_shader (pipeline)))
|
||||
if ((backend_shader = _cogl_pipeline_vertend_glsl_get_shader (pipeline)))
|
||||
GE( ctx, glAttachShader (program_state->program, backend_shader) );
|
||||
|
||||
link_program (program_state->program);
|
||||
@ -779,10 +789,8 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
|
||||
|
||||
gl_program = program_state->program;
|
||||
|
||||
if (pipeline->fragend == COGL_PIPELINE_FRAGEND_GLSL)
|
||||
_cogl_use_fragment_program (gl_program, COGL_PIPELINE_PROGRAM_TYPE_GLSL);
|
||||
if (pipeline->vertend == COGL_PIPELINE_VERTEND_GLSL)
|
||||
_cogl_use_vertex_program (gl_program, COGL_PIPELINE_PROGRAM_TYPE_GLSL);
|
||||
_cogl_use_fragment_program (gl_program, COGL_PIPELINE_PROGRAM_TYPE_GLSL);
|
||||
_cogl_use_vertex_program (gl_program, COGL_PIPELINE_PROGRAM_TYPE_GLSL);
|
||||
|
||||
state.unit = 0;
|
||||
state.gl_program = gl_program;
|
||||
@ -939,9 +947,6 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline,
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
if (pipeline->vertend != COGL_PIPELINE_VERTEND_GLSL)
|
||||
return;
|
||||
|
||||
program_state = get_program_state (pipeline);
|
||||
|
||||
projection_entry = ctx->current_projection_entry;
|
||||
@ -1099,6 +1104,9 @@ update_float_uniform (CoglPipeline *pipeline,
|
||||
|
||||
const CoglPipelineProgend _cogl_pipeline_glsl_progend =
|
||||
{
|
||||
COGL_PIPELINE_VERTEND_GLSL,
|
||||
COGL_PIPELINE_FRAGEND_GLSL,
|
||||
_cogl_pipeline_progend_glsl_start,
|
||||
_cogl_pipeline_progend_glsl_end,
|
||||
_cogl_pipeline_progend_glsl_pre_change_notify,
|
||||
_cogl_pipeline_progend_glsl_layer_pre_change_notify,
|
||||
|
@ -44,38 +44,13 @@
|
||||
|
||||
const CoglPipelineVertend _cogl_pipeline_fixed_vertend;
|
||||
|
||||
static CoglBool
|
||||
static void
|
||||
_cogl_pipeline_vertend_fixed_start (CoglPipeline *pipeline,
|
||||
int n_layers,
|
||||
unsigned long pipelines_difference,
|
||||
int n_tex_coord_attribs)
|
||||
{
|
||||
CoglProgram *user_program;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED)))
|
||||
return FALSE;
|
||||
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
return FALSE;
|
||||
|
||||
/* Vertex snippets are only supported in the GLSL fragend */
|
||||
if (_cogl_pipeline_has_vertex_snippets (pipeline))
|
||||
return FALSE;
|
||||
|
||||
/* If there is a user program with a vertex shader then the
|
||||
appropriate backend for that language should handle it. We can
|
||||
still use the fixed vertex backend if the program only contains
|
||||
a fragment shader */
|
||||
user_program = cogl_pipeline_get_user_program (pipeline);
|
||||
if (user_program != COGL_INVALID_HANDLE &&
|
||||
_cogl_program_has_vertex_shader (user_program))
|
||||
return FALSE;
|
||||
|
||||
_cogl_use_vertex_program (0, COGL_PIPELINE_PROGRAM_TYPE_FIXED);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
|
@ -149,7 +149,7 @@ get_layer_vertex_snippets (CoglPipelineLayer *layer)
|
||||
return &layer->big_state->vertex_snippets;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
static void
|
||||
_cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
|
||||
int n_layers,
|
||||
unsigned long pipelines_difference,
|
||||
@ -157,21 +157,9 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
|
||||
{
|
||||
CoglPipelineShaderState *shader_state;
|
||||
CoglPipeline *template_pipeline = NULL;
|
||||
CoglProgram *user_program;
|
||||
CoglProgram *user_program = cogl_pipeline_get_user_program (pipeline);
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL))
|
||||
return FALSE;
|
||||
|
||||
user_program = cogl_pipeline_get_user_program (pipeline);
|
||||
|
||||
/* If the user program has a vertex shader that isn't GLSL then the
|
||||
appropriate vertend for that language should handle it */
|
||||
if (user_program &&
|
||||
_cogl_program_has_vertex_shader (user_program) &&
|
||||
_cogl_program_get_language (user_program) != COGL_SHADER_LANGUAGE_GLSL)
|
||||
return FALSE;
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Now lookup our glsl backend private state (allocating if
|
||||
* necessary) */
|
||||
@ -238,7 +226,7 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
|
||||
shader_state->user_program_age == user_program->age)
|
||||
&& (ctx->driver != COGL_DRIVER_GLES2 ||
|
||||
shader_state->n_tex_coord_attribs == n_tex_coord_attribs))
|
||||
return TRUE;
|
||||
return;
|
||||
|
||||
/* We need to recreate the shader so destroy the existing one */
|
||||
GE( ctx, glDeleteShader (shader_state->gl_shader) );
|
||||
@ -258,7 +246,7 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
|
||||
to generate one */
|
||||
if (user_program &&
|
||||
_cogl_program_has_vertex_shader (user_program))
|
||||
return TRUE;
|
||||
return;
|
||||
|
||||
/* We reuse two grow-only GStrings for code-gen. One string
|
||||
contains the uniform and attribute declarations while the
|
||||
@ -280,8 +268,6 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
|
||||
to copy it from the custom uniform in the vertex shader */
|
||||
g_string_append (shader_state->source,
|
||||
" cogl_point_size_out = cogl_point_size_in;\n");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
|
@ -155,7 +155,7 @@ dirty_shader_state (CoglPipeline *pipeline)
|
||||
NULL);
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
static void
|
||||
_cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline,
|
||||
int n_layers,
|
||||
unsigned long pipelines_difference,
|
||||
@ -164,38 +164,9 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline,
|
||||
CoglPipelineShaderState *shader_state;
|
||||
CoglPipeline *authority;
|
||||
CoglPipeline *template_pipeline = NULL;
|
||||
CoglHandle user_program;
|
||||
CoglProgram *user_program = cogl_pipeline_get_user_program (pipeline);
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
/* First validate that we can handle the current state using ARBfp
|
||||
*/
|
||||
|
||||
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_ARBFP))
|
||||
return FALSE;
|
||||
|
||||
/* TODO: support fog */
|
||||
if (_cogl_pipeline_get_fog_enabled (pipeline))
|
||||
return FALSE;
|
||||
|
||||
/* Fragment snippets are only supported in the GLSL fragend */
|
||||
if (_cogl_pipeline_has_fragment_snippets (pipeline))
|
||||
return FALSE;
|
||||
|
||||
user_program = cogl_pipeline_get_user_program (pipeline);
|
||||
if (user_program != COGL_INVALID_HANDLE)
|
||||
{
|
||||
/* If the program doesn't have a fragment shader then some other
|
||||
vertend will handle the vertex shader state and we still need
|
||||
to generate a fragment program */
|
||||
if (!_cogl_program_has_fragment_shader (user_program))
|
||||
user_program = COGL_INVALID_HANDLE;
|
||||
/* If the user program does have a fragment shader then we can
|
||||
only handle it if it's in ARBfp */
|
||||
else if (_cogl_program_get_language (user_program) !=
|
||||
COGL_SHADER_LANGUAGE_ARBFP)
|
||||
return FALSE;
|
||||
}
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Now lookup our ARBfp backend private state */
|
||||
shader_state = get_shader_state (pipeline);
|
||||
@ -203,7 +174,7 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *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 TRUE;
|
||||
return;
|
||||
|
||||
/* If we don't have an associated arbfp program yet then find the
|
||||
* arbfp-authority (the oldest ancestor whose state will result in
|
||||
@ -226,7 +197,7 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline,
|
||||
* arbfp-authority... */
|
||||
shader_state->ref_count++;
|
||||
set_shader_state (pipeline, shader_state);
|
||||
return TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we haven't yet found an existing program then before we resort to
|
||||
@ -285,8 +256,6 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline,
|
||||
shader_state->ref_count++;
|
||||
set_shader_state (template_pipeline, shader_state);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const char *
|
||||
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||
*
|
||||
* Copyright (C) 2011 Intel Corporation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors:
|
||||
* Neil Roberts <neil@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifndef __COGL_PIPELINE_PROGEND_FIXED_ARBFP_PRIVATE_H
|
||||
#define __COGL_PIPELINE_PROGEND_FIXED_ARBFP_PRIVATE_H
|
||||
|
||||
#include "cogl-pipeline-private.h"
|
||||
|
||||
extern const CoglPipelineProgend _cogl_pipeline_fixed_arbfp_progend;
|
||||
|
||||
#endif /* __COGL_PIPELINE_PROGEND_FIXED_ARBFP_PRIVATE_H */
|
||||
|
110
cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c
Normal file
110
cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||
*
|
||||
* Copyright (C) 2012 Intel Corporation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors:
|
||||
* Robert Bragg <robert@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "cogl-pipeline-private.h"
|
||||
#include "cogl-pipeline-state-private.h"
|
||||
|
||||
#ifdef COGL_PIPELINE_PROGEND_FIXED_ARBFP
|
||||
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-context-private.h"
|
||||
#include "cogl-framebuffer-private.h"
|
||||
#include "cogl-program-private.h"
|
||||
|
||||
static CoglBool
|
||||
_cogl_pipeline_progend_fixed_arbfp_start (CoglPipeline *pipeline)
|
||||
{
|
||||
CoglHandle user_program;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED)))
|
||||
return FALSE;
|
||||
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
return FALSE;
|
||||
|
||||
/* Vertex snippets are only supported in the GLSL fragend */
|
||||
if (_cogl_pipeline_has_vertex_snippets (pipeline))
|
||||
return FALSE;
|
||||
|
||||
/* Validate that we can handle the fragment state using ARBfp
|
||||
*/
|
||||
|
||||
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_ARBFP))
|
||||
return FALSE;
|
||||
|
||||
/* Fragment snippets are only supported in the GLSL fragend */
|
||||
if (_cogl_pipeline_has_fragment_snippets (pipeline))
|
||||
return FALSE;
|
||||
|
||||
user_program = cogl_pipeline_get_user_program (pipeline);
|
||||
if (user_program &&
|
||||
_cogl_program_get_language (user_program) != COGL_SHADER_LANGUAGE_ARBFP)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_pipeline_progend_fixed_arbfp_pre_paint (CoglPipeline *pipeline,
|
||||
CoglFramebuffer *framebuffer)
|
||||
{
|
||||
CoglContext *ctx = framebuffer->context;
|
||||
|
||||
if (ctx->current_projection_entry)
|
||||
_cogl_matrix_entry_flush_to_gl_builtins (ctx,
|
||||
ctx->current_projection_entry,
|
||||
COGL_MATRIX_PROJECTION,
|
||||
framebuffer,
|
||||
FALSE /* enable flip */);
|
||||
if (ctx->current_modelview_entry)
|
||||
_cogl_matrix_entry_flush_to_gl_builtins (ctx,
|
||||
ctx->current_modelview_entry,
|
||||
COGL_MATRIX_MODELVIEW,
|
||||
framebuffer,
|
||||
FALSE /* enable flip */);
|
||||
}
|
||||
|
||||
const CoglPipelineProgend _cogl_pipeline_fixed_arbfp_progend =
|
||||
{
|
||||
COGL_PIPELINE_VERTEND_FIXED,
|
||||
COGL_PIPELINE_FRAGEND_ARBFP,
|
||||
_cogl_pipeline_progend_fixed_arbfp_start,
|
||||
NULL, /* end */
|
||||
NULL, /* pre_change_notify */
|
||||
NULL, /* layer_pre_change_notify */
|
||||
_cogl_pipeline_progend_fixed_arbfp_pre_paint
|
||||
};
|
||||
|
||||
#endif /* COGL_PIPELINE_PROGEND_FIXED_ARBFP */
|
Loading…
Reference in New Issue
Block a user