material: Adds backend abstraction for fragment processing

As part of an effort to improve the architecture of CoglMaterial
internally this overhauls how we flush layer state to OpenGL by adding a
formal backend abstraction for fragment processing and further
formalizing the CoglTextureUnit abstraction.

There are three backends: "glsl", "arbfp" and "fixed". The fixed backend
uses the OpenGL fixed function APIs to setup the fragment processing,
the arbfp backend uses code generation to handle fragment processing
using an ARBfp program, and the GLSL backend is currently only there as
a formality to handle user programs associated with a material. (i.e.
the glsl backend doesn't yet support code generation)

The GLSL backend has highest precedence, then arbfp and finally the
fixed. If a backend can't support some particular CoglMaterial feature
then it will fallback to the next backend.

This adds three new COGL_DEBUG options:
* "disable-texturing" as expected should disable all texturing
* "disable-arbfp" always make the arbfp backend fallback
* "disable-glsl" always make the glsl backend fallback
* "show-source" show code generated by the arbfp/glsl backends
This commit is contained in:
Robert Bragg 2010-04-26 10:01:43 +01:00
parent 8ebf76a9a9
commit acc44161c1
20 changed files with 2445 additions and 1076 deletions

View File

@ -58,8 +58,6 @@
#define glDeleteBuffers ctx->drv.pf_glDeleteBuffers #define glDeleteBuffers ctx->drv.pf_glDeleteBuffers
#define glMapBuffer ctx->drv.pf_glMapBuffer #define glMapBuffer ctx->drv.pf_glMapBuffer
#define glUnmapBuffer ctx->drv.pf_glUnmapBuffer #define glUnmapBuffer ctx->drv.pf_glUnmapBuffer
#define glActiveTexture ctx->drv.pf_glActiveTexture
#define glClientActiveTexture ctx->drv.pf_glClientActiveTexture
#ifndef GL_ARRAY_BUFFER #ifndef GL_ARRAY_BUFFER
#define GL_ARRAY_BUFFER GL_ARRAY_BUFFER_ARB #define GL_ARRAY_BUFFER GL_ARRAY_BUFFER_ARB
#endif #endif

View File

@ -70,6 +70,7 @@ cogl_create_context (void)
_context->enable_flags = 0; _context->enable_flags = 0;
_context->color_alpha = 0; _context->color_alpha = 0;
_context->fog_enabled = FALSE;
_context->enable_backface_culling = FALSE; _context->enable_backface_culling = FALSE;
_context->flushed_front_winding = COGL_FRONT_WINDING_COUNTER_CLOCKWISE; _context->flushed_front_winding = COGL_FRONT_WINDING_COUNTER_CLOCKWISE;
@ -81,10 +82,20 @@ cogl_create_context (void)
cogl_matrix_scale (&_context->y_flip_matrix, 1, -1, 1); cogl_matrix_scale (&_context->y_flip_matrix, 1, -1, 1);
_context->flushed_matrix_mode = COGL_MATRIX_MODELVIEW; _context->flushed_matrix_mode = COGL_MATRIX_MODELVIEW;
_context->texture_units = NULL;
_context->texture_units =
g_array_new (FALSE, FALSE, sizeof (CoglTextureUnit));
/* See cogl-material.c for more details about why we leave texture unit 1
* active by default... */
_context->active_texture_unit = 1;
GE (glActiveTexture (GL_TEXTURE1));
_context->simple_material = cogl_material_new (); _context->simple_material = cogl_material_new ();
_context->source_material = NULL; _context->source_material = NULL;
_context->arbfp_source_buffer = g_string_new ("");
_context->legacy_state_set = 0;
_context->default_gl_texture_2d_tex = COGL_INVALID_HANDLE; _context->default_gl_texture_2d_tex = COGL_INVALID_HANDLE;
_context->default_gl_texture_rect_tex = COGL_INVALID_HANDLE; _context->default_gl_texture_rect_tex = COGL_INVALID_HANDLE;
@ -93,15 +104,25 @@ cogl_create_context (void)
_context->logged_vertices = g_array_new (FALSE, FALSE, sizeof (GLfloat)); _context->logged_vertices = g_array_new (FALSE, FALSE, sizeof (GLfloat));
_context->current_material = NULL; _context->current_material = NULL;
_context->current_material_flags = 0; _context->current_material_flags = COGL_MATERIAL_FLAGS_INIT;
memset (&_context->current_material_flush_options, _context->current_material_fallback_layers = 0;
0, sizeof (CoglMaterialFlushOptions)); _context->current_material_disable_layers = 0;
_context->current_layers = g_array_new (FALSE, FALSE, _context->current_material_layer0_override = 0;
sizeof (CoglLayerInfo)); _context->current_material_skip_gl_color = FALSE;
_cogl_bitmask_init (&_context->texcoord_arrays_enabled); _cogl_bitmask_init (&_context->texcoord_arrays_enabled);
_cogl_bitmask_init (&_context->temp_bitmask); _cogl_bitmask_init (&_context->temp_bitmask);
_cogl_bitmask_init (&_context->texcoord_arrays_to_disable); _cogl_bitmask_init (&_context->texcoord_arrays_to_disable);
_context->max_texture_units = -1;
_context->max_texture_image_units = -1;
_context->max_activateable_texture_units = -1;
_context->current_program = COGL_INVALID_HANDLE;
_context->current_use_program_type = COGL_MATERIAL_PROGRAM_TYPE_FIXED;
_context->current_gl_program = 0;
_context->framebuffer_stack = _cogl_create_framebuffer_stack (); _context->framebuffer_stack = _cogl_create_framebuffer_stack ();
window_buffer = _cogl_onscreen_new (); window_buffer = _cogl_onscreen_new ();
@ -162,8 +183,6 @@ cogl_create_context (void)
_context->current_pbo = NULL; _context->current_pbo = NULL;
_context->max_texture_units = -1;
return TRUE; return TRUE;
} }
@ -194,9 +213,6 @@ _cogl_destroy_context (void)
if (_context->logged_vertices) if (_context->logged_vertices)
g_array_free (_context->logged_vertices, TRUE); g_array_free (_context->logged_vertices, TRUE);
if (_context->current_layers)
g_array_free (_context->current_layers, TRUE);
if (_context->quad_indices_byte) if (_context->quad_indices_byte)
cogl_handle_unref (_context->quad_indices_byte); cogl_handle_unref (_context->quad_indices_byte);
if (_context->quad_indices_short) if (_context->quad_indices_short)

View File

@ -53,6 +53,7 @@ typedef struct
/* Enable cache */ /* Enable cache */
unsigned long enable_flags; unsigned long enable_flags;
guint8 color_alpha; guint8 color_alpha;
gboolean fog_enabled;
gboolean enable_backface_culling; gboolean enable_backface_culling;
CoglFrontWinding flushed_front_winding; CoglFrontWinding flushed_front_winding;
@ -65,11 +66,16 @@ typedef struct
/* Client-side matrix stack or NULL if none */ /* Client-side matrix stack or NULL if none */
CoglMatrixMode flushed_matrix_mode; CoglMatrixMode flushed_matrix_mode;
GList *texture_units;
GArray *texture_units;
int active_texture_unit;
/* Materials */ /* Materials */
CoglHandle simple_material; CoglHandle simple_material;
CoglHandle source_material; CoglHandle source_material;
GString *arbfp_source_buffer;
int legacy_state_set;
/* Textures */ /* Textures */
CoglHandle default_gl_texture_2d_tex; CoglHandle default_gl_texture_2d_tex;
@ -86,8 +92,10 @@ typedef struct
/* Some simple caching, to minimize state changes... */ /* Some simple caching, to minimize state changes... */
CoglHandle current_material; CoglHandle current_material;
unsigned long current_material_flags; unsigned long current_material_flags;
CoglMaterialFlushOptions current_material_flush_options; gboolean current_material_fallback_layers;
GArray *current_layers; gboolean current_material_disable_layers;
GLuint current_material_layer0_override;
gboolean current_material_skip_gl_color;
/* Bitmask of texture coordinates arrays that are enabled */ /* Bitmask of texture coordinates arrays that are enabled */
CoglBitmask texcoord_arrays_enabled; CoglBitmask texcoord_arrays_enabled;
/* These are temporary bitmasks that are used when disabling /* These are temporary bitmasks that are used when disabling
@ -129,9 +137,15 @@ typedef struct
chances of getting the same colour during an animation */ chances of getting the same colour during an animation */
guint8 journal_rectangles_color; guint8 journal_rectangles_color;
/* Cached value for GL_MAX_TEXTURE_UNITS to avoid calling /* Cached values for GL_MAX_TEXTURE_[IMAGE_]UNITS to avoid calling
glGetInteger too often */ glGetInteger too often */
GLint max_texture_units; GLint max_texture_units;
GLint max_texture_image_units;
GLint max_activateable_texture_units;
CoglHandle current_program;
CoglMaterialProgramType current_use_program_type;
GLuint current_gl_program;
CoglContextDriver drv; CoglContextDriver drv;
} CoglContext; } CoglContext;

View File

@ -50,6 +50,7 @@ static const GDebugKey cogl_log_debug_keys[] = {
{ "draw", COGL_DEBUG_DRAW }, { "draw", COGL_DEBUG_DRAW },
{ "opengl", COGL_DEBUG_OPENGL }, { "opengl", COGL_DEBUG_OPENGL },
{ "pango", COGL_DEBUG_PANGO }, { "pango", COGL_DEBUG_PANGO },
{ "show-source", COGL_DEBUG_SHOW_SOURCE}
}; };
static const int n_cogl_log_debug_keys = static const int n_cogl_log_debug_keys =
G_N_ELEMENTS (cogl_log_debug_keys); G_N_ELEMENTS (cogl_log_debug_keys);
@ -61,7 +62,10 @@ static const GDebugKey cogl_behavioural_debug_keys[] = {
{ "disable-software-transform", COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM }, { "disable-software-transform", COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM },
{ "force-scanline-paths", COGL_DEBUG_FORCE_SCANLINE_PATHS }, { "force-scanline-paths", COGL_DEBUG_FORCE_SCANLINE_PATHS },
{ "dump-atlas-image", COGL_DEBUG_DUMP_ATLAS_IMAGE }, { "dump-atlas-image", COGL_DEBUG_DUMP_ATLAS_IMAGE },
{ "disable-atlas", COGL_DEBUG_DISABLE_ATLAS } { "disable-atlas", COGL_DEBUG_DISABLE_ATLAS },
{ "disable-texturing", COGL_DEBUG_DISABLE_TEXTURING},
{ "disable-arbfp", COGL_DEBUG_DISABLE_ARBFP},
{ "disable-glsl", COGL_DEBUG_DISABLE_GLSL}
}; };
static const int n_cogl_behavioural_debug_keys = static const int n_cogl_behavioural_debug_keys =
G_N_ELEMENTS (cogl_behavioural_debug_keys); G_N_ELEMENTS (cogl_behavioural_debug_keys);
@ -115,6 +119,10 @@ _cogl_parse_debug_string (const char *value,
OPT ("force-scanline-paths:", "use a scanline based path rasterizer"); OPT ("force-scanline-paths:", "use a scanline based path rasterizer");
OPT ("dump-atlas-image:", "dump atlas changes to an image file"); OPT ("dump-atlas-image:", "dump atlas changes to an image file");
OPT ("disable-atlas:", "disable texture atlasing"); OPT ("disable-atlas:", "disable texture atlasing");
OPT ("disable-texturing:", "disable texturing primitives");
OPT ("disable-arbfp:", "disable use of ARBfp");
OPT ("disable-glsl:", "disable use of GLSL");
OPT ("show-source:", "show generated ARBfp/GLSL");
OPT ("opengl:", "traces some select OpenGL calls"); OPT ("opengl:", "traces some select OpenGL calls");
g_printerr ("\n%28s\n", "Special debug values:"); g_printerr ("\n%28s\n", "Special debug values:");
OPT ("all:", "Enables all non-behavioural debug options"); OPT ("all:", "Enables all non-behavioural debug options");

View File

@ -46,7 +46,11 @@ typedef enum {
COGL_DEBUG_ATLAS = 1 << 15, COGL_DEBUG_ATLAS = 1 << 15,
COGL_DEBUG_DUMP_ATLAS_IMAGE = 1 << 16, COGL_DEBUG_DUMP_ATLAS_IMAGE = 1 << 16,
COGL_DEBUG_DISABLE_ATLAS = 1 << 17, COGL_DEBUG_DISABLE_ATLAS = 1 << 17,
COGL_DEBUG_OPENGL = 1 << 18 COGL_DEBUG_OPENGL = 1 << 18,
COGL_DEBUG_DISABLE_TEXTURING = 1 << 19,
COGL_DEBUG_DISABLE_ARBFP = 1 << 20,
COGL_DEBUG_DISABLE_GLSL = 1 << 21,
COGL_DEBUG_SHOW_SOURCE = 1 << 22
} CoglDebugFlags; } CoglDebugFlags;
#ifdef COGL_ENABLE_DEBUG #ifdef COGL_ENABLE_DEBUG

View File

@ -115,21 +115,6 @@ _cogl_enable (unsigned long flags);
unsigned long unsigned long
_cogl_get_enable (void); _cogl_get_enable (void);
typedef struct _CoglTextureUnit
{
int index;
CoglMatrixStack *matrix_stack;
} CoglTextureUnit;
CoglTextureUnit *
_cogl_get_texture_unit (int index_);
void
_cogl_destroy_texture_units (void);
unsigned int
_cogl_get_max_texture_image_units (void);
void void
_cogl_flush_face_winding (void); _cogl_flush_face_winding (void);

View File

@ -792,7 +792,16 @@ _cogl_journal_log_quad (const float *position,
disable_layers = (1 << n_layers) - 1; disable_layers = (1 << n_layers) - 1;
disable_layers = ~disable_layers; disable_layers = ~disable_layers;
if (G_UNLIKELY (ctx->legacy_state_set))
{
material = cogl_material_copy (material);
_cogl_material_apply_legacy_state (material);
entry->material = _cogl_material_journal_ref (material); entry->material = _cogl_material_journal_ref (material);
cogl_handle_unref (material);
}
else
entry->material = _cogl_material_journal_ref (material);
entry->n_layers = n_layers; entry->n_layers = n_layers;
entry->flush_options.flags = entry->flush_options.flags =
COGL_MATERIAL_FLUSH_FALLBACK_MASK | COGL_MATERIAL_FLUSH_FALLBACK_MASK |

View File

@ -29,6 +29,7 @@
#include "cogl-material.h" #include "cogl-material.h"
#include "cogl-matrix.h" #include "cogl-matrix.h"
#include "cogl-matrix-stack.h"
#include "cogl-handle.h" #include "cogl-handle.h"
#include <glib.h> #include <glib.h>
@ -36,6 +37,92 @@
typedef struct _CoglMaterial CoglMaterial; typedef struct _CoglMaterial CoglMaterial;
typedef struct _CoglMaterialLayer CoglMaterialLayer; typedef struct _CoglMaterialLayer CoglMaterialLayer;
/*
* cogl-material.c owns the GPU's texture unit state so we have some
* private structures for describing the current state of a texture
* unit that we track in a per context array (ctx->texture_units) that
* grows according to the largest texture unit used so far...
*
* Roughly speaking the members in this structure are of two kinds:
* either they are a low level reflection of the state we send to
* OpenGL or they are for high level meta data assoicated with the
* texture unit when flushing CoglMaterialLayers that is typically
* used to optimize subsequent re-flushing of the same layer.
*
* The low level members are at the top, and the high level members
* start with the .layer member.
*/
typedef struct _CoglTextureUnit
{
/* The base 0 texture unit index which can be used with
* glActiveTexture () */
int index;
/* Whether or not the corresponding gl_target has been glEnabled */
gboolean enabled;
/* The GL target currently glEnabled or 0 if .enabled == FALSE */
GLenum enabled_gl_target;
/* The raw GL texture object name for which we called glBindTexture when
* we flushed the last layer. (NB: The CoglTexture associated
* with a layer may represent more than one GL texture) */
GLuint gl_texture;
/* A matrix stack giving us the means to associate a texture
* transform matrix with the texture unit. */
CoglMatrixStack *matrix_stack;
/*
* Higher level layer state associated with the unit...
*/
/* The CoglMaterialLayer whos state was flushed to update this
* texture unit last.
*
* This will be set to NULL if the layer is modified or freed which
* means when we come to flush a layer; if this pointer is still
* valid and == to the layer being flushed we don't need to update
* any texture unit state. */
CoglMaterialLayer *layer;
/* To help minimize the state changes required we track the
* difference flags associated with the layer whos state was last
* flushed to update this texture unit.
*
* Note: we track this explicitly because .layer may get invalidated
* if that layer is modified or deleted. Even if the layer is
* invalidated though these flags can be used to optimize the state
* flush of the next layer
*/
unsigned long layer_differences;
/* The options that may have affected how the layer state updated
* this texture unit. */
gboolean fallback;
gboolean layer0_overridden;
/* When flushing a layers state, fallback options may mean that a
* different CoglTexture is used than layer->texture.
*
* Once a layers state has been flushed we have to keep track of
* changes to that layer so if we are asked to re-flush the same
* layer later we will know what work is required. This also means
* we need to keep track of changes to the CoglTexture of that layer
* so we need to explicitly keep a reference to the final texture
* chosen.
*/
CoglHandle texture;
} CoglTextureUnit;
CoglTextureUnit *
_cogl_get_texture_unit (int index_);
void
_cogl_destroy_texture_units (void);
typedef enum _CoglMaterialEqualFlags typedef enum _CoglMaterialEqualFlags
{ {
/* Return FALSE if any component of either material isn't set to its /* Return FALSE if any component of either material isn't set to its
@ -46,35 +133,41 @@ typedef enum _CoglMaterialEqualFlags
} CoglMaterialEqualFlags; } CoglMaterialEqualFlags;
/* XXX: I don't think gtk-doc supports having private enums so these aren't typedef enum _CoglMaterialLayerDifferenceFlags
* bundled in with CoglMaterialLayerFlags */
typedef enum _CoglMaterialLayerPrivFlags
{ {
/* Ref: CoglMaterialLayerFlags COGL_MATERIAL_LAYER_DIFFERENCE_TEXTURE = 1L<<0,
COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX = 1L<<0 COGL_MATERIAL_LAYER_DIFFERENCE_COMBINE = 1L<<1,
*/ COGL_MATERIAL_LAYER_DIFFERENCE_COMBINE_CONSTANT = 1L<<2,
COGL_MATERIAL_LAYER_FLAG_DIRTY = 1L<<1, COGL_MATERIAL_LAYER_DIFFERENCE_USER_MATRIX = 1L<<3,
COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE = 1L<<2 COGL_MATERIAL_LAYER_DIFFERENCE_FILTERS = 1L<<4
} CoglMaterialLayerPrivFlags; } CoglMaterialLayerDifferenceFlags;
/* For tracking the state of a layer that's been flushed to OpenGL */ typedef enum _CoglMaterialLayerChangeFlags
typedef struct _CoglLayerInfo
{ {
CoglHandle handle; COGL_MATERIAL_LAYER_CHANGE_TEXTURE = 1L<<0,
unsigned long flags; COGL_MATERIAL_LAYER_CHANGE_COMBINE = 1L<<1,
GLenum gl_target; COGL_MATERIAL_LAYER_CHANGE_COMBINE_CONSTANT = 1L<<2,
GLuint gl_texture; COGL_MATERIAL_LAYER_CHANGE_USER_MATRIX = 1L<<3,
gboolean fallback; COGL_MATERIAL_LAYER_CHANGE_FILTERS = 1L<<4,
gboolean disabled;
gboolean layer0_overridden; COGL_MATERIAL_LAYER_CHANGE_TEXTURE_INTERN = 1L<<5,
} CoglLayerInfo; COGL_MATERIAL_LAYER_CHANGE_UNIT = 1L<<6
} CoglMaterialLayerChangeFlags;
struct _CoglMaterialLayer struct _CoglMaterialLayer
{ {
CoglHandleObject _parent; CoglHandleObject _parent;
/* Parent material */
CoglMaterial *material;
unsigned int index; /*!< lowest index is blended first then others on unsigned int index; /*!< lowest index is blended first then others on
top */ top */
unsigned long flags;
int unit_index;
unsigned long differences;
CoglHandle texture; /*!< The texture for this layer, or CoglHandle texture; /*!< The texture for this layer, or
COGL_INVALID_HANDLE for an empty layer */ COGL_INVALID_HANDLE for an empty layer */
@ -100,33 +193,48 @@ struct _CoglMaterialLayer
/* TODO: Support purely GLSL based material layers */ /* TODO: Support purely GLSL based material layers */
CoglMatrix matrix; CoglMatrix matrix;
/* Different material backends (GLSL/ARBfp/Fixed Function) may
* want to associate private data with a layer... */
void *backend_priv;
}; };
typedef enum _CoglMaterialFlags typedef enum _CoglMaterialFlags
{ {
COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING = 1L<<0,
COGL_MATERIAL_FLAG_DEFAULT_COLOR = 1L<<1, COGL_MATERIAL_FLAG_DEFAULT_COLOR = 1L<<1,
COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL = 1L<<2, COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL = 1L<<2,
COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC = 1L<<3, COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC = 1L<<3,
COGL_MATERIAL_FLAG_ENABLE_BLEND = 1L<<4, COGL_MATERIAL_FLAG_ENABLE_BLEND = 1L<<4,
COGL_MATERIAL_FLAG_DEFAULT_BLEND = 1L<<5 COGL_MATERIAL_FLAG_DEFAULT_BLEND = 1L<<5,
COGL_MATERIAL_FLAG_DEFAULT_USER_SHADER = 1L<<6,
COGL_MATERIAL_FLAG_DEFAULT_LAYERS = 1L<<7
} CoglMaterialFlags; } CoglMaterialFlags;
/* ARBfp1.0 program (Fog + ARB_texture_env_combine) */ /* This defines the initialization state for
typedef struct _CoglMaterialProgram * ctx->current_material_flags which should result in the first
{ * material flush explicitly initializing everything
GString *source; */
GLuint gl_program; #define COGL_MATERIAL_FLAGS_INIT \
COGL_MATERIAL_FLAG_DEFAULT_USER_SHADER
gboolean *sampled; typedef enum _CoglMaterialChangeFlag
} CoglMaterialProgram; {
COGL_MATERIAL_CHANGE_COLOR = 1L<<1,
COGL_MATERIAL_CHANGE_GL_MATERIAL = 1L<<2,
COGL_MATERIAL_CHANGE_ALPHA_FUNC = 1L<<3,
COGL_MATERIAL_CHANGE_ENABLE_BLEND = 1L<<4,
COGL_MATERIAL_CHANGE_BLEND = 1L<<5,
COGL_MATERIAL_CHANGE_USER_SHADER = 1L<<6,
COGL_MATERIAL_CHANGE_LAYERS = 1L<<7
} CoglMaterialChangeFlag;
struct _CoglMaterial struct _CoglMaterial
{ {
CoglHandleObject _parent; CoglHandleObject _parent;
unsigned long journal_ref_count; unsigned long journal_ref_count;
int backend;
unsigned long flags; unsigned long flags;
/* If no lighting is enabled; this is the basic material color */ /* If no lighting is enabled; this is the basic material color */
@ -154,12 +262,39 @@ struct _CoglMaterial
GLint blend_src_factor_rgb; GLint blend_src_factor_rgb;
GLint blend_dst_factor_rgb; GLint blend_dst_factor_rgb;
CoglMaterialProgram program; CoglHandle user_program;
GList *layers; GList *layers;
unsigned int n_layers; unsigned int n_layers;
void *backend_priv;
}; };
typedef struct _CoglMaterialBackend
{
int (*get_max_texture_units) (void);
gboolean (*start) (CoglMaterial *material);
gboolean (*add_layer) (CoglMaterialLayer *layer);
gboolean (*passthrough) (CoglMaterial *material);
gboolean (*end) (CoglMaterial *material);
void (*material_change_notify) (CoglMaterial *material,
unsigned long changes,
GLubyte *new_color);
void (*layer_change_notify) (CoglMaterialLayer *layer,
unsigned long changes);
void (*free_priv) (CoglMaterial *material);
} CoglMaterialBackend;
typedef enum
{
COGL_MATERIAL_PROGRAM_TYPE_GLSL = 1,
COGL_MATERIAL_PROGRAM_TYPE_ARBFP,
COGL_MATERIAL_PROGRAM_TYPE_FIXED
} CoglMaterialProgramType;
/* /*
* SECTION:cogl-material-internals * SECTION:cogl-material-internals
* @short_description: Functions for creating custom primitives that make use * @short_description: Functions for creating custom primitives that make use
@ -197,29 +332,8 @@ _cogl_material_init_default_material (void);
unsigned long unsigned long
_cogl_material_get_cogl_enable_flags (CoglHandle handle); _cogl_material_get_cogl_enable_flags (CoglHandle handle);
/* gboolean
* CoglMaterialLayerFlags: _cogl_material_layer_has_user_matrix (CoglHandle layer_handle);
* @COGL_MATERIAL_LAYER_FLAG_USER_MATRIX: Means the user has supplied a
* custom texture matrix.
*/
typedef enum _CoglMaterialLayerFlags
{
COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX = 1L<<0
} CoglMaterialLayerFlags;
/* XXX: NB: if you add flags here you will need to update
* CoglMaterialLayerPrivFlags!!! */
/*
* cogl_material_layer_get_flags:
* @layer_handle: A CoglMaterialLayer layer handle
*
* This lets you get a number of flag attributes about the layer. Normally
* you shouldn't need to use this function directly since Cogl will do this
* internally, but if you are developing custom primitives directly with
* OpenGL you may need this.
*/
unsigned long
_cogl_material_layer_get_flags (CoglHandle layer_handle);
/* /*
* Ensures the mipmaps are available for the texture in the layer if * Ensures the mipmaps are available for the texture in the layer if
@ -322,5 +436,15 @@ _cogl_material_set_layer_wrap_mode_r (CoglHandle material,
CoglMaterialWrapMode CoglMaterialWrapMode
_cogl_material_layer_get_wrap_mode_r (CoglHandle layer); _cogl_material_layer_get_wrap_mode_r (CoglHandle layer);
void
_cogl_material_set_user_program (CoglHandle handle,
CoglHandle program);
void
_cogl_material_apply_legacy_state (CoglHandle handle);
void
_cogl_gl_use_program_wrapper (GLuint program);
#endif /* __COGL_MATERIAL_PRIVATE_H */ #endif /* __COGL_MATERIAL_PRIVATE_H */

File diff suppressed because it is too large Load Diff

View File

@ -132,6 +132,7 @@ _cogl_path_stroke_nodes (void)
unsigned long enable_flags = COGL_ENABLE_VERTEX_ARRAY; unsigned long enable_flags = COGL_ENABLE_VERTEX_ARRAY;
CoglPathData *data; CoglPathData *data;
CoglMaterialFlushOptions options; CoglMaterialFlushOptions options;
CoglHandle source;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -151,7 +152,15 @@ _cogl_path_stroke_nodes (void)
/* disable all texture layers */ /* disable all texture layers */
options.disable_layers = (guint32)~0; options.disable_layers = (guint32)~0;
_cogl_material_flush_gl_state (ctx->source_material, &options); if (G_UNLIKELY (ctx->legacy_state_set))
{
source = cogl_material_copy (ctx->source_material);
_cogl_material_apply_legacy_state (source);
}
else
source = ctx->source_material;
_cogl_material_flush_gl_state (source, &options);
while (path_start < data->path_nodes->len) while (path_start < data->path_nodes->len)
{ {
@ -163,6 +172,9 @@ _cogl_path_stroke_nodes (void)
path_start += node->path_size; path_start += node->path_size;
} }
if (G_UNLIKELY (source != ctx->source_material))
cogl_handle_unref (source);
} }
static void static void
@ -332,6 +344,8 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
unsigned int bounds_w, unsigned int bounds_w,
unsigned int bounds_h) unsigned int bounds_h)
{ {
CoglHandle source;
/* This is our edge list it stores intersections between our /* This is our edge list it stores intersections between our
* curve and scanlines, it should probably be implemented with a * curve and scanlines, it should probably be implemented with a
* data structure that has smaller overhead for inserting the * data structure that has smaller overhead for inserting the
@ -359,6 +373,14 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
* always be done first when preparing to draw. */ * always be done first when preparing to draw. */
_cogl_framebuffer_flush_state (_cogl_get_framebuffer (), 0); _cogl_framebuffer_flush_state (_cogl_get_framebuffer (), 0);
if (G_UNLIKELY (ctx->legacy_state_set))
{
source = cogl_material_copy (ctx->source_material);
_cogl_material_apply_legacy_state (source);
}
else
source = ctx->source_material;
_cogl_material_flush_gl_state (ctx->source_material, NULL); _cogl_material_flush_gl_state (ctx->source_material, NULL);
_cogl_enable (COGL_ENABLE_VERTEX_ARRAY _cogl_enable (COGL_ENABLE_VERTEX_ARRAY
@ -502,6 +524,9 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
GE (glDrawArrays (GL_TRIANGLES, 0, spans * 2 * 3)); GE (glDrawArrays (GL_TRIANGLES, 0, spans * 2 * 3));
g_free (coords); g_free (coords);
} }
if (G_UNLIKELY (source != ctx->source_material))
cogl_handle_unref (source);
} }
static void static void

View File

@ -59,8 +59,6 @@
#define glDeleteBuffers ctx->drv.pf_glDeleteBuffers #define glDeleteBuffers ctx->drv.pf_glDeleteBuffers
#define glMapBuffer ctx->drv.pf_glMapBuffer #define glMapBuffer ctx->drv.pf_glMapBuffer
#define glUnmapBuffer ctx->drv.pf_glUnmapBuffer #define glUnmapBuffer ctx->drv.pf_glUnmapBuffer
#define glActiveTexture ctx->drv.pf_glActiveTexture
#define glClientActiveTexture ctx->drv.pf_glClientActiveTexture
#ifndef GL_PIXEL_UNPACK_BUFFER #ifndef GL_PIXEL_UNPACK_BUFFER
#define GL_PIXEL_UNPACK_BUFFER GL_PIXEL_UNPACK_BUFFER_ARB #define GL_PIXEL_UNPACK_BUFFER GL_PIXEL_UNPACK_BUFFER_ARB

View File

@ -516,7 +516,6 @@ _cogl_rectangles_with_multitexture_coords (
{ {
CoglHandle layer = tmp->data; CoglHandle layer = tmp->data;
CoglHandle tex_handle; CoglHandle tex_handle;
unsigned long flags;
if (cogl_material_layer_get_type (layer) if (cogl_material_layer_get_type (layer)
!= COGL_MATERIAL_LAYER_TYPE_TEXTURE) != COGL_MATERIAL_LAYER_TYPE_TEXTURE)
@ -619,8 +618,7 @@ _cogl_rectangles_with_multitexture_coords (
* waste or if using GL_TEXTURE_RECTANGLE_ARB) then we don't support * waste or if using GL_TEXTURE_RECTANGLE_ARB) then we don't support
* multi texturing since we don't know if the result will end up trying * multi texturing since we don't know if the result will end up trying
* to texture from the waste area. */ * to texture from the waste area. */
flags = _cogl_material_layer_get_flags (layer); if (_cogl_material_layer_has_user_matrix (layer)
if (flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX
&& !_cogl_texture_can_hardware_repeat (tex_handle)) && !_cogl_texture_can_hardware_repeat (tex_handle))
{ {
static gboolean warning_seen = FALSE; static gboolean warning_seen = FALSE;
@ -838,6 +836,7 @@ draw_polygon_sub_texture_cb (CoglHandle tex_handle,
float virtual_origin_y; float virtual_origin_y;
float v_to_s_scale_x; float v_to_s_scale_x;
float v_to_s_scale_y; float v_to_s_scale_y;
CoglHandle source;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -888,9 +887,20 @@ draw_polygon_sub_texture_cb (CoglHandle tex_handle,
options.wrap_mode_overrides.values[0].t = options.wrap_mode_overrides.values[0].t =
COGL_MATERIAL_WRAP_MODE_OVERRIDE_CLAMP_TO_BORDER; COGL_MATERIAL_WRAP_MODE_OVERRIDE_CLAMP_TO_BORDER;
_cogl_material_flush_gl_state (ctx->source_material, &options); if (G_UNLIKELY (ctx->legacy_state_set))
{
source = cogl_material_copy (ctx->source_material);
_cogl_material_apply_legacy_state (source);
}
else
source = ctx->source_material;
_cogl_material_flush_gl_state (source, &options);
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, state->n_vertices)); GE (glDrawArrays (GL_TRIANGLE_FAN, 0, state->n_vertices));
if (G_UNLIKELY (source != ctx->source_material))
cogl_handle_unref (source);
} }
/* handles 2d-sliced textures with > 1 slice */ /* handles 2d-sliced textures with > 1 slice */
@ -963,6 +973,7 @@ _cogl_multitexture_polygon_single_primitive (const CoglTextureVertex *vertices,
GList *tmp; GList *tmp;
GLfloat *v; GLfloat *v;
CoglMaterialFlushOptions options; CoglMaterialFlushOptions options;
CoglHandle source;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -1028,9 +1039,21 @@ _cogl_multitexture_polygon_single_primitive (const CoglTextureVertex *vertices,
options.flags |= COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES; options.flags |= COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES;
options.wrap_mode_overrides = *wrap_mode_overrides; options.wrap_mode_overrides = *wrap_mode_overrides;
} }
_cogl_material_flush_gl_state (ctx->source_material, &options);
if (G_UNLIKELY (ctx->legacy_state_set))
{
source = cogl_material_copy (ctx->source_material);
_cogl_material_apply_legacy_state (source);
}
else
source = ctx->source_material;
_cogl_material_flush_gl_state (source, &options);
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices)); GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices));
if (G_UNLIKELY (source != ctx->source_material))
cogl_handle_unref (source);
} }
void void

View File

@ -159,7 +159,6 @@
#define glDeleteBuffers ctx->drv.pf_glDeleteBuffers #define glDeleteBuffers ctx->drv.pf_glDeleteBuffers
#define glMapBuffer ctx->drv.pf_glMapBuffer #define glMapBuffer ctx->drv.pf_glMapBuffer
#define glUnmapBuffer ctx->drv.pf_glUnmapBuffer #define glUnmapBuffer ctx->drv.pf_glUnmapBuffer
#define glActiveTexture ctx->drv.pf_glActiveTexture
#define glClientActiveTexture ctx->drv.pf_glClientActiveTexture #define glClientActiveTexture ctx->drv.pf_glClientActiveTexture
#ifndef GL_ARRAY_BUFFER #ifndef GL_ARRAY_BUFFER
#define GL_ARRAY_BUFFER GL_ARRAY_BUFFER_ARB #define GL_ARRAY_BUFFER GL_ARRAY_BUFFER_ARB
@ -1509,7 +1508,7 @@ get_gl_type_from_attribute_flags (CoglVertexBufferAttribFlags flags)
} }
} }
static void static CoglHandle
enable_state_for_drawing_buffer (CoglVertexBuffer *buffer) enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
{ {
GList *tmp; GList *tmp;
@ -1522,8 +1521,9 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
guint32 fallback_layers = 0; guint32 fallback_layers = 0;
int i; int i;
CoglMaterialFlushOptions options; CoglMaterialFlushOptions options;
CoglHandle source;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
if (buffer->new_attributes) if (buffer->new_attributes)
cogl_vertex_buffer_submit_real (buffer); cogl_vertex_buffer_submit_real (buffer);
@ -1717,18 +1717,29 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
options.fallback_layers = fallback_layers; options.fallback_layers = fallback_layers;
_cogl_material_flush_gl_state (ctx->source_material, &options); if (G_UNLIKELY (ctx->legacy_state_set))
enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material); {
source = cogl_material_copy (ctx->source_material);
_cogl_material_apply_legacy_state (source);
}
else
source = ctx->source_material;
_cogl_material_flush_gl_state (source, &options);
enable_flags |= _cogl_material_get_cogl_enable_flags (source);
if (ctx->enable_backface_culling) if (ctx->enable_backface_culling)
enable_flags |= COGL_ENABLE_BACKFACE_CULLING; enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
_cogl_enable (enable_flags); _cogl_enable (enable_flags);
_cogl_flush_face_winding (); _cogl_flush_face_winding ();
return source;
} }
static void static void
disable_state_for_drawing_buffer (CoglVertexBuffer *buffer) disable_state_for_drawing_buffer (CoglVertexBuffer *buffer,
CoglHandle source)
{ {
GList *tmp; GList *tmp;
GLenum gl_type; GLenum gl_type;
@ -1738,6 +1749,9 @@ disable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (G_UNLIKELY (source != ctx->source_material))
cogl_handle_unref (source);
/* Disable all the client state that cogl doesn't currently know /* Disable all the client state that cogl doesn't currently know
* about: * about:
*/ */
@ -1798,6 +1812,7 @@ cogl_vertex_buffer_draw (CoglHandle handle,
int count) int count)
{ {
CoglVertexBuffer *buffer; CoglVertexBuffer *buffer;
CoglHandle source;
if (!cogl_is_vertex_buffer (handle)) if (!cogl_is_vertex_buffer (handle))
return; return;
@ -1806,11 +1821,11 @@ cogl_vertex_buffer_draw (CoglHandle handle,
buffer = _cogl_vertex_buffer_pointer_from_handle (handle); buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
enable_state_for_drawing_buffer (buffer); source = enable_state_for_drawing_buffer (buffer);
GE (glDrawArrays (mode, first, count)); GE (glDrawArrays (mode, first, count));
disable_state_for_drawing_buffer (buffer); disable_state_for_drawing_buffer (buffer, source);
} }
static int static int
@ -1934,6 +1949,7 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle,
(cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE; (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
gsize byte_offset; gsize byte_offset;
CoglVertexBufferIndices *indices = NULL; CoglVertexBufferIndices *indices = NULL;
CoglHandle source;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -1949,7 +1965,7 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle,
indices = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle); indices = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
enable_state_for_drawing_buffer (buffer); source = enable_state_for_drawing_buffer (buffer);
byte_offset = indices_offset * get_indices_type_size (indices->type); byte_offset = indices_offset * get_indices_type_size (indices->type);
if (fallback) if (fallback)
@ -1961,7 +1977,7 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle,
GE (glDrawRangeElements (mode, min_index, max_index, GE (glDrawRangeElements (mode, min_index, max_index,
count, indices->type, (void *)byte_offset)); count, indices->type, (void *)byte_offset));
disable_state_for_drawing_buffer (buffer); disable_state_for_drawing_buffer (buffer, source);
GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0)); GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0));
} }

View File

@ -493,6 +493,9 @@ cogl_get_features (void)
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_VBOS)) if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_VBOS))
ctx->feature_flags &= ~COGL_FEATURE_VBOS; ctx->feature_flags &= ~COGL_FEATURE_VBOS;
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_GLSL))
ctx->feature_flags &= ~COGL_FEATURE_SHADERS_GLSL;
return ctx->feature_flags; return ctx->feature_flags;
} }
@ -515,6 +518,9 @@ _cogl_features_available_private (CoglFeatureFlagsPrivate features)
if (!ctx->features_cached) if (!ctx->features_cached)
_cogl_features_init (); _cogl_features_init ();
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_ARBFP))
ctx->feature_flags_private &= ~COGL_FEATURE_PRIVATE_ARB_FP;
return (ctx->feature_flags_private & features) == features; return (ctx->feature_flags_private & features) == features;
} }
@ -571,6 +577,8 @@ cogl_set_fog (const CoglColor *fog_color,
GLfloat fogColor[4]; GLfloat fogColor[4];
GLenum gl_mode = GL_LINEAR; GLenum gl_mode = GL_LINEAR;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* The cogl journal doesn't currently track fog state changes */ /* The cogl journal doesn't currently track fog state changes */
_cogl_journal_flush (); _cogl_journal_flush ();
@ -606,15 +614,20 @@ cogl_set_fog (const CoglColor *fog_color,
glFogf (GL_FOG_DENSITY, (GLfloat) density); glFogf (GL_FOG_DENSITY, (GLfloat) density);
glFogf (GL_FOG_START, (GLfloat) z_near); glFogf (GL_FOG_START, (GLfloat) z_near);
glFogf (GL_FOG_END, (GLfloat) z_far); glFogf (GL_FOG_END, (GLfloat) z_far);
ctx->fog_enabled = TRUE;
} }
void void
cogl_disable_fog (void) cogl_disable_fog (void)
{ {
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* Currently the journal can't track changes to fog state... */ /* Currently the journal can't track changes to fog state... */
_cogl_journal_flush (); _cogl_journal_flush ();
glDisable (GL_FOG); glDisable (GL_FOG);
ctx->fog_enabled = FALSE;
} }
void void
@ -876,102 +889,6 @@ cogl_end_gl (void)
ctx->in_begin_gl_block = FALSE; ctx->in_begin_gl_block = FALSE;
} }
static CoglTextureUnit *
_cogl_texture_unit_new (int index_)
{
CoglTextureUnit *unit = g_new0 (CoglTextureUnit, 1);
unit->matrix_stack = _cogl_matrix_stack_new ();
unit->index = index_;
return unit;
}
static void
_cogl_texture_unit_free (CoglTextureUnit *unit)
{
_cogl_matrix_stack_destroy (unit->matrix_stack);
g_free (unit);
}
CoglTextureUnit *
_cogl_get_texture_unit (int index_)
{
GList *l;
CoglTextureUnit *unit;
_COGL_GET_CONTEXT (ctx, NULL);
for (l = ctx->texture_units; l; l = l->next)
{
unit = l->data;
if (unit->index == index_)
return unit;
/* The units are always sorted, so at this point we know this unit
* doesn't exist */
if (unit->index > index_)
break;
}
/* NB: if we now insert a new layer before l, that will maintain order.
*/
unit = _cogl_texture_unit_new (index_);
/* Note: see comment after for() loop above */
ctx->texture_units =
g_list_insert_before (ctx->texture_units, l, unit);
return unit;
}
void
_cogl_destroy_texture_units (void)
{
GList *l;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
for (l = ctx->texture_units; l; l = l->next)
_cogl_texture_unit_free (l->data);
g_list_free (ctx->texture_units);
}
/*
* This is more complicated than that, another pass needs to be done when
* cogl have a neat way of saying if we are using the fixed function pipeline
* or not (for the GL case):
* MAX_TEXTURE_UNITS: fixed function pipeline, a texture unit has both a
* sampler and a set of texture coordinates
* MAX_TEXTURE_IMAGE_UNITS: number of samplers one can use from a fragment
* program/shader (ARBfp1.0 asm/GLSL)
* MAX_VERTEX_TEXTURE_UNITS: number of samplers one can use from a vertex
* program/shader (can be 0)
* MAX_COMBINED_TEXTURE_IMAGE_UNITS: Maximum samplers one can use, counting both
* the vertex and fragment shaders
*
* If both the vertex shader and the fragment processing stage access the same
* texture image unit, then that counts as using two texture image units
* against the latter limit: http://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
*
* Note that, for now, we use GL_MAX_TEXTURE_UNITS as we are exposing the
* fixed function pipeline.
*/
unsigned int
_cogl_get_max_texture_image_units (void)
{
_COGL_GET_CONTEXT (ctx, 0);
/* This function is called quite often so we cache the value to
avoid too many GL calls */
if (ctx->max_texture_units == -1)
{
ctx->max_texture_units = 1;
GE( glGetIntegerv (GL_MAX_TEXTURE_UNITS, &ctx->max_texture_units) );
}
return ctx->max_texture_units;
}
void void
cogl_push_matrix (void) cogl_push_matrix (void)
{ {

View File

@ -41,6 +41,8 @@ typedef struct _CoglContextDriver
{ {
/* This defines a list of function pointers */ /* This defines a list of function pointers */
#include "cogl-feature-functions.h" #include "cogl-feature-functions.h"
GLint gl_max_program_temoraries_arb;
} CoglContextDriver; } CoglContextDriver;
#undef COGL_FEATURE_BEGIN #undef COGL_FEATURE_BEGIN

View File

@ -119,6 +119,9 @@ COGL_FEATURE_BEGIN (arbfp, 255, 255,
COGL_FEATURE_FUNCTION (void, glGenPrograms, COGL_FEATURE_FUNCTION (void, glGenPrograms,
(GLsizei n, (GLsizei n,
GLuint *programs)) GLuint *programs))
COGL_FEATURE_FUNCTION (void, glDeletePrograms,
(GLsizei n,
GLuint *programs))
COGL_FEATURE_FUNCTION (void, glBindProgram, COGL_FEATURE_FUNCTION (void, glBindProgram,
(GLenum target, (GLenum target,
GLuint program)) GLuint program))
@ -127,47 +130,51 @@ COGL_FEATURE_FUNCTION (void, glProgramString,
GLenum format, GLenum format,
GLsizei len, GLsizei len,
const void *program)) const void *program))
COGL_FEATURE_FUNCTION (void, glProgramLocalParameter4fv,
(GLenum target,
GLuint index,
GLfloat *params))
COGL_FEATURE_END () COGL_FEATURE_END ()
/* The function names in OpenGL 2.0 are different so we can't easily /* The function names in OpenGL 2.0 are different so we can't easily
just check for GL 2.0 */ just check for GL 2.0 */
COGL_FEATURE_BEGIN (shaders_glsl, 255, 255, COGL_FEATURE_BEGIN (shaders_glsl, 2, 0,
"ARB\0", "\0",
"shader_objects\0" "\0",
"vertex_shader\0"
"fragment_shader\0",
COGL_FEATURE_SHADERS_GLSL, COGL_FEATURE_SHADERS_GLSL,
0) 0)
COGL_FEATURE_FUNCTION (GLhandleARB, glCreateProgramObject, COGL_FEATURE_FUNCTION (GLuint, glCreateProgram,
(void)) (void))
COGL_FEATURE_FUNCTION (GLhandleARB, glCreateShaderObject, COGL_FEATURE_FUNCTION (GLuint, glCreateShader,
(GLenum shaderType)) (GLenum shaderType))
COGL_FEATURE_FUNCTION (void, glShaderSource, COGL_FEATURE_FUNCTION (void, glShaderSource,
(GLhandleARB shaderObj, (GLuint shader,
GLsizei count, GLsizei count,
const GLcharARB* *string, const GLchar **string,
const GLint *length)) const GLint *length))
COGL_FEATURE_FUNCTION (void, glCompileShader, COGL_FEATURE_FUNCTION (void, glCompileShader,
(GLhandleARB shaderObj)) (GLuint shader))
COGL_FEATURE_FUNCTION (void, glAttachObject, COGL_FEATURE_FUNCTION (void, glDeleteShader,
(GLhandleARB containerObj, (GLuint shader))
GLhandleARB obj)) COGL_FEATURE_FUNCTION (void, glAttachShader,
(GLuint program,
GLuint shader))
COGL_FEATURE_FUNCTION (void, glLinkProgram, COGL_FEATURE_FUNCTION (void, glLinkProgram,
(GLhandleARB programObj)) (GLuint program))
COGL_FEATURE_FUNCTION (void, glUseProgramObject, COGL_FEATURE_FUNCTION (void, glUseProgram,
(GLhandleARB programObj)) (GLuint program))
COGL_FEATURE_FUNCTION (GLint, glGetUniformLocation, COGL_FEATURE_FUNCTION (GLint, glGetUniformLocation,
(GLhandleARB programObj, (GLuint program,
const GLcharARB *name)) const GLchar *name))
COGL_FEATURE_FUNCTION (void, glDeleteObject, COGL_FEATURE_FUNCTION (void, glDeleteProgram,
(GLhandleARB obj)) (GLuint program))
COGL_FEATURE_FUNCTION (void, glGetInfoLog, COGL_FEATURE_FUNCTION (void, glGetShaderInfoLog,
(GLhandleARB obj, (GLuint shader,
GLsizei maxLength, GLsizei maxLength,
GLsizei *length, GLsizei *length,
GLcharARB *infoLog)) GLchar *infoLog))
COGL_FEATURE_FUNCTION (void, glGetObjectParameteriv, COGL_FEATURE_FUNCTION (void, glGetShaderiv,
(GLhandleARB obj, (GLuint shader,
GLenum pname, GLenum pname,
GLint *params)) GLint *params))

View File

@ -3,7 +3,7 @@
* *
* An object oriented GL/GLES Abstraction/Utility Layer * An object oriented GL/GLES Abstraction/Utility Layer
* *
* Copyright (C) 2008,2009 Intel Corporation. * Copyright (C) 2008,2009,2010 Intel Corporation.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -35,9 +35,9 @@
#include <glib.h> #include <glib.h>
#define glCreateProgramObject ctx->drv.pf_glCreateProgramObject #define glCreateProgram ctx->drv.pf_glCreateProgram
#define glAttachObject ctx->drv.pf_glAttachObject #define glAttachShader ctx->drv.pf_glAttachShader
#define glUseProgramObject ctx->drv.pf_glUseProgramObject #define glUseProgram ctx->drv.pf_glUseProgram
#define glLinkProgram ctx->drv.pf_glLinkProgram #define glLinkProgram ctx->drv.pf_glLinkProgram
#define glGetUniformLocation ctx->drv.pf_glGetUniformLocation #define glGetUniformLocation ctx->drv.pf_glGetUniformLocation
#define glUniform1f ctx->drv.pf_glUniform1f #define glUniform1f ctx->drv.pf_glUniform1f
@ -59,7 +59,7 @@
#define glUniformMatrix2fv ctx->drv.pf_glUniformMatrix2fv #define glUniformMatrix2fv ctx->drv.pf_glUniformMatrix2fv
#define glUniformMatrix3fv ctx->drv.pf_glUniformMatrix3fv #define glUniformMatrix3fv ctx->drv.pf_glUniformMatrix3fv
#define glUniformMatrix4fv ctx->drv.pf_glUniformMatrix4fv #define glUniformMatrix4fv ctx->drv.pf_glUniformMatrix4fv
#define glDeleteObject ctx->drv.pf_glDeleteObject #define glDeleteProgram ctx->drv.pf_glDeleteProgram
static void _cogl_program_free (CoglProgram *program); static void _cogl_program_free (CoglProgram *program);
@ -71,7 +71,7 @@ _cogl_program_free (CoglProgram *program)
/* Frees program resources but its handle is not /* Frees program resources but its handle is not
released! Do that separately before this! */ released! Do that separately before this! */
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
glDeleteObject (program->gl_handle); GE (glDeleteProgram (program->gl_handle));
} }
CoglHandle CoglHandle
@ -81,7 +81,7 @@ cogl_create_program (void)
_COGL_GET_CONTEXT (ctx, NULL); _COGL_GET_CONTEXT (ctx, NULL);
program = g_slice_new (CoglProgram); program = g_slice_new (CoglProgram);
program->gl_handle = glCreateProgramObject (); program->gl_handle = glCreateProgram ();
return _cogl_program_handle_new (program); return _cogl_program_handle_new (program);
} }
@ -101,7 +101,7 @@ cogl_program_attach_shader (CoglHandle program_handle,
program = _cogl_program_pointer_from_handle (program_handle); program = _cogl_program_pointer_from_handle (program_handle);
shader = _cogl_shader_pointer_from_handle (shader_handle); shader = _cogl_shader_pointer_from_handle (shader_handle);
glAttachObject (program->gl_handle, shader->gl_handle); GE (glAttachShader (program->gl_handle, shader->gl_handle));
} }
void void
@ -115,33 +115,27 @@ cogl_program_link (CoglHandle handle)
program = _cogl_program_pointer_from_handle (handle); program = _cogl_program_pointer_from_handle (handle);
glLinkProgram (program->gl_handle); GE (glLinkProgram (program->gl_handle));
} }
void void
cogl_program_use (CoglHandle handle) cogl_program_use (CoglHandle handle)
{ {
CoglProgram *program;
GLhandleARB gl_handle;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (handle != COGL_INVALID_HANDLE && !cogl_is_program (handle)) g_return_if_fail (handle == COGL_INVALID_HANDLE ||
return; cogl_is_program (handle));
/* The Cogl journal doesn't currently cope with the use of if (ctx->current_program == 0 && handle != 0)
* shaders so we have to flush all priitives whenever the ctx->legacy_state_set++;
* current shader changes... */ else if (handle == 0 && ctx->current_program != 0)
_cogl_journal_flush (); ctx->legacy_state_set--;
if (handle == COGL_INVALID_HANDLE) if (handle != COGL_INVALID_HANDLE)
gl_handle = 0; cogl_handle_ref (handle);
else if (ctx->current_program != COGL_INVALID_HANDLE)
{ cogl_handle_unref (ctx->current_program);
program = _cogl_program_pointer_from_handle (handle); ctx->current_program = handle;
gl_handle = program->gl_handle;
}
glUseProgramObject (gl_handle);
} }
int int
@ -163,16 +157,34 @@ void
cogl_program_uniform_1f (int uniform_no, cogl_program_uniform_1f (int uniform_no,
float value) float value)
{ {
CoglProgram *program;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
glUniform1f (uniform_no, value);
program = ctx->current_program;
g_return_if_fail (program != NULL);
_cogl_gl_use_program_wrapper (program->gl_handle);
GE (glUniform1f (uniform_no, value));
} }
void void
cogl_program_uniform_1i (int uniform_no, cogl_program_uniform_1i (int uniform_no,
int value) int value)
{ {
CoglProgram *program;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
glUniform1i (uniform_no, value);
program = ctx->current_program;
g_return_if_fail (program != NULL);
_cogl_gl_use_program_wrapper (program->gl_handle);
GE (glUniform1i (uniform_no, value));
} }
void void
@ -181,21 +193,29 @@ cogl_program_uniform_float (int uniform_no,
int count, int count,
const GLfloat *value) const GLfloat *value)
{ {
CoglProgram *program;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
program = ctx->current_program;
g_return_if_fail (program != NULL);
_cogl_gl_use_program_wrapper (program->gl_handle);
switch (size) switch (size)
{ {
case 1: case 1:
glUniform1fv (uniform_no, count, value); GE (glUniform1fv (uniform_no, count, value));
break; break;
case 2: case 2:
glUniform2fv (uniform_no, count, value); GE (glUniform2fv (uniform_no, count, value));
break; break;
case 3: case 3:
glUniform3fv (uniform_no, count, value); GE (glUniform3fv (uniform_no, count, value));
break; break;
case 4: case 4:
glUniform4fv (uniform_no, count, value); GE (glUniform4fv (uniform_no, count, value));
break; break;
default: default:
g_warning ("%s called with invalid size parameter", G_STRFUNC); g_warning ("%s called with invalid size parameter", G_STRFUNC);
@ -208,8 +228,16 @@ cogl_program_uniform_int (int uniform_no,
int count, int count,
const int *value) const int *value)
{ {
CoglProgram *program;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
program = ctx->current_program;
g_return_if_fail (program != NULL);
_cogl_gl_use_program_wrapper (program->gl_handle);
switch (size) switch (size)
{ {
case 1: case 1:
@ -236,18 +264,26 @@ cogl_program_uniform_matrix (int uniform_no,
gboolean transpose, gboolean transpose,
const GLfloat *value) const GLfloat *value)
{ {
CoglProgram *program;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
program = ctx->current_program;
g_return_if_fail (program != NULL);
_cogl_gl_use_program_wrapper (program->gl_handle);
switch (size) switch (size)
{ {
case 2 : case 2 :
glUniformMatrix2fv (uniform_no, count, transpose, value); GE (glUniformMatrix2fv (uniform_no, count, transpose, value));
break; break;
case 3 : case 3 :
glUniformMatrix3fv (uniform_no, count, transpose, value); GE (glUniformMatrix3fv (uniform_no, count, transpose, value));
break; break;
case 4 : case 4 :
glUniformMatrix4fv (uniform_no, count, transpose, value); GE (glUniformMatrix4fv (uniform_no, count, transpose, value));
break; break;
default : default :
g_warning ("%s called with invalid size parameter", G_STRFUNC); g_warning ("%s called with invalid size parameter", G_STRFUNC);

View File

@ -31,7 +31,7 @@ typedef struct _CoglProgram CoglProgram;
struct _CoglProgram struct _CoglProgram
{ {
CoglHandleObject _parent; CoglHandleObject _parent;
GLhandleARB gl_handle; GLuint gl_handle;
}; };
CoglProgram *_cogl_program_pointer_from_handle (CoglHandle handle); CoglProgram *_cogl_program_pointer_from_handle (CoglHandle handle);

View File

@ -3,7 +3,7 @@
* *
* An object oriented GL/GLES Abstraction/Utility Layer * An object oriented GL/GLES Abstraction/Utility Layer
* *
* Copyright (C) 2007,2008,2009 Intel Corporation. * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -33,12 +33,12 @@
#include <glib.h> #include <glib.h>
#define glCreateShaderObject ctx->drv.pf_glCreateShaderObject #define glCreateShader ctx->drv.pf_glCreateShader
#define glGetObjectParameteriv ctx->drv.pf_glGetObjectParameteriv #define glGetShaderiv ctx->drv.pf_glGetShaderiv
#define glGetInfoLog ctx->drv.pf_glGetInfoLog #define glGetShaderInfoLog ctx->drv.pf_glGetShaderInfoLog
#define glCompileShader ctx->drv.pf_glCompileShader #define glCompileShader ctx->drv.pf_glCompileShader
#define glShaderSource ctx->drv.pf_glShaderSource #define glShaderSource ctx->drv.pf_glShaderSource
#define glDeleteObject ctx->drv.pf_glDeleteObject #define glDeleteShader ctx->drv.pf_glDeleteShader
static void _cogl_shader_free (CoglShader *shader); static void _cogl_shader_free (CoglShader *shader);
@ -50,7 +50,7 @@ _cogl_shader_free (CoglShader *shader)
/* Frees shader resources but its handle is not /* Frees shader resources but its handle is not
released! Do that separately before this! */ released! Do that separately before this! */
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
glDeleteObject (shader->gl_handle); glDeleteShader (shader->gl_handle);
} }
CoglHandle CoglHandle
@ -73,7 +73,7 @@ cogl_create_shader (CoglShaderType type)
} }
shader = g_slice_new (CoglShader); shader = g_slice_new (CoglShader);
shader->gl_handle = glCreateShaderObject (gl_type); shader->gl_handle = glCreateShader (gl_type);
return _cogl_shader_handle_new (shader); return _cogl_shader_handle_new (shader);
} }
@ -112,7 +112,7 @@ cogl_shader_get_info_log (CoglHandle handle)
{ {
CoglShader *shader; CoglShader *shader;
char buffer[512]; char buffer[512];
int len; GLsizei len;
_COGL_GET_CONTEXT (ctx, NULL); _COGL_GET_CONTEXT (ctx, NULL);
if (!cogl_is_shader (handle)) if (!cogl_is_shader (handle))
@ -120,7 +120,7 @@ cogl_shader_get_info_log (CoglHandle handle)
shader = _cogl_shader_pointer_from_handle (handle); shader = _cogl_shader_pointer_from_handle (handle);
glGetInfoLog (shader->gl_handle, 511, &len, buffer); glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer);
buffer[len]='\0'; buffer[len]='\0';
return g_strdup (buffer); return g_strdup (buffer);
@ -142,7 +142,7 @@ cogl_shader_get_type (CoglHandle handle)
shader = _cogl_shader_pointer_from_handle (handle); shader = _cogl_shader_pointer_from_handle (handle);
GE (glGetObjectParameteriv (shader->gl_handle, GL_SHADER_TYPE, &type)); GE (glGetShaderiv (shader->gl_handle, GL_SHADER_TYPE, &type));
if (type == GL_VERTEX_SHADER) if (type == GL_VERTEX_SHADER)
return COGL_SHADER_TYPE_VERTEX; return COGL_SHADER_TYPE_VERTEX;
else if (type == GL_FRAGMENT_SHADER) else if (type == GL_FRAGMENT_SHADER)
@ -167,7 +167,7 @@ cogl_shader_is_compiled (CoglHandle handle)
shader = _cogl_shader_pointer_from_handle (handle); shader = _cogl_shader_pointer_from_handle (handle);
GE (glGetObjectParameteriv (shader->gl_handle, GL_COMPILE_STATUS, &status)); GE (glGetShaderiv (shader->gl_handle, GL_COMPILE_STATUS, &status));
if (status == GL_TRUE) if (status == GL_TRUE)
return TRUE; return TRUE;
else else

View File

@ -115,11 +115,22 @@ cogl_program_use (CoglHandle handle)
{ {
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (handle != COGL_INVALID_HANDLE && !cogl_is_program (handle)) g_return_if_fail (handle == COGL_INVALID_HANDLE ||
return; cogl_is_program (handle));
if (ctx->current_program == 0 && handle != 0)
ctx->legacy_state_set++;
else if (handle == 0 && ctx->current_program != 0)
ctx->legacy_state_set--;
ctx->drv.gles2.settings.user_program = handle; ctx->drv.gles2.settings.user_program = handle;
ctx->drv.gles2.settings_dirty = TRUE; ctx->drv.gles2.settings_dirty = TRUE;
if (handle != COGL_INVALID_HANDLE)
cogl_handle_ref (handle);
if (ctx->current_program != COGL_INVALID_HANDLE)
cogl_handle_unref (ctx->current_program);
ctx->current_program = handle;
} }
int int