mirror of
https://github.com/brl/mutter.git
synced 2025-02-18 14:14:10 +00:00
cogl-pango: Use a seperate cache of pipelines
Instead of creating just two materials (one for texturing and one for solid primitives) the pango renderer now maintains a cache of pipelines. The display list can request a pipeline for a texture from the cache. The same pipeline cache is used by all display lists so that the pipelines can be shared. This avoids changing the texture on the material during a paint run.
This commit is contained in:
parent
22ce8a7111
commit
9083fc8e1f
@ -4,14 +4,16 @@ source_c = \
|
|||||||
cogl-pango-display-list.c \
|
cogl-pango-display-list.c \
|
||||||
cogl-pango-fontmap.c \
|
cogl-pango-fontmap.c \
|
||||||
cogl-pango-render.c \
|
cogl-pango-render.c \
|
||||||
cogl-pango-glyph-cache.c
|
cogl-pango-glyph-cache.c \
|
||||||
|
cogl-pango-pipeline-cache.c
|
||||||
|
|
||||||
source_h = cogl-pango.h
|
source_h = cogl-pango.h
|
||||||
|
|
||||||
source_h_priv = \
|
source_h_priv = \
|
||||||
cogl-pango-display-list.h \
|
cogl-pango-display-list.h \
|
||||||
cogl-pango-private.h \
|
cogl-pango-private.h \
|
||||||
cogl-pango-glyph-cache.h
|
cogl-pango-glyph-cache.h \
|
||||||
|
cogl-pango-pipeline-cache.h
|
||||||
|
|
||||||
if COGL_STANDALONE_BUILD
|
if COGL_STANDALONE_BUILD
|
||||||
lib_LTLIBRARIES = libcoglpango.la
|
lib_LTLIBRARIES = libcoglpango.la
|
||||||
|
@ -47,6 +47,7 @@ struct _CoglPangoDisplayList
|
|||||||
CoglColor color;
|
CoglColor color;
|
||||||
GSList *nodes;
|
GSList *nodes;
|
||||||
GSList *last_node;
|
GSList *last_node;
|
||||||
|
CoglPangoPipelineCache *pipeline_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _CoglPangoDisplayListNode
|
struct _CoglPangoDisplayListNode
|
||||||
@ -56,6 +57,8 @@ struct _CoglPangoDisplayListNode
|
|||||||
gboolean color_override;
|
gboolean color_override;
|
||||||
CoglColor color;
|
CoglColor color;
|
||||||
|
|
||||||
|
CoglPipeline *pipeline;
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
@ -92,9 +95,13 @@ struct _CoglPangoDisplayListVertex
|
|||||||
};
|
};
|
||||||
|
|
||||||
CoglPangoDisplayList *
|
CoglPangoDisplayList *
|
||||||
_cogl_pango_display_list_new (void)
|
_cogl_pango_display_list_new (CoglPangoPipelineCache *pipeline_cache)
|
||||||
{
|
{
|
||||||
return g_slice_new0 (CoglPangoDisplayList);
|
CoglPangoDisplayList *dl = g_slice_new0 (CoglPangoDisplayList);
|
||||||
|
|
||||||
|
dl->pipeline_cache = pipeline_cache;
|
||||||
|
|
||||||
|
return dl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -156,6 +163,7 @@ _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
|
|||||||
node->type = COGL_PANGO_DISPLAY_LIST_TEXTURE;
|
node->type = COGL_PANGO_DISPLAY_LIST_TEXTURE;
|
||||||
node->color_override = dl->color_override;
|
node->color_override = dl->color_override;
|
||||||
node->color = dl->color;
|
node->color = dl->color;
|
||||||
|
node->pipeline = NULL;
|
||||||
node->d.texture.texture = cogl_handle_ref (texture);
|
node->d.texture.texture = cogl_handle_ref (texture);
|
||||||
node->d.texture.verts
|
node->d.texture.verts
|
||||||
= g_array_new (FALSE, FALSE, sizeof (CoglPangoDisplayListVertex));
|
= g_array_new (FALSE, FALSE, sizeof (CoglPangoDisplayListVertex));
|
||||||
@ -205,6 +213,7 @@ _cogl_pango_display_list_add_rectangle (CoglPangoDisplayList *dl,
|
|||||||
node->d.rectangle.y_1 = y_1;
|
node->d.rectangle.y_1 = y_1;
|
||||||
node->d.rectangle.x_2 = x_2;
|
node->d.rectangle.x_2 = x_2;
|
||||||
node->d.rectangle.y_2 = y_2;
|
node->d.rectangle.y_2 = y_2;
|
||||||
|
node->pipeline = NULL;
|
||||||
|
|
||||||
_cogl_pango_display_list_append_node (dl, node);
|
_cogl_pango_display_list_append_node (dl, node);
|
||||||
}
|
}
|
||||||
@ -229,6 +238,7 @@ _cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
|
|||||||
node->d.trapezoid.y_2 = y_2;
|
node->d.trapezoid.y_2 = y_2;
|
||||||
node->d.trapezoid.x_12 = x_12;
|
node->d.trapezoid.x_12 = x_12;
|
||||||
node->d.trapezoid.x_22 = x_22;
|
node->d.trapezoid.x_22 = x_22;
|
||||||
|
node->pipeline = NULL;
|
||||||
|
|
||||||
_cogl_pango_display_list_append_node (dl, node);
|
_cogl_pango_display_list_append_node (dl, node);
|
||||||
}
|
}
|
||||||
@ -309,17 +319,8 @@ emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_pango_display_list_render_texture (CoglMaterial *material,
|
_cogl_pango_display_list_render_texture (CoglPangoDisplayListNode *node)
|
||||||
const CoglColor *color,
|
|
||||||
CoglPangoDisplayListNode *node)
|
|
||||||
{
|
{
|
||||||
CoglColor premult_color = *color;
|
|
||||||
|
|
||||||
cogl_material_set_layer (material, 0, node->d.texture.texture);
|
|
||||||
cogl_material_set_color (material, &premult_color);
|
|
||||||
|
|
||||||
cogl_push_source (material);
|
|
||||||
|
|
||||||
/* For small runs of text like icon labels, we can get better performance
|
/* For small runs of text like icon labels, we can get better performance
|
||||||
* going through the Cogl journal since text may then be batched together
|
* going through the Cogl journal since text may then be batched together
|
||||||
* with other geometry. */
|
* with other geometry. */
|
||||||
@ -329,15 +330,11 @@ _cogl_pango_display_list_render_texture (CoglMaterial *material,
|
|||||||
emit_rectangles_through_journal (node);
|
emit_rectangles_through_journal (node);
|
||||||
else
|
else
|
||||||
emit_vertex_buffer_geometry (node);
|
emit_vertex_buffer_geometry (node);
|
||||||
|
|
||||||
cogl_pop_source ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_display_list_render (CoglPangoDisplayList *dl,
|
_cogl_pango_display_list_render (CoglPangoDisplayList *dl,
|
||||||
const CoglColor *color,
|
const CoglColor *color)
|
||||||
CoglMaterial *glyph_material,
|
|
||||||
CoglMaterial *solid_material)
|
|
||||||
{
|
{
|
||||||
GSList *l;
|
GSList *l;
|
||||||
|
|
||||||
@ -346,6 +343,18 @@ _cogl_pango_display_list_render (CoglPangoDisplayList *dl,
|
|||||||
CoglPangoDisplayListNode *node = l->data;
|
CoglPangoDisplayListNode *node = l->data;
|
||||||
CoglColor draw_color;
|
CoglColor draw_color;
|
||||||
|
|
||||||
|
if (node->pipeline == NULL)
|
||||||
|
{
|
||||||
|
if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE)
|
||||||
|
node->pipeline =
|
||||||
|
_cogl_pango_pipeline_cache_get (dl->pipeline_cache,
|
||||||
|
node->d.texture.texture);
|
||||||
|
else
|
||||||
|
node->pipeline =
|
||||||
|
_cogl_pango_pipeline_cache_get (dl->pipeline_cache,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (node->color_override)
|
if (node->color_override)
|
||||||
/* Use the override color but preserve the alpha from the
|
/* Use the override color but preserve the alpha from the
|
||||||
draw color */
|
draw color */
|
||||||
@ -358,21 +367,20 @@ _cogl_pango_display_list_render (CoglPangoDisplayList *dl,
|
|||||||
draw_color = *color;
|
draw_color = *color;
|
||||||
cogl_color_premultiply (&draw_color);
|
cogl_color_premultiply (&draw_color);
|
||||||
|
|
||||||
|
cogl_pipeline_set_color (node->pipeline, &draw_color);
|
||||||
|
cogl_push_source (node->pipeline);
|
||||||
|
|
||||||
switch (node->type)
|
switch (node->type)
|
||||||
{
|
{
|
||||||
case COGL_PANGO_DISPLAY_LIST_TEXTURE:
|
case COGL_PANGO_DISPLAY_LIST_TEXTURE:
|
||||||
_cogl_pango_display_list_render_texture (glyph_material,
|
_cogl_pango_display_list_render_texture (node);
|
||||||
&draw_color, node);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COGL_PANGO_DISPLAY_LIST_RECTANGLE:
|
case COGL_PANGO_DISPLAY_LIST_RECTANGLE:
|
||||||
cogl_material_set_color (solid_material, &draw_color);
|
|
||||||
cogl_push_source (solid_material);
|
|
||||||
cogl_rectangle (node->d.rectangle.x_1,
|
cogl_rectangle (node->d.rectangle.x_1,
|
||||||
node->d.rectangle.y_1,
|
node->d.rectangle.y_1,
|
||||||
node->d.rectangle.x_2,
|
node->d.rectangle.x_2,
|
||||||
node->d.rectangle.y_2);
|
node->d.rectangle.y_2);
|
||||||
cogl_pop_source ();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COGL_PANGO_DISPLAY_LIST_TRAPEZOID:
|
case COGL_PANGO_DISPLAY_LIST_TRAPEZOID:
|
||||||
@ -389,16 +397,15 @@ _cogl_pango_display_list_render (CoglPangoDisplayList *dl,
|
|||||||
points[6] = node->d.trapezoid.x_21;
|
points[6] = node->d.trapezoid.x_21;
|
||||||
points[7] = node->d.trapezoid.y_1;
|
points[7] = node->d.trapezoid.y_1;
|
||||||
|
|
||||||
cogl_material_set_color (solid_material, &draw_color);
|
|
||||||
cogl_push_source (solid_material);
|
|
||||||
path = cogl_path_new ();
|
path = cogl_path_new ();
|
||||||
cogl_path_polygon (path, points, 4);
|
cogl_path_polygon (path, points, 4);
|
||||||
cogl_path_fill (path);
|
cogl_path_fill (path);
|
||||||
cogl_object_unref (path);
|
cogl_object_unref (path);
|
||||||
cogl_pop_source ();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cogl_pop_source ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,6 +421,9 @@ _cogl_pango_display_list_node_free (CoglPangoDisplayListNode *node)
|
|||||||
cogl_handle_unref (node->d.texture.vertex_buffer);
|
cogl_handle_unref (node->d.texture.vertex_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node->pipeline)
|
||||||
|
cogl_object_unref (node->pipeline);
|
||||||
|
|
||||||
g_slice_free (CoglPangoDisplayListNode, node);
|
g_slice_free (CoglPangoDisplayListNode, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,12 +26,13 @@
|
|||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <cogl/cogl.h>
|
#include <cogl/cogl.h>
|
||||||
|
#include "cogl-pango-pipeline-cache.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
typedef struct _CoglPangoDisplayList CoglPangoDisplayList;
|
typedef struct _CoglPangoDisplayList CoglPangoDisplayList;
|
||||||
|
|
||||||
CoglPangoDisplayList *_cogl_pango_display_list_new (void);
|
CoglPangoDisplayList *_cogl_pango_display_list_new (CoglPangoPipelineCache *);
|
||||||
|
|
||||||
void _cogl_pango_display_list_set_color_override (CoglPangoDisplayList *dl,
|
void _cogl_pango_display_list_set_color_override (CoglPangoDisplayList *dl,
|
||||||
const CoglColor *color);
|
const CoglColor *color);
|
||||||
@ -57,9 +58,7 @@ void _cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
|
|||||||
float x_22);
|
float x_22);
|
||||||
|
|
||||||
void _cogl_pango_display_list_render (CoglPangoDisplayList *dl,
|
void _cogl_pango_display_list_render (CoglPangoDisplayList *dl,
|
||||||
const CoglColor *color,
|
const CoglColor *color);
|
||||||
CoglMaterial *glyph_material,
|
|
||||||
CoglMaterial *solid_material);
|
|
||||||
|
|
||||||
void _cogl_pango_display_list_clear (CoglPangoDisplayList *dl);
|
void _cogl_pango_display_list_clear (CoglPangoDisplayList *dl);
|
||||||
|
|
||||||
|
211
clutter/cogl/pango/cogl-pango-pipeline-cache.c
Normal file
211
clutter/cogl/pango/cogl-pango-pipeline-cache.c
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
* Cogl
|
||||||
|
*
|
||||||
|
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Neil Roberts <neil@linux.intel.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
#include "cogl-pango-pipeline-cache.h"
|
||||||
|
|
||||||
|
typedef struct _CoglPangoPipelineCacheEntry CoglPangoPipelineCacheEntry;
|
||||||
|
|
||||||
|
struct _CoglPangoPipelineCache
|
||||||
|
{
|
||||||
|
GHashTable *hash_table;
|
||||||
|
|
||||||
|
CoglPipeline *base_texture_pipeline;
|
||||||
|
|
||||||
|
gboolean use_mipmapping;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _CoglPangoPipelineCacheEntry
|
||||||
|
{
|
||||||
|
/* This will take a reference or it can be NULL to represent the
|
||||||
|
pipeline used to render colors */
|
||||||
|
CoglHandle texture;
|
||||||
|
|
||||||
|
/* This will only take a weak reference */
|
||||||
|
CoglHandle pipeline;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_pango_pipeline_cache_key_destroy (gpointer data)
|
||||||
|
{
|
||||||
|
if (data)
|
||||||
|
cogl_object_unref (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_pango_pipeline_cache_value_destroy (gpointer data)
|
||||||
|
{
|
||||||
|
CoglPangoPipelineCacheEntry *cache_entry = data;
|
||||||
|
|
||||||
|
if (cache_entry->texture)
|
||||||
|
cogl_object_unref (cache_entry->texture);
|
||||||
|
|
||||||
|
/* We don't need to unref the pipeline because it only takes a weak
|
||||||
|
reference */
|
||||||
|
|
||||||
|
g_slice_free (CoglPangoPipelineCacheEntry, cache_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglPangoPipelineCache *
|
||||||
|
_cogl_pango_pipeline_cache_new (gboolean use_mipmapping)
|
||||||
|
{
|
||||||
|
CoglPangoPipelineCache *cache = g_new (CoglPangoPipelineCache, 1);
|
||||||
|
|
||||||
|
/* The key is the pipeline pointer. A reference is taken when the
|
||||||
|
pipeline is used as a key so we should unref it again in the
|
||||||
|
destroy function */
|
||||||
|
cache->hash_table =
|
||||||
|
g_hash_table_new_full (g_direct_hash,
|
||||||
|
g_direct_equal,
|
||||||
|
_cogl_pango_pipeline_cache_key_destroy,
|
||||||
|
_cogl_pango_pipeline_cache_value_destroy);
|
||||||
|
|
||||||
|
cache->base_texture_pipeline = NULL;
|
||||||
|
|
||||||
|
cache->use_mipmapping = use_mipmapping;
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglPipeline *
|
||||||
|
get_base_texture_pipeline (CoglPangoPipelineCache *cache)
|
||||||
|
{
|
||||||
|
if (cache->base_texture_pipeline == NULL)
|
||||||
|
{
|
||||||
|
CoglPipeline *pipeline;
|
||||||
|
|
||||||
|
pipeline = cache->base_texture_pipeline = cogl_pipeline_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 font color)
|
||||||
|
*
|
||||||
|
* Since the RGB for an alpha texture is defined as 0, this gives us:
|
||||||
|
*
|
||||||
|
* result.rgb = color.rgb * 0
|
||||||
|
* result.a = color.a * texture.a
|
||||||
|
*
|
||||||
|
* What we want is premultiplied rgba values:
|
||||||
|
*
|
||||||
|
* result.rgba = color.rgb * texture.a
|
||||||
|
* result.a = color.a * texture.a
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CoglPangoPipelineCache *cache;
|
||||||
|
CoglHandle texture;
|
||||||
|
} PipelineDestroyNotifyData;
|
||||||
|
|
||||||
|
static void
|
||||||
|
pipeline_destroy_notify_cb (void *user_data)
|
||||||
|
{
|
||||||
|
PipelineDestroyNotifyData *data = user_data;
|
||||||
|
|
||||||
|
g_hash_table_remove (data->cache->hash_table, data->texture);
|
||||||
|
g_slice_free (PipelineDestroyNotifyData, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglPipeline *
|
||||||
|
_cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
|
||||||
|
CoglHandle texture)
|
||||||
|
{
|
||||||
|
CoglPangoPipelineCacheEntry *entry;
|
||||||
|
PipelineDestroyNotifyData *destroy_data;
|
||||||
|
static CoglUserDataKey pipeline_destroy_notify_key;
|
||||||
|
|
||||||
|
/* Look for an existing entry */
|
||||||
|
entry = g_hash_table_lookup (cache->hash_table, texture);
|
||||||
|
|
||||||
|
if (entry)
|
||||||
|
return cogl_object_ref (entry->pipeline);
|
||||||
|
|
||||||
|
/* No existing pipeline was found so let's create another */
|
||||||
|
entry = g_slice_new (CoglPangoPipelineCacheEntry);
|
||||||
|
|
||||||
|
if (texture)
|
||||||
|
{
|
||||||
|
entry->texture = cogl_handle_ref (texture);
|
||||||
|
entry->pipeline = cogl_pipeline_copy (get_base_texture_pipeline (cache));
|
||||||
|
|
||||||
|
cogl_pipeline_set_layer_texture (entry->pipeline, 0 /* layer */, texture);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry->texture = NULL;
|
||||||
|
entry->pipeline = cogl_pipeline_new ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a weak reference to the pipeline so we can remove it from the
|
||||||
|
hash table when it is destroyed */
|
||||||
|
destroy_data = g_slice_new (PipelineDestroyNotifyData);
|
||||||
|
destroy_data->cache = cache;
|
||||||
|
destroy_data->texture = texture;
|
||||||
|
cogl_object_set_user_data (entry->pipeline,
|
||||||
|
&pipeline_destroy_notify_key,
|
||||||
|
destroy_data,
|
||||||
|
pipeline_destroy_notify_cb);
|
||||||
|
|
||||||
|
g_hash_table_insert (cache->hash_table,
|
||||||
|
texture ? cogl_handle_ref (texture) : NULL,
|
||||||
|
entry);
|
||||||
|
|
||||||
|
/* This doesn't take a reference on the pipeline so that it will use
|
||||||
|
the newly created reference */
|
||||||
|
return entry->pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_pango_pipeline_cache_free (CoglPangoPipelineCache *cache)
|
||||||
|
{
|
||||||
|
if (cache->base_texture_pipeline)
|
||||||
|
cogl_object_unref (cache->base_texture_pipeline);
|
||||||
|
|
||||||
|
g_hash_table_destroy (cache->hash_table);
|
||||||
|
|
||||||
|
g_free (cache);
|
||||||
|
}
|
53
clutter/cogl/pango/cogl-pango-pipeline-cache.h
Normal file
53
clutter/cogl/pango/cogl-pango-pipeline-cache.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Cogl
|
||||||
|
*
|
||||||
|
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Neil Roberts <neil@linux.intel.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COGL_PANGO_PIPELINE_CACHE_H__
|
||||||
|
#define __COGL_PANGO_PIPELINE_CACHE_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _CoglPangoPipelineCache CoglPangoPipelineCache;
|
||||||
|
|
||||||
|
CoglPangoPipelineCache *
|
||||||
|
_cogl_pango_pipeline_cache_new (gboolean use_mipmapping);
|
||||||
|
|
||||||
|
/* Returns a pipeline that can be used to render glyphs in the given
|
||||||
|
texture. The pipeline has a new reference so it is up to the caller
|
||||||
|
to unref it */
|
||||||
|
CoglPipeline *
|
||||||
|
_cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
|
||||||
|
CoglHandle texture);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_pango_pipeline_cache_free (CoglPangoPipelineCache *cache);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __COGL_PANGO_PIPELINE_CACHE_H__ */
|
@ -44,16 +44,14 @@ struct _CoglPangoRenderer
|
|||||||
{
|
{
|
||||||
PangoRenderer parent_instance;
|
PangoRenderer parent_instance;
|
||||||
|
|
||||||
/* The material used to texture from the glyph cache with */
|
|
||||||
CoglMaterial *glyph_material;
|
|
||||||
/* The material used for solid fills. (boxes, rectangles + trapezoids) */
|
|
||||||
CoglMaterial *solid_material;
|
|
||||||
|
|
||||||
/* Two caches of glyphs as textures, one with mipmapped textures and
|
/* Two caches of glyphs as textures, one with mipmapped textures and
|
||||||
one without */
|
one without */
|
||||||
CoglPangoGlyphCache *glyph_cache;
|
CoglPangoGlyphCache *glyph_cache;
|
||||||
CoglPangoGlyphCache *mipmapped_glyph_cache;
|
CoglPangoGlyphCache *mipmapped_glyph_cache;
|
||||||
|
|
||||||
|
CoglPangoPipelineCache *pipeline_cache;
|
||||||
|
CoglPangoPipelineCache *mipmapped_pipeline_cache;
|
||||||
|
|
||||||
gboolean use_mipmapping;
|
gboolean use_mipmapping;
|
||||||
|
|
||||||
/* The current display list that is being built */
|
/* The current display list that is being built */
|
||||||
@ -173,30 +171,8 @@ G_DEFINE_TYPE (CoglPangoRenderer, cogl_pango_renderer, PANGO_TYPE_RENDERER);
|
|||||||
static void
|
static void
|
||||||
cogl_pango_renderer_init (CoglPangoRenderer *priv)
|
cogl_pango_renderer_init (CoglPangoRenderer *priv)
|
||||||
{
|
{
|
||||||
priv->glyph_material = cogl_material_new ();
|
priv->pipeline_cache = _cogl_pango_pipeline_cache_new (FALSE);
|
||||||
|
priv->mipmapped_pipeline_cache = _cogl_pango_pipeline_cache_new (TRUE);
|
||||||
/* 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 font color)
|
|
||||||
*
|
|
||||||
* Since the RGB for an alpha texture is defined as 0, this gives us:
|
|
||||||
*
|
|
||||||
* result.rgb = color.rgb * 0
|
|
||||||
* result.a = color.a * texture.a
|
|
||||||
*
|
|
||||||
* What we want is premultiplied rgba values:
|
|
||||||
*
|
|
||||||
* result.rgba = color.rgb * texture.a
|
|
||||||
* result.a = color.a * texture.a
|
|
||||||
*/
|
|
||||||
cogl_material_set_layer_combine (priv->glyph_material, 0, /* layer */
|
|
||||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
|
||||||
NULL);
|
|
||||||
cogl_material_set_layer_wrap_mode (priv->glyph_material, 0,
|
|
||||||
COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
priv->solid_material = cogl_material_new ();
|
|
||||||
|
|
||||||
priv->glyph_cache = cogl_pango_glyph_cache_new (FALSE);
|
priv->glyph_cache = cogl_pango_glyph_cache_new (FALSE);
|
||||||
priv->mipmapped_glyph_cache = cogl_pango_glyph_cache_new (TRUE);
|
priv->mipmapped_glyph_cache = cogl_pango_glyph_cache_new (TRUE);
|
||||||
priv->use_mipmapping = TRUE;
|
priv->use_mipmapping = TRUE;
|
||||||
@ -224,6 +200,9 @@ cogl_pango_renderer_finalize (GObject *object)
|
|||||||
cogl_pango_glyph_cache_free (priv->mipmapped_glyph_cache);
|
cogl_pango_glyph_cache_free (priv->mipmapped_glyph_cache);
|
||||||
cogl_pango_glyph_cache_free (priv->glyph_cache);
|
cogl_pango_glyph_cache_free (priv->glyph_cache);
|
||||||
|
|
||||||
|
_cogl_pango_pipeline_cache_free (priv->pipeline_cache);
|
||||||
|
_cogl_pango_pipeline_cache_free (priv->mipmapped_pipeline_cache);
|
||||||
|
|
||||||
G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->finalize (object);
|
G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,9 +312,13 @@ cogl_pango_render_layout_subpixel (PangoLayout *layout,
|
|||||||
|
|
||||||
if (qdata->display_list == NULL)
|
if (qdata->display_list == NULL)
|
||||||
{
|
{
|
||||||
|
CoglPangoPipelineCache *pipeline_cache =
|
||||||
|
(priv->use_mipmapping ?
|
||||||
|
priv->mipmapped_pipeline_cache : priv->pipeline_cache);
|
||||||
|
|
||||||
cogl_pango_ensure_glyph_cache_for_layout (layout);
|
cogl_pango_ensure_glyph_cache_for_layout (layout);
|
||||||
|
|
||||||
qdata->display_list = _cogl_pango_display_list_new ();
|
qdata->display_list = _cogl_pango_display_list_new (pipeline_cache);
|
||||||
|
|
||||||
/* Register for notification of when the glyph cache changes so
|
/* Register for notification of when the glyph cache changes so
|
||||||
we can rebuild the display list */
|
we can rebuild the display list */
|
||||||
@ -354,9 +337,7 @@ cogl_pango_render_layout_subpixel (PangoLayout *layout,
|
|||||||
cogl_push_matrix ();
|
cogl_push_matrix ();
|
||||||
cogl_translate (x / (gfloat) PANGO_SCALE, y / (gfloat) PANGO_SCALE, 0);
|
cogl_translate (x / (gfloat) PANGO_SCALE, y / (gfloat) PANGO_SCALE, 0);
|
||||||
_cogl_pango_display_list_render (qdata->display_list,
|
_cogl_pango_display_list_render (qdata->display_list,
|
||||||
color,
|
color);
|
||||||
priv->glyph_material,
|
|
||||||
priv->solid_material);
|
|
||||||
cogl_pop_matrix ();
|
cogl_pop_matrix ();
|
||||||
|
|
||||||
/* Keep a reference to the first line of the layout so we can detect
|
/* Keep a reference to the first line of the layout so we can detect
|
||||||
@ -418,22 +399,24 @@ cogl_pango_render_layout_line (PangoLayoutLine *line,
|
|||||||
{
|
{
|
||||||
PangoContext *context;
|
PangoContext *context;
|
||||||
CoglPangoRenderer *priv;
|
CoglPangoRenderer *priv;
|
||||||
|
CoglPangoPipelineCache *pipeline_cache;
|
||||||
|
|
||||||
context = pango_layout_get_context (line->layout);
|
context = pango_layout_get_context (line->layout);
|
||||||
priv = cogl_pango_get_renderer_from_context (context);
|
priv = cogl_pango_get_renderer_from_context (context);
|
||||||
if (G_UNLIKELY (!priv))
|
if (G_UNLIKELY (!priv))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
priv->display_list = _cogl_pango_display_list_new ();
|
pipeline_cache = (priv->use_mipmapping ?
|
||||||
|
priv->mipmapped_pipeline_cache : priv->pipeline_cache);
|
||||||
|
|
||||||
|
priv->display_list = _cogl_pango_display_list_new (pipeline_cache);
|
||||||
|
|
||||||
_cogl_pango_ensure_glyph_cache_for_layout_line (line);
|
_cogl_pango_ensure_glyph_cache_for_layout_line (line);
|
||||||
|
|
||||||
pango_renderer_draw_layout_line (PANGO_RENDERER (priv), line, x, y);
|
pango_renderer_draw_layout_line (PANGO_RENDERER (priv), line, x, y);
|
||||||
|
|
||||||
_cogl_pango_display_list_render (priv->display_list,
|
_cogl_pango_display_list_render (priv->display_list,
|
||||||
color,
|
color);
|
||||||
priv->glyph_material,
|
|
||||||
priv->solid_material);
|
|
||||||
|
|
||||||
_cogl_pango_display_list_free (priv->display_list);
|
_cogl_pango_display_list_free (priv->display_list);
|
||||||
priv->display_list = NULL;
|
priv->display_list = NULL;
|
||||||
@ -450,21 +433,7 @@ void
|
|||||||
_cogl_pango_renderer_set_use_mipmapping (CoglPangoRenderer *renderer,
|
_cogl_pango_renderer_set_use_mipmapping (CoglPangoRenderer *renderer,
|
||||||
gboolean value)
|
gboolean value)
|
||||||
{
|
{
|
||||||
if (renderer->use_mipmapping != value)
|
|
||||||
{
|
|
||||||
CoglMaterialFilter min_filter;
|
|
||||||
|
|
||||||
renderer->use_mipmapping = value;
|
renderer->use_mipmapping = value;
|
||||||
|
|
||||||
if (value)
|
|
||||||
min_filter = COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR;
|
|
||||||
else
|
|
||||||
min_filter = COGL_MATERIAL_FILTER_LINEAR;
|
|
||||||
|
|
||||||
cogl_material_set_layer_filters (renderer->glyph_material, 0,
|
|
||||||
min_filter,
|
|
||||||
COGL_MATERIAL_FILTER_LINEAR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
Loading…
x
Reference in New Issue
Block a user