+2007-06-08 Matthew Allum <mallum@openedhand.com>
+
+ * clutter/clutter-actor.c:
+ * clutter/clutter-debug.h:
+ * clutter/clutter-main.c:
+ * clutter/clutter-main.h:
+ * clutter/clutter-private.h:
+ * clutter/clutter-timeline.c:
+ Add 'schedule' debug flag and new CLUTTER_TIMESTAMP macro.
+
+ * clutter/clutter-texture.c:
+ * clutter/clutter-texture.h:
+ * clutter/cogl/cogl.h:
+ * clutter/cogl/gl/cogl-defines.h:
+ * clutter/cogl/gles/cogl-defines.h:
+ * clutter/cogl/gl/cogl.c:
+ * clutter/cogl/gles/cogl.c:
+ Add initial experiemental YUV texture support.
+ Move texture rect size checks into cogl.
+ Better handle moving texture data from video -> system memory
+ (if support available).
+
2007-06-07 Neil J. Patel <njp@o-hand.com>
* clutter/clutter-entry.c: (clutter_entry_class_init),
(clutter_entry_handle_key_event):
* clutter/clutter-entry.h:
- Added an 'activated' signal, whihc is emitted when the 'Enter' key is
+ Added an 'activated' signal, which is emitted when the 'Enter' key is
pressed.
* examples/test-entry.c: (on_entry_activated), (main):
if (!ctx->update_idle)
{
+ CLUTTER_TIMESTAMP (SCHEDULER,
+ "Adding ideler for actor: %p", self);
ctx->update_idle = g_idle_add_full (-100 , /* very high priority */
redraw_update_idle,
NULL, NULL);
#define __CLUTTER_DEBUG_H__
#include <glib.h>
+#include "clutter-main.h"
G_BEGIN_DECLS
CLUTTER_DEBUG_ALPHA = 1 << 6,
CLUTTER_DEBUG_BEHAVIOUR = 1 << 7,
CLUTTER_DEBUG_PANGO = 1 << 8,
- CLUTTER_DEBUG_BACKEND = 1 << 9
+ CLUTTER_DEBUG_BACKEND = 1 << 9,
+ CLUTTER_DEBUG_SCHEDULER = 1 << 10
} ClutterDebugFlag;
#ifdef CLUTTER_ENABLE_DEBUG
g_warning (G_STRLOC ": GL Error %x", _err); \
} } G_STMT_END
+#define CLUTTER_TIMESTAMP(type,x,a...) G_STMT_START { \
+ if (clutter_debug_flags & CLUTTER_DEBUG_##type) \
+ { g_message ("[" #type "]" " %li:" G_STRLOC ": " \
+ x, clutter_get_timestamp(), ##a); } \
+ } G_STMT_END
+
#else /* !CLUTTER_ENABLE_DEBUG */
#define CLUTTER_NOTE(type,x,a...)
#define CLUTTER_MARK()
#define CLUTTER_DBG(x)
#define CLUTTER_GLERR()
+#define CLUTTER_TIMESTAMP(type,x,a...)
#endif /* CLUTTER_ENABLE_DEBUG */
{ "behaviour", CLUTTER_DEBUG_BEHAVIOUR },
{ "pango", CLUTTER_DEBUG_PANGO },
{ "backend", CLUTTER_DEBUG_BACKEND },
+ { "scheduler", CLUTTER_DEBUG_SCHEDULER },
};
#endif /* CLUTTER_ENABLE_DEBUG */
stage = _clutter_backend_get_stage (ctx->backend);
+ CLUTTER_TIMESTAMP (SCHEDULER, "Redraw start");
+
CLUTTER_NOTE (PAINT, " Redraw enter");
/* Setup FPS count */
}
CLUTTER_NOTE (PAINT, " Redraw leave");
+
+ CLUTTER_TIMESTAMP (SCHEDULER, "Redraw finish");
}
/**
if (!stage)
return;
+ CLUTTER_TIMESTAMP (SCHEDULER, "Event recieved");
+
switch (event->type)
{
case CLUTTER_NOTHING:
ctx->backend = g_object_new (_clutter_backend_impl_get_type (), NULL);
ctx->is_initialized = FALSE;
-
+#ifdef CLUTTER_ENABLE_DEBUG
+ ctx->timer = g_timer_new ();
+ g_timer_start (ctx->timer);
+#endif
ClutterCntx = ctx;
}
return ClutterCntx;
}
+/**
+ * clutter_get_timestamp:
+ *
+ * Returns the approximate number of microseconds passed since clutter was
+ * intialised.
+ *
+ * Return value: Number of microseconds since clutter_init() was called.
+ */
+gulong
+clutter_get_timestamp (void)
+{
+#ifdef CLUTTER_ENABLE_DEBUG
+ ClutterMainContext *ctx;
+ gdouble seconds;
+
+ ctx = clutter_context_get_default ();
+
+ /* FIXME: may need a custom timer for embedded setups */
+ seconds = g_timer_elapsed (ctx->timer, NULL);
+
+ return (gulong)(seconds / 0.0000001);
+#else
+ return 0;
+#endif
+}
+
+
#ifdef CLUTTER_ENABLE_DEBUG
static gboolean
clutter_arg_debug_cb (const char *key,
void clutter_base_init (void);
+gulong clutter_get_timestamp (void);
+
G_END_DECLS
#endif
guint main_loop_level;
GSList *main_loops;
guint is_initialized : 1;
- guint pick_mode :1;
+ guint pick_mode :1; /* Indicates pick render mode */
+ GTimer *timer; /* Used for debugging scheduler */
};
#define CLUTTER_CONTEXT() (clutter_context_get_default ())
static int texture_signals[LAST_SIGNAL] = { 0 };
-
-static gboolean
-can_create_rect_arb (int width,
- int height,
- GLenum pixel_format,
- GLenum pixel_type)
-{
-#if HAVE_COGL_GL
- gint max_size = 0;
-
- glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &max_size);
-
- return (max_size && width <= max_size && height <= max_size);
-#endif
- return FALSE;
-}
-
static int
tile_dimension (int to_fill,
int start_size,
x_pot = clutter_util_next_p2 (priv->width);
y_pot = clutter_util_next_p2 (priv->height);
- while (!(cogl_texture_can_size (priv->pixel_format, priv->pixel_type,
+ while (!(cogl_texture_can_size (CGL_TEXTURE_2D,
+ priv->pixel_format,
+ priv->pixel_type,
x_pot, y_pot)
&& (x_pot - priv->width < priv->max_tile_waste)
&& (y_pot - priv->height < priv->max_tile_waste)))
g_return_if_fail(priv->tiles != NULL);
- /* OPT: Put in display list */
-
- /* OPT: Optionally avoid tiling and use texture rectangles ext if
- * supported.
- */
-
if (!priv->is_tiled)
{
cogl_texture_bind (priv->target_type, priv->tiles[0]);
- /* FIXME: FIXED */
-
if (priv->target_type == CGL_TEXTURE_2D) /* POT */
{
tx = (float) priv->width / clutter_util_next_p2 (priv->width);
CLUTTER_NOTE (TEXTURE, "syncing for single tile");
cogl_texture_bind (priv->target_type, priv->tiles[0]);
-
cogl_texture_set_alignment (priv->target_type, 4, priv->width);
cogl_texture_set_filters
* where this behaviour can be better controlled.
*/
if (priv->local_pixbuf == NULL)
- priv->local_pixbuf = clutter_texture_get_pixbuf (texture);
-
+ {
+ priv->local_pixbuf = clutter_texture_get_pixbuf (texture);
+ CLUTTER_NOTE (TEXTURE, "moved pixels into system (pixbuf) mem");
+ }
+
texture_free_gl_resources (texture);
}
}
else
{
- /* Dont allow realization with no pixbuf - note set_pixbuf/data
- * will set realize flags.
- */
- CLUTTER_NOTE (TEXTURE,
- "Texture has no image data cannot realize");
-
- CLUTTER_NOTE (TEXTURE, "flags %i", actor->flags);
- CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
- CLUTTER_NOTE (TEXTURE, "flags %i", actor->flags);
- return;
+ if (clutter_feature_available (CLUTTER_FEATURE_TEXTURE_READ_PIXELS))
+ {
+ /* Dont allow realization with no pixbuf - note set_pixbuf/data
+ * will set realize flags.
+ */
+ CLUTTER_NOTE (TEXTURE,
+ "Texture has no image data cannot realize");
+
+ CLUTTER_NOTE (TEXTURE, "flags %i", actor->flags);
+ CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
+ CLUTTER_NOTE (TEXTURE, "flags %i", actor->flags);
+ return;
+ }
}
CLUTTER_NOTE (TEXTURE, "Texture realized");
/* FIXME: cogl */
+ printf("grabbing single tile - %i x %i\n", priv->width, priv->height);
+
glBindTexture(priv->target_type, priv->tiles[0]);
glPixelStorei (GL_UNPACK_ROW_LENGTH, priv->width);
GError **error)
{
ClutterTexturePrivate *priv;
- gboolean texture_dirty = TRUE;
+ gboolean texture_dirty = TRUE, size_change = FALSE;
COGLenum prev_format;
priv = texture->priv;
/* Needed for GL_RGBA (internal format) and gdk pixbuf usage */
g_return_val_if_fail (bpp == 4, FALSE);
- texture_dirty = (width != priv->width || height != priv->height);
+ texture_dirty = size_change = (width != priv->width
+ || height != priv->height);
prev_format = priv->pixel_format;
if (flags & CLUTTER_TEXTURE_RGB_FLAG_BGR)
{
+ /* FIXME: We actually need to convert for GLES */
if (has_alpha)
priv->pixel_format = CGL_BGRA;
else
if (priv->is_tiled == FALSE)
{
if (priv->target_type == CGL_TEXTURE_RECTANGLE_ARB
- && !can_create_rect_arb (priv->width,
- priv->height,
- priv->pixel_format,
- priv->pixel_type))
+ && !cogl_texture_can_size (CGL_TEXTURE_RECTANGLE_ARB,
+ priv->pixel_format,
+ priv->pixel_type,
+ priv->width,
+ priv->height))
{
/* If we cant create NPOT tex of this size fall back to tiles */
CLUTTER_NOTE (TEXTURE,
}
if (priv->target_type == CGL_TEXTURE_2D
- && !cogl_texture_can_size
- (priv->pixel_format,
- priv->pixel_type,
- clutter_util_next_p2(priv->width),
- clutter_util_next_p2(priv->height)))
+ && !cogl_texture_can_size (CGL_TEXTURE_2D,
+ priv->pixel_format,
+ priv->pixel_type,
+ clutter_util_next_p2(priv->width),
+ clutter_util_next_p2(priv->height)))
{
priv->is_tiled = TRUE;
}
CLUTTER_ACTOR_SET_FLAGS (CLUTTER_ACTOR (texture), CLUTTER_ACTOR_REALIZED);
- if (texture_dirty)
+ if (size_change)
{
g_signal_emit (texture, texture_signals[SIZE_CHANGE],
0, priv->width, priv->height);
ClutterTextureFlags flags,
GError **error)
{
-#if 0
- gboolean texture_dirty = TRUE;
- COGLenum prev_format;
+ ClutterTexturePrivate *priv;
+ gboolean texture_dirty = TRUE, size_change = FALSE;
if (!clutter_feature_available(CLUTTER_FEATURE_TEXTURE_YUV))
return FALSE;
priv = texture->priv;
/* FIXME: check other image props */
- texture_dirty = (width != priv->width || height != priv->height);
+ size_change = (width != priv->width || height != priv->height);
+ texture_dirty = size_change || (priv->pixel_format != CGL_YCBCR_MESA);
priv->width = width;
priv->height = height;
-
- /* #ifdef GL_YCBCR_MESA */
+ priv->pixel_type = (flags & CLUTTER_TEXTURE_YUV_FLAG_YUV2) ?
+ CGL_UNSIGNED_SHORT_8_8_REV_MESA :
+ CGL_UNSIGNED_SHORT_8_8_MESA;
priv->pixel_format = CGL_YCBCR_MESA;
+ priv->target_type = CGL_TEXTURE_2D;
+
+ if (texture_dirty)
+ texture_free_gl_resources (texture);
if (!priv->tiles)
{
if (texture_dirty)
{
- if (cogl_texture_can_size(priv->pixel_format,
- priv->pixel_type,
- clutter_util_next_p2(priv->width),
- clutter_util_next_p2(priv->height)))
+ /* FIXME: need to check size limits correctly - does not
+ * seem to work if correct format and typre are used so
+ * this is really a guess...
+ */
+ if (cogl_texture_can_size (CGL_TEXTURE_2D,
+ CGL_RGBA,
+ CGL_UNSIGNED_BYTE,
+ clutter_util_next_p2(priv->width),
+ clutter_util_next_p2(priv->height)))
{
- glTexImage2D (CGL_TEXTURE_2D,
- 0,
- GL_YCBCR_MESA,
- clutter_util_next_p2(priv->width),
- clutter_util_next_p2(priv->height),
- 0,
- GL_YCBCR_MESA,
- GL_UNSIGNED_SHORT_8_8_REV_MESA,
- NULL);
+ cogl_texture_image_2d (priv->target_type,
+ priv->pixel_format,
+ clutter_util_next_p2(priv->width),
+ clutter_util_next_p2(priv->height),
+ priv->pixel_format,
+ priv->pixel_type,
+ NULL);
}
else
- /* No tiled support for YUV textures as yet */
- return FALSE; /* Set Error */
+ return FALSE; /* FIXME: add tiling */
}
- if (flags & CLUTTER_TEXTURE_YUV_FLAG_YUV2)
- {
- glTexSubImage2D (GL_TEXTURE_2D,
- 0,
- 0,
- 0,
- priv->width,
- priv->height
- CGL_YCBCR_MESA,
- CGL_UNSIGNED_SHORT_8_8_REV_MESA,
- data);
- }
- else
+ cogl_texture_sub_image_2d (priv->target_type,
+ 0,
+ 0,
+ priv->width,
+ priv->height,
+ priv->pixel_format,
+ priv->pixel_type,
+ data);
+
+ CLUTTER_ACTOR_SET_FLAGS (CLUTTER_ACTOR (texture), CLUTTER_ACTOR_REALIZED);
+
+ if (size_change)
{
- glTexSubImage2D (GL_TEXTURE_2D,
- 0,
- 0,
- 0,
- priv->width,
- priv->height
- CGL_YCBCR_MESA,
- CGL_UNSIGNED_SHORT_8_8_MESA,
- data);
+ g_signal_emit (texture, texture_signals[SIZE_CHANGE],
+ 0, priv->width, priv->height);
+
+ if (priv->sync_actor_size)
+ clutter_actor_set_size (CLUTTER_ACTOR(texture),
+ priv->width,
+ priv->height);
}
-#endif
- return FALSE;
+
+ g_signal_emit (texture, texture_signals[PIXBUF_CHANGE], 0);
+
+ if (CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR(texture)))
+ clutter_actor_queue_redraw (CLUTTER_ACTOR(texture));
+
+ return TRUE;
}
/**
typedef enum ClutterTextureFlags
{
CLUTTER_TEXTURE_RGB_FLAG_BGR = (1<<1),
- CLUTTER_TEXTURE_RGB_FLAG_PREMULT = (1<<2),
+ CLUTTER_TEXTURE_RGB_FLAG_PREMULT = (1<<2), /* FIXME: not handled */
CLUTTER_TEXTURE_YUV_FLAG_YUV2 = (1<<3)
/* FIXME: add compressed types ? */
} ClutterTextureFlags;
priv = timeline->priv;
+ CLUTTER_TIMESTAMP (SCHEDULER, "Timeline:%p activated\n", timeline);
+
/* Figure out potential frame skips */
g_get_current_time (&timeval);
n_frames = 1;
if (n_frames > 1)
- CLUTTER_NOTE (MISC, "Skipping %i frames", n_frames);
+ {
+ CLUTTER_TIMESTAMP (SCHEDULER,
+ "Timeline %p, skipping %i frames\n",
+ timeline, n_frames);
+ }
}
else
{
cogl_enable (gulong flags);
gboolean
-cogl_texture_can_size (COGLenum pixel_format,
+cogl_texture_can_size (COGLenum target,
+ COGLenum pixel_format,
COGLenum pixel_type,
int width,
int height);
+
void
cogl_texture_quad (gint x1,
gint x2,
#define CGL_TEXTURE_2D GL_TEXTURE_2D
#define CGL_ARGB GL_ARGB
#define CGL_TEXTURE_RECTANGLE_ARB GL_TEXTURE_RECTANGLE_ARB
+#ifdef GL_YCBCR_MESA
+#define CGL_YCBCR_MESA GL_YCBCR_MESA
+#define CGL_UNSIGNED_SHORT_8_8_REV_MESA GL_UNSIGNED_SHORT_8_8_REV_MESA
+#define CGL_UNSIGNED_SHORT_8_8_MESA GL_UNSIGNED_SHORT_8_8_MESA
+#else
+#define CGL_YCBCR_MESA 0
+#define CGL_UNSIGNED_SHORT_8_8_REV_MESA 0
+#define CGL_UNSIGNED_SHORT_8_8_MESA 0
+#endif
G_END_DECLS
}
gboolean
-cogl_texture_can_size (COGLenum pixel_format,
+cogl_texture_can_size (COGLenum target,
+ COGLenum pixel_format,
COGLenum pixel_type,
int width,
int height)
{
- GLint new_width = 0;
+ if (target == CGL_TEXTURE_RECTANGLE_ARB)
+ {
+ gint max_size = 0;
+
+ GE( glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &max_size) );
+
+ return (max_size && width <= max_size && height <= max_size);
+ }
+ else /* Assumes CGL_TEXTURE_2D */
+ {
+ GLint new_width = 0;
- GE( glTexImage2D (GL_PROXY_TEXTURE_2D, 0, GL_RGBA,
- width, height, 0 /* border */,
- pixel_format, pixel_type, NULL) );
+ GE( glTexImage2D (GL_PROXY_TEXTURE_2D, 0, GL_RGBA,
+ width, height, 0 /* border */,
+ pixel_format, pixel_type, NULL) );
- GE( glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0,
- GL_TEXTURE_WIDTH, &new_width) );
+ GE( glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0,
+ GL_TEXTURE_WIDTH, &new_width) );
- return new_width != 0;
+ return new_width != 0;
+ }
}
void
#define CGL_BGR GL_RGB
#define CGL_BGRA GL_RGBA
-#define CGL_TEXTURE_RECTANGLE_ARB 0 /* Its unlikely we support this */
+/* Its unlikely we support this */
+#define CGL_TEXTURE_RECTANGLE_ARB 0
+
+/* YUV textures also unsupported */
+#define CGL_YCBCR_MESA 0
+#define CGL_UNSIGNED_SHORT_8_8_REV_MESA 0
+#define CGL_UNSIGNED_SHORT_8_8_MESA 0
G_END_DECLS
GE( glDisable (GL_STENCIL_TEST) );
}
-
-
gboolean
-cogl_texture_can_size (COGLenum pixel_format,
+cogl_texture_can_size (COGLenum target,
+ COGLenum pixel_format,
COGLenum pixel_type,
int width,
int height)
{
- /* FIXME */
+ /* FIXME: How we get this is likely GLES implementation dependant. */
return TRUE;
-
-#if 0
- GLint new_width = 0;
-
- GE( glTexImage2D (GL_PROXY_TEXTURE_2D, 0, GL_RGBA,
- width, height, 0 /* border */,
- pixel_format, pixel_type, NULL) );
-
- GE( glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0,
- GL_TEXTURE_WIDTH, &new_width) );
-
- return new_width != 0;
-#endif
}
void