cogl-pango: Don't set the special combine function for atlased textures

The material cache will now only set the special combine mode if the
texture only has an alpha component. The atlased textures will have
all four components so it will leave the combine functions at the
default. This increases the chances of batching between glyphs and
images.

When using the global atlas, the glyph from cairo is now rendered into
an ARGB surface rather than an alpha-only surface.
This commit is contained in:
Neil Roberts 2010-02-26 13:01:54 +00:00
parent 9083fc8e1f
commit 41e464fc9e
2 changed files with 70 additions and 19 deletions

View File

@ -39,7 +39,8 @@ struct _CoglPangoPipelineCache
{
GHashTable *hash_table;
CoglPipeline *base_texture_pipeline;
CoglPipeline *base_texture_alpha_pipeline;
CoglPipeline *base_texture_rgba_pipeline;
gboolean use_mipmapping;
};
@ -89,7 +90,8 @@ _cogl_pango_pipeline_cache_new (gboolean use_mipmapping)
_cogl_pango_pipeline_cache_key_destroy,
_cogl_pango_pipeline_cache_value_destroy);
cache->base_texture_pipeline = NULL;
cache->base_texture_rgba_pipeline = NULL;
cache->base_texture_alpha_pipeline = NULL;
cache->use_mipmapping = use_mipmapping;
@ -97,13 +99,36 @@ _cogl_pango_pipeline_cache_new (gboolean use_mipmapping)
}
static CoglPipeline *
get_base_texture_pipeline (CoglPangoPipelineCache *cache)
get_base_texture_rgba_pipeline (CoglPangoPipelineCache *cache)
{
if (cache->base_texture_pipeline == NULL)
if (cache->base_texture_rgba_pipeline == NULL)
{
CoglPipeline *pipeline;
pipeline = cache->base_texture_pipeline = cogl_pipeline_new ();
pipeline = cache->base_texture_rgba_pipeline = cogl_pipeline_new ();
cogl_pipeline_set_layer_wrap_mode (pipeline, 0,
COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE);
if (cache->use_mipmapping)
cogl_pipeline_set_layer_filters
(pipeline, 0,
COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR,
COGL_PIPELINE_FILTER_LINEAR);
}
return cache->base_texture_rgba_pipeline;
}
static CoglPipeline *
get_base_texture_alpha_pipeline (CoglPangoPipelineCache *cache)
{
if (cache->base_texture_alpha_pipeline == NULL)
{
CoglPipeline *pipeline;
pipeline = cogl_pipeline_copy (get_base_texture_rgba_pipeline (cache));
cache->base_texture_alpha_pipeline = pipeline;
/* The default combine mode of materials is to modulate (A x B)
* the texture RGBA channels with the RGBA channels of the
@ -122,17 +147,9 @@ get_base_texture_pipeline (CoglPangoPipelineCache *cache)
cogl_pipeline_set_layer_combine (pipeline, 0, /* layer */
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
NULL);
cogl_pipeline_set_layer_wrap_mode (pipeline, 0,
COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE);
if (cache->use_mipmapping)
cogl_pipeline_set_layer_filters
(pipeline, 0,
COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR,
COGL_PIPELINE_FILTER_LINEAR);
}
return cache->base_texture_pipeline;
return cache->base_texture_alpha_pipeline;
}
typedef struct
@ -169,8 +186,16 @@ _cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
if (texture)
{
CoglPipeline *base;
entry->texture = cogl_handle_ref (texture);
entry->pipeline = cogl_pipeline_copy (get_base_texture_pipeline (cache));
if (cogl_texture_get_format (entry->texture) == COGL_PIXEL_FORMAT_A_8)
base = get_base_texture_alpha_pipeline (cache);
else
base = get_base_texture_rgba_pipeline (cache);
entry->pipeline = cogl_pipeline_copy (base);
cogl_pipeline_set_layer_texture (entry->pipeline, 0 /* layer */, texture);
}
@ -202,8 +227,10 @@ _cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
void
_cogl_pango_pipeline_cache_free (CoglPangoPipelineCache *cache)
{
if (cache->base_texture_pipeline)
cogl_object_unref (cache->base_texture_pipeline);
if (cache->base_texture_rgba_pipeline)
cogl_object_unref (cache->base_texture_rgba_pipeline);
if (cache->base_texture_alpha_pipeline)
cogl_object_unref (cache->base_texture_alpha_pipeline);
g_hash_table_destroy (cache->hash_table);

View File

@ -467,6 +467,8 @@ cogl_pango_renderer_set_dirty_glyph (PangoFont *font,
cairo_t *cr;
cairo_scaled_font_t *scaled_font;
cairo_glyph_t cairo_glyph;
cairo_format_t format_cairo;
CoglPixelFormat format_cogl;
COGL_NOTE (PANGO, "redrawing glyph %i", glyph);
@ -475,7 +477,27 @@ cogl_pango_renderer_set_dirty_glyph (PangoFont *font,
here */
g_return_if_fail (value->texture != COGL_INVALID_HANDLE);
surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
if (cogl_texture_get_format (value->texture) == COGL_PIXEL_FORMAT_A_8)
{
format_cairo = CAIRO_FORMAT_A8;
format_cogl = COGL_PIXEL_FORMAT_A_8;
}
else
{
format_cairo = CAIRO_FORMAT_ARGB32;
/* Cairo stores the data in native byte order as ARGB but Cogl's
pixel formats specify the actual byte order. Therefore we
need to use a different format depending on the
architecture */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
format_cogl = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
#else
format_cogl = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
#endif
}
surface = cairo_image_surface_create (format_cairo,
value->draw_width,
value->draw_height);
cr = cairo_create (surface);
@ -483,6 +505,8 @@ cogl_pango_renderer_set_dirty_glyph (PangoFont *font,
scaled_font = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
cairo_set_scaled_font (cr, scaled_font);
cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
cairo_glyph.x = -value->draw_x;
cairo_glyph.y = -value->draw_y;
/* The PangoCairo glyph numbers directly map to Cairo glyph
@ -503,7 +527,7 @@ cogl_pango_renderer_set_dirty_glyph (PangoFont *font,
value->draw_height, /* dst_height */
value->draw_width, /* width */
value->draw_height, /* height */
COGL_PIXEL_FORMAT_A_8,
format_cogl,
cairo_image_surface_get_stride (surface),
cairo_image_surface_get_data (surface));