texture: Use a base material for all instances

Creating new materials for every Texture instance results in a lot of
ARBfp programs being generated/compiled. Since most textures will just
be similar we should create a template material for all of them, and
then copy it in every instance. Cogl will try to optimize the generation
of the program and, hopefully, will reuse the same program most of the
time.

With this change, a simple test shows that loading 48 textures will
result in just two programs being compiled - with and without batching
enabled.

http://bugzilla.clutter-project.org/show_bug.cgi?id=2295
This commit is contained in:
Emmanuele Bassi 2010-09-02 14:48:30 +01:00
parent 283dce8e21
commit 7e56a98413
3 changed files with 65 additions and 2 deletions

View File

@ -167,6 +167,8 @@ static guint repaint_upload_func = 0;
static GList *upload_list = NULL;
static GStaticMutex upload_list_mutex = G_STATIC_MUTEX_INIT;
static CoglMaterial *texture_template_material = NULL;
static void
texture_fbo_free_resources (ClutterTexture *texture);
@ -559,7 +561,7 @@ create_pick_material (ClutterActor *self)
{
ClutterTexture *texture = CLUTTER_TEXTURE (self);
ClutterTexturePrivate *priv = texture->priv;
CoglHandle pick_material = cogl_material_new ();
CoglHandle pick_material = cogl_material_copy (texture_template_material);
GError *error = NULL;
if (!cogl_material_set_layer_combine (pick_material, 0,
@ -1234,13 +1236,26 @@ clutter_texture_init (ClutterTexture *self)
priv->repeat_x = FALSE;
priv->repeat_y = FALSE;
priv->sync_actor_size = TRUE;
priv->material = cogl_material_new ();
priv->fbo_handle = COGL_INVALID_HANDLE;
priv->pick_material = COGL_INVALID_HANDLE;
priv->keep_aspect_ratio = FALSE;
priv->pick_with_alpha = FALSE;
priv->pick_with_alpha_supported = TRUE;
priv->seen_create_pick_material_warning = FALSE;
if (G_UNLIKELY (texture_template_material == NULL))
{
CoglHandle dummy_tex;
dummy_tex = cogl_texture_new_with_size (1, 1, COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_RGBA_8888_PRE);
texture_template_material = cogl_material_new ();
cogl_material_set_layer (texture_template_material, 0, dummy_tex);
cogl_handle_unref (dummy_tex);
}
priv->material = cogl_material_copy (texture_template_material);
}
/**

View File

@ -3,6 +3,7 @@ include $(top_srcdir)/build/autotools/Makefile.am.silent
UNIT_TESTS = \
test-textures.c \
test-texture-async.c \
test-texture-material.c \
test-events.c \
test-offscreen.c \
test-scale.c \

View File

@ -0,0 +1,47 @@
#include <stdlib.h>
#include <glib.h>
#include <gmodule.h>
#include <clutter/clutter.h>
G_MODULE_EXPORT int
test_texture_material_main (int argc, char *argv[])
{
ClutterActor *stage, *box;
ClutterLayoutManager *manager;
int i;
g_thread_init (NULL);
clutter_threads_init ();
clutter_init (&argc, &argv);
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Texture Material");
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
manager = clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL);
box = clutter_box_new (manager);
clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_WIDTH, -25.0));
clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_HEIGHT, -25.0));
clutter_actor_set_position (box, 25.0, 25.0);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), box);
for (i = 0; i < 48; i++)
{
ClutterActor *texture = clutter_texture_new ();
clutter_texture_set_load_data_async (CLUTTER_TEXTURE (texture), TRUE);
clutter_texture_set_keep_aspect_ratio (CLUTTER_TEXTURE (texture), TRUE);
clutter_texture_set_from_file (CLUTTER_TEXTURE (texture),
TESTS_DATADIR "/redhand.png",
NULL);
clutter_actor_set_width (texture, 96);
clutter_container_add_actor (CLUTTER_CONTAINER (box), texture);
}
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}