From 5985eef44cce8177bf8a93c6ffaf2b78cc634ece Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Fri, 23 Jan 2009 16:15:40 +0000 Subject: [PATCH] Fully integrates CoglMaterial throughout the rest of Cogl This glues CoglMaterial in as the fundamental way that Cogl describes how to fill in geometry. It adds cogl_set_source (), which is used to set the material which will be used by all subsequent drawing functions It adds cogl_set_source_texture as a convenience for setting up a default material with a single texture layer, and cogl_set_source_color is now also a convenience for setting up a material with a solid fill. "drawing functions" include, cogl_rectangle, cogl_texture_rectangle, cogl_texture_multiple_rectangles, cogl_texture_polygon (though the cogl_texture_* funcs have been renamed; see below for details), cogl_path_fill/stroke and cogl_vertex_buffer_draw*. cogl_texture_rectangle, cogl_texture_multiple_rectangles and cogl_texture_polygon no longer take a texture handle; instead the current source material is referenced. The functions have also been renamed to: cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords and cogl_polygon respectivly. Most code that previously did: cogl_texture_rectangle (tex_handle, x, y,...); needs to be changed to now do: cogl_set_source_texture (tex_handle); cogl_rectangle_with_texture_coords (x, y,....); In the less likely case where you were blending your source texture with a color like: cogl_set_source_color4ub (r,g,b,a); /* where r,g,b,a isn't just white */ cogl_texture_rectangle (tex_handle, x, y,...); you will need your own material to do that: mat = cogl_material_new (); cogl_material_set_color4ub (r,g,b,a); cogl_material_set_layer (mat, 0, tex_handle)); cogl_set_source_material (mat); Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use cog_rectangle_with_texure_coords since these are the coordinates that cogl_rectangle will use. For cogl_texture_polygon; as well as dropping the texture handle, the n_vertices and vertices arguments were transposed for consistency. So code previously written as: cogl_texture_polygon (tex_handle, 3, verts, TRUE); need to be written as: cogl_set_source_texture (tex_handle); cogl_polygon (verts, 3, TRUE); All of the unit tests have been updated to now use the material API and test-cogl-material has been renamed to test-cogl-multitexture since any textured quad is now technically a test of CoglMaterial but this test specifically creates a material with multiple texture layers. Note: The GLES backend has not been updated yet; that will be done in a following commit. --- README | 49 + clutter/clutter-clone-texture.c | 23 +- clutter/clutter-main.c | 27 +- clutter/clutter-texture.c | 22 +- clutter/cogl/cogl-material.h | 175 +- clutter/cogl/cogl-path.h | 3 +- clutter/cogl/cogl-texture.h | 185 ++- clutter/cogl/cogl.h.in | 2 +- clutter/cogl/common/cogl-material-private.h | 31 +- clutter/cogl/common/cogl-material.c | 641 ++++++-- clutter/cogl/common/cogl-primitives.c | 13 +- clutter/cogl/common/cogl-vertex-buffer.c | 80 +- clutter/cogl/gl/cogl-context.c | 91 +- clutter/cogl/gl/cogl-context.h | 44 +- clutter/cogl/gl/cogl-internal.h | 11 +- clutter/cogl/gl/cogl-primitives.c | 50 +- clutter/cogl/gl/cogl-texture-private.h | 39 +- clutter/cogl/gl/cogl-texture.c | 1424 ++++++++++------- clutter/cogl/gl/cogl.c | 128 +- clutter/pango/cogl-pango-render.c | 114 +- tests/conform/test-backface-culling.c | 42 +- tests/interactive/Makefile.am | 5 +- tests/interactive/test-clip.c | 12 +- ...gl-material.c => test-cogl-multitexture.c} | 30 +- tests/interactive/test-cogl-offscreen.c | 38 +- tests/interactive/test-cogl-tex-convert.c | 50 +- tests/interactive/test-cogl-tex-foreign.c | 14 +- tests/interactive/test-cogl-tex-getset.c | 14 +- tests/interactive/test-cogl-tex-polygon.c | 18 +- tests/interactive/test-cogl-tex-tile.c | 13 +- 30 files changed, 2235 insertions(+), 1153 deletions(-) rename tests/interactive/{test-cogl-material.c => test-cogl-multitexture.c} (84%) diff --git a/README b/README index 5f0518e66..c179fae8c 100644 --- a/README +++ b/README @@ -199,6 +199,55 @@ Release Notes for Clutter 1.0 API. The change removed the private (yet publicly exported) and the already deprecated ClutterFixed API. + Cogl API changes for Clutter 1.0 + -------------------------------- + +* All drawing functions now use a source material to determine how geometry is + filled. The source material is set via cogl_set_source. Or the convenience + functions cogl_set_source_color and cogl_set_source_texture. + + "drawing functions" include: cogl_rectangle, cogl_texture_rectangle, + cogl_texture_multiple_rectangles, cogl_texture_polygon (though the + cogl_texture_* funcs have been renamed; see below for details), + cogl_path_fill/stroke and cogl_vertex_buffer_draw*. + + cogl_texture_rectangle, cogl_texture_multiple_rectangles and + cogl_texture_polygon no longer take a texture handle; instead the current + source material is referenced. The functions have also been renamed to: + cogl_rectangle_with_texture_coords, cogl_rectangles_with_texture_coords + and cogl_polygon respectively. + + Most code that previously did: + cogl_texture_rectangle (tex_handle, x, y,...); + needs to be changed to now do: + cogl_set_source_texture (tex_handle); + cogl_rectangle_with_texture_coords (x, y,....); + + In the less likely case where you were blending your source texture with a + color like: + cogl_set_source_color4ub (r,g,b,a); /* (where r,g,b,a isn't just white) */ + cogl_texture_rectangle (tex_handle, x, y,...); + you will need your own material to do that: + material = cogl_material_new (); + cogl_material_set_color4ub (r,g,b,a); + cogl_material_set_layer (material, 0, tex_handle)); + cogl_set_source_material (material); + + Code that uses the texture coordinates, 0, 0, 1, 1 don't need to use + cogl_rectangle_with_texure_coords since these are the coordinates that + cogl_rectangle will use. + + For cogl_texture_polygon; as well as dropping the texture handle, the + n_vertices and vertices arguments were transposed for consistency. So + code previously written as: + cogl_texture_polygon (tex_handle, 3, verts, TRUE); + need to be written as: + cogl_set_source_texture (tex_handle); + cogl_polygon (verts, 3, TRUE); + +* A CoglMesh type and utility API has been added; this is currently used to + support describing texture matrices. + Release Notes for Clutter 0.8 ------------------------------- diff --git a/clutter/clutter-clone-texture.c b/clutter/clutter-clone-texture.c index 2cd19899e..a3deeaad9 100644 --- a/clutter/clutter-clone-texture.c +++ b/clutter/clutter-clone-texture.c @@ -195,7 +195,7 @@ clutter_clone_texture_paint (ClutterActor *self) #if USE_COGL_MATERIAL cogl_material = clutter_texture_get_cogl_material (priv->parent_texture); - /* FIXME: This is a lazy way of extracting the cogl_texture for the + /* This is just a convenient way of extracting the cogl_texture for the * the first layer of the above material... */ cogl_texture = clutter_texture_get_cogl_texture (priv->parent_texture); #else @@ -221,23 +221,14 @@ clutter_clone_texture_paint (ClutterActor *self) #if USE_COGL_MATERIAL cogl_set_source (cogl_material); - - tex_coords[0] = 0; - tex_coords[1] = 0; - tex_coords[2] = t_w; - tex_coords[3] = t_h; - cogl_material_rectangle (0, 0, - COGL_FIXED_FROM_INT (x_2 - x_1), - COGL_FIXED_FROM_INT (y_2 - y_1), - 0, - tex_coords); #else - /* Parent paint translated us into position */ - cogl_texture_rectangle (cogl_texture, 0, 0, - (float)(x_2 - x_1), - (float)(y_2 - y_1), - 0, 0, t_w, t_h); + cogl_set_source_texture (cogl_texture); #endif + /* Parent paint translated us into position */ + cogl_rectangle_with_texture_coords (0, 0, + (float) (x_2 - x_1), + (float) (y_2 - y_1), + 0, 0, t_w, t_h); } static void diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 745fcbbd7..cd3dae423 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -1157,18 +1157,6 @@ clutter_init_real (GError **error) if (!_clutter_backend_post_parse (backend, error)) return CLUTTER_INIT_ERROR_BACKEND; - /* - * Resolution requires display to be open, so can only be queried after - * the post_parse hooks run. - */ - ctx->font_map = COGL_PANGO_FONT_MAP (cogl_pango_font_map_new ()); - - resolution = clutter_backend_get_resolution (ctx->backend); - cogl_pango_font_map_set_resolution (ctx->font_map, resolution); - cogl_pango_font_map_set_use_mipmapping (ctx->font_map, TRUE); - - clutter_text_direction = clutter_get_text_direction (); - /* Stage will give us a GL Context etc */ stage = clutter_stage_get_default (); if (!stage) @@ -1201,6 +1189,21 @@ clutter_init_real (GError **error) * start issueing cogl commands */ + /* + * Resolution requires display to be open, so can only be queried after + * the post_parse hooks run. + * + * NB: cogl_pango requires a Cogl context. + */ + ctx->font_map = COGL_PANGO_FONT_MAP (cogl_pango_font_map_new ()); + + resolution = clutter_backend_get_resolution (ctx->backend); + cogl_pango_font_map_set_resolution (ctx->font_map, resolution); + cogl_pango_font_map_set_use_mipmapping (ctx->font_map, TRUE); + + clutter_text_direction = clutter_get_text_direction (); + + /* Figure out framebuffer masks used for pick */ cogl_get_bitmasks (&ctx->fb_r_mask, &ctx->fb_g_mask, &ctx->fb_b_mask, NULL); diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index d6601123c..2ab341cc5 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -635,22 +635,13 @@ clutter_texture_paint (ClutterActor *self) /* Paint will have translated us */ #if USE_COGL_MATERIAL cogl_set_source (priv->material); - - tex_coords[0] = 0; - tex_coords[1] = 0; - tex_coords[2] = t_w; - tex_coords[3] = t_h; - cogl_material_rectangle (0, 0, - (float)(x_2 - x_1), - (float)(y_2 - y_1), - 4, - tex_coords); #else - cogl_texture_rectangle (priv->texture, 0, 0, - (float)(x_2 - x_1), - (float)(y_2 - y_1), - 0, 0, t_w, t_h); + cogl_set_source_texture (priv->texture); #endif + cogl_rectangle_with_texture_coords (0, 0, + (float) (x_2 - x_1), + (float) (y_2 - y_1), + 0, 0, t_w, t_h); } /* @@ -769,6 +760,7 @@ clutter_texture_set_property (GObject *object, (texture, (CoglHandle) g_value_get_boxed (value)); break; #if USE_COGL_MATERIAL + case PROP_COGL_MATERIAL: clutter_texture_set_cogl_material (texture, (CoglHandle) g_value_get_boxed (value)); break; @@ -2188,7 +2180,7 @@ on_fbo_source_size_change (GObject *object, if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH) flags |= COGL_TEXTURE_AUTO_MIPMAP; - priv->fdo_texture = + priv->fbo_texture = cogl_texture_new_with_size (MAX (priv->width, 1), MAX (priv->height, 1), -1, diff --git a/clutter/cogl/cogl-material.h b/clutter/cogl/cogl-material.h index 59cb47d04..915e447e5 100644 --- a/clutter/cogl/cogl-material.h +++ b/clutter/cogl/cogl-material.h @@ -52,6 +52,8 @@ CoglHandle cogl_material_ref (CoglHandle handle); */ void cogl_material_unref (CoglHandle handle); + + /** * cogl_material_set_color: * @material: A CoglMaterial object @@ -65,6 +67,37 @@ void cogl_material_unref (CoglHandle handle); */ void cogl_material_set_color (CoglHandle material, const CoglColor *color); +/** + * cogl_material_set_color: + * @material: A CoglMaterial object + * @red: The red component + * @green: The green component + * @blue: The blue component + * @alpha: The alpha component + * + * This is the basic color of the material, used when no lighting is enabled. + * + * The default value is (1.0, 1.0, 1.0, 1.0) + * + * Since 1.0 + */ +void cogl_material_set_color4ub (CoglHandle handle, + guint8 red, + guint8 green, + guint8 blue, + guint8 alpha); + +/** + * cogl_material_get_color: + * @material: A CoglMaterial object + * @color: The location to store the color + * + * This retrieves the current material color. + * + * Since 1.0 + */ +void cogl_material_get_color (CoglHandle handle, CoglColor *color); + /** * cogl_material_set_ambient: * @material: A CoglMaterial object @@ -83,6 +116,17 @@ void cogl_material_set_color (CoglHandle material, const CoglColor *color); void cogl_material_set_ambient (CoglHandle material, const CoglColor *ambient); +/** + * cogl_material_get_ambient: + * @material: A CoglMaterial object + * @ambient: The location to store the ambient color + * + * This retrieves the materials current ambient color. + * + * Since 1.0 + */ +void cogl_material_get_ambient (CoglHandle handle, CoglColor *ambient); + /** * cogl_material_set_diffuse: * @material: A CoglMaterial object @@ -100,6 +144,17 @@ void cogl_material_set_ambient (CoglHandle material, void cogl_material_set_diffuse (CoglHandle material, const CoglColor *diffuse); +/** + * cogl_material_get_diffuse: + * @material: A CoglMaterial object + * @diffuse: The location to store the diffuse color + * + * This retrieves the materials current diffuse color. + * + * Since 1.0 + */ +void cogl_material_get_diffuse (CoglHandle handle, CoglColor *diffuse); + /** * cogl_material_set_ambient_and_diffuse: * @material: A CoglMaterial object @@ -133,6 +188,17 @@ void cogl_material_set_ambient_and_diffuse (CoglHandle material, void cogl_material_set_specular (CoglHandle material, const CoglColor *specular); +/** + * cogl_material_get_specular: + * @material: A CoglMaterial object + * @specular: The location to store the specular color + * + * This retrieves the materials current specular color. + * + * Since 1.0 + */ +void cogl_material_get_specular (CoglHandle handle, CoglColor *specular); + /** * cogl_material_set_shininess: * @material: A CoglMaterial object @@ -148,6 +214,17 @@ void cogl_material_set_specular (CoglHandle material, */ void cogl_material_set_shininess (CoglHandle material, float shininess); +/** + * cogl_material_get_shininess: + * @material: A CoglMaterial object + * + * This retrieves the materials current emission color. + * + * Return value: The materials current shininess value + * + * Since 1.0 + */ +float cogl_material_get_shininess (CoglHandle handle); /** * cogl_material_set_emission: @@ -165,6 +242,17 @@ void cogl_material_set_shininess (CoglHandle material, void cogl_material_set_emission (CoglHandle material, const CoglColor *emission); +/** + * cogl_material_get_emission: + * @material: A CoglMaterial object + * @emission: The location to store the emission color + * + * This retrieves the materials current emission color. + * + * Since 1.0 + */ +void cogl_material_get_emission (CoglHandle handle, CoglColor *emission); + /** * CoglMaterialAlphaFunc: * @COGL_MATERIAL_ALPHA_FUNC_NEVER: Never let the fragment through. @@ -638,7 +726,7 @@ CoglMaterialLayerType cogl_material_layer_get_type (CoglHandle layer_handle); /** * cogl_material_layer_get_texture: - * @material: A CoglMaterial object + * @layer_handle: A CoglMaterial layer object * * This lets you extract a CoglTexture handle for a specific layer. Normally * you shouldn't need to use this function directly since Cogl will do this @@ -653,18 +741,66 @@ CoglMaterialLayerType cogl_material_layer_get_type (CoglHandle layer_handle); CoglHandle cogl_material_layer_get_texture (CoglHandle layer_handle); /** - * cogl_material_layer_flush_gl_sampler_state: - * @material: A CoglMaterial object - * - * This commits the sampler state for a single material layer to the OpenGL - * driver. 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 want to use this. - * - * Note: It assumes you have already activated the appropriate sampler - * by calling glActiveTexture (); + * CoglMaterialLayerFlags: + * @COGL_MATERIAL_LAYER_FLAG_USER_MATRIX: Means the user has supplied a + * custom texture matrix. */ -void cogl_material_layer_flush_gl_sampler_state (CoglHandle layer_handle); +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 CoglMaterial layer object + * + * 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. + */ +gulong cogl_material_layer_get_flags (CoglHandle layer_handle); + +/** + * CoglMaterialFlushOption: + * @COGL_MATERIAL_FLUSH_FALLBACK_MASK: Follow this by a guin32 mask + * of the layers that can't be supported with the user supplied texture + * and need to be replaced with fallback textures. (1 = fallback, and the + * least significant bit = layer 0) + * @COGL_MATERIAL_FLUSH_DISABLE_MASK: Follow this by a guint32 mask + * of the layers that you want to completly disable texturing for + * (1 = fallback, and the least significant bit = layer 0) + * @COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE: Follow this by a GLuint OpenGL texture + * name to override the texture used for layer 0 of the material. This is + * intended for dealing with sliced textures where you will need to point + * to each of the texture slices in turn when drawing your geometry. + * Passing a value of 0 is the same as not passing the option at all. + */ +typedef enum _CoglMaterialFlushOption +{ + COGL_MATERIAL_FLUSH_FALLBACK_MASK = 1, + COGL_MATERIAL_FLUSH_DISABLE_MASK, + COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE, +} CoglMaterialFlushOption; + +/** + * cogl_material_flush_gl_state: + * @material: A CoglMaterial object + * @...: A NULL terminated list of (CoglMaterialFlushOption, data) pairs + * + * This function commits the state of the specified CoglMaterial - including + * the texture state for all the layers - to the OpenGL[ES] driver. + * + * Normally you shouldn't need to use this function directly, but if you + * are developing a custom primitive using raw OpenGL that works with + * CoglMaterials, then you may want to use this function. + * + * Since 1.0 + */ +void cogl_material_flush_gl_state (CoglHandle material, + ...) G_GNUC_NULL_TERMINATED; /** * cogl_set_source: @@ -684,19 +820,16 @@ void cogl_material_layer_flush_gl_sampler_state (CoglHandle layer_handle); void cogl_set_source (CoglHandle material); /** - * cogl_flush_material_gl_state: + * cogl_set_source_texture: + * @texture_handle: The Cogl texture you want as your source * - * This function commits all the state of the source CoglMaterial - not - * including the per-layer state - to the OpenGL[ES] driver. - * - * Normally you shouldn't need to use this function directly, but if you - * are developing a custom primitive using raw OpenGL that works with - * CoglMaterials, then you may want to use this function. + * This is a convenience function for creating a material with the first + * layer set to #texture_handle and setting that material as the source with + * cogl_set_source. * * Since 1.0 */ -/* XXX: This should be moved with cogl_set_source to cogl.h */ -void cogl_flush_material_gl_state (void); +void cogl_set_source_texture (CoglHandle texture_handle); G_END_DECLS diff --git a/clutter/cogl/cogl-path.h b/clutter/cogl/cogl-path.h index aa378647a..d1433fe4d 100644 --- a/clutter/cogl/cogl-path.h +++ b/clutter/cogl/cogl-path.h @@ -57,8 +57,7 @@ G_BEGIN_DECLS * @width: Width of the rectangle * @height: Height of the rectangle * - * Fills a rectangle at the given coordinates with the current - * drawing color in a highly optimizied fashion. + * Fills a rectangle at the given coordinates with the current source material **/ void cogl_rectangle (float x, float y, diff --git a/clutter/cogl/cogl-texture.h b/clutter/cogl/cogl-texture.h index d21265304..b35b22f36 100644 --- a/clutter/cogl/cogl-texture.h +++ b/clutter/cogl/cogl-texture.h @@ -359,90 +359,6 @@ CoglHandle cogl_texture_ref (CoglHandle handle); */ void cogl_texture_unref (CoglHandle handle); -/** - * cogl_texture_rectangle: - * @handle: a @CoglHandle. - * @x1: x coordinate upper left on screen. - * @y1: y coordinate upper left on screen. - * @x2: x coordinate lower right on screen. - * @y2: y coordinate lower right on screen. - * @tx1: x part of texture coordinate to use for upper left pixel - * @ty1: y part of texture coordinate to use for upper left pixel - * @tx2: x part of texture coordinate to use for lower right pixel - * @ty2: y part of texture coordinate to use for left pixel - * - * Draw a rectangle from a texture to the display, to draw the entire - * texture pass in @tx1=0.0 @ty1=0.0 @tx2=1.0 @ty2=1.0. - */ -void cogl_texture_rectangle (CoglHandle handle, - float x1, - float y1, - float x2, - float y2, - float tx1, - float ty1, - float tx2, - float ty2); - -/** - * cogl_texture_polygon: - * @handle: A CoglHandle for a texture - * @n_vertices: The length of the vertices array - * @vertices: An array of #CoglTextureVertex structs - * @use_color: %TRUE if the color member of #CoglTextureVertex should be used - * - * Draws a polygon from a texture with the given model and texture - * coordinates. This can be used to draw arbitrary shapes textured - * with a COGL texture. If @use_color is %TRUE then the current COGL - * color will be changed for each vertex using the value specified in - * the color member of #CoglTextureVertex. This can be used for - * example to make the texture fade out by setting the alpha value of - * the color. - * - * All of the texture coordinates must be in the range [0,1] and - * repeating the texture is not supported. - * - * Because of the way this function is implemented it will currently - * only work if either the texture is not sliced or the backend is not - * OpenGL ES and the minifying and magnifying functions are both set - * to CGL_NEAREST. - */ -void cogl_texture_polygon (CoglHandle handle, - guint n_vertices, - CoglTextureVertex *vertices, - gboolean use_color); - -/** - * cogl_material_rectangle: - * @x1: x coordinate upper left on screen. - * @y1: y coordinate upper left on screen. - * @x2: x coordinate lower right on screen. - * @y2: y coordinate lower right on screen. - * @tex_coords_len: The length of the tex_coords array. (e.g. for one layer - * and one group of texture coordinates, this would be 4) - * @tex_coords: An array containing groups of 4 CoglFixed values: - * [tx1, ty1, tx2, ty2] that are interpreted as two texture coordinates; one - * for the upper left texel, and one for the lower right texel. Each value - * should be between 0.0 and 1.0, where the coordinate (0.0, 0.0) represents - * the top left of the texture, and (1.0, 1.0) the bottom right. - * - * This function draws a rectangle using the current source material to - * texture or fill with. Since a material may contain multiple texture - * layers the interface lets you supply corresponding sets of texture - * coordinates. - * - * The first pair of coordinates are for the first layer (with the smallest - * layer index) and if you supply less texture coordinates than there are - * layers in the current source material then default texture coordinates - * [0.0, 0.0, 1.0, 1.0] are generated. - */ -void cogl_material_rectangle (CoglFixed x1, - CoglFixed y1, - CoglFixed x2, - CoglFixed y2, - gint tex_coords_len, - const CoglFixed *tex_coords); - /** * cogl_bitmap_new_from_file: * @filename: the file to load. @@ -483,27 +399,110 @@ gboolean cogl_bitmap_get_size_from_file (const gchar *filename, void cogl_bitmap_free (CoglBitmap *bmp); /** - * cogl_texture_multiple_rectangles: - * @handle: a @CoglHandle. + * cogl_rectangle_with_texture_coords: + * @x1: x coordinate upper left on screen. + * @y1: y coordinate upper left on screen. + * @x2: x coordinate lower right on screen. + * @y2: y coordinate lower right on screen. + * @tx1: x part of texture coordinate to use for upper left pixel + * @ty1: y part of texture coordinate to use for upper left pixel + * @tx2: x part of texture coordinate to use for lower right pixel + * @ty2: y part of texture coordinate to use for left pixel + * + * Draw a rectangle using the current material and supply texture coordinates + * to be used for the first texture layer of the material. To draw the entire + * texture pass in @tx1=0.0 @ty1=0.0 @tx2=1.0 @ty2=1.0. + * + * Since 1.0 + */ +void cogl_rectangle_with_texture_coords (float x1, + float y1, + float x2, + float y2, + float tx1, + float ty1, + float tx2, + float ty2); + +/** + * cogl_rectangle_with_multitexture_coords: + * @x1: x coordinate upper left on screen. + * @y1: y coordinate upper left on screen. + * @x2: x coordinate lower right on screen. + * @y2: y coordinate lower right on screen. + * @tex_coords: An array containing groups of 4 float values: + * [tx1, ty1, tx2, ty2] that are interpreted as two texture coordinates; one + * for the upper left texel, and one for the lower right texel. Each value + * should be between 0.0 and 1.0, where the coordinate (0.0, 0.0) represents + * the top left of the texture, and (1.0, 1.0) the bottom right. + * @tex_coords_len: The length of the tex_coords array. (e.g. for one layer + * and one group of texture coordinates, this would be 4) + * + * This function draws a rectangle using the current source material to + * texture or fill with. As a material may contain multiple texture layers + * this interface lets you supply texture coordinates for each layer of the + * material. + * + * The first pair of coordinates are for the first layer (with the smallest + * layer index) and if you supply less texture coordinates than there are + * layers in the current source material then default texture coordinates + * (0.0, 0.0, 1.0, 1.0) are generated. + * + * Since 1.0 + */ +void cogl_rectangle_with_multitexture_coords (float x1, + float y1, + float x2, + float y2, + const float *tex_coords, + gint tex_coords_len); + +/** + * cogl_rectangles_with_texture_coords: * @verts: an array of vertices * @n_rects: number of rectangles to draw * * Draws a series of rectangles in the same way that - * cogl_texture_rectangle() does. In some situations it can give a + * cogl_rectangle_with_texture_coords() does. In some situations it can give a * significant performance boost to use this function rather than - * calling cogl_texture_rectangle() separately for each rectangle. + * calling cogl_rectangle_with_texture_coords() separately for each rectangle. * * @verts should point to an array of #floats with * @n_rects * 8 elements. Each group of 8 values corresponds to the * parameters x1, y1, x2, y2, tx1, ty1, tx2 and ty2 and have the same - * meaning as in cogl_texture_rectangle(). + * meaning as in cogl_rectangle_with_texture_coords(). * * Since: 0.8.6 */ -void cogl_texture_multiple_rectangles - (CoglHandle handle, - const float *verts, - guint n_rects); +void cogl_rectangles_with_texture_coords (const float *verts, + guint n_rects); + +/** + * cogl_polygon: + * @vertices: An array of #CoglTextureVertex structs + * @n_vertices: The length of the vertices array + * @use_color: %TRUE if the color member of #CoglTextureVertex should be used + * + * Draws a convex polygon using the current source material to fill / texture + * with according to the texture coordinates passed. + * + * If @use_color is %TRUE then the color will be changed for each vertex using + * the value specified in the color member of #CoglTextureVertex. This can be + * used for example to make the texture fade out by setting the alpha value of + * the color. + * + * All of the texture coordinates must be in the range [0,1] and repeating the + * texture is not supported. + * + * Because of the way this function is implemented it will currently only work + * if either the texture is not sliced or the backend is not OpenGL ES and the + * minifying and magnifying functions are both set to CGL_NEAREST. + * + * Since 1.0 + */ +void cogl_polygon (CoglTextureVertex *vertices, + guint n_vertices, + gboolean use_color); G_END_DECLS diff --git a/clutter/cogl/cogl.h.in b/clutter/cogl/cogl.h.in index 18612aacc..e0cf44a82 100644 --- a/clutter/cogl/cogl.h.in +++ b/clutter/cogl/cogl.h.in @@ -32,7 +32,7 @@ #include -#include +#include #include #include #include diff --git a/clutter/cogl/common/cogl-material-private.h b/clutter/cogl/common/cogl-material-private.h index 935e0ae79..b4c36e78d 100644 --- a/clutter/cogl/common/cogl-material-private.h +++ b/clutter/cogl/common/cogl-material-private.h @@ -9,10 +9,28 @@ typedef struct _CoglMaterial CoglMaterial; typedef struct _CoglMaterialLayer CoglMaterialLayer; -typedef enum _CoglMaterialLayerFlags +/* XXX: I don't think gtk-doc supports having private enums so these aren't + * bundled in with CoglMaterialLayerFlags */ +typedef enum _CoglMaterialLayerPrivFlags { - COGL_MATERIAL_LAYER_FLAG_USER_MATRIX = 1L<<0, -} CoglMaterialLayerFlags; + /* Ref: CoglMaterialLayerFlags + COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX = 1L<<0 + */ + COGL_MATERIAL_LAYER_FLAG_DIRTY = 1L<<1, + COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE = 1L<<2 +} CoglMaterialLayerPrivFlags; + +/* For tracking the state of a layer that's been flushed to OpenGL */ +typedef struct _CoglLayerInfo +{ + CoglHandle handle; + gulong flags; + GLenum gl_target; + GLuint gl_texture; + gboolean fallback; + gboolean disabled; + gboolean layer0_overridden; +} CoglLayerInfo; struct _CoglMaterialLayer { @@ -42,7 +60,12 @@ typedef enum _CoglMaterialFlags { COGL_MATERIAL_FLAG_ENABLE_BLEND = 1L<<0, COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING = 1L<<1, - COGL_MATERIAL_FLAG_DIRTY = 1L<<2 + COGL_MATERIAL_FLAG_DIRTY = 1L<<2, + COGL_MATERIAL_FLAG_LAYERS_DIRTY = 1L<<3, + COGL_MATERIAL_FLAG_DEFAULT_COLOR = 1L<<4, + COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL = 1L<<5, + COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC = 1L<<6, + COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC = 1L<<7 } CoglMaterialFlags; struct _CoglMaterial diff --git a/clutter/cogl/common/cogl-material.c b/clutter/cogl/common/cogl-material.c index b0b9fd955..0b4b9dc6b 100644 --- a/clutter/cogl/common/cogl-material.c +++ b/clutter/cogl/common/cogl-material.c @@ -37,20 +37,24 @@ cogl_material_new (void) /* Use the same defaults as the GL spec... */ unlit[0] = 1.0; unlit[1] = 1.0; unlit[2] = 1.0; unlit[3] = 1.0; + material->flags |= COGL_MATERIAL_FLAG_DEFAULT_COLOR; /* Use the same defaults as the GL spec... */ ambient[0] = 0.2; ambient[1] = 0.2; ambient[2] = 0.2; ambient[3] = 1.0; diffuse[0] = 0.8; diffuse[1] = 0.8; diffuse[2] = 0.8; diffuse[3] = 1.0; specular[0] = 0; specular[1] = 0; specular[2] = 0; specular[3] = 1.0; emission[0] = 0; emission[1] = 0; emission[2] = 0; emission[3] = 1.0; + material->flags |= COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL; /* Use the same defaults as the GL spec... */ material->alpha_func = COGL_MATERIAL_ALPHA_FUNC_ALWAYS; material->alpha_func_reference = 0.0; + material->flags |= COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC; /* Not the same as the GL default, but seems saner... */ material->blend_src_factor = COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA; material->blend_dst_factor = COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + material->flags |= COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC; material->layers = NULL; @@ -69,7 +73,24 @@ _cogl_material_free (CoglMaterial *material) } void -cogl_material_set_color (CoglHandle handle, +cogl_material_get_color (CoglHandle handle, + CoglColor *color) +{ + CoglMaterial *material; + + g_return_if_fail (cogl_is_material (handle)); + + material = _cogl_material_pointer_from_handle (handle); + + cogl_color_set_from_4f (color, + material->unlit[0], + material->unlit[1], + material->unlit[2], + material->unlit[3]); +} + +void +cogl_material_set_color (CoglHandle handle, const CoglColor *unlit_color) { CoglMaterial *material; @@ -88,7 +109,46 @@ cogl_material_set_color (CoglHandle handle, memcpy (material->unlit, unlit, sizeof (unlit)); + if (unlit[0] == 1.0 && + unlit[1] == 1.0 && + unlit[2] == 1.0 && + unlit[3] == 1.0) + material->flags |= COGL_MATERIAL_FLAG_DEFAULT_COLOR; + + if (unlit[3] != 1.0) + material->flags |= COGL_MATERIAL_FLAG_ENABLE_BLEND; + material->flags |= COGL_MATERIAL_FLAG_DIRTY; + material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_COLOR; +} + +void +cogl_material_set_color4ub (CoglHandle handle, + guint8 red, + guint8 green, + guint8 blue, + guint8 alpha) +{ + CoglColor color; + cogl_color_set_from_4ub (&color, red, green, blue, alpha); + cogl_material_set_color (handle, &color); +} + +void +cogl_material_get_ambient (CoglHandle handle, + CoglColor *ambient) +{ + CoglMaterial *material; + + g_return_if_fail (cogl_is_material (handle)); + + material = _cogl_material_pointer_from_handle (handle); + + cogl_color_set_from_4f (ambient, + material->ambient[0], + material->ambient[1], + material->ambient[2], + material->ambient[3]); } void @@ -109,6 +169,24 @@ cogl_material_set_ambient (CoglHandle handle, ambient[3] = cogl_color_get_alpha_float (ambient_color); material->flags |= COGL_MATERIAL_FLAG_DIRTY; + material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL; +} + +void +cogl_material_get_diffuse (CoglHandle handle, + CoglColor *diffuse) +{ + CoglMaterial *material; + + g_return_if_fail (cogl_is_material (handle)); + + material = _cogl_material_pointer_from_handle (handle); + + cogl_color_set_from_4f (diffuse, + material->diffuse[0], + material->diffuse[1], + material->diffuse[2], + material->diffuse[3]); } void @@ -129,6 +207,7 @@ cogl_material_set_diffuse (CoglHandle handle, diffuse[3] = cogl_color_get_alpha_float (diffuse_color); material->flags |= COGL_MATERIAL_FLAG_DIRTY; + material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL; } void @@ -139,6 +218,23 @@ cogl_material_set_ambient_and_diffuse (CoglHandle handle, cogl_material_set_diffuse (handle, color); } +void +cogl_material_get_specular (CoglHandle handle, + CoglColor *specular) +{ + CoglMaterial *material; + + g_return_if_fail (cogl_is_material (handle)); + + material = _cogl_material_pointer_from_handle (handle); + + cogl_color_set_from_4f (specular, + material->specular[0], + material->specular[1], + material->specular[2], + material->specular[3]); +} + void cogl_material_set_specular (CoglHandle handle, const CoglColor *specular_color) @@ -157,6 +253,19 @@ cogl_material_set_specular (CoglHandle handle, specular[3] = cogl_color_get_alpha_float (specular_color); material->flags |= COGL_MATERIAL_FLAG_DIRTY; + material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL; +} + +float +cogl_material_get_shininess (CoglHandle handle) +{ + CoglMaterial *material; + + g_return_val_if_fail (cogl_is_material (handle), 0); + + material = _cogl_material_pointer_from_handle (handle); + + return material->shininess; } void @@ -176,6 +285,24 @@ cogl_material_set_shininess (CoglHandle handle, material->shininess = (GLfloat)shininess * 128.0; material->flags |= COGL_MATERIAL_FLAG_DIRTY; + material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL; +} + +void +cogl_material_get_emission (CoglHandle handle, + CoglColor *emission) +{ + CoglMaterial *material; + + g_return_if_fail (cogl_is_material (handle)); + + material = _cogl_material_pointer_from_handle (handle); + + cogl_color_set_from_4f (emission, + material->emission[0], + material->emission[1], + material->emission[2], + material->emission[3]); } void @@ -196,6 +323,7 @@ cogl_material_set_emission (CoglHandle handle, emission[3] = cogl_color_get_alpha_float (emission_color); material->flags |= COGL_MATERIAL_FLAG_DIRTY; + material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL; } void @@ -212,6 +340,7 @@ cogl_material_set_alpha_test_function (CoglHandle handle, material->alpha_func_reference = (GLfloat)alpha_reference; material->flags |= COGL_MATERIAL_FLAG_DIRTY; + material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC; } void @@ -228,6 +357,7 @@ cogl_material_set_blend_factors (CoglHandle handle, material->blend_dst_factor = dst_factor; material->flags |= COGL_MATERIAL_FLAG_DIRTY; + material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC; } /* Asserts that a layer corresponding to the given index exists. If no @@ -264,6 +394,7 @@ _cogl_material_get_layer (CoglMaterial *material, layer->ref_count = 1; layer->index = index; + layer->flags = COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE; layer->texture = COGL_INVALID_HANDLE; /* Choose the same default combine mode as OpenGL: @@ -284,6 +415,8 @@ _cogl_material_get_layer (CoglMaterial *material, layer->texture_combine_alpha_op[1] = COGL_MATERIAL_LAYER_COMBINE_OP_SRC_ALPHA; + cogl_matrix_init_identity (&layer->matrix); + layer_handle = _cogl_material_layer_handle_new (layer); /* Note: see comment after for() loop above */ material->layers = @@ -317,7 +450,7 @@ cogl_material_set_layer (CoglHandle material_handle, { if (!(material->flags & COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING)) { - g_warning ("Your hardware doesnot have enough texture samplers" + g_warning ("Your hardware does not have enough texture samplers" "to handle this many texture layers"); material->flags |= COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING; } @@ -328,11 +461,14 @@ cogl_material_set_layer (CoglHandle material_handle, * MAX_COMBINED_TEXTURE_IMAGE_UNITS layers. */ } + cogl_texture_ref (texture_handle); + if (layer->texture) cogl_texture_unref (layer->texture); - cogl_texture_ref (texture_handle); layer->texture = texture_handle; + layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY; + material->flags |= COGL_MATERIAL_FLAG_LAYERS_DIRTY; } void @@ -350,9 +486,7 @@ cogl_material_set_layer_combine_function ( g_return_if_fail (cogl_is_material (handle)); material = _cogl_material_pointer_from_handle (handle); - layer = _cogl_material_get_layer (material, layer_index, FALSE); - if (!layer) - return; + layer = _cogl_material_get_layer (material, layer_index, TRUE); if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA) set_alpha_func = set_rgb_func = TRUE; @@ -365,6 +499,10 @@ cogl_material_set_layer_combine_function ( layer->texture_combine_rgb_func = func; if (set_alpha_func) layer->texture_combine_alpha_func = func; + + material->flags |= COGL_MATERIAL_FLAG_LAYERS_DIRTY; + layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY; + layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE; } void @@ -377,16 +515,14 @@ cogl_material_set_layer_combine_arg_src ( { CoglMaterial *material; CoglMaterialLayer *layer; - gboolean set_arg_alpha_src = FALSE; - gboolean set_arg_rgb_src = FALSE; + gboolean set_arg_alpha_src = FALSE; + gboolean set_arg_rgb_src = FALSE; g_return_if_fail (cogl_is_material (handle)); g_return_if_fail (argument >=0 && argument <= 3); material = _cogl_material_pointer_from_handle (handle); - layer = _cogl_material_get_layer (material, layer_index, FALSE); - if (!layer) - return; + layer = _cogl_material_get_layer (material, layer_index, TRUE); if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA) set_arg_alpha_src = set_arg_rgb_src = TRUE; @@ -399,6 +535,10 @@ cogl_material_set_layer_combine_arg_src ( layer->texture_combine_rgb_src[argument] = src; if (set_arg_alpha_src) layer->texture_combine_alpha_src[argument] = src; + + material->flags |= COGL_MATERIAL_FLAG_LAYERS_DIRTY; + layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY; + layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE; } void @@ -418,9 +558,7 @@ cogl_material_set_layer_combine_arg_op ( g_return_if_fail (argument >=0 && argument <= 3); material = _cogl_material_pointer_from_handle (material_handle); - layer = _cogl_material_get_layer (material, layer_index, FALSE); - if (!layer) - return; + layer = _cogl_material_get_layer (material, layer_index, TRUE); if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA) set_arg_alpha_op = set_arg_rgb_op = TRUE; @@ -433,6 +571,10 @@ cogl_material_set_layer_combine_arg_op ( layer->texture_combine_rgb_op[argument] = op; if (set_arg_alpha_op) layer->texture_combine_alpha_op[argument] = op; + + material->flags |= COGL_MATERIAL_FLAG_LAYERS_DIRTY; + layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY; + layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE; } void @@ -446,12 +588,14 @@ cogl_material_set_layer_matrix (CoglHandle material_handle, g_return_if_fail (cogl_is_material (material_handle)); material = _cogl_material_pointer_from_handle (material_handle); - layer = _cogl_material_get_layer (material, layer_index, FALSE); - if (!layer) - return; + layer = _cogl_material_get_layer (material, layer_index, TRUE); layer->matrix = *matrix; - layer->flags |= COGL_MATERIAL_LAYER_FLAG_USER_MATRIX; + + material->flags |= COGL_MATERIAL_FLAG_LAYERS_DIRTY; + layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY; + layer->flags |= COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX; + layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE; } static void @@ -490,6 +634,10 @@ cogl_material_remove_layer (CoglHandle material_handle, if (cogl_texture_get_format (layer->texture) & COGL_A_BIT) material->flags |= COGL_MATERIAL_FLAG_ENABLE_BLEND; } + + if (material->unlit[3] != 1.0) + material->flags |= COGL_MATERIAL_FLAG_ENABLE_BLEND; + material->flags |= COGL_MATERIAL_FLAG_LAYERS_DIRTY; } /* XXX: This API is hopfully just a stop-gap solution. Ideally cogl_enable @@ -553,6 +701,18 @@ cogl_material_layer_get_texture (CoglHandle layer_handle) return layer->texture; } +gulong +cogl_material_layer_get_flags (CoglHandle layer_handle) +{ + CoglMaterialLayer *layer; + + g_return_val_if_fail (cogl_is_material_layer (layer_handle), 0); + + layer = _cogl_material_layer_pointer_from_handle (layer_handle); + + return layer->flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX; +} + static guint get_n_args_for_combine_func (CoglMaterialLayerCombineFunc func) { @@ -573,89 +733,81 @@ get_n_args_for_combine_func (CoglMaterialLayerCombineFunc func) return 0; } -void -cogl_material_layer_flush_gl_sampler_state (CoglHandle layer_handle) +static void +_cogl_material_layer_flush_gl_sampler_state (CoglMaterialLayer *layer, + CoglLayerInfo *gl_layer_info) { - CoglMaterialLayer *layer; int n_rgb_func_args; int n_alpha_func_args; - g_return_if_fail (cogl_is_material_layer (layer_handle)); - - layer = _cogl_material_layer_pointer_from_handle (layer_handle); - - /* XXX: We really want some kind of cache/dirty flag mechanism - * somewhere here so we can avoid as much mucking about with - * the texture units per primitive as possible! - * - * E.g. some recent profiling of clutter-actor suggested that - * validating/updating the texture environment may currently - * be a significant bottleneck. Given that all the actors should - * have the same texture environment, that implies we could do a - * much better job of avoiding redundant glTexEnv calls. - */ - - GE (glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE)); - - /* Set the combiner functions... */ - GE (glTexEnvi (GL_TEXTURE_ENV, - GL_COMBINE_RGB, - layer->texture_combine_rgb_func)); - GE (glTexEnvi (GL_TEXTURE_ENV, - GL_COMBINE_ALPHA, - layer->texture_combine_alpha_func)); - - /* - * Setup the function arguments... - */ - - /* For the RGB components... */ - n_rgb_func_args = - get_n_args_for_combine_func (layer->texture_combine_rgb_func); - - GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, - layer->texture_combine_rgb_src[0])); - GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, - layer->texture_combine_rgb_op[0])); - if (n_rgb_func_args > 1) + if (!(gl_layer_info && + gl_layer_info->flags & COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE && + layer->flags & COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE)) { - GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, - layer->texture_combine_rgb_src[1])); - GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, - layer->texture_combine_rgb_op[1])); - } - if (n_rgb_func_args > 2) - { - GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_RGB, - layer->texture_combine_rgb_src[2])); - GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_RGB, - layer->texture_combine_rgb_op[2])); + GE (glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE)); + + /* Set the combiner functions... */ + GE (glTexEnvi (GL_TEXTURE_ENV, + GL_COMBINE_RGB, + layer->texture_combine_rgb_func)); + GE (glTexEnvi (GL_TEXTURE_ENV, + GL_COMBINE_ALPHA, + layer->texture_combine_alpha_func)); + + /* + * Setup the function arguments... + */ + + /* For the RGB components... */ + n_rgb_func_args = + get_n_args_for_combine_func (layer->texture_combine_rgb_func); + + GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, + layer->texture_combine_rgb_src[0])); + GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, + layer->texture_combine_rgb_op[0])); + if (n_rgb_func_args > 1) + { + GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, + layer->texture_combine_rgb_src[1])); + GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, + layer->texture_combine_rgb_op[1])); + } + if (n_rgb_func_args > 2) + { + GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_RGB, + layer->texture_combine_rgb_src[2])); + GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_RGB, + layer->texture_combine_rgb_op[2])); + } + + /* For the Alpha component */ + n_alpha_func_args = + get_n_args_for_combine_func (layer->texture_combine_alpha_func); + + GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, + layer->texture_combine_alpha_src[0])); + GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, + layer->texture_combine_alpha_op[0])); + if (n_alpha_func_args > 1) + { + GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, + layer->texture_combine_alpha_src[1])); + GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, + layer->texture_combine_alpha_op[1])); + } + if (n_alpha_func_args > 2) + { + GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_ALPHA, + layer->texture_combine_alpha_src[2])); + GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, + layer->texture_combine_alpha_op[2])); + } } - /* For the Alpha component */ - n_alpha_func_args = - get_n_args_for_combine_func (layer->texture_combine_alpha_func); - - GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, - layer->texture_combine_alpha_src[0])); - GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, - layer->texture_combine_alpha_op[0])); - if (n_alpha_func_args > 1) - { - GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, - layer->texture_combine_alpha_src[1])); - GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, - layer->texture_combine_alpha_op[1])); - } - if (n_alpha_func_args > 2) - { - GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_ALPHA, - layer->texture_combine_alpha_src[2])); - GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, - layer->texture_combine_alpha_op[2])); - } - - if (layer->flags & COGL_MATERIAL_LAYER_FLAG_USER_MATRIX) + if (gl_layer_info && + (gl_layer_info->flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX || + layer->flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX)) { GE (glMatrixMode (GL_TEXTURE)); GE (glLoadMatrixf ((GLfloat *)&layer->matrix)); @@ -663,6 +815,275 @@ cogl_material_layer_flush_gl_sampler_state (CoglHandle layer_handle) } } +/** + * _cogl_material_flush_layers_gl_state: + * @fallback_mask: is a bitmask of the material layers that need to be + * replaced with the default, fallback textures. The fallback textures are + * fully transparent textures so they hopefully wont contribute to the + * texture combining. + * + * The intention of fallbacks is to try and preserve + * the number of layers the user is expecting so that texture coordinates + * they gave will mostly still correspond to the textures they intended, and + * have a fighting chance of looking close to their originally intended + * result. + * + * @disable_mask: is a bitmask of the material layers that will simply have + * texturing disabled. It's only really intended for disabling all layers + * > X; i.e. we'd expect to see a contiguous run of 0 starting from the LSB + * and at some point the remaining bits flip to 1. It might work to disable + * arbitrary layers; though I'm not sure a.t.m how OpenGL would take to + * that. + * + * The intention of the disable_mask is for emitting geometry when the user + * hasn't supplied enough texture coordinates for all the layers and it's + * not possible to auto generate default texture coordinates for those + * layers. + * + * @layer0_override_texture: forcibly tells us to bind this GL texture name for + * layer 0 instead of plucking the gl_texture from the CoglTexture of layer + * 0. + * + * The intention of this is for any geometry that supports sliced textures. + * The code will can iterate each of the slices and re-flush the material + * forcing the GL texture of each slice in turn. + * + * XXX: It might also help if we could specify a texture matrix for code + * dealing with slicing that would be multiplied with the users own matrix. + * + * Normaly texture coords in the range [0, 1] refer to the extents of the + * texture, but when your GL texture represents a slice of the real texture + * (from the users POV) then a texture matrix would be a neat way of + * transforming the mapping for each slice. + * + * Currently for textured rectangles we manually calculate the texture + * coords for each slice based on the users given coords, but this solution + * isn't ideal, and can't be used with CoglVertexBuffers. + */ +static void +_cogl_material_flush_layers_gl_state (CoglMaterial *material, + guint32 fallback_mask, + guint32 disable_mask, + GLuint layer0_override_texture) +{ + GList *tmp; + int i; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + for (tmp = material->layers, i = 0; tmp != NULL; tmp = tmp->next, i++) + { + CoglHandle layer_handle = (CoglHandle)tmp->data; + CoglMaterialLayer *layer = + _cogl_material_layer_pointer_from_handle (layer_handle); + CoglLayerInfo *gl_layer_info = NULL; + CoglLayerInfo new_gl_layer_info; + GLuint gl_texture; + GLenum gl_target; + + new_gl_layer_info.layer0_overridden = + layer0_override_texture ? TRUE : FALSE; + new_gl_layer_info.fallback = + (fallback_mask & (1<current_layers->len) + { + gl_layer_info = + &g_array_index (ctx->current_layers, CoglLayerInfo, i); + + if (gl_layer_info->handle == layer_handle && + !(layer->flags & COGL_MATERIAL_LAYER_FLAG_DIRTY) && + (gl_layer_info->layer0_overridden + == new_gl_layer_info.layer0_overridden) && + (gl_layer_info->fallback + == new_gl_layer_info.fallback) && + (gl_layer_info->disabled + == new_gl_layer_info.disabled)) + continue; + } + + cogl_texture_get_gl_texture (layer->texture, &gl_texture, &gl_target); + + if (new_gl_layer_info.layer0_overridden) + gl_texture = layer0_override_texture; + else if (new_gl_layer_info.fallback) + { + CoglHandle tex_handle; + + if (gl_target == GL_TEXTURE_2D) + tex_handle = ctx->default_gl_texture_2d_tex; + else if (gl_target == GL_TEXTURE_RECTANGLE_ARB) + tex_handle = ctx->default_gl_texture_rect_tex; + else + { + g_warning ("We don't have a default texture we can use to fill " + "in for an invalid material layer, since it was " + "using an unsupported texture target "); + /* might get away with this... */ + tex_handle = ctx->default_gl_texture_2d_tex; + } + cogl_texture_get_gl_texture (tex_handle, &gl_texture, NULL); + } + + GE (glActiveTexture (GL_TEXTURE0 + i)); + + if (!gl_layer_info + || gl_layer_info->gl_target != gl_target + || gl_layer_info->gl_texture != gl_texture) + GE (glBindTexture (gl_target, gl_texture)); + + /* Disable the previous target if it was different */ + if (gl_layer_info && + gl_layer_info->gl_target != gl_target && + !gl_layer_info->disabled) + GE (glDisable (gl_layer_info->gl_target)); + + /* Enable/Disable the new target */ + if (!new_gl_layer_info.disabled) + { + if (!(gl_layer_info && + gl_layer_info->gl_target == gl_target && + !gl_layer_info->disabled)) + GE (glEnable (gl_target)); + } + else + { + if (!(gl_layer_info && + gl_layer_info->gl_target == gl_target && + gl_layer_info->disabled)) + GE (glDisable (gl_target)); + } + + _cogl_material_layer_flush_gl_sampler_state (layer, gl_layer_info); + + new_gl_layer_info.handle = layer_handle; + new_gl_layer_info.flags = layer->flags; + new_gl_layer_info.gl_target = gl_target; + new_gl_layer_info.gl_texture = gl_texture; + + if (i < ctx->current_layers->len) + *gl_layer_info = new_gl_layer_info; + else + g_array_append_val (ctx->current_layers, new_gl_layer_info); + + layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DIRTY; + + if ((i+1) >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS) + break; + } + + /* Disable additional texture units that may have previously been in use.. */ + for (; i < ctx->current_layers->len; i++) + { + CoglLayerInfo *gl_layer_info = + &g_array_index (ctx->current_layers, CoglLayerInfo, i); + + if (!gl_layer_info->disabled) + { + GE (glActiveTexture (GL_TEXTURE0 + i)); + GE (glDisable (gl_layer_info->gl_target)); + gl_layer_info->disabled = TRUE; + } + } + + material->flags &= ~COGL_MATERIAL_FLAG_DIRTY; +} + +static void +_cogl_material_flush_base_gl_state (CoglMaterial *material) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!(ctx->current_material_flags & COGL_MATERIAL_FLAG_DEFAULT_COLOR + && material->flags & COGL_MATERIAL_FLAG_DEFAULT_COLOR)) + { + GE (glColor4fv (material->unlit)); + } + + if (!(ctx->current_material_flags & COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL + && material->flags & COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL)) + { + /* FIXME - we only need to set these if lighting is enabled... */ + GE (glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, material->ambient)); + GE (glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, material->diffuse)); + GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, material->specular)); + GE (glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, material->emission)); + GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, &material->shininess)); + } + + if (!(ctx->current_material_flags & COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC + && material->flags & COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC)) + { + /* NB: Currently the Cogl defines are compatible with the GL ones: */ + GE (glAlphaFunc (material->alpha_func, material->alpha_func_reference)); + } + + if (!(ctx->current_material_flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC + && material->flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC)) + { + GE (glBlendFunc (material->blend_src_factor, material->blend_dst_factor)); + } +} + +void +cogl_material_flush_gl_state (CoglHandle handle, ...) +{ + CoglMaterial *material; + va_list ap; + CoglMaterialFlushOption option; + guint32 fallback_layers = 0; + guint32 disable_layers = 0; + GLuint layer0_override_texture = 0; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + material = _cogl_material_pointer_from_handle (handle); + + if (ctx->current_material == material && + !(material->flags & COGL_MATERIAL_FLAG_DIRTY) && + !(material->flags & COGL_MATERIAL_FLAG_LAYERS_DIRTY)) + return; + + if (ctx->current_material != material || + material->flags & COGL_MATERIAL_FLAG_DIRTY) + _cogl_material_flush_base_gl_state (material); + + if (ctx->current_material != material || + material->flags & COGL_MATERIAL_FLAG_LAYERS_DIRTY) + { + va_start (ap, handle); + while ((option = va_arg (ap, CoglMaterialFlushOption))) + { + if (option == COGL_MATERIAL_FLUSH_FALLBACK_MASK) + fallback_layers = va_arg (ap, guint32); + else if (option == COGL_MATERIAL_FLUSH_DISABLE_MASK) + disable_layers = va_arg (ap, guint32); + else if (option == COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE) + layer0_override_texture = va_arg (ap, GLuint); + } + va_end (ap); + + _cogl_material_flush_layers_gl_state (material, + fallback_layers, + disable_layers, + layer0_override_texture); + } + + /* NB: we have to take a reference so that next time + * cogl_material_flush_gl_state is called, we can compare the incomming + * material pointer with ctx->current_material + */ + cogl_material_ref (handle); + cogl_material_unref (ctx->current_material); + + ctx->current_material = handle; + ctx->current_material_flags = material->flags; +} + + + /* TODO: Should go in cogl.c, but that implies duplication which is also * not ideal. */ void @@ -675,40 +1096,24 @@ cogl_set_source (CoglHandle material_handle) if (ctx->source_material == material_handle) return; + cogl_material_ref (material_handle); + if (ctx->source_material) cogl_material_unref (ctx->source_material); - cogl_material_ref (material_handle); ctx->source_material = material_handle; } /* TODO: add cogl_set_front_source (), and cogl_set_back_source () */ void -cogl_flush_material_gl_state (void) +cogl_set_source_texture (CoglHandle texture_handle) { - CoglMaterial *material; _COGL_GET_CONTEXT (ctx, NO_RETVAL); + CoglColor white; - material = _cogl_material_pointer_from_handle (ctx->source_material); - - if (ctx->source_material == ctx->current_material - && !(material->flags & COGL_MATERIAL_FLAG_DIRTY)) - return; - - GE (glColor4fv (material->unlit)); - - /* FIXME - we only need to set these if lighting is enabled... */ - GE (glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, material->ambient)); - GE (glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, material->diffuse)); - GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, material->specular)); - GE (glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, material->emission)); - GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, &material->shininess)); - - /* NB: Currently the Cogl defines are compatible with the GL ones: */ - GE (glAlphaFunc (material->alpha_func, material->alpha_func_reference)); - - GE (glBlendFunc (material->blend_src_factor, material->blend_dst_factor)); - - ctx->current_material = ctx->source_material; + cogl_material_set_layer (ctx->default_material, 0, texture_handle); + cogl_color_set_from_4ub (&white, 0xff, 0xff, 0xff, 0xff); + cogl_material_set_color (ctx->default_material, &white); + cogl_set_source (ctx->default_material); } diff --git a/clutter/cogl/common/cogl-primitives.c b/clutter/cogl/common/cogl-primitives.c index 7e9b1b94e..54111de50 100644 --- a/clutter/cogl/common/cogl-primitives.c +++ b/clutter/cogl/common/cogl-primitives.c @@ -43,19 +43,18 @@ void _cogl_path_add_node (gboolean new_sub_path, float y); void _cogl_path_fill_nodes (); void _cogl_path_stroke_nodes (); -void _cogl_rectangle (float x, - float y, - float width, - float height); + void cogl_rectangle (float x, float y, float width, float height) { - cogl_clip_ensure (); - - _cogl_rectangle (x, y, width, height); + cogl_rectangle_with_multitexture_coords (x, y, + x+width, + y+height, + NULL, + 0); } void diff --git a/clutter/cogl/common/cogl-vertex-buffer.c b/clutter/cogl/common/cogl-vertex-buffer.c index 45833cdd6..0b617244c 100644 --- a/clutter/cogl/common/cogl-vertex-buffer.c +++ b/clutter/cogl/common/cogl-vertex-buffer.c @@ -134,6 +134,7 @@ #include "cogl-context.h" #include "cogl-handle.h" #include "cogl-vertex-buffer-private.h" +#include "cogl-texture-private.h" #define PAD_FOR_ALIGNMENT(VAR, TYPE_SIZE) \ (VAR = TYPE_SIZE + ((VAR - 1) & ~(TYPE_SIZE - 1))) @@ -1416,12 +1417,15 @@ get_gl_type_from_attribute_flags (CoglVertexBufferAttribFlags flags) static void enable_state_for_drawing_attributes_buffer (CoglVertexBuffer *buffer) { - GList *tmp; - GLenum gl_type; - GLuint generic_index = 0; - gulong enable_flags = COGL_ENABLE_BLEND; - /* FIXME: I don't think it's appropriate to force enable - * GL_BLEND here. */ + GList *tmp; + GLenum gl_type; + GLuint generic_index = 0; + gulong enable_flags = 0; + guint max_texcoord_attrib_unit = 0; + const GList *layers; + guint32 fallback_mask = 0; + guint32 disable_mask = ~0; + int i; _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -1460,17 +1464,16 @@ enable_state_for_drawing_attributes_buffer (CoglVertexBuffer *buffer) (const GLvoid *)attribute->u.vbo_offset)); break; case COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY: - /* FIXME: set the active texture unit */ - /* NB: Cogl currently manages unit 0 */ - enable_flags |= (COGL_ENABLE_TEXCOORD_ARRAY - | COGL_ENABLE_TEXTURE_2D); - /* FIXME: I don't think it's appropriate to force enable - * GL_TEXTURE_2D here. */ - /* GE (glEnableClientState (GL_VERTEX_ARRAY)); */ + GE (glClientActiveTexture (GL_TEXTURE0 + + attribute->texture_unit)); + GE (glEnableClientState (GL_TEXTURE_COORD_ARRAY)); GE (glTexCoordPointer (attribute->n_components, gl_type, attribute->stride, (const GLvoid *)attribute->u.vbo_offset)); + if (attribute->texture_unit > max_texcoord_attrib_unit) + max_texcoord_attrib_unit = attribute->texture_unit; + disable_mask &= ~(1 << attribute->texture_unit); break; case COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY: enable_flags |= COGL_ENABLE_VERTEX_ARRAY; @@ -1505,8 +1508,51 @@ enable_state_for_drawing_attributes_buffer (CoglVertexBuffer *buffer) } } - cogl_enable (enable_flags); + layers = cogl_material_get_layers (ctx->source_material); + for (tmp = (GList *)layers, i = 0; + tmp != NULL && i <= max_texcoord_attrib_unit; + tmp = tmp->next, i++) + { + CoglHandle layer = (CoglHandle)tmp->data; + CoglHandle tex_handle = cogl_material_layer_get_texture (layer); + CoglTexture *texture = + _cogl_texture_pointer_from_handle (tex_handle); + if (cogl_texture_is_sliced (tex_handle) + || _cogl_texture_span_has_waste (texture, 0, 0)) + { + g_warning ("Disabling layer %d of the current source material, " + "because texturing with the vertex buffer API is not " + "currently supported using sliced textures, or textures " + "with waste\n", i); + + /* XXX: maybe we can add a mechanism for users to forcibly use + * textures with waste where it would be their responsability to use + * texture coords in the range [0,1] such that sampling outside isn't + * required. We can then use a texture matrix (or a modification of + * the users own matrix) to map 1 to the edge of the texture data. + * + * Potentially, given the same guarantee as above we could also + * support a single sliced layer too. We would have to redraw the + * vertices once for each layer, each time with a fiddled texture + * matrix. + */ + fallback_mask |= (1 << i); + } + else if (!(disable_mask & (1 << i))) + fallback_mask |= (1 << i); + } + + cogl_material_flush_gl_state (ctx->source_material, + COGL_MATERIAL_FLUSH_FALLBACK_MASK, + fallback_mask, + COGL_MATERIAL_FLUSH_DISABLE_MASK, + disable_mask, + NULL); + + enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material); + + cogl_enable (enable_flags); } static void @@ -1550,9 +1596,9 @@ disable_state_for_drawing_buffer (CoglVertexBuffer *buffer) GE (glDisableClientState (GL_NORMAL_ARRAY)); break; case COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY: - /* FIXME: set the active texture unit */ - /* NB: Cogl currently manages unit 0 */ - /* GE (glDisableClientState (GL_VERTEX_ARRAY)); */ + GE (glClientActiveTexture (GL_TEXTURE0 + + attribute->texture_unit)); + GE (glDisableClientState (GL_TEXTURE_COORD_ARRAY)); break; case COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY: /* GE (glDisableClientState (GL_VERTEX_ARRAY)); */ diff --git a/clutter/cogl/gl/cogl-context.c b/clutter/cogl/gl/cogl-context.c index cd89fcf9a..6a3c032e4 100644 --- a/clutter/cogl/gl/cogl-context.c +++ b/clutter/cogl/gl/cogl-context.c @@ -31,6 +31,8 @@ #include "cogl-internal.h" #include "cogl-util.h" #include "cogl-context.h" +#include "cogl-texture-private.h" +#include "cogl-material-private.h" #include @@ -39,6 +41,9 @@ static CoglContext *_context = NULL; gboolean cogl_create_context () { + GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 }; + gulong enable_flags = 0; + if (_context != NULL) return FALSE; @@ -52,19 +57,26 @@ cogl_create_context () _context->enable_flags = 0; _context->color_alpha = 255; - _context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode)); - _context->last_path = 0; - - _context->texture_handles = NULL; - _context->texture_vertices = g_array_new (FALSE, FALSE, - sizeof (CoglTextureGLVertex)); - _context->texture_indices = g_array_new (FALSE, FALSE, - sizeof (GLushort)); - _context->material_handles = NULL; _context->material_layer_handles = NULL; + _context->default_material = cogl_material_new (); _context->source_material = NULL; + + _context->texture_handles = NULL; + _context->default_gl_texture_2d_tex = COGL_INVALID_HANDLE; + _context->default_gl_texture_rect_tex = COGL_INVALID_HANDLE; + + _context->journal = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry)); + _context->logged_vertices = g_array_new (FALSE, FALSE, sizeof (GLfloat)); + _context->static_indices = g_array_new (FALSE, FALSE, sizeof (GLushort)); + _context->polygon_vertices = g_array_new (FALSE, FALSE, + sizeof (CoglTextureGLVertex)); + _context->current_material = NULL; + _context->current_material_flags = 0; + _context->current_layers = g_array_new (FALSE, FALSE, + sizeof (CoglLayerInfo)); + _context->n_texcoord_arrays_enabled = 0; _context->fbo_handles = NULL; _context->draw_buffer = COGL_WINDOW_BUFFER; @@ -78,6 +90,10 @@ cogl_create_context () _context->vertex_buffer_handles = NULL; + _context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode)); + _context->last_path = 0; + _context->stencil_material = cogl_material_new (); + _context->pf_glGenRenderbuffersEXT = NULL; _context->pf_glBindRenderbufferEXT = NULL; _context->pf_glRenderbufferStorageEXT = NULL; @@ -123,15 +139,37 @@ cogl_create_context () _context->pf_glDrawRangeElements = NULL; - /* Init OpenGL state */ - GE( glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) ); - GE( glColorMask (TRUE, TRUE, TRUE, FALSE) ); - GE( glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ); - cogl_enable (0); - /* Initialise the clip stack */ _cogl_clip_stack_state_init (); + /* Create default textures used for fall backs */ + _context->default_gl_texture_2d_tex = + cogl_texture_new_from_data (1, /* width */ + 1, /* height */ + -1, /* max waste */ + FALSE, /* auto mipmap */ + COGL_PIXEL_FORMAT_RGBA_8888, /* data format */ + /* internal format */ + COGL_PIXEL_FORMAT_RGBA_8888, + 0, /* auto calc row stride */ + &default_texture_data); + _context->default_gl_texture_rect_tex = + cogl_texture_new_from_data (1, /* width */ + 1, /* height */ + -1, /* max waste */ + FALSE, /* auto mipmap */ + COGL_PIXEL_FORMAT_RGBA_8888, /* data format */ + /* internal format */ + COGL_PIXEL_FORMAT_RGBA_8888, + 0, /* auto calc row stride */ + &default_texture_data); + + cogl_set_source (_context->default_material); + cogl_material_flush_gl_state (_context->source_material, NULL); + enable_flags = + cogl_material_get_cogl_enable_flags (_context->source_material); + cogl_enable (enable_flags); + return TRUE; } @@ -155,10 +193,25 @@ cogl_destroy_context () if (_context->program_handles) g_array_free (_context->program_handles, TRUE); - if (_context->texture_vertices) - g_array_free (_context->texture_vertices, TRUE); - if (_context->texture_indices) - g_array_free (_context->texture_indices, TRUE); + if (_context->default_gl_texture_2d_tex) + cogl_texture_unref (_context->default_gl_texture_2d_tex); + if (_context->default_gl_texture_rect_tex) + cogl_texture_unref (_context->default_gl_texture_rect_tex); + + if (_context->default_material) + cogl_material_unref (_context->default_material); + + if (_context->journal) + g_array_free (_context->journal, TRUE); + if (_context->logged_vertices) + g_array_free (_context->logged_vertices, TRUE); + + if (_context->static_indices) + g_array_free (_context->static_indices, TRUE); + if (_context->polygon_vertices) + g_array_free (_context->polygon_vertices, TRUE); + if (_context->current_layers) + g_array_free (_context->current_layers, TRUE); g_free (_context); } diff --git a/clutter/cogl/gl/cogl-context.h b/clutter/cogl/gl/cogl-context.h index ae1b80c85..db3a333a1 100644 --- a/clutter/cogl/gl/cogl-context.h +++ b/clutter/cogl/gl/cogl-context.h @@ -50,33 +50,34 @@ typedef struct gboolean enable_backface_culling; - /* Primitives */ - floatVec2 path_start; - floatVec2 path_pen; - GArray *path_nodes; - guint last_path; - floatVec2 path_nodes_min; - floatVec2 path_nodes_max; - /* Cache of inverse projection matrix */ GLfloat inverse_projection[16]; /* Textures */ - GArray *texture_handles; - GArray *texture_vertices; - GArray *texture_indices; - /* The gl texture number that the above vertices apply to. This to - detect when a different slice is encountered so that the vertices - can be flushed */ - GLuint texture_current; - GLenum texture_target; - GLenum texture_wrap_mode; + GArray *texture_handles; + CoglHandle default_gl_texture_2d_tex; + CoglHandle default_gl_texture_rect_tex; /* Materials */ GArray *material_handles; GArray *material_layer_handles; + CoglHandle default_material; CoglHandle source_material; + + /* Batching geometry... */ + /* We journal the texture rectangles we want to submit to OpenGL so + * we have an oppertunity to optimise the final order so that we + * can batch things together. */ + GArray *journal; + GArray *logged_vertices; + GArray *static_indices; + GArray *polygon_vertices; + + /* Some simple caching, to minimize state changes... */ CoglHandle current_material; + gulong current_material_flags; + GArray *current_layers; + guint n_texcoord_arrays_enabled; /* Framebuffer objects */ GArray *fbo_handles; @@ -94,6 +95,15 @@ typedef struct /* Vertex buffers */ GArray *vertex_buffer_handles; + /* Primitives */ + floatVec2 path_start; + floatVec2 path_pen; + GArray *path_nodes; + guint last_path; + floatVec2 path_nodes_min; + floatVec2 path_nodes_max; + CoglHandle stencil_material; + /* Relying on glext.h to define these */ COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT; COGL_PFNGLDELETERENDERBUFFERSEXTPROC pf_glDeleteRenderbuffersEXT; diff --git a/clutter/cogl/gl/cogl-internal.h b/clutter/cogl/gl/cogl-internal.h index 8887788c2..735e005ee 100644 --- a/clutter/cogl/gl/cogl-internal.h +++ b/clutter/cogl/gl/cogl-internal.h @@ -51,13 +51,10 @@ const char *_cogl_error_string(GLenum errorCode); #endif /* COGL_DEBUG */ #define COGL_ENABLE_BLEND (1<<1) -#define COGL_ENABLE_TEXTURE_2D (1<<2) -#define COGL_ENABLE_ALPHA_TEST (1<<3) -#define COGL_ENABLE_TEXTURE_RECT (1<<4) -#define COGL_ENABLE_VERTEX_ARRAY (1<<5) -#define COGL_ENABLE_TEXCOORD_ARRAY (1<<6) -#define COGL_ENABLE_COLOR_ARRAY (1<<7) -#define COGL_ENABLE_BACKFACE_CULLING (1<<8) +#define COGL_ENABLE_ALPHA_TEST (1<<2) +#define COGL_ENABLE_VERTEX_ARRAY (1<<3) +#define COGL_ENABLE_COLOR_ARRAY (1<<4) +#define COGL_ENABLE_BACKFACE_CULLING (1<<5) gint _cogl_get_format_bpp (CoglPixelFormat format); diff --git a/clutter/cogl/gl/cogl-primitives.c b/clutter/cogl/gl/cogl-primitives.c index e44565780..6c00ed193 100644 --- a/clutter/cogl/gl/cogl-primitives.c +++ b/clutter/cogl/gl/cogl-primitives.c @@ -38,27 +38,13 @@ #define _COGL_MAX_BEZ_RECURSE_DEPTH 16 -void -_cogl_rectangle (float x, - float y, - float width, - float height) -{ - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - cogl_enable (ctx->color_alpha < 255 - ? COGL_ENABLE_BLEND : 0); - - GE( glRectf (x, y, x + width, y + height) ); -} - void _cogl_path_add_node (gboolean new_sub_path, float x, float y) { CoglPathNode new_node; - + _COGL_GET_CONTEXT (ctx, NO_RETVAL); new_node.x = (x); @@ -89,13 +75,18 @@ _cogl_path_add_node (gboolean new_sub_path, void _cogl_path_stroke_nodes () { - guint path_start = 0; + guint path_start = 0; + gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY; _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - cogl_enable (COGL_ENABLE_VERTEX_ARRAY - | (ctx->color_alpha < 255 - ? COGL_ENABLE_BLEND : 0)); + + enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material); + cogl_enable (enable_flags); + + cogl_material_flush_gl_state (ctx->source_material, + COGL_MATERIAL_FLUSH_DISABLE_MASK, + (guint32)~0, /* disable all texture layers */ + NULL); while (path_start < ctx->path_nodes->len) { @@ -106,7 +97,7 @@ _cogl_path_stroke_nodes () (guchar *) path + G_STRUCT_OFFSET (CoglPathNode, x)) ); GE( glDrawArrays (GL_LINE_STRIP, 0, path->path_size) ); - + path_start += path->path_size; } } @@ -139,6 +130,8 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, float bounds_w; float bounds_h; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + _cogl_path_get_bounds (nodes_min, nodes_max, &bounds_x, &bounds_y, &bounds_w, &bounds_h); @@ -159,10 +152,17 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, GE( glColorMask (FALSE, FALSE, FALSE, FALSE) ); GE( glDepthMask (FALSE) ); - + while (path_start < path_size) { - cogl_enable (COGL_ENABLE_VERTEX_ARRAY); + gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY; + + /* Just setup a simple material that doesn't use texturing... */ + cogl_material_flush_gl_state (ctx->stencil_material, NULL); + + enable_flags |= + cogl_material_get_cogl_enable_flags (ctx->source_material); + cogl_enable (enable_flags); GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode), (guchar *) path @@ -207,11 +207,11 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, GE( glMatrixMode (GL_MODELVIEW) ); GE( glPopMatrix () ); } - + GE( glStencilMask (~(GLuint) 0) ); GE( glDepthMask (TRUE) ); GE( glColorMask (TRUE, TRUE, TRUE, TRUE) ); - + GE( glStencilFunc (GL_EQUAL, 0x1, 0x1) ); GE( glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) ); } diff --git a/clutter/cogl/gl/cogl-texture-private.h b/clutter/cogl/gl/cogl-texture-private.h index 44fd7712e..59bcad108 100644 --- a/clutter/cogl/gl/cogl-texture-private.h +++ b/clutter/cogl/gl/cogl-texture-private.h @@ -28,11 +28,9 @@ #include "cogl-bitmap.h" -typedef struct _CoglTexture CoglTexture; -typedef struct _CoglTexSliceSpan CoglTexSliceSpan; -typedef struct _CoglSpanIter CoglSpanIter; -typedef struct _CoglCompositeTexture CoglCompositeTexture; -typedef struct _CoglCompositeTextureLayer CoglCompositeTextureLayer; +typedef struct _CoglTexture CoglTexture; +typedef struct _CoglTexSliceSpan CoglTexSliceSpan; +typedef struct _CoglSpanIter CoglSpanIter; struct _CoglTexSliceSpan { @@ -61,26 +59,23 @@ struct _CoglTexture gboolean auto_mipmap; }; -struct _CoglCompositeTextureLayer +/* To improve batching of geometry when submitting vertices to OpenGL we + * log the texture rectangles we want to draw to a journal, so when we + * later flush the journal we aim to batch data, and gl draw calls. */ +typedef struct _CoglJournalEntry { - guint ref_count; - - guint index; /*!< lowest index is blended first then others - on top */ - CoglTexture *tex; /*!< The texture for this layer, or NULL - for an empty layer */ - - /* TODO: Add more control over the texture environment for each texture - * unit. For example we should support dot3 normal mapping. */ -}; - -struct _CoglCompositeTexture -{ - guint ref_count; - GList *layers; -}; + CoglHandle material; + gint n_layers; + guint32 fallback_mask; + GLuint layer0_override_texture; +} CoglJournalEntry; CoglTexture* _cogl_texture_pointer_from_handle (CoglHandle handle); +gboolean +_cogl_texture_span_has_waste (CoglTexture *tex, + gint x_span_index, + gint y_span_index); + #endif /* __COGL_TEXTURE_H */ diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c index df85e9bf1..0a84457c5 100644 --- a/clutter/cogl/gl/cogl-texture.c +++ b/clutter/cogl/gl/cogl-texture.c @@ -51,6 +51,8 @@ printf("err: 0x%x\n", err); \ } */ +static void _cogl_journal_flush (void); + static void _cogl_texture_free (CoglTexture *tex); COGL_HANDLE_DEFINE (Texture, texture, texture_handles); @@ -774,6 +776,10 @@ _cogl_texture_set_wrap_mode_parameter (CoglTexture *tex, { int i; + /* Any queued texture rectangles may be depending on the previous + * wrap mode... */ + _cogl_journal_flush (); + for (i = 0; i < tex->slice_gl_handles->len; i++) { GLuint texnum = g_array_index (tex->slice_gl_handles, GLuint, i); @@ -990,6 +996,20 @@ _cogl_texture_slices_free (CoglTexture *tex) } } +gboolean +_cogl_texture_span_has_waste (CoglTexture *tex, + gint x_span_index, + gint y_span_index) +{ + CoglTexSliceSpan *x_span; + CoglTexSliceSpan *y_span; + + x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x_span_index); + y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, y_span_index); + + return (x_span->waste || y_span->waste) ? TRUE : FALSE; +} + static gboolean _cogl_pixel_format_from_gl_internal (GLenum gl_int_format, CoglPixelFormat *out_format) @@ -1392,12 +1412,12 @@ cogl_texture_new_from_file (const gchar *filename, { CoglBitmap *bmp; CoglHandle handle; - + g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE); if (!(bmp = cogl_bitmap_new_from_file (filename, error))) return COGL_INVALID_HANDLE; - + handle = cogl_texture_new_from_bitmap (bmp, max_waste, flags, @@ -1920,130 +1940,307 @@ cogl_texture_get_data (CoglHandle handle, return byte_size; } + +/****************************************************************************** + * XXX: Here ends the code that strictly implements "CoglTextures". + * + * The following consists of code for rendering rectangles and polygons. It + * might be neater to move this code somewhere else. I think everything below + * here should be implementable without access to CoglTexture internals, but + * that will at least mean exposing the cogl_span_iter_* funcs. + */ + static void -_cogl_texture_flush_vertices (void) +_cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start, + gint batch_len, + GLfloat *vertex_pointer) { + int needed_indices; + gsize stride; + int i; + gulong enable_flags = 0; + guint32 disable_mask; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); - if (ctx->texture_vertices->len > 0) + /* The indices are always the same sequence regardless of the vertices so we + * only need to change it if there are more vertices than ever before. */ + needed_indices = batch_len * 6; + if (needed_indices > ctx->static_indices->len) { - int needed_indices; - CoglTextureGLVertex *p - = (CoglTextureGLVertex *) ctx->texture_vertices->data; + int old_len = ctx->static_indices->len; + int vert_num = old_len / 6 * 4; + GLushort *q; - /* The indices are always the same sequence regardless of the - vertices so we only need to change it if there are more - vertices than ever before */ - needed_indices = ctx->texture_vertices->len / 4 * 6; - if (needed_indices > ctx->texture_indices->len) + /* Add two triangles for each quad to the list of + indices. That makes six new indices but two of the + vertices in the triangles are shared. */ + g_array_set_size (ctx->static_indices, needed_indices); + q = &g_array_index (ctx->static_indices, GLushort, old_len); + + for (i = old_len; + i < ctx->static_indices->len; + i += 6, vert_num += 4) { - int old_len = ctx->texture_indices->len; - int vert_num = old_len / 6 * 4; - int i; - GLushort *q; + *(q++) = vert_num + 0; + *(q++) = vert_num + 1; + *(q++) = vert_num + 3; - /* Add two triangles for each quad to the list of - indices. That makes six new indices but two of the - vertices in the triangles are shared. */ - g_array_set_size (ctx->texture_indices, needed_indices); - q = &g_array_index (ctx->texture_indices, GLushort, old_len); + *(q++) = vert_num + 1; + *(q++) = vert_num + 2; + *(q++) = vert_num + 3; + } + } - for (i = old_len; - i < ctx->texture_indices->len; - i += 6, vert_num += 4) - { - *(q++) = vert_num + 0; - *(q++) = vert_num + 1; - *(q++) = vert_num + 3; + /* XXX NB: + * Our vertex data is arranged as follows: + * 4 vertices per quad: 2 GLfloats per position, + * 2 GLfloats per tex coord * n_layers + */ + stride = 2 + 2 * batch_start->n_layers; + stride *= sizeof (GLfloat); - *(q++) = vert_num + 1; - *(q++) = vert_num + 2; - *(q++) = vert_num + 3; - } + disable_mask = (1 << batch_start->n_layers) - 1; + disable_mask = ~disable_mask; + + cogl_material_flush_gl_state (ctx->source_material, + COGL_MATERIAL_FLUSH_FALLBACK_MASK, + batch_start->fallback_mask, + COGL_MATERIAL_FLUSH_DISABLE_MASK, + disable_mask, + /* Redundant when dealing with unsliced + * textures but does no harm... */ + COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE, + batch_start->layer0_override_texture, + NULL); + + for (i = 0; i < batch_start->n_layers; i++) + { + GE (glClientActiveTexture (GL_TEXTURE0 + i)); + GE (glEnableClientState (GL_TEXTURE_COORD_ARRAY)); + GE (glTexCoordPointer (2, GL_FLOAT, stride, vertex_pointer + 2 + 2 * i)); + } + for (; i < ctx->n_texcoord_arrays_enabled; i++) + { + GE (glClientActiveTexture (GL_TEXTURE0 + i)); + GE (glDisableClientState (GL_TEXTURE_COORD_ARRAY)); + } + ctx->n_texcoord_arrays_enabled = 0; + + /* FIXME: This api is a bit yukky, ideally it will be removed if we + * re-work the cogl_enable mechanism */ + enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material); + + if (ctx->enable_backface_culling) + enable_flags |= COGL_ENABLE_BACKFACE_CULLING; + + enable_flags |= COGL_ENABLE_VERTEX_ARRAY; + cogl_enable (enable_flags); + + GE (glVertexPointer (2, GL_FLOAT, stride, vertex_pointer)); + + GE (ctx->pf_glDrawRangeElements (GL_TRIANGLES, + 0, ctx->static_indices->len - 1, + 6 * batch_len, + GL_UNSIGNED_SHORT, + ctx->static_indices->data)); +} + +static void +_cogl_journal_flush (void) +{ + GLfloat *current_vertex_pointer; + GLfloat *batch_vertex_pointer; + CoglJournalEntry *batch_start; + guint batch_len; + int i; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->journal->len == 0) + return; + + /* Current non-variables / constraints: + * + * - We don't have to worry about much GL state changing between journal + * entries since currently the journal never out lasts a single call to + * _cogl_multitexture_multiple_rectangles. So the user doesn't get the + * chance to fiddle with anything. (XXX: later this will be extended at + * which point we can start logging certain state changes) + * + * - Implied from above: all entries will refer to the same material. + * + * - Although _cogl_multitexture_multiple_rectangles can cause the wrap mode + * of textures to be modified, the journal is flushed if a wrap mode is + * changed so we don't currently have to log wrap mode changes. + * + * - XXX - others? + */ + + /* TODO: "compile" the journal to find ways of batching draw calls and vertex + * data. + * + * Simple E.g. given current constraints... + * pass 0 - load all data into a single CoglVertexBuffer + * pass 1 - batch gl draw calls according to entries that use the same + * textures. + * + * We will be able to do cooler stuff here when we extend the life of + * journals beyond _cogl_multitexture_multiple_rectangles. + */ + + batch_vertex_pointer = (GLfloat *)ctx->logged_vertices->data; + batch_start = (CoglJournalEntry *)ctx->journal->data; + batch_len = 1; + + current_vertex_pointer = batch_vertex_pointer; + + for (i = 1; i < ctx->journal->len; i++) + { + CoglJournalEntry *prev_entry = + &g_array_index (ctx->journal, CoglJournalEntry, i - 1); + CoglJournalEntry *current_entry = prev_entry + 1; + gsize stride; + + /* Progress the vertex pointer */ + stride = 2 + current_entry->n_layers * 2; + current_vertex_pointer += stride; + + /* batch rectangles using the same textures */ + if (current_entry->material == prev_entry->material && + current_entry->n_layers == prev_entry->n_layers && + current_entry->fallback_mask == prev_entry->fallback_mask && + current_entry->layer0_override_texture + == prev_entry->layer0_override_texture) + { + batch_len++; + continue; } - GE( glVertexPointer (2, GL_FLOAT, - sizeof (CoglTextureGLVertex), p->v ) ); - GE( glTexCoordPointer (2, GL_FLOAT, - sizeof (CoglTextureGLVertex), p->t ) ); + _cogl_journal_flush_quad_batch (batch_start, + batch_len, + batch_vertex_pointer); - GE( glBindTexture (ctx->texture_target, ctx->texture_current) ); - GE( ctx->pf_glDrawRangeElements (GL_TRIANGLES, - 0, ctx->texture_vertices->len - 1, - needed_indices, - GL_UNSIGNED_SHORT, - ctx->texture_indices->data) ); - - g_array_set_size (ctx->texture_vertices, 0); + batch_start = current_entry; + batch_len = 1; + batch_vertex_pointer = current_vertex_pointer; } + + /* The last batch... */ + _cogl_journal_flush_quad_batch (batch_start, + batch_len, + batch_vertex_pointer); + + + g_array_set_size (ctx->journal, 0); + g_array_set_size (ctx->logged_vertices, 0); } static void -_cogl_texture_add_quad_vertices (GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - GLfloat tx1, GLfloat ty1, - GLfloat tx2, GLfloat ty2) +_cogl_journal_log_quad (float x1, + float y1, + float x2, + float y2, + CoglHandle material, + gint n_layers, + guint32 fallback_mask, + GLuint layer0_override_texture, + float *tex_coords, + guint tex_coords_len) { - CoglTextureGLVertex *p; - GLushort first_vert; + int stride; + int next_vert; + GLfloat *v; + int i; + int next_entry; + CoglJournalEntry *entry; _COGL_GET_CONTEXT (ctx, NO_RETVAL); - /* Add the four vertices of the quad to the list of queued - vertices */ - first_vert = ctx->texture_vertices->len; - g_array_set_size (ctx->texture_vertices, first_vert + 4); - p = &g_array_index (ctx->texture_vertices, CoglTextureGLVertex, first_vert); + /* The vertex data is logged into a seperate array in a layout that can be + * directly passed to OpenGL + */ - p->v[0] = x1; p->v[1] = y1; - p->t[0] = tx1; p->t[1] = ty1; - p++; - p->v[0] = x1; p->v[1] = y2; - p->t[0] = tx1; p->t[1] = ty2; - p++; - p->v[0] = x2; p->v[1] = y2; - p->t[0] = tx2; p->t[1] = ty2; - p++; - p->v[0] = x2; p->v[1] = y1; - p->t[0] = tx2; p->t[1] = ty1; - p++; + /* We pack the vertex data as 2 (x,y) GLfloats folowed by 2 (tx,ty) GLfloats + * for each texture being used, E.g.: + * [X, Y, TX0, TY0, TX1, TY1, X, Y, TX0, TY0, X, Y, ...] + */ + stride = 2 + n_layers * 2; + + next_vert = ctx->logged_vertices->len; + g_array_set_size (ctx->logged_vertices, next_vert + 4 * stride); + v = &g_array_index (ctx->logged_vertices, GLfloat, next_vert); + + /* XXX: All the jumping around to fill in this strided buffer doesn't + * seem ideal. */ + + /* XXX: we could defer expanding the vertex data for GL until we come + * to flushing the journal. */ + + v[0] = x1; v[1] = y1; + v += stride; + v[0] = x1; v[1] = y2; + v += stride; + v[0] = x2; v[1] = y2; + v += stride; + v[0] = x2; v[1] = y1; + + for (i = 0; i < n_layers; i++) + { + GLfloat *t = + &g_array_index (ctx->logged_vertices, GLfloat, next_vert + 2 + 2 * i); + + t[0] = tex_coords[0]; t[1] = tex_coords[1]; + t += stride; + t[0] = tex_coords[0]; t[1] = tex_coords[3]; + t += stride; + t[0] = tex_coords[2]; t[1] = tex_coords[3]; + t += stride; + t[0] = tex_coords[2]; t[1] = tex_coords[1]; + } + + next_entry = ctx->journal->len; + g_array_set_size (ctx->journal, next_entry + 1); + entry = &g_array_index (ctx->journal, CoglJournalEntry, next_entry); + + entry->material = material; + entry->n_layers = n_layers; + entry->fallback_mask = fallback_mask; + entry->layer0_override_texture = layer0_override_texture; } static void -_cogl_texture_quad_sw (CoglTexture *tex, - float x1, - float y1, - float x2, - float y2, - float tx1, - float ty1, - float tx2, - float ty2) +_cogl_texture_sliced_quad (CoglTexture *tex, + CoglHandle material, + float x1, + float y1, + float x2, + float y2, + float tx1, + float ty1, + float tx2, + float ty2) { - CoglSpanIter iter_x , iter_y; - float tw , th; - float tqx , tqy; - float first_tx , first_ty; - float first_qx , first_qy; - float slice_tx1 , slice_ty1; - float slice_tx2 , slice_ty2; - float slice_qx1 , slice_qy1; - float slice_qx2 , slice_qy2; - GLuint gl_handle; + CoglSpanIter iter_x , iter_y; + float tw , th; + float tqx , tqy; + float first_tx , first_ty; + float first_qx , first_qy; + float slice_tx1 , slice_ty1; + float slice_tx2 , slice_ty2; + float slice_qx1 , slice_qy1; + float slice_qx2 , slice_qy2; + GLuint gl_handle; _COGL_GET_CONTEXT (ctx, NO_RETVAL); #if COGL_DEBUG - printf("=== Drawing Tex Quad (Software Tiling Mode) ===\n"); + printf("=== Drawing Tex Quad (Sliced Mode) ===\n"); #endif /* We can't use hardware repeat so we need to set clamp to edge otherwise it might pull in edge pixels from the other side */ - if (ctx->texture_vertices->len > 0 - && ctx->texture_wrap_mode != GL_CLAMP_TO_EDGE) - _cogl_texture_flush_vertices (); _cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_EDGE); - ctx->texture_wrap_mode = GL_CLAMP_TO_EDGE; /* If the texture coordinates are backwards then swap both the geometry and texture coordinates so that the texture will be @@ -2098,6 +2295,8 @@ _cogl_texture_quad_sw (CoglTexture *tex, !_cogl_span_iter_end (&iter_y) ; _cogl_span_iter_next (&iter_y) ) { + float tex_coords[4]; + /* Discard slices out of quad early */ if (!iter_y.intersects) continue; @@ -2161,183 +2360,358 @@ _cogl_texture_quad_sw (CoglTexture *tex, iter_y.index * iter_x.array->len + iter_x.index); - /* If we're using a different texture from the one already queued - then flush the vertices */ - if (ctx->texture_vertices->len > 0 - && gl_handle != ctx->texture_current) - _cogl_texture_flush_vertices (); - ctx->texture_target = tex->gl_target; - ctx->texture_current = gl_handle; - - _cogl_texture_add_quad_vertices ( (slice_qx1), - (slice_qy1), - (slice_qx2), - (slice_qy2), - (slice_tx1), - (slice_ty1), - (slice_tx2), - (slice_ty2)); + tex_coords[0] = slice_tx1; + tex_coords[1] = slice_ty1; + tex_coords[2] = slice_tx2; + tex_coords[3] = slice_ty2; + _cogl_journal_log_quad (slice_qx1, + slice_qy1, + slice_qx2, + slice_qy2, + material, + 1, /* one layer */ + 0, /* don't need to use fallbacks */ + gl_handle, /* replace the layer0 texture */ + tex_coords, + 4); } } } -static void -_cogl_texture_quad_hw (CoglTexture *tex, - float x1, - float y1, - float x2, - float y2, - float tx1, - float ty1, - float tx2, - float ty2) +static gboolean +_cogl_multitexture_unsliced_quad (float x1, + float y1, + float x2, + float y2, + CoglHandle material, + gint n_layers, + guint32 fallback_mask, + const float *user_tex_coords, + gint user_tex_coords_len) { - GLuint gl_handle; - CoglTexSliceSpan *x_span; - CoglTexSliceSpan *y_span; - GLenum wrap_mode; + float *final_tex_coords = alloca (sizeof (float) * 4 * n_layers); + const GList *layers; + GList *tmp; + int i; -#if COGL_DEBUG - printf("=== Drawing Tex Quad (Hardware Tiling Mode) ===\n"); -#endif + _COGL_GET_CONTEXT (ctx, FALSE); - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - /* If the texture coords are all in the range [0,1] then we want to - clamp the coords to the edge otherwise it can pull in edge pixels - from the wrong side when scaled */ - if (tx1 >= 0 && tx1 <= 1.0 - && tx2 >= 0 && tx2 <= 1.0 - && ty1 >= 0 && ty1 <= 1.0 - && ty2 >= 0 && ty2 <= 1.0) - wrap_mode = GL_CLAMP_TO_EDGE; - else - wrap_mode = GL_REPEAT; - - /* Pick and bind opengl texture object */ - gl_handle = g_array_index (tex->slice_gl_handles, GLuint, 0); - - /* If we're using a different texture from the one already queued - then flush the vertices */ - if (ctx->texture_vertices->len > 0 - && (gl_handle != ctx->texture_current - || ctx->texture_wrap_mode != wrap_mode)) - _cogl_texture_flush_vertices (); - ctx->texture_target = tex->gl_target; - ctx->texture_current = gl_handle; - ctx->texture_wrap_mode = wrap_mode; - - _cogl_texture_set_wrap_mode_parameter (tex, wrap_mode); - - /* Don't include the waste in the texture coordinates */ - x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0); - y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, 0); - - /* Don't include the waste in the texture coordinates */ - tx1 = tx1 * (x_span->size - x_span->waste) / x_span->size; - tx2 = tx2 * (x_span->size - x_span->waste) / x_span->size; - ty1 = ty1 * (y_span->size - y_span->waste) / y_span->size; - ty2 = ty2 * (y_span->size - y_span->waste) / y_span->size; - - /* Denormalize texture coordinates for rectangle textures */ - if (tex->gl_target == GL_TEXTURE_RECTANGLE_ARB) + /* + * Validate the texture coordinates for this rectangle. + */ + layers = cogl_material_get_layers (material); + for (tmp = (GList *)layers, i = 0; tmp != NULL; tmp = tmp->next, i++) { - tx1 *= x_span->size; - tx2 *= x_span->size; - ty1 *= y_span->size; - ty2 *= y_span->size; + CoglHandle layer = (CoglHandle)tmp->data; + /* CoglLayerInfo *layer_info; */ + CoglHandle tex_handle; + CoglTexture *tex; + const float *in_tex_coords; + float *out_tex_coords; + CoglTexSliceSpan *x_span; + CoglTexSliceSpan *y_span; + + /* layer_info = &layers[i]; */ + + /* FIXME - we shouldn't be checking this stuff if layer_info->gl_texture + * already == 0 */ + + tex_handle = cogl_material_layer_get_texture (layer); + tex = _cogl_texture_pointer_from_handle (tex_handle); + + in_tex_coords = &user_tex_coords[i * 4]; + out_tex_coords = &final_tex_coords[i * 4]; + + + /* If the texture has waste or we are using GL_TEXTURE_RECT we + * can't handle texture repeating so we check that the texture + * coords lie in the range [0,1]. + * + * NB: We already know that no texture matrix is being used + * if the texture has waste since we validated that early on. + * TODO: check for a texture matrix in the GL_TEXTURE_RECT + * case. + */ + if ((tex->gl_target == GL_TEXTURE_RECTANGLE_ARB + || _cogl_texture_span_has_waste (tex, 0, 0)) + && (in_tex_coords[0] < 0 || in_tex_coords[0] > 1.0 + || in_tex_coords[1] < 0 || in_tex_coords[1] > 1.0 + || in_tex_coords[2] < 0 || in_tex_coords[2] > 1.0 + || in_tex_coords[3] < 0 || in_tex_coords[3] > 1.0)) + { + if (i == 0) + { + if (n_layers > 1) + { + g_warning ("Skipping layers 1..n of your material since the " + "first layer has waste and you supplied texture " + "coordinates outside the range [0,1]. We don't " + "currently support any multi-texturing using " + "textures with waste when repeating is " + "necissary so we are falling back to sliced " + "textures assuming layer 0 is the most " + "important one keep"); + } + return FALSE; + } + else + { + g_warning ("Skipping layer %d of your material " + "consisting of a texture with waste since " + "you have supplied texture coords outside " + "the range [0,1] (unsupported when " + "multi-texturing)", i); + + /* NB: marking for fallback will replace the layer with + * a default transparent texture */ + fallback_mask |= (1 << i); + } + } + + + /* + * Setup the texture unit... + */ + + /* NB: The user might not have supplied texture coordinates for all + * layers... */ + if (i < (user_tex_coords_len / 4)) + { + GLenum wrap_mode; + + /* If the texture coords are all in the range [0,1] then we want to + clamp the coords to the edge otherwise it can pull in edge pixels + from the wrong side when scaled */ + if (in_tex_coords[0] >= 0 && in_tex_coords[0] <= 1.0 + && in_tex_coords[1] >= 0 && in_tex_coords[1] <= 1.0 + && in_tex_coords[2] >= 0 && in_tex_coords[2] <= 1.0 + && in_tex_coords[3] >= 0 && in_tex_coords[3] <= 1.0) + wrap_mode = GL_CLAMP_TO_EDGE; + else + wrap_mode = GL_REPEAT; + + _cogl_texture_set_wrap_mode_parameter (tex, wrap_mode); + } + else + { + out_tex_coords[0] = 0; /* tx1 */ + out_tex_coords[1] = 0; /* ty1 */ + out_tex_coords[2] = 1.0; /* tx2 */ + out_tex_coords[3] = 1.0; /* ty2 */ + + _cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_EDGE); + } + + /* Don't include the waste in the texture coordinates */ + x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0); + y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, 0); + + out_tex_coords[0] = + in_tex_coords[0] * (x_span->size - x_span->waste) / x_span->size; + out_tex_coords[1] = + in_tex_coords[1] * (x_span->size - x_span->waste) / x_span->size; + out_tex_coords[2] = + in_tex_coords[2] * (y_span->size - y_span->waste) / y_span->size; + out_tex_coords[3] = + in_tex_coords[3] * (y_span->size - y_span->waste) / y_span->size; + + /* Denormalize texture coordinates for rectangle textures */ + if (tex->gl_target == GL_TEXTURE_RECTANGLE_ARB) + { + out_tex_coords[0] *= x_span->size; + out_tex_coords[1] *= x_span->size; + out_tex_coords[2] *= y_span->size; + out_tex_coords[3] *= y_span->size; + } } - _cogl_texture_add_quad_vertices ( (x1), - (y1), - (x2), - (y2), - (tx1), - (ty1), - (tx2), - (ty2)); + _cogl_journal_log_quad (x1, + y1, + x2, + y2, + material, + n_layers, + fallback_mask, + 0, /* don't replace the layer0 texture */ + final_tex_coords, + n_layers * 4); + + return TRUE; } -void -cogl_texture_multiple_rectangles (CoglHandle handle, - const float *verts, - guint n_rects) +struct _CoglMutiTexturedRect { - CoglTexture *tex; - gulong enable_flags = (COGL_ENABLE_VERTEX_ARRAY - | COGL_ENABLE_TEXCOORD_ARRAY); + float x1; + float y1; + float x2; + float y2; + const float *tex_coords; + gint tex_coords_len; +}; + +static void +_cogl_rectangles_with_multitexture_coords ( + struct _CoglMutiTexturedRect *rects, + gint n_rects) +{ + CoglHandle material; + const GList *layers; + int n_layers; + const GList *tmp; + guint32 fallback_mask = 0; + gboolean all_use_sliced_quad_fallback = FALSE; + int i; _COGL_GET_CONTEXT (ctx, NO_RETVAL); - /* Check if valid texture */ - if (!cogl_is_texture (handle)) - return; - cogl_clip_ensure (); - tex = _cogl_texture_pointer_from_handle (handle); + material = ctx->source_material; - /* Make sure we got stuff to draw */ - if (tex->slice_gl_handles == NULL) - return; + layers = cogl_material_get_layers (material); + n_layers = g_list_length ((GList *)layers); - if (tex->slice_gl_handles->len == 0) - return; + /* + * Validate all the layers of the current source material... + */ - /* Prepare GL state */ - if (tex->gl_target == CGL_TEXTURE_RECTANGLE_ARB) - enable_flags |= COGL_ENABLE_TEXTURE_RECT; - else - enable_flags |= COGL_ENABLE_TEXTURE_2D; - - if (ctx->color_alpha < 255 - || tex->bitmap.format & COGL_A_BIT) - enable_flags |= COGL_ENABLE_BLEND; - - if (ctx->enable_backface_culling) - enable_flags |= COGL_ENABLE_BACKFACE_CULLING; - - cogl_enable (enable_flags); - - g_array_set_size (ctx->texture_vertices, 0); - - while (n_rects-- > 0) + for (tmp = layers, i = 0; tmp != NULL; tmp = tmp->next, i++) { - if (verts[4] != verts[6] && verts[5] != verts[7]) - { - /* If there is only one GL texture and either the texture is - NPOT (no waste) or all of the coordinates are in the - range [0,1] then we can use hardware tiling */ - if (tex->slice_gl_handles->len == 1 - && ((cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) - && tex->gl_target == GL_TEXTURE_2D) - || (verts[4] >= 0 && verts[4] <= 1.0 - && verts[6] >= 0 && verts[6] <= 1.0 - && verts[5] >= 0 && verts[5] <= 1.0 - && verts[7] >= 0 && verts[7] <= 1.0))) - _cogl_texture_quad_hw (tex, verts[0],verts[1], verts[2],verts[3], - verts[4],verts[5], verts[6],verts[7]); - else - _cogl_texture_quad_sw (tex, verts[0],verts[1], verts[2],verts[3], - verts[4],verts[5], verts[6],verts[7]); - } + CoglHandle layer = tmp->data; + CoglHandle tex_handle = cogl_material_layer_get_texture (layer); + CoglTexture *texture = _cogl_texture_pointer_from_handle (tex_handle); + gulong flags; - verts += 8; + if (cogl_material_layer_get_type (layer) + != COGL_MATERIAL_LAYER_TYPE_TEXTURE) + continue; + + /* XXX: + * For now, if the first layer is sliced then all other layers are + * ignored since we currently don't support multi-texturing with + * sliced textures. If the first layer is not sliced then any other + * layers found to be sliced will be skipped. (with a warning) + * + * TODO: Add support for multi-texturing rectangles with sliced + * textures if no texture matrices are in use. + */ + if (cogl_texture_is_sliced (tex_handle)) + { + if (i == 0) + { + fallback_mask = ~1; /* fallback all except the first layer */ + all_use_sliced_quad_fallback = TRUE; + if (tmp->next) + { + g_warning ("Skipping layers 1..n of your material since the " + "first layer is sliced. We don't currently " + "support any multi-texturing with sliced " + "textures but assume layer 0 is the most " + "important to keep"); + } + break; + } + else + { + g_warning ("Skipping layer %d of your material consisting of a " + "sliced texture (unsuported for multi texturing)", + i); + + /* NB: marking for fallback will replace the layer with + * a default transparent texture */ + fallback_mask |= (1 << i); + continue; + } + } + + /* We don't support multi texturing using textures with any waste if the + * user has supplied a custom texture matrix, since we don't know if + * the result will end up trying to texture from the waste area. */ + flags = cogl_material_layer_get_flags (layer); + if (flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX + && _cogl_texture_span_has_waste (texture, 0, 0)) + { + g_warning ("Skipping layer %d of your material consisting of a " + "texture with waste since you have supplied a custom " + "texture matrix and the result may try to sample from " + "the waste area of your texture.", i); + + /* NB: marking for fallback will replace the layer with + * a default transparent texture */ + fallback_mask |= (1 << i); + continue; + } } - _cogl_texture_flush_vertices (); + /* + * Emit geometry for each of the rectangles... + */ + + for (i = 0; i < n_rects; i++) + { + if (all_use_sliced_quad_fallback + || !_cogl_multitexture_unsliced_quad (rects[i].x1, rects[i].y1, + rects[i].x2, rects[i].y2, + material, + n_layers, + fallback_mask, + rects[i].tex_coords, + rects[i].tex_coords_len)) + { + const GList *layers; + CoglHandle tex_handle; + CoglTexture *texture; + + layers = cogl_material_get_layers (material); + tex_handle = + cogl_material_layer_get_texture ((CoglHandle)layers->data); + texture = _cogl_texture_pointer_from_handle (tex_handle); + _cogl_texture_sliced_quad (texture, + material, + rects[i].x1, rects[i].y1, + rects[i].x2, rects[i].y2, + rects[i].tex_coords[0], + rects[i].tex_coords[1], + rects[i].tex_coords[2], + rects[i].tex_coords[3]); + } + } + + _cogl_journal_flush (); } void -cogl_texture_rectangle (CoglHandle handle, - float x1, - float y1, - float x2, - float y2, - float tx1, - float ty1, - float tx2, - float ty2) +cogl_rectangles_with_texture_coords (const float *verts, + guint n_rects) +{ + struct _CoglMutiTexturedRect rects[n_rects]; + int i; + + for (i = 0; i < n_rects; i++) + { + rects[i].x1 = verts[i * 8]; + rects[i].y1 = verts[i * 8 + 1]; + rects[i].x2 = verts[i * 8 + 2]; + rects[i].y2 = verts[i * 8 + 3]; + /* FIXME: rect should be defined to have a const float *geom; + * instead, to avoid this copy + * rect[i].geom = &verts[n_rects * 8]; */ + rects[i].tex_coords = &verts[i * 8 + 4]; + rects[i].tex_coords_len = 4; + } + + _cogl_rectangles_with_multitexture_coords (rects, n_rects); +} + +void +cogl_rectangle_with_texture_coords (float x1, + float y1, + float x2, + float y2, + float tx1, + float ty1, + float tx2, + float ty2) { float verts[8]; @@ -2350,92 +2724,76 @@ cogl_texture_rectangle (CoglHandle handle, verts[6] = tx2; verts[7] = ty2; - cogl_texture_multiple_rectangles (handle, verts, 1); + cogl_rectangles_with_texture_coords (verts, 1); } void -cogl_texture_polygon (CoglHandle handle, - guint n_vertices, - CoglTextureVertex *vertices, - gboolean use_color) +cogl_rectangle_with_multitexture_coords (float x1, + float y1, + float x2, + float y2, + const float *user_tex_coords, + gint user_tex_coords_len) { - CoglTexture *tex; - int i, x, y, tex_num; - GLuint gl_handle; - CoglTexSliceSpan *y_span, *x_span; - gulong enable_flags; - CoglTextureGLVertex *p; + struct _CoglMutiTexturedRect rect; + + rect.x1 = x1; + rect.y1 = y1; + rect.x2 = x2; + rect.y2 = y2; + rect.tex_coords = user_tex_coords; + rect.tex_coords_len = user_tex_coords_len; + + _cogl_rectangles_with_multitexture_coords (&rect, 1); +} + +static void +_cogl_texture_sliced_polygon (CoglTextureVertex *vertices, + guint n_vertices, + guint stride, + gboolean use_color) +{ + const GList *layers; + CoglHandle layer0; + CoglHandle tex_handle; + CoglTexture *tex; + CoglTexSliceSpan *y_span, *x_span; + int x, y, tex_num, i; + GLuint gl_handle; + GLfloat *v; _COGL_GET_CONTEXT (ctx, NO_RETVAL); - /* Check if valid texture */ - if (!cogl_is_texture (handle)) - return; + /* We can assume in this case that we have at least one layer in the + * material that corresponds to a sliced cogl texture */ + layers = cogl_material_get_layers (ctx->source_material); + layer0 = (CoglHandle)layers->data; + tex_handle = cogl_material_layer_get_texture (layer0); + tex = _cogl_texture_pointer_from_handle (tex_handle); - cogl_clip_ensure (); - - tex = _cogl_texture_pointer_from_handle (handle); - - /* The polygon will have artifacts where the slices join if the wrap - mode is GL_LINEAR because the filtering will pull in pixels from - the transparent border. To make it clear that the function - shouldn't be used in these circumstances we just bail out and - draw nothing */ - if (tex->slice_gl_handles->len != 1 - && (tex->min_filter != GL_NEAREST || tex->mag_filter != GL_NEAREST)) + v = (GLfloat *)ctx->logged_vertices->data; + for (i = 0; i < n_vertices; i++) { - static gboolean shown_warning = FALSE; + GLfloat *c; - if (!shown_warning) - { - g_warning ("cogl_texture_polygon does not work for sliced textures " - "when the minification and magnification filters are not " - "CGL_NEAREST"); - shown_warning = TRUE; - } - return; + v[0] = vertices[i].x; + v[1] = vertices[i].y; + v[2] = vertices[i].z; + + /* NB: [X,Y,Z,TX,TY,R,G,B,A,...] */ + c = v + 5; + c[0] = cogl_color_get_red_byte (&vertices[i].color); + c[1] = cogl_color_get_green_byte (&vertices[i].color); + c[2] = cogl_color_get_blue_byte (&vertices[i].color); + c[3] = cogl_color_get_alpha_byte (&vertices[i].color); + + v += stride; } - /* Make sure there is enough space in the global texture vertex - array. This is used so we can render the polygon with a single - call to OpenGL but still support any number of vertices */ - g_array_set_size (ctx->texture_vertices, n_vertices); - p = (CoglTextureGLVertex *) ctx->texture_vertices->data; - - /* Prepare GL state */ - enable_flags = (COGL_ENABLE_VERTEX_ARRAY - | COGL_ENABLE_TEXCOORD_ARRAY - | COGL_ENABLE_BLEND); - - if (tex->gl_target == CGL_TEXTURE_RECTANGLE_ARB) - enable_flags |= COGL_ENABLE_TEXTURE_RECT; - else - enable_flags |= COGL_ENABLE_TEXTURE_2D; - - if (ctx->enable_backface_culling) - enable_flags |= COGL_ENABLE_BACKFACE_CULLING; - - if (use_color) - { - enable_flags |= COGL_ENABLE_COLOR_ARRAY; - GE( glColorPointer (4, GL_UNSIGNED_BYTE, - sizeof (CoglTextureGLVertex), p->c) ); - } - - GE( glVertexPointer (3, GL_FLOAT, sizeof (CoglTextureGLVertex), p->v ) ); - GE( glTexCoordPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex), p->t ) ); - - cogl_enable (enable_flags); - - /* Temporarily change the wrapping mode on all of the slices to use - a transparent border */ - _cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_BORDER); - - tex_num = 0; - /* Render all of the slices with the full geometry but use a transparent border color so that any part of the texture not covered by the slice will be ignored */ + tex_num = 0; for (y = 0; y < tex->slice_y_spans->len; y++) { y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, y); @@ -2446,15 +2804,13 @@ cogl_texture_polygon (CoglHandle handle, gl_handle = g_array_index (tex->slice_gl_handles, GLuint, tex_num++); - p = (CoglTextureGLVertex *) ctx->texture_vertices->data; - /* Convert the vertices into an array of GLfloats ready to pass to OpenGL */ - for (i = 0; i < n_vertices; i++, p++) + v = (GLfloat *)ctx->logged_vertices->data; + for (i = 0; i < n_vertices; i++) { - float tx, ty; - -#define CFX_F + GLfloat *t; + float tx, ty; tx = ((vertices[i].tx - ((float)(x_span->start) @@ -2472,250 +2828,248 @@ cogl_texture_polygon (CoglHandle handle, ty *= y_span->size; } - p->v[0] = CFX_F(vertices[i].x); - p->v[1] = CFX_F(vertices[i].y); - p->v[2] = CFX_F(vertices[i].z); - p->t[0] = CFX_F(tx); - p->t[1] = CFX_F(ty); - p->c[0] = cogl_color_get_red_byte(&vertices[i].color); - p->c[1] = cogl_color_get_green_byte(&vertices[i].color); - p->c[2] = cogl_color_get_blue_byte(&vertices[i].color); - p->c[3] = cogl_color_get_alpha_byte(&vertices[i].color); + /* NB: [X,Y,Z,TX,TY,R,G,B,A,...] */ + t = v + 3; + t[0] = tx; + t[1] = ty; -#undef CFX_F + v += stride; } - GE( glBindTexture (tex->gl_target, gl_handle) ); + cogl_material_flush_gl_state (ctx->source_material, + COGL_MATERIAL_FLUSH_DISABLE_MASK, + (guint32)~1, /* disable all except the + first layer */ + COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE, + gl_handle, + NULL); GE( glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) ); } } } -void -cogl_material_rectangle (CoglFixed x1, - CoglFixed y1, - CoglFixed x2, - CoglFixed y2, - gint user_tex_coords_len, - const CoglFixed *user_tex_coords) -{ - CoglHandle material; - const GList *layers; - int n_layers; - const GList *tmp; - CoglHandle *valid_layers = NULL; - int n_valid_layers = 0; - gboolean handle_slicing = FALSE; - int i; - GLfloat *tex_coords_buff; - GLfloat quad_coords[8]; - gulong enable_flags = 0; - /* FIXME - currently cogl deals with enabling texturing via enable flags, - * but that can't scale to n texture units. Currently we have to be carefull - * how we leave the environment so we don't break things. See the cleanup - * notes at the end of this function */ +static void +_cogl_multitexture_unsliced_polygon (CoglTextureVertex *vertices, + guint n_vertices, + guint n_layers, + guint stride, + gboolean use_color, + guint32 fallback_mask) +{ + CoglHandle material; + const GList *layers; + int i; + GList *tmp; + CoglTexSliceSpan *y_span, *x_span; + GLfloat *v; _COGL_GET_CONTEXT (ctx, NO_RETVAL); + material = ctx->source_material; - layers = cogl_material_get_layers (material); - n_layers = g_list_length ((GList *)layers); - valid_layers = alloca (sizeof (CoglHandle) * n_layers); - for (tmp = layers; tmp != NULL; tmp = tmp->next) + /* Convert the vertices into an array of GLfloats ready to pass to + OpenGL */ + for (v = (GLfloat *)ctx->logged_vertices->data, i = 0; + i < n_vertices; + v += stride, i++) { - CoglHandle layer = tmp->data; - CoglHandle texture = cogl_material_layer_get_texture (layer); + GLfloat *c; + int j; - if (cogl_material_layer_get_type (layer) - != COGL_MATERIAL_LAYER_TYPE_TEXTURE) - continue; + /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ + v[0] = vertices[i].x; + v[1] = vertices[i].y; + v[2] = vertices[i].z; - /* FIXME: support sliced textures. For now if the first layer is - * sliced then all other layers are ignored, or if the first layer - * is not sliced, we ignore sliced textures in other layers. */ - if (cogl_texture_is_sliced (texture)) - { - if (n_valid_layers == 0) - { - valid_layers[n_valid_layers++] = layer; - handle_slicing = TRUE; - break; - } - continue; - } - valid_layers[n_valid_layers++] = tmp->data; - - if (n_valid_layers >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS) - break; - } - - /* We at least support slicing as much as cogl_texture_rectangle... */ - if (n_valid_layers == 1 && handle_slicing) - { - CoglHandle texture = cogl_material_layer_get_texture (valid_layers[0]); - cogl_texture_rectangle (texture, - x1, y1, x2, y2, - user_tex_coords[0], user_tex_coords[1], - user_tex_coords[2], user_tex_coords[3]); - return; - } - - /* NB: It could be that no valid texture layers were found, but - * we will still submit a non-textured rectangle in that case. */ - if (n_valid_layers) - tex_coords_buff = alloca (sizeof(GLfloat) * 8 * n_valid_layers); - - for (i = 0; i < n_valid_layers; i++) - { - CoglHandle layer = valid_layers[i]; - CoglHandle texture = cogl_material_layer_get_texture (layer); - const CoglFixed *in_tex_coords; - GLfloat *out_tex_coords = &tex_coords_buff[i * 8]; - GLuint gl_tex_handle; - -#define CFX_F COGL_FIXED_TO_FLOAT - /* IN LAYOUT: [ tx1:0, ty1:1, tx2:2, ty2:3 ] */ - if (i < (user_tex_coords_len / 4)) + for (tmp = (GList *)layers, j = 0; tmp != NULL; tmp = tmp->next, j++) { - in_tex_coords = &user_tex_coords[i * 4]; - /* FIXME: don't include waste in the texture coordinates */ - out_tex_coords[0] = CFX_F (in_tex_coords[0]); /* tx1 */ - out_tex_coords[1] = CFX_F (in_tex_coords[1]); /* ty1 */ - out_tex_coords[2] = CFX_F (in_tex_coords[2]); /* tx2 */ - out_tex_coords[3] = CFX_F (in_tex_coords[1]); /* ty1 */ - out_tex_coords[4] = CFX_F (in_tex_coords[0]); /* tx1 */ - out_tex_coords[5] = CFX_F (in_tex_coords[3]); /* ty2 */ - out_tex_coords[6] = CFX_F (in_tex_coords[2]); /* tx2 */ - out_tex_coords[7] = CFX_F (in_tex_coords[3]); /* ty2 */ - } - else - { - out_tex_coords[0] = 0.0; /* tx1 */ - out_tex_coords[1] = 0.0; /* ty1 */ - out_tex_coords[2] = 1.0; /* tx2 */ - out_tex_coords[3] = 0.0; /* ty1 */ - out_tex_coords[4] = 0.0; /* tx1 */ - out_tex_coords[5] = 1.0; /* ty2 */ - out_tex_coords[6] = 1.0; /* tx2 */ - out_tex_coords[7] = 1.0; /* ty2 */ - } -#undef CFX_F + CoglHandle layer = (CoglHandle)tmp->data; + CoglHandle tex_handle; + CoglTexture *tex; + GLfloat *t; + float tx, ty; - /* TODO - support sliced textures */ - cogl_texture_get_gl_texture (texture, &gl_tex_handle, NULL); + tex_handle = cogl_material_layer_get_texture (layer); + tex = _cogl_texture_pointer_from_handle (tex_handle); - GE (glActiveTexture (GL_TEXTURE0 + i)); - cogl_material_layer_flush_gl_sampler_state (layer); - { - /* FIXME - we should avoid redundant calls to glBindTexture. - * Profiling test-actors, I've seen ~ 10% of the time spent in - * _mesa_UpdateTexEnvProgram, which the following simple test can - * show is as a result of these redundant glBindTexture calls. - */ -#if 0 - static int debug = 0; - if (!debug) - GE (glBindTexture (GL_TEXTURE_2D, gl_tex_handle)); - debug = 1; -#else - GE (glBindTexture (GL_TEXTURE_2D, gl_tex_handle)); -#endif + y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, 0); + x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0); + + tx = ((vertices[i].tx + - ((float)(x_span->start) + / tex->bitmap.width)) + * tex->bitmap.width / x_span->size); + ty = ((vertices[i].ty + - ((float)(y_span->start) + / tex->bitmap.height)) + * tex->bitmap.height / y_span->size); + + /* Scale the coordinates up for rectangle textures */ + if (tex->gl_target == CGL_TEXTURE_RECTANGLE_ARB) + { + tx *= x_span->size; + ty *= y_span->size; + } + + /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ + t = v + 3 + 2 * j; + t[0] = tx; + t[1] = ty; } - GE (glClientActiveTexture (GL_TEXTURE0 + i)); - GE (glTexCoordPointer (2, GL_FLOAT, 0, out_tex_coords)); - - /* FIXME - cogl only knows about one texture unit a.t.m - * (Also see cleanup note below) */ - if (i == 0) - enable_flags |= COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_TEXCOORD_ARRAY; - else - { - GE (glEnable (GL_TEXTURE_2D)); - GE (glEnableClientState (GL_TEXTURE_COORD_ARRAY)); - } + /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ + c = v + 3 + 2 * n_layers; + c[0] = cogl_color_get_red_float (&vertices[i].color); + c[1] = cogl_color_get_green_float (&vertices[i].color); + c[2] = cogl_color_get_blue_float (&vertices[i].color); + c[3] = cogl_color_get_alpha_float (&vertices[i].color); } -#define CFX_F COGL_FIXED_TO_FLOAT - quad_coords[0] = CFX_F (x1); - quad_coords[1] = CFX_F (y1); - quad_coords[2] = CFX_F (x2); - quad_coords[3] = CFX_F (y1); - quad_coords[4] = CFX_F (x1); - quad_coords[5] = CFX_F (y2); - quad_coords[6] = CFX_F (x2); - quad_coords[7] = CFX_F (y2); -#undef CFX_F + cogl_material_flush_gl_state (ctx->source_material, + COGL_MATERIAL_FLUSH_FALLBACK_MASK, + fallback_mask, + NULL); - enable_flags |= COGL_ENABLE_VERTEX_ARRAY; - GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords)); - - /* Setup the remaining GL state according to this material... */ - cogl_flush_material_gl_state (); - - /* FIXME: This api is a bit yukky, ideally it will be removed if we - * re-work the cogl_enable mechanism */ - enable_flags |= cogl_material_get_cogl_enable_flags (material); - - /* FIXME - cogl only knows about one texture unit so assumes that unit 0 - * is always active... */ - if (n_valid_layers > 1) - { - GE (glActiveTexture (GL_TEXTURE0)); - GE (glClientActiveTexture (GL_TEXTURE0)); - } - cogl_enable (enable_flags); - glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); - - /* FIXME - cogl doesn't currently have a way of caching the - * enable states for more than one texture unit so for now, - * we just disable anything relating to additional units once - * we are done with them. */ - for (i = 1; i < n_valid_layers; i++) - { - GE (glActiveTexture (GL_TEXTURE0 + i)); - GE (glDisable (GL_TEXTURE_2D)); - } - - /* The rest of Cogl expects the texture mode to be GL_MODULATE so we - need to restore that */ - GE( glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) ); - - /* XXX: a bit over precautious. For one we don't support lighting yet - * so there's no real need to reset the material properties. */ -#if 0 - /* FIXME - cogl doesn't currently have a way of caching the - * enable states for more than one texture unit so for now, - * we just disable anything relating to additional units once - * we are done with them. */ - for (i = 1; i < n_valid_layers; i++) - { - GE (glActiveTexture (GL_TEXTURE0 + i)); - GE (glClientActiveTexture (GL_TEXTURE0 + i)); - - GE (glDisable (GL_TEXTURE_2D)); - GE (glDisableClientState (GL_TEXTURE_COORD_ARRAY)); - } - - /* FIXME - CoglMaterials aren't yet used pervasively throughout - * the cogl API, so we currently need to cleanup material state - * that will confuse other parts of the API. - * Other places to tweak, include the primitives API and lite - * GL wrappers like cogl_rectangle */ - values[0] = 0.2; values[1] = 0.2; values[2] = 0.2; values[3] = 1.0; - GE (glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, values)); - values[0] = 0.8; values[1] = 0.8; values[2] = 0.8; values[3] = 1.0; - GE (glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, values)); - values[0] = 0; values[1] = 0; values[2] = 0; values[3] = 1.0; - GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, values)); - values[0] = 0; values[1] = 0; values[2] = 0; values[3] = 1.0; - GE (glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, values)); - values[0] = 0; - GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, values)); -#endif + GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices)); +} + +void +cogl_polygon (CoglTextureVertex *vertices, + guint n_vertices, + gboolean use_color) +{ + CoglHandle material; + const GList *layers; + int n_layers; + GList *tmp; + gboolean use_sliced_polygon_fallback = FALSE; + guint32 fallback_mask = 0; + int i; + gulong enable_flags; + guint stride; + gsize stride_bytes; + GLfloat *v; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + cogl_clip_ensure (); + + material = ctx->source_material; + layers = cogl_material_get_layers (ctx->source_material); + n_layers = g_list_length ((GList *)layers); + + for (tmp = (GList *)layers, i = 0; tmp != NULL; tmp = tmp->next, i++) + { + CoglHandle layer = (CoglHandle)tmp->data; + CoglHandle tex_handle = cogl_material_layer_get_texture (layer); + CoglTexture *tex = _cogl_texture_pointer_from_handle (tex_handle); + + if (i == 0 && cogl_texture_is_sliced (tex_handle)) + { + if (n_layers > 1) + { + static gboolean shown_slicing_warning = FALSE; + if (!shown_slicing_warning) + { + g_warning ("Disabling layers 1..n since multi-texturing with " + "cogl_polygon isn't supported when using sliced " + "textures\n"); + shown_slicing_warning = TRUE; + } + } + use_sliced_polygon_fallback = TRUE; + n_layers = 1; + + if (tex->min_filter != GL_NEAREST || tex->mag_filter != GL_NEAREST) + { + static gboolean shown_filter_warning = FALSE; + if (!shown_filter_warning) + { + g_warning ("cogl_texture_polygon does not work for sliced textures " + "when the minification and magnification filters are not " + "CGL_NEAREST"); + shown_filter_warning = TRUE; + } + return; + } + + /* Temporarily change the wrapping mode on all of the slices to use + * a transparent border + * XXX: it's doesn't look like we save/restore this, like the comment + * implies? */ + _cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_BORDER); + + break; + } + + if (cogl_texture_is_sliced (tex_handle)) + { + g_warning ("Disabling layer %d of the current source material, " + "because texturing with the vertex buffer API is not " + "currently supported using sliced textures, or textures " + "with waste\n", i); + + fallback_mask |= (1 << i); + continue; + } + } + + /* Our data is arranged like: + * [X, Y, Z, TX0, TY0, TX1, TY1..., R, G, B, A,...] */ + stride = 3 + (2 * n_layers) + (use_color ? 4 : 0); + stride_bytes = stride * sizeof (GLfloat); + + /* Make sure there is enough space in the global vertex + array. This is used so we can render the polygon with a single + call to OpenGL but still support any number of vertices */ + g_array_set_size (ctx->logged_vertices, n_vertices * stride); + v = (GLfloat *)ctx->logged_vertices->data; + + /* Prepare GL state */ + enable_flags = COGL_ENABLE_VERTEX_ARRAY; + enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material); + + if (ctx->enable_backface_culling) + enable_flags |= COGL_ENABLE_BACKFACE_CULLING; + + if (use_color) + { + enable_flags |= COGL_ENABLE_COLOR_ARRAY; + GE( glColorPointer (4, GL_FLOAT, + stride_bytes, + /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ + v + 3 + 2 * n_layers) ); + } + + cogl_enable (enable_flags); + + GE (glVertexPointer (3, GL_FLOAT, stride_bytes, v)); + + for (i = 0; i < n_layers; i++) + { + GE (glClientActiveTexture (GL_TEXTURE0 + i)); + GE (glEnableClientState (GL_TEXTURE_COORD_ARRAY)); + GE (glTexCoordPointer (2, GL_FLOAT, + stride_bytes, + /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ + v + 3 + 2 * i)); + } + + if (use_sliced_polygon_fallback) + _cogl_texture_sliced_polygon (vertices, + n_vertices, + stride, + use_color); + else + _cogl_multitexture_unsliced_polygon (vertices, + n_vertices, + n_layers, + stride, + use_color, + fallback_mask); } diff --git a/clutter/cogl/gl/cogl.c b/clutter/cogl/gl/cogl.c index 78b2a908c..3568493b9 100644 --- a/clutter/cogl/gl/cogl.c +++ b/clutter/cogl/gl/cogl.c @@ -180,16 +180,16 @@ cogl_paint_init (const CoglColor *color) glDisable (GL_LIGHTING); glDisable (GL_FOG); - /* + /* * Disable the depth test for now as has some strange side effects, - * mainly on x/y axis rotation with multiple layers at same depth - * (eg rotating text on a bg has very strange effect). Seems no clean - * 100% effective way to fix without other odd issues.. So for now + * mainly on x/y axis rotation with multiple layers at same depth + * (eg rotating text on a bg has very strange effect). Seems no clean + * 100% effective way to fix without other odd issues.. So for now * move to application to handle and add cogl_enable_depth_test() * as for custom actors (i.e groups) to enable if need be. * - * glEnable (GL_DEPTH_TEST); - * glEnable (GL_ALPHA_TEST) + * glEnable (GL_DEPTH_TEST); + * glEnable (GL_ALPHA_TEST) * glDepthFunc (GL_LEQUAL); * glAlphaFunc (GL_GREATER, 0.1); */ @@ -251,7 +251,7 @@ cogl_toggle_flag (CoglContext *ctx, GE( glDisable (gl_flag) ); ctx->enable_flags &= ~flag; } - + return FALSE; } @@ -278,7 +278,7 @@ cogl_toggle_client_flag (CoglContext *ctx, GE( glDisableClientState (gl_flag) ); ctx->enable_flags &= ~flag; } - + return FALSE; } @@ -289,33 +289,19 @@ cogl_enable (gulong flags) * hope of lessening number GL traffic. */ _COGL_GET_CONTEXT (ctx, NO_RETVAL); - + cogl_toggle_flag (ctx, flags, COGL_ENABLE_BLEND, GL_BLEND); - - cogl_toggle_flag (ctx, flags, - COGL_ENABLE_TEXTURE_2D, - GL_TEXTURE_2D); cogl_toggle_flag (ctx, flags, COGL_ENABLE_BACKFACE_CULLING, GL_CULL_FACE); -#ifdef GL_TEXTURE_RECTANGLE_ARB - cogl_toggle_flag (ctx, flags, - COGL_ENABLE_TEXTURE_RECT, - GL_TEXTURE_RECTANGLE_ARB); -#endif - cogl_toggle_client_flag (ctx, flags, COGL_ENABLE_VERTEX_ARRAY, GL_VERTEX_ARRAY); - - cogl_toggle_client_flag (ctx, flags, - COGL_ENABLE_TEXCOORD_ARRAY, - GL_TEXTURE_COORD_ARRAY); - + cogl_toggle_client_flag (ctx, flags, COGL_ENABLE_COLOR_ARRAY, GL_COLOR_ARRAY); @@ -325,7 +311,7 @@ gulong cogl_get_enable () { _COGL_GET_CONTEXT (ctx, 0); - + return ctx->enable_flags; } @@ -336,7 +322,7 @@ cogl_blend_func (COGLenum src_factor, COGLenum dst_factor) * hope of lessening GL traffic. */ _COGL_GET_CONTEXT (ctx, NO_RETVAL); - + if (ctx->blend_src_factor != src_factor || ctx->blend_dst_factor != dst_factor) { @@ -351,14 +337,14 @@ cogl_enable_depth_test (gboolean setting) { if (setting) { - glEnable (GL_DEPTH_TEST); + glEnable (GL_DEPTH_TEST); glEnable (GL_ALPHA_TEST); glDepthFunc (GL_LEQUAL); glAlphaFunc (GL_GREATER, 0.1); } else { - glDisable (GL_DEPTH_TEST); + glDisable (GL_DEPTH_TEST); glDisable (GL_ALPHA_TEST); } } @@ -375,14 +361,12 @@ void cogl_set_source_color (const CoglColor *color) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - glColor4ub (cogl_color_get_red_byte (color), - cogl_color_get_green_byte (color), - cogl_color_get_blue_byte (color), - cogl_color_get_alpha_byte (color)); - - /* Store alpha for proper blending enables */ - ctx->color_alpha = cogl_color_get_alpha_byte (color); + + /* In case cogl_set_source_texture was previously used... */ + cogl_material_remove_layer (ctx->default_material, 0); + + cogl_material_set_color (ctx->default_material, color); + cogl_set_source (ctx->default_material); } static void @@ -512,7 +496,7 @@ _cogl_add_stencil_clip (float x_offset, if (first) { GE( glEnable (GL_STENCIL_TEST) ); - + /* Initially disallow everything */ GE( glClearStencil (0) ); GE( glClear (GL_STENCIL_BUFFER_BIT) ); @@ -815,7 +799,7 @@ _cogl_features_init () GLint num_stencil_bits = 0; _COGL_GET_CONTEXT (ctx, NO_RETVAL); - + flags = COGL_FEATURE_TEXTURE_READ_PIXELS; gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS); @@ -827,7 +811,7 @@ _cogl_features_init () #endif flags |= COGL_FEATURE_TEXTURE_NPOT; } - + #ifdef GL_YCBCR_MESA if (cogl_check_extension ("GL_MESA_ycbcr_texture", gl_extensions)) { @@ -842,47 +826,47 @@ _cogl_features_init () ctx->pf_glCreateProgramObjectARB = (COGL_PFNGLCREATEPROGRAMOBJECTARBPROC) cogl_get_proc_address ("glCreateProgramObjectARB"); - + ctx->pf_glCreateShaderObjectARB = (COGL_PFNGLCREATESHADEROBJECTARBPROC) cogl_get_proc_address ("glCreateShaderObjectARB"); - + ctx->pf_glShaderSourceARB = (COGL_PFNGLSHADERSOURCEARBPROC) cogl_get_proc_address ("glShaderSourceARB"); - + ctx->pf_glCompileShaderARB = (COGL_PFNGLCOMPILESHADERARBPROC) cogl_get_proc_address ("glCompileShaderARB"); - + ctx->pf_glAttachObjectARB = (COGL_PFNGLATTACHOBJECTARBPROC) cogl_get_proc_address ("glAttachObjectARB"); - + ctx->pf_glLinkProgramARB = (COGL_PFNGLLINKPROGRAMARBPROC) cogl_get_proc_address ("glLinkProgramARB"); - + ctx->pf_glUseProgramObjectARB = (COGL_PFNGLUSEPROGRAMOBJECTARBPROC) cogl_get_proc_address ("glUseProgramObjectARB"); - + ctx->pf_glGetUniformLocationARB = (COGL_PFNGLGETUNIFORMLOCATIONARBPROC) cogl_get_proc_address ("glGetUniformLocationARB"); - + ctx->pf_glDeleteObjectARB = (COGL_PFNGLDELETEOBJECTARBPROC) cogl_get_proc_address ("glDeleteObjectARB"); - + ctx->pf_glGetInfoLogARB = (COGL_PFNGLGETINFOLOGARBPROC) cogl_get_proc_address ("glGetInfoLogARB"); - + ctx->pf_glGetObjectParameterivARB = (COGL_PFNGLGETOBJECTPARAMETERIVARBPROC) cogl_get_proc_address ("glGetObjectParameterivARB"); - + ctx->pf_glUniform1fARB = (COGL_PFNGLUNIFORM1FARBPROC) cogl_get_proc_address ("glUniform1fARB"); @@ -898,7 +882,7 @@ _cogl_features_init () ctx->pf_glDisableVertexAttribArrayARB = (COGL_PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) cogl_get_proc_address ("glDisableVertexAttribArrayARB"); - + ctx->pf_glUniform2fARB = (COGL_PFNGLUNIFORM2FARBPROC) cogl_get_proc_address ("glUniform2fARB"); @@ -962,7 +946,7 @@ _cogl_features_init () ctx->pf_glUniformMatrix2fvARB = (COGL_PFNGLUNIFORMMATRIX2FVARBPROC) cogl_get_proc_address ("glUniformMatrix2fvARB"); - + ctx->pf_glUniformMatrix3fvARB = (COGL_PFNGLUNIFORMMATRIX3FVARBPROC) cogl_get_proc_address ("glUniformMatrix3fvARB"); @@ -1006,50 +990,50 @@ _cogl_features_init () ctx->pf_glDisableVertexAttribArrayARB) flags |= COGL_FEATURE_SHADERS_GLSL; } - + if (cogl_check_extension ("GL_EXT_framebuffer_object", gl_extensions) || cogl_check_extension ("GL_ARB_framebuffer_object", gl_extensions)) - { + { ctx->pf_glGenRenderbuffersEXT = (COGL_PFNGLGENRENDERBUFFERSEXTPROC) cogl_get_proc_address ("glGenRenderbuffersEXT"); - + ctx->pf_glDeleteRenderbuffersEXT = (COGL_PFNGLDELETERENDERBUFFERSEXTPROC) cogl_get_proc_address ("glDeleteRenderbuffersEXT"); - + ctx->pf_glBindRenderbufferEXT = (COGL_PFNGLBINDRENDERBUFFEREXTPROC) cogl_get_proc_address ("glBindRenderbufferEXT"); - + ctx->pf_glRenderbufferStorageEXT = (COGL_PFNGLRENDERBUFFERSTORAGEEXTPROC) cogl_get_proc_address ("glRenderbufferStorageEXT"); - + ctx->pf_glGenFramebuffersEXT = (COGL_PFNGLGENFRAMEBUFFERSEXTPROC) cogl_get_proc_address ("glGenFramebuffersEXT"); - + ctx->pf_glBindFramebufferEXT = (COGL_PFNGLBINDFRAMEBUFFEREXTPROC) cogl_get_proc_address ("glBindFramebufferEXT"); - + ctx->pf_glFramebufferTexture2DEXT = (COGL_PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) cogl_get_proc_address ("glFramebufferTexture2DEXT"); - + ctx->pf_glFramebufferRenderbufferEXT = (COGL_PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) cogl_get_proc_address ("glFramebufferRenderbufferEXT"); - + ctx->pf_glCheckFramebufferStatusEXT = (COGL_PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) cogl_get_proc_address ("glCheckFramebufferStatusEXT"); - + ctx->pf_glDeleteFramebuffersEXT = (COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC) cogl_get_proc_address ("glDeleteFramebuffersEXT"); - + if (ctx->pf_glGenRenderbuffersEXT && ctx->pf_glBindRenderbufferEXT && ctx->pf_glRenderbufferStorageEXT && @@ -1061,23 +1045,23 @@ _cogl_features_init () ctx->pf_glDeleteFramebuffersEXT) flags |= COGL_FEATURE_OFFSCREEN; } - + if (cogl_check_extension ("GL_EXT_framebuffer_blit", gl_extensions)) { ctx->pf_glBlitFramebufferEXT = (COGL_PFNGLBLITFRAMEBUFFEREXTPROC) cogl_get_proc_address ("glBlitFramebufferEXT"); - + if (ctx->pf_glBlitFramebufferEXT) flags |= COGL_FEATURE_OFFSCREEN_BLIT; } - + if (cogl_check_extension ("GL_EXT_framebuffer_multisample", gl_extensions)) { ctx->pf_glRenderbufferStorageMultisampleEXT = (COGL_PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) cogl_get_proc_address ("glRenderbufferStorageMultisampleEXT"); - + if (ctx->pf_glRenderbufferStorageMultisampleEXT) flags |= COGL_FEATURE_OFFSCREEN_MULTISAMPLE; } @@ -1140,10 +1124,10 @@ CoglFeatureFlags cogl_get_features () { _COGL_GET_CONTEXT (ctx, 0); - + if (!ctx->features_cached) _cogl_features_init (); - + return ctx->feature_flags; } @@ -1151,10 +1135,10 @@ gboolean cogl_features_available (CoglFeatureFlags features) { _COGL_GET_CONTEXT (ctx, 0); - + if (!ctx->features_cached) _cogl_features_init (); - + return (ctx->feature_flags & features) == features; } diff --git a/clutter/pango/cogl-pango-render.c b/clutter/pango/cogl-pango-render.c index 3cafc81e2..0e839c573 100644 --- a/clutter/pango/cogl-pango-render.c +++ b/clutter/pango/cogl-pango-render.c @@ -42,8 +42,10 @@ struct _CoglPangoRenderer { PangoRenderer parent_instance; - /* The color to draw the glyphs with */ - CoglColor color; + /* The material used to texture from the glyph cache with */ + CoglHandle glyph_material; + /* The material used for solid fills. (boxes, rectangles + trapezoids) */ + CoglHandle solid_material; /* Two caches of glyphs as textures, one with mipmapped textures and one without */ @@ -68,8 +70,10 @@ cogl_pango_renderer_glyphs_end (CoglPangoRenderer *priv) if (priv->glyph_rectangles->len > 0) { float *rectangles = (float *) priv->glyph_rectangles->data; - cogl_texture_multiple_rectangles (priv->glyph_texture, rectangles, - priv->glyph_rectangles->len / 8); + cogl_material_set_layer (priv->glyph_material, 0, priv->glyph_texture); + cogl_set_source (priv->glyph_material); + cogl_rectangles_with_texture_coords (rectangles, + priv->glyph_rectangles->len / 8); g_array_set_size (priv->glyph_rectangles, 0); } } @@ -128,6 +132,38 @@ G_DEFINE_TYPE (CoglPangoRenderer, cogl_pango_renderer, PANGO_TYPE_RENDERER); static void cogl_pango_renderer_init (CoglPangoRenderer *priv) { + priv->glyph_material = cogl_material_new (); + + /* The default combine mode of materials is to modulate (A x B) the texture + * RGBA channels with the RGBA channels of the previous layer (which in our + * case is just the solid font color) + * + * Since our glyph cache textures are component alpha textures, and so the + * RGB channels are defined as (0, 0, 0) we don't want to modulate the RGB + * channels, instead we want to simply replace them with our solid font + * color... + * + * XXX: we could really do with a neat string based way for describing + * combine modes, like: "REPLACE(PREVIOUS[RGB])" + * XXX: potentially materials could have a fuzzy default combine mode + * such that they default to this for component alpha textures? This would + * give the same semantics as the old-style GL_MODULATE mode but sounds a + * bit hacky. + */ + cogl_material_set_layer_combine_function ( + priv->glyph_material, + 0, /* layer */ + COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB, + COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE); + cogl_material_set_layer_combine_arg_src ( + priv->glyph_material, + 0, /* layer */ + 0, /* arg */ + COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB, + COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS); + + priv->solid_material = cogl_material_new (); + priv->glyph_cache = cogl_pango_glyph_cache_new (FALSE); priv->mipmapped_glyph_cache = cogl_pango_glyph_cache_new (TRUE); priv->use_mipmapping = FALSE; @@ -203,7 +239,8 @@ cogl_pango_render_layout_subpixel (PangoLayout *layout, if (G_UNLIKELY (!priv)) return; - priv->color = *color; + cogl_material_set_color (priv->glyph_material, color); + cogl_material_set_color (priv->solid_material, color); pango_renderer_draw_layout (PANGO_RENDERER (priv), layout, x, y); } @@ -259,7 +296,8 @@ cogl_pango_render_layout_line (PangoLayoutLine *line, if (G_UNLIKELY (!priv)) return; - priv->color = *color; + cogl_material_set_color (priv->glyph_material, color); + cogl_material_set_color (priv->solid_material, color); pango_renderer_draw_layout_line (PANGO_RENDERER (priv), line, x, y); } @@ -351,12 +389,12 @@ cogl_pango_ensure_glyph_cache_for_layout (PangoLayout *layout) PangoContext *context; PangoRenderer *renderer; PangoLayoutIter *iter; - + g_return_if_fail (PANGO_IS_LAYOUT (layout)); - + if ((iter = pango_layout_get_iter (layout)) == NULL) return; - + context = pango_layout_get_context (layout); renderer = PANGO_RENDERER (cogl_pango_get_renderer_from_context (context)); @@ -365,19 +403,19 @@ cogl_pango_ensure_glyph_cache_for_layout (PangoLayout *layout) { PangoLayoutLine *line; GSList *l; - + line = pango_layout_iter_get_line_readonly (iter); - + for (l = line->runs; l; l = l->next) { PangoLayoutRun *run = l->data; PangoGlyphString *glyphs = run->glyphs; int i; - + for (i = 0; i < glyphs->num_glyphs; i++) { PangoGlyphInfo *gi = &glyphs->glyphs[i]; - + cogl_pango_renderer_get_cached_glyph (renderer, run->item->analysis.font, gi->glyph); @@ -385,7 +423,7 @@ cogl_pango_ensure_glyph_cache_for_layout (PangoLayout *layout) } } while (pango_layout_iter_next_line (iter)); - + pango_layout_iter_free (iter); } @@ -398,19 +436,32 @@ cogl_pango_renderer_set_color_for_part (PangoRenderer *renderer, if (pango_color) { - cogl_set_source_color4ub (pango_color->red >> 8, - pango_color->green >> 8, - pango_color->blue >> 8, - cogl_color_get_alpha_byte (&priv->color)); + CoglColor color; + guint8 red = pango_color->red >> 8; + guint8 green = pango_color->green >> 8; + guint8 blue = pango_color->blue >> 8; + guint8 alpha; + + cogl_material_get_color (priv->solid_material, &color); + alpha = cogl_color_get_alpha_byte (&color); + + cogl_material_set_color4ub (priv->solid_material, + red, green, blue, alpha); + cogl_material_set_color4ub (priv->glyph_material, + red, green, blue, alpha); } - else - cogl_set_source_color (&priv->color); } static void -cogl_pango_renderer_draw_box (int x, int y, - int width, int height) +cogl_pango_renderer_draw_box (PangoRenderer *renderer, + int x, + int y, + int width, + int height) { + CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer); + + cogl_set_source (priv->solid_material); cogl_path_rectangle ((float)(x), (float)(y - height), (float)(width), @@ -450,6 +501,7 @@ cogl_pango_renderer_draw_rectangle (PangoRenderer *renderer, int width, int height) { + CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer); float x1, x2, y1, y2; cogl_pango_renderer_set_color_for_part (renderer, part); @@ -461,6 +513,7 @@ cogl_pango_renderer_draw_rectangle (PangoRenderer *renderer, x + width, y + height, &x2, &y2); + cogl_set_source (priv->solid_material); cogl_rectangle (x1, y1, x2 - x1, y2 - y1); } @@ -474,6 +527,7 @@ cogl_pango_renderer_draw_trapezoid (PangoRenderer *renderer, double x12, double x22) { + CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer); float points[8]; points[0] = (x11); @@ -487,6 +541,7 @@ cogl_pango_renderer_draw_trapezoid (PangoRenderer *renderer, cogl_pango_renderer_set_color_for_part (renderer, part); + cogl_set_source (priv->solid_material); cogl_path_polygon (points, 4); cogl_path_fill (); } @@ -524,15 +579,17 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer, if (font == NULL || (metrics = pango_font_get_metrics (font, NULL)) == NULL) { - cogl_pango_renderer_draw_box ( (x), - (y), + cogl_pango_renderer_draw_box (renderer, + x, + y, PANGO_UNKNOWN_GLYPH_WIDTH, PANGO_UNKNOWN_GLYPH_HEIGHT); } else { - cogl_pango_renderer_draw_box ( (x), - (y), + cogl_pango_renderer_draw_box (renderer, + x, + y, metrics->approximate_char_width / PANGO_SCALE, metrics->ascent / PANGO_SCALE); @@ -553,8 +610,9 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer, { cogl_pango_renderer_glyphs_end (priv); - cogl_pango_renderer_draw_box ( (x), - (y), + cogl_pango_renderer_draw_box (renderer, + x, + y, PANGO_UNKNOWN_GLYPH_WIDTH, PANGO_UNKNOWN_GLYPH_HEIGHT); } diff --git a/tests/conform/test-backface-culling.c b/tests/conform/test-backface-culling.c index f43b7a38b..f021ce81c 100644 --- a/tests/conform/test-backface-culling.c +++ b/tests/conform/test-backface-culling.c @@ -127,47 +127,45 @@ on_paint (ClutterActor *actor, TestState *state) x2 = x1 + (float)(TEXTURE_SIZE); /* Draw a front-facing texture */ - cogl_texture_rectangle (state->texture, - x1, y1, x2, y2, - 0, 0, 1.0, 1.0); + cogl_set_source_texture (state->texture); + cogl_rectangle (x1, y1, x2, y2); x1 = x2; x2 = x1 + (float)(TEXTURE_SIZE); /* Draw a back-facing texture */ - cogl_texture_rectangle (state->texture, - x2, y1, x1, y2, - 0, 0, 1.0, 1.0); + cogl_set_source_texture (state->texture); + cogl_rectangle (x2, y1, x1, y2); x1 = x2; x2 = x1 + (float)(TEXTURE_SIZE); /* Draw a front-facing texture polygon */ - verts[0].x = x1; verts[0].y = y2; - verts[1].x = x2; verts[1].y = y2; - verts[2].x = x2; verts[2].y = y1; - verts[3].x = x1; verts[3].y = y1; - verts[0].tx = 0; verts[0].ty = 0; + verts[0].x = x1; verts[0].y = y2; + verts[1].x = x2; verts[1].y = y2; + verts[2].x = x2; verts[2].y = y1; + verts[3].x = x1; verts[3].y = y1; + verts[0].tx = 0; verts[0].ty = 0; verts[1].tx = 1.0; verts[1].ty = 0; verts[2].tx = 1.0; verts[2].ty = 1.0; - verts[3].tx = 0; verts[3].ty = 1.0; - cogl_texture_polygon (state->texture, 4, - verts, FALSE); + verts[3].tx = 0; verts[3].ty = 1.0; + cogl_set_source_texture (state->texture); + cogl_polygon (verts, 4, FALSE); x1 = x2; x2 = x1 + (float)(TEXTURE_SIZE); /* Draw a back-facing texture polygon */ - verts[0].x = x1; verts[0].y = y1; - verts[1].x = x2; verts[1].y = y1; - verts[2].x = x2; verts[2].y = y2; - verts[3].x = x1; verts[3].y = y2; - verts[0].tx = 0; verts[0].ty = 0; + verts[0].x = x1; verts[0].y = y1; + verts[1].x = x2; verts[1].y = y1; + verts[2].x = x2; verts[2].y = y2; + verts[3].x = x1; verts[3].y = y2; + verts[0].tx = 0; verts[0].ty = 0; verts[1].tx = 1.0; verts[1].ty = 0; verts[2].tx = 1.0; verts[2].ty = 1.0; - verts[3].tx = 0; verts[3].ty = 1.0; - cogl_texture_polygon (state->texture, 4, - verts, FALSE); + verts[3].tx = 0; verts[3].ty = 1.0; + cogl_set_source_texture (state->texture); + cogl_polygon (verts, 4, FALSE); x1 = x2; x2 = x1 + (float)(TEXTURE_SIZE); diff --git a/tests/interactive/Makefile.am b/tests/interactive/Makefile.am index 5ba1d1794..b316be3bf 100644 --- a/tests/interactive/Makefile.am +++ b/tests/interactive/Makefile.am @@ -28,7 +28,7 @@ UNIT_TESTS = \ test-cogl-tex-getset.c \ test-cogl-offscreen.c \ test-cogl-tex-polygon.c \ - test-cogl-material.c \ + test-cogl-multitexture.c \ test-stage-read-pixels.c \ test-random-text.c \ test-clip.c \ @@ -40,7 +40,8 @@ UNIT_TESTS = \ test-binding-pool.c \ test-text.c \ test-text-field.c \ - test-clutter-cairo-flowers.c + test-clutter-cairo-flowers.c \ + test-simple.c if X11_TESTS UNIT_TESTS += test-pixmap.c diff --git a/tests/interactive/test-clip.c b/tests/interactive/test-clip.c index 119b4ac68..ed3f8d7b0 100644 --- a/tests/interactive/test-clip.c +++ b/tests/interactive/test-clip.c @@ -165,12 +165,12 @@ on_paint (ClutterActor *actor, CallbackData *data) cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff); - cogl_texture_rectangle (data->hand, - CLUTTER_INT_TO_FIXED (-hand_width / 2), - CLUTTER_INT_TO_FIXED (-hand_height / 2), - CLUTTER_INT_TO_FIXED (hand_width / 2), - CLUTTER_INT_TO_FIXED (hand_height / 2), - 0, 0, CFX_ONE, CFX_ONE); + cogl_set_source_texture (data->hand); + cogl_rectangle_with_texture_coords (CLUTTER_INT_TO_FIXED (-hand_width / 2), + CLUTTER_INT_TO_FIXED (-hand_height / 2), + CLUTTER_INT_TO_FIXED (hand_width / 2), + CLUTTER_INT_TO_FIXED (hand_height / 2), + 0, 0, CFX_ONE, CFX_ONE); cogl_pop_matrix (); } diff --git a/tests/interactive/test-cogl-material.c b/tests/interactive/test-cogl-multitexture.c similarity index 84% rename from tests/interactive/test-cogl-material.c rename to tests/interactive/test-cogl-multitexture.c index 8d6bdf3fe..4f0dbfc8b 100644 --- a/tests/interactive/test-cogl-material.c +++ b/tests/interactive/test-cogl-multitexture.c @@ -45,16 +45,17 @@ material_rectangle_paint (ClutterActor *actor, gpointer data) TestMultiLayerMaterialState *state = data; cogl_set_source (state->material); - cogl_material_rectangle (CLUTTER_INT_TO_FIXED(0), - CLUTTER_INT_TO_FIXED(0), - CLUTTER_INT_TO_FIXED(TIMELINE_FRAME_COUNT), - CLUTTER_INT_TO_FIXED(TIMELINE_FRAME_COUNT), - 12, - state->tex_coords); + cogl_rectangle_with_multitexture_coords ( + CLUTTER_INT_TO_FIXED(0), + CLUTTER_INT_TO_FIXED(0), + CLUTTER_INT_TO_FIXED(TIMELINE_FRAME_COUNT), + CLUTTER_INT_TO_FIXED(TIMELINE_FRAME_COUNT), + state->tex_coords, + 12); } G_MODULE_EXPORT int -test_cogl_material_main (int argc, char *argv[]) +test_cogl_multitexture_main (int argc, char *argv[]) { ClutterTimeline *timeline; ClutterAlpha *alpha; @@ -130,15 +131,12 @@ test_cogl_material_main (int argc, char *argv[]) g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), state); - /* Set an alpha func to power behaviour - ramp is constant rise/fall */ - alpha = clutter_alpha_new_for_mode (CLUTTER_LINEAR); - clutter_alpha_set_timeline (alpha, timeline); - - /* Create a behaviour for that alpha */ - r_behave = clutter_behaviour_rotate_new (alpha, - CLUTTER_Y_AXIS, - CLUTTER_ROTATE_CW, - 0.0, 360.0); + r_behave = + clutter_behaviour_rotate_new (clutter_alpha_new_full (timeline, + CLUTTER_LINEAR), + CLUTTER_Y_AXIS, + CLUTTER_ROTATE_CW, + 0.0, 360.0); /* Apply it to our actor */ clutter_behaviour_apply (r_behave, state->group); diff --git a/tests/interactive/test-cogl-offscreen.c b/tests/interactive/test-cogl-offscreen.c index 893862e08..eabb754f7 100644 --- a/tests/interactive/test-cogl-offscreen.c +++ b/tests/interactive/test-cogl-offscreen.c @@ -87,20 +87,20 @@ test_coglbox_paint(ClutterActor *self) CLUTTER_FLOAT_TO_FIXED (1.0f), CLUTTER_FLOAT_TO_FIXED (1.0f) }; + CoglHandle material; priv = TEST_COGLBOX_GET_PRIVATE (self); cogl_set_source_color4ub (0x66, 0x66, 0xdd, 0xff); cogl_rectangle (0, 0, 400, 400); - cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff); - cogl_texture_rectangle (priv->texhand_id, - 0, 0, - CLUTTER_INT_TO_FIXED (400), - CLUTTER_INT_TO_FIXED (400), - 0, 0, - CLUTTER_INT_TO_FIXED (6), - CLUTTER_INT_TO_FIXED (6)); + cogl_set_source_texture (priv->texhand_id); + cogl_rectangle_with_texture_coords (0, 0, + CLUTTER_INT_TO_FIXED (400), + CLUTTER_INT_TO_FIXED (400), + 0, 0, + CLUTTER_INT_TO_FIXED (6), + CLUTTER_INT_TO_FIXED (6)); cogl_draw_buffer (COGL_OFFSCREEN_BUFFER, priv->offscreen_id); @@ -112,16 +112,18 @@ test_coglbox_paint(ClutterActor *self) cogl_draw_buffer (COGL_WINDOW_BUFFER, 0); - cogl_set_source_color4ub (0xff, 0xff, 0xff, 0x88); - cogl_texture_rectangle (priv->texture_id, - CLUTTER_INT_TO_FIXED (100), - CLUTTER_INT_TO_FIXED (100), - CLUTTER_INT_TO_FIXED (300), - CLUTTER_INT_TO_FIXED (300), - texcoords[0], - texcoords[1], - texcoords[2], - texcoords[3]); + material = cogl_material_new (); + cogl_material_set_color4ub (material, 0xff, 0xff, 0xff, 0x88); + cogl_material_set_layer (material, 0, priv->texture_id); + cogl_set_source (material); + cogl_rectangle_with_texture_coords (CLUTTER_INT_TO_FIXED (100), + CLUTTER_INT_TO_FIXED (100), + CLUTTER_INT_TO_FIXED (300), + CLUTTER_INT_TO_FIXED (300), + texcoords[0], + texcoords[1], + texcoords[2], + texcoords[3]); } static void diff --git a/tests/interactive/test-cogl-tex-convert.c b/tests/interactive/test-cogl-tex-convert.c index 816ea403b..a19bd29ae 100644 --- a/tests/interactive/test-cogl-tex-convert.c +++ b/tests/interactive/test-cogl-tex-convert.c @@ -92,45 +92,43 @@ test_coglbox_paint(ClutterActor *self) cogl_set_source_color4ub (0x66, 0x66, 0xdd, 0xff); cogl_rectangle (0, 0, 400, 400); - cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff); - cogl_push_matrix (); - cogl_texture_rectangle (priv->cogl_tex_id[0], - 0, 0, - CLUTTER_INT_TO_FIXED (200), - CLUTTER_INT_TO_FIXED (213), - texcoords[0], texcoords[1], - texcoords[2], texcoords[3]); + cogl_set_source_texture (priv->cogl_tex_id[0]); + cogl_rectangle_with_texture_coords (0, 0, + CLUTTER_INT_TO_FIXED (200), + CLUTTER_INT_TO_FIXED (213), + texcoords[0], texcoords[1], + texcoords[2], texcoords[3]); cogl_pop_matrix (); cogl_push_matrix (); cogl_translate (200, 0, 0); - cogl_texture_rectangle (priv->cogl_tex_id[1], - 0, 0, - CLUTTER_INT_TO_FIXED (200), - CLUTTER_INT_TO_FIXED (213), - texcoords[0], texcoords[1], - texcoords[2], texcoords[3]); + cogl_set_source_texture (priv->cogl_tex_id[1]); + cogl_rectangle_with_texture_coords (0, 0, + CLUTTER_INT_TO_FIXED (200), + CLUTTER_INT_TO_FIXED (213), + texcoords[0], texcoords[1], + texcoords[2], texcoords[3]); cogl_pop_matrix (); cogl_push_matrix (); cogl_translate (0, 200, 0); - cogl_texture_rectangle (priv->cogl_tex_id[2], - 0, 0, - CLUTTER_INT_TO_FIXED (200), - CLUTTER_INT_TO_FIXED (213), - texcoords[0], texcoords[1], - texcoords[2], texcoords[3]); + cogl_set_source_texture (priv->cogl_tex_id[2]); + cogl_rectangle_with_texture_coords (0, 0, + CLUTTER_INT_TO_FIXED (200), + CLUTTER_INT_TO_FIXED (213), + texcoords[0], texcoords[1], + texcoords[2], texcoords[3]); cogl_pop_matrix (); cogl_push_matrix (); cogl_translate (200, 200, 0); - cogl_texture_rectangle (priv->cogl_tex_id[3], - 0, 0, - CLUTTER_INT_TO_FIXED (200), - CLUTTER_INT_TO_FIXED (213), - texcoords[0], texcoords[1], - texcoords[2], texcoords[3]); + cogl_set_source_texture (priv->cogl_tex_id[3]); + cogl_rectangle_with_texture_coords (0, 0, + CLUTTER_INT_TO_FIXED (200), + CLUTTER_INT_TO_FIXED (213), + texcoords[0], texcoords[1], + texcoords[2], texcoords[3]); cogl_pop_matrix(); } diff --git a/tests/interactive/test-cogl-tex-foreign.c b/tests/interactive/test-cogl-tex-foreign.c index 09d693b24..88c8f8bb5 100644 --- a/tests/interactive/test-cogl-tex-foreign.c +++ b/tests/interactive/test-cogl-tex-foreign.c @@ -92,17 +92,15 @@ test_coglbox_paint(ClutterActor *self) cogl_set_source_color4ub (0x66, 0x66, 0xdd, 0xff); cogl_rectangle (0,0,400,400); - cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff); - cogl_push_matrix (); cogl_translate (100,100,0); - cogl_texture_rectangle (priv->cogl_handle, - 0, 0, - CLUTTER_INT_TO_FIXED (200), - CLUTTER_INT_TO_FIXED (200), - texcoords[0], texcoords[1], - texcoords[2], texcoords[3]); + cogl_set_source_texture (priv->cogl_handle); + cogl_rectangle_with_texture_coords (0, 0, + CLUTTER_INT_TO_FIXED (200), + CLUTTER_INT_TO_FIXED (200), + texcoords[0], texcoords[1], + texcoords[2], texcoords[3]); cogl_pop_matrix(); } diff --git a/tests/interactive/test-cogl-tex-getset.c b/tests/interactive/test-cogl-tex-getset.c index 056b5693d..84b3b6141 100644 --- a/tests/interactive/test-cogl-tex-getset.c +++ b/tests/interactive/test-cogl-tex-getset.c @@ -91,17 +91,15 @@ test_coglbox_paint(ClutterActor *self) cogl_set_source_color4ub (0x66, 0x66, 0xdd, 0xff); cogl_rectangle (0, 0, 400, 400); - cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff); - cogl_push_matrix (); cogl_translate (100, 100, 0); - cogl_texture_rectangle (priv->cogl_tex_id[1], - 0, 0, - CLUTTER_INT_TO_FIXED (200), - CLUTTER_INT_TO_FIXED (213), - texcoords[0], texcoords[1], - texcoords[2], texcoords[3]); + cogl_set_source_texture (priv->cogl_tex_id[1]); + cogl_rectangle_with_texture_coords (0, 0, + CLUTTER_INT_TO_FIXED (200), + CLUTTER_INT_TO_FIXED (213), + texcoords[0], texcoords[1], + texcoords[2], texcoords[3]); cogl_pop_matrix(); } diff --git a/tests/interactive/test-cogl-tex-polygon.c b/tests/interactive/test-cogl-tex-polygon.c index ae64998df..9bf9580d7 100644 --- a/tests/interactive/test-cogl-tex-polygon.c +++ b/tests/interactive/test-cogl-tex-polygon.c @@ -122,7 +122,8 @@ test_coglbox_fade_texture (CoglHandle tex_id, ((i ^ (i >> 1)) & 1) ? 0 : 128); } - cogl_texture_polygon (tex_id, 4, vertices, TRUE); + cogl_set_source_texture (tex_id); + cogl_polygon (vertices, 4, TRUE); cogl_set_source_color4ub (255, 255, 255, 255); } @@ -160,7 +161,8 @@ test_coglbox_triangle_texture (CoglHandle tex_id, vertices[2].tx = tx3; vertices[2].ty = ty3; - cogl_texture_polygon (tex_id, 3, vertices, FALSE); + cogl_set_source_texture (tex_id); + cogl_polygon (vertices, 3, FALSE); } static void @@ -172,8 +174,6 @@ test_coglbox_paint (ClutterActor *self) int tex_width = cogl_texture_get_width (tex_handle); int tex_height = cogl_texture_get_height (tex_handle); - cogl_set_source_color4ub (255, 255, 255, 255); - cogl_texture_set_filters (tex_handle, priv->use_linear_filtering ? CGL_LINEAR : CGL_NEAREST, @@ -186,11 +186,11 @@ test_coglbox_paint (ClutterActor *self) cogl_translate (-tex_width / 2, 0, 0); /* Draw a hand and refect it */ - cogl_texture_rectangle (tex_handle, - 0, 0, - CLUTTER_INT_TO_FIXED (tex_width), - CLUTTER_INT_TO_FIXED (tex_height), - 0, 0, CFX_ONE, CFX_ONE); + cogl_set_source_texture (tex_handle); + cogl_rectangle_with_texture_coords (0, 0, + CLUTTER_INT_TO_FIXED (tex_width), + CLUTTER_INT_TO_FIXED (tex_height), + 0, 0, CFX_ONE, CFX_ONE); test_coglbox_fade_texture (tex_handle, 0, CLUTTER_INT_TO_FIXED (tex_height), CLUTTER_INT_TO_FIXED (tex_width), diff --git a/tests/interactive/test-cogl-tex-tile.c b/tests/interactive/test-cogl-tex-tile.c index 8e2739a92..08a72f0eb 100644 --- a/tests/interactive/test-cogl-tex-tile.c +++ b/tests/interactive/test-cogl-tex-tile.c @@ -115,14 +115,13 @@ test_coglbox_paint(ClutterActor *self) cogl_set_source_color4ub (0x66, 0x66, 0xdd, 0xff); cogl_rectangle (0, 0, 400, 400); - cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff); cogl_translate (100, 100, 0); - cogl_texture_rectangle (priv->cogl_tex_id, - 0, 0, - CLUTTER_INT_TO_FIXED (200), - CLUTTER_INT_TO_FIXED (213), - texcoords[0], texcoords[1], - texcoords[2], texcoords[3]); + cogl_set_source_texture (priv->cogl_tex_id); + cogl_rectangle_with_texture_coords (0, 0, + CLUTTER_INT_TO_FIXED (200), + CLUTTER_INT_TO_FIXED (213), + texcoords[0], texcoords[1], + texcoords[2], texcoords[3]); cogl_pop_matrix(); }