2006-06-08 Matthew Allum <mallum@openedhand.com>

* clutter/clutter-main.c:
        * clutter/clutter-private.h:
        * clutter/clutter-stage.c:
        Rework and fix offscreen rendering, also rejig GLX
        context handling, moving mostly into stage.
        Require at least OpenGL 1.2 ( CLAMP_TO_EDGE )

        * clutter/clutter-texture.c:
        Explicity set props on _init() as to avoid nasty can_create
        bug failing miserably in certain situations.
        Switch to CLAMP_TO_EDGE for textures to avoid tile seams.
        Add some more GL error checks.

        * clutter/clutter-label.c:
        Extra debug info

        * configure.ac:
        Require gdk-pixbuf-xlib-2.0
This commit is contained in:
Matthew Allum 2006-06-08 21:28:05 +00:00
parent f00e84606c
commit 9c572ff45a
5 changed files with 252 additions and 125 deletions

View File

@ -317,6 +317,7 @@ clutter_label_init (ClutterLabel *self)
pango_ft2_font_map_substitute_changed (font_map); pango_ft2_font_map_substitute_changed (font_map);
g_object_unref (font_map); g_object_unref (font_map);
*/ */
CLUTTER_MARK();
} }
/** /**
@ -332,6 +333,8 @@ ClutterElement *
clutter_label_new_with_text (const gchar *font_name, clutter_label_new_with_text (const gchar *font_name,
const gchar *text) const gchar *text)
{ {
CLUTTER_MARK();
return g_object_new (CLUTTER_TYPE_LABEL, return g_object_new (CLUTTER_TYPE_LABEL,
"font-name", font_name, "font-name", font_name,
"text", text, "text", text,

View File

@ -42,9 +42,6 @@ typedef struct
} }
ClutterXEventSource; ClutterXEventSource;
#define GLX_SAMPLE_BUFFERS_ARB 100000
#define GLX_SAMPLES_ARB 100001
typedef void (*ClutterXEventFunc) (XEvent *xev, gpointer user_data); typedef void (*ClutterXEventFunc) (XEvent *xev, gpointer user_data);
static gboolean __clutter_has_debug = FALSE; static gboolean __clutter_has_debug = FALSE;
@ -289,19 +286,21 @@ clutter_redraw (void)
{ {
#if 0 #if 0
unsigned int retraceCount; unsigned int retraceCount;
/* Wait for vertical retrace */
// Wait for vertical retrace /* glXGetVideoSyncSGI(&retraceCount); */
// glXGetVideoSyncSGI(&retraceCount); /* glXWaitVideoSyncSGI(2, (retraceCount+1)%2, &retraceCount); */
// glXWaitVideoSyncSGI(2, (retraceCount+1)%2, &retraceCount);
glXWaitVideoSyncSGI(1, 0, &retraceCount); glXWaitVideoSyncSGI(1, 0, &retraceCount);
#endif #endif
glXSwapBuffers(ctx->xdpy, clutter_stage_get_xwindow (stage)); glXSwapBuffers(ctx->xdpy, clutter_stage_get_xwindow (stage));
} }
else else
{ {
glFlush(); glXWaitGL();
CLUTTER_GLERR();
} }
if (clutter_want_fps ()) if (clutter_want_fps ())
{ {
timer_n_frames++; timer_n_frames++;
@ -439,19 +438,6 @@ clutter_root_xwindow (void)
return ClutterCntx->xwin_root; return ClutterCntx->xwin_root;
} }
/**
* clutter_xvisual:
*
* FIXME
*
* Return value: FIXME
*/
XVisualInfo*
clutter_xvisual (void)
{
return ClutterCntx->xvinfo;
}
/** /**
* clutter_want_debug: * clutter_want_debug:
* *
@ -465,18 +451,6 @@ clutter_want_debug (void)
return __clutter_has_debug; return __clutter_has_debug;
} }
/**
* clutter_gl_context_set_indirect:
* @indirect: FIXME
*
* FIXME
*/
void
clutter_gl_context_set_indirect (gboolean indirect)
{
}
ClutterMainContext* ClutterMainContext*
clutter_context_get_default (void) clutter_context_get_default (void)
{ {
@ -493,6 +467,32 @@ clutter_context_get_default (void)
return ClutterCntx; return ClutterCntx;
} }
static gboolean
is_gl_version_at_least_12 (void)
{
#define NON_VENDOR_VERSION_MAX_LEN 32
gchar non_vendor_version[NON_VENDOR_VERSION_MAX_LEN];
const gchar *version;
gint i = 0;
version = (const gchar*)glGetString(GL_VERSION);
while ( ((version[i] <= '9' && version[i] >= '0') || version[i] == '.')
&& i < NON_VENDOR_VERSION_MAX_LEN)
{
non_vendor_version[i] = version[i];
i++;
}
non_vendor_version[i] = '\0';
if (strstr (non_vendor_version, "1.0") == NULL
&& strstr (non_vendor_version, "1.0") == NULL)
return TRUE;
return FALSE;
}
/** /**
* clutter_init: * clutter_init:
* @argc: FIXME * @argc: FIXME
@ -506,20 +506,8 @@ int
clutter_init (int *argc, char ***argv) clutter_init (int *argc, char ***argv)
{ {
ClutterMainContext *context; ClutterMainContext *context;
XVisualInfo *vinfo;
static gboolean is_initialized = FALSE; static gboolean is_initialized = FALSE;
int gl_attributes[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
/* GLX_DEPTH_SIZE, 1, */
/* GLX_DEPTH_SIZE, 32, */
0
};
if (is_initialized) if (is_initialized)
return 1; return 1;
@ -545,22 +533,13 @@ clutter_init (int *argc, char ***argv)
if ((context->xdpy = XOpenDisplay (g_getenv ("DISPLAY"))) == NULL) if ((context->xdpy = XOpenDisplay (g_getenv ("DISPLAY"))) == NULL)
{ {
g_warning("Unable to connect to X DISPLAY."); g_critical ("Unable to connect to X DISPLAY.");
return -1; return -1;
} }
context->xscreen = DefaultScreen(context->xdpy); context->xscreen = DefaultScreen(context->xdpy);
context->xwin_root = RootWindow(context->xdpy, context->xwin_root = RootWindow(context->xdpy,
context->xscreen); context->xscreen);
context->xvinfo = glXChooseVisual (context->xdpy,
context->xscreen,
gl_attributes);
if (!context->xvinfo)
{
g_warning ("Unable to find suitable GL visual.");
return -2;
}
context->font_map = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ()); context->font_map = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ());
pango_ft2_font_map_set_resolution (context->font_map, 96.0, 96.0); pango_ft2_font_map_set_resolution (context->font_map, 96.0, 96.0);
@ -571,6 +550,12 @@ clutter_init (int *argc, char ***argv)
g_return_val_if_fail (CLUTTER_IS_STAGE (context->stage), -3); g_return_val_if_fail (CLUTTER_IS_STAGE (context->stage), -3);
clutter_element_realize (CLUTTER_ELEMENT (context->stage)); clutter_element_realize (CLUTTER_ELEMENT (context->stage));
g_return_val_if_fail
(CLUTTER_ELEMENT_IS_REALIZED(CLUTTER_ELEMENT(context->stage)), -4);
/* At least GL 1.2 is needed for CLAMP_TO_EDGE */
g_return_val_if_fail(is_gl_version_at_least_12 (), -5);
events_init (); events_init ();
context->is_initialized = TRUE; context->is_initialized = TRUE;

View File

@ -52,8 +52,6 @@ struct _ClutterMainContext
Display *xdpy; Display *xdpy;
Window xwin_root; Window xwin_root;
int xscreen; int xscreen;
XVisualInfo *xvinfo;
GC xgc; GC xgc;
PangoFT2FontMap *font_map; PangoFT2FontMap *font_map;

View File

@ -35,6 +35,8 @@
#include <GL/glx.h> #include <GL/glx.h>
#include <GL/gl.h> #include <GL/gl.h>
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
/* the stage is a singleton instance */ /* the stage is a singleton instance */
static ClutterStage *stage_singleton = NULL; static ClutterStage *stage_singleton = NULL;
@ -45,12 +47,14 @@ G_DEFINE_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP);
struct _ClutterStagePrivate struct _ClutterStagePrivate
{ {
XVisualInfo *xvisinfo;
Window xwin; Window xwin;
Pixmap xpixmap; Pixmap xpixmap;
gint xwin_width, xwin_height; /* FIXME target_width / height */ gint xwin_width, xwin_height; /* FIXME target_width / height */
GLXPixmap glxpixmap; GLXPixmap glxpixmap;
GLXContext gl_context; GLXContext gl_context;
ClutterColor color; ClutterColor color;
@ -245,8 +249,12 @@ clutter_stage_unrealize (ClutterElement *element)
stage = CLUTTER_STAGE(element); stage = CLUTTER_STAGE(element);
priv = stage->priv; priv = stage->priv;
CLUTTER_MARK();
if (priv->want_offscreen) if (priv->want_offscreen)
{ {
if (priv->glxpixmap) if (priv->glxpixmap)
{ {
glXDestroyGLXPixmap (clutter_xdisplay(), priv->glxpixmap); glXDestroyGLXPixmap (clutter_xdisplay(), priv->glxpixmap);
@ -267,6 +275,10 @@ clutter_stage_unrealize (ClutterElement *element)
priv->xwin = None; priv->xwin = None;
} }
} }
glXMakeCurrent(clutter_xdisplay(), None, NULL);
glXDestroyContext (clutter_xdisplay(), priv->gl_context);
priv->gl_context = None;
} }
static void static void
@ -279,31 +291,105 @@ clutter_stage_realize (ClutterElement *element)
priv = stage->priv; priv = stage->priv;
CLUTTER_MARK();
if (priv->want_offscreen) if (priv->want_offscreen)
{ {
priv->xpixmap = XCreatePixmap (clutter_xdisplay(), int gl_attributes[] = {
clutter_root_xwindow(), GLX_RGBA,
priv->xwin_width, priv->xwin_height, GLX_RED_SIZE, 1,
clutter_xvisual()->depth); GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
0
};
priv->glxpixmap = glXCreateGLXPixmap(clutter_xdisplay(), if (priv->xvisinfo)
clutter_xvisual(), XFree(priv->xvisinfo);
priv->xpixmap);
sync_fullscreen (stage); priv->xvisinfo = glXChooseVisual (clutter_xdisplay(),
clutter_xscreen(),
gl_attributes);
if (!priv->xvisinfo)
{
g_critical ("Unable to find suitable GL visual.");
CLUTTER_ELEMENT_UNSET_FLAGS (element, CLUTTER_ELEMENT_REALIZED);
return;
}
if (priv->gl_context) if (priv->gl_context)
glXDestroyContext (clutter_xdisplay(), priv->gl_context); glXDestroyContext (clutter_xdisplay(), priv->gl_context);
priv->xpixmap = XCreatePixmap (clutter_xdisplay(),
clutter_root_xwindow(),
priv->xwin_width,
priv->xwin_height,
priv->xvisinfo->depth);
priv->glxpixmap = glXCreateGLXPixmap(clutter_xdisplay(),
priv->xvisinfo,
priv->xpixmap);
sync_fullscreen (stage);
/* indirect */ /* indirect */
priv->gl_context = glXCreateContext (clutter_xdisplay(), priv->gl_context = glXCreateContext (clutter_xdisplay(),
clutter_xvisual(), priv->xvisinfo,
0, 0,
False); False);
glXMakeCurrent(clutter_xdisplay(), priv->glxpixmap, priv->gl_context); glXMakeCurrent(clutter_xdisplay(), priv->glxpixmap, priv->gl_context);
#if 0
/* Debug code for monitoring a off screen pixmap via window */
{
Colormap cmap;
XSetWindowAttributes swa;
cmap = XCreateColormap(clutter_xdisplay(),
clutter_root_xwindow(),
priv->xvisinfo->visual, AllocNone);
/* create a window */
swa.colormap = cmap;
foo_win = XCreateWindow(clutter_xdisplay(),
clutter_root_xwindow(),
0, 0,
priv->xwin_width, priv->xwin_height,
0,
priv->xvisinfo->depth,
InputOutput,
priv->xvisinfo->visual,
CWColormap, &swa);
XMapWindow(clutter_xdisplay(), foo_win);
}
#endif
} }
else else
{ {
int gl_attributes[] =
{
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
0
};
if (priv->xvisinfo)
XFree(priv->xvisinfo);
priv->xvisinfo = glXChooseVisual (clutter_xdisplay(),
clutter_xscreen(),
gl_attributes);
if (!priv->xvisinfo)
{
g_critical ("Unable to find suitable GL visual.");
CLUTTER_ELEMENT_UNSET_FLAGS (element, CLUTTER_ELEMENT_REALIZED);
return;
}
priv->xwin = XCreateSimpleWindow(clutter_xdisplay(), priv->xwin = XCreateSimpleWindow(clutter_xdisplay(),
clutter_root_xwindow(), clutter_root_xwindow(),
0, 0, 0, 0,
@ -329,13 +415,20 @@ clutter_stage_realize (ClutterElement *element)
glXDestroyContext (clutter_xdisplay(), priv->gl_context); glXDestroyContext (clutter_xdisplay(), priv->gl_context);
priv->gl_context = glXCreateContext (clutter_xdisplay(), priv->gl_context = glXCreateContext (clutter_xdisplay(),
clutter_xvisual(), priv->xvisinfo,
0, 0,
True); True);
glXMakeCurrent(clutter_xdisplay(), priv->xwin, priv->gl_context); glXMakeCurrent(clutter_xdisplay(), priv->xwin, priv->gl_context);
} }
CLUTTER_DBG("===========================================")
CLUTTER_DBG("GL_VENDOR: %s\n", glGetString(GL_VENDOR));
CLUTTER_DBG("GL_RENDERER: %s\n", glGetString(GL_RENDERER));
CLUTTER_DBG("GL_VERSION: %s\n", glGetString(GL_VERSION));
CLUTTER_DBG("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));
CLUTTER_DBG("===========================================")
sync_gl_viewport (stage); sync_gl_viewport (stage);
} }
@ -439,6 +532,12 @@ clutter_stage_set_property (GObject *object,
if (priv->want_offscreen != g_value_get_boolean (value)) if (priv->want_offscreen != g_value_get_boolean (value))
{ {
clutter_element_unrealize (CLUTTER_ELEMENT(stage)); clutter_element_unrealize (CLUTTER_ELEMENT(stage));
/* NOTE: as we are changing GL contexts here. so
* all textures will need unreleasing as they will
* likely have set up ( i.e labels ) in the old
* context. We should probably somehow do this
* automatically
*/
priv->want_offscreen = g_value_get_boolean (value); priv->want_offscreen = g_value_get_boolean (value);
clutter_element_realize (CLUTTER_ELEMENT(stage)); clutter_element_realize (CLUTTER_ELEMENT(stage));
} }
@ -530,7 +629,7 @@ clutter_stage_class_init (ClutterStageClass *klass)
"Fullscreen", "Fullscreen",
"Make Clutter stage fullscreen", "Make Clutter stage fullscreen",
FALSE, FALSE,
G_PARAM_READWRITE)); G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
g_object_class_install_property g_object_class_install_property
(gobject_class, PROP_OFFSCREEN, (gobject_class, PROP_OFFSCREEN,
@ -538,7 +637,7 @@ clutter_stage_class_init (ClutterStageClass *klass)
"Offscreen", "Offscreen",
"Make Clutter stage offscreen", "Make Clutter stage offscreen",
FALSE, FALSE,
G_PARAM_READWRITE)); G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
g_object_class_install_property g_object_class_install_property
@ -547,7 +646,7 @@ clutter_stage_class_init (ClutterStageClass *klass)
"Hide Cursor", "Hide Cursor",
"Make Clutter stage cursor-less", "Make Clutter stage cursor-less",
FALSE, FALSE,
G_PARAM_READWRITE)); G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
g_object_class_install_property g_object_class_install_property
(gobject_class, PROP_COLOR, (gobject_class, PROP_COLOR,
@ -623,9 +722,9 @@ clutter_stage_init (ClutterStage *self)
self->priv = priv = CLUTTER_STAGE_GET_PRIVATE (self); self->priv = priv = CLUTTER_STAGE_GET_PRIVATE (self);
priv->want_offscreen = FALSE; priv->want_offscreen = FALSE;
priv->want_fullscreen = FALSE; priv->want_fullscreen = FALSE;
priv->hide_cursor = FALSE; priv->hide_cursor = FALSE;
priv->xwin_width = 100; priv->xwin_width = 100;
priv->xwin_height = 100; priv->xwin_height = 100;
@ -693,6 +792,20 @@ clutter_stage_get_xwindow (ClutterStage *stage)
return stage->priv->xwin; return stage->priv->xwin;
} }
/**
* clutter_stage_get_xvisual
* @stage: A #ClutterStage
*
* Get the stages XVisualInfo.
*
* Return Value: Thes Stages XVisualInfo
**/
const XVisualInfo*
clutter_stage_get_xvisual (ClutterStage *stage)
{
return stage->priv->xvisinfo;
}
/** /**
* clutter_stage_set_color * clutter_stage_set_color
* @stage: A #ClutterStage * @stage: A #ClutterStage
@ -773,13 +886,16 @@ clutter_stage_snapshot (ClutterStage *stage,
gint width, gint width,
gint height) gint height)
{ {
guchar *data; guchar *data;
GdkPixbuf *pixb, *fpixb; GdkPixbuf *pixb, *fpixb;
ClutterElement *element; ClutterElement *element;
ClutterStagePrivate *priv;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
g_return_val_if_fail (x >= 0 && y >= 0, NULL); g_return_val_if_fail (x >= 0 && y >= 0, NULL);
priv = stage->priv;
element = CLUTTER_ELEMENT (stage); element = CLUTTER_ELEMENT (stage);
if (width < 0) if (width < 0)
@ -788,32 +904,46 @@ clutter_stage_snapshot (ClutterStage *stage,
if (height < 0) if (height < 0)
height = clutter_element_get_height (element); height = clutter_element_get_height (element);
data = g_malloc0 (sizeof (guchar) * width * height * 3);
glReadPixels (x, if (priv->want_offscreen)
clutter_element_get_height (element) {
- y - height, gdk_pixbuf_xlib_init (clutter_xdisplay(), clutter_xscreen());
width,
height, GL_RGB, GL_UNSIGNED_BYTE, data);
pixb = gdk_pixbuf_new_from_data (data, pixb = gdk_pixbuf_xlib_get_from_drawable
GDK_COLORSPACE_RGB, (NULL,
FALSE, (Drawable)priv->xpixmap,
8, DefaultColormap(clutter_xdisplay(),
width, clutter_xscreen()),
height, priv->xvisinfo->visual,
width * 3, x, y, 0, 0, width, height);
snapshot_pixbuf_free, return pixb;
NULL); }
else
{
data = g_malloc0 (sizeof (guchar) * width * height * 4);
if (pixb == NULL) glReadPixels (x,
return NULL; clutter_element_get_height (element)
- y - height,
width,
height, GL_RGBA, GL_UNSIGNED_BYTE, data);
pixb = gdk_pixbuf_new_from_data (data,
GDK_COLORSPACE_RGB,
TRUE,
8,
width,
height,
width * 4,
snapshot_pixbuf_free,
NULL);
fpixb = gdk_pixbuf_flip (pixb, TRUE);
fpixb = gdk_pixbuf_flip (pixb, TRUE); g_object_unref (pixb);
g_object_unref (pixb); return fpixb;
}
return fpixb;
} }
/** /**

View File

@ -40,7 +40,7 @@ G_DEFINE_TYPE (ClutterTexture, clutter_texture, CLUTTER_TYPE_ELEMENT);
#define PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV #define PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
#endif #endif
#define OVERLAP 0 #define OVERLAP 0 /* Dont need as CLAMP_TO_EDGE */
/* FIXME: actually use */ /* FIXME: actually use */
typedef struct ClutterTextureTileDimention typedef struct ClutterTextureTileDimention
@ -103,15 +103,15 @@ can_create (int width,
CLUTTER_DBG("checking %ix%i", width, height); CLUTTER_DBG("checking %ix%i", width, height);
glTexImage2D (GL_PROXY_TEXTURE_2D, 0, GL_RGBA, glTexImage2D (GL_PROXY_TEXTURE_2D, 0, GL_RGBA,
width, height, 0 /* border */, width, height, 0 /* border */,
pixel_format, pixel_type, NULL); pixel_format, pixel_type, NULL);
CLUTTER_GLERR();
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0,
GL_TEXTURE_WIDTH, &new_width); GL_TEXTURE_WIDTH, &new_width);
return new_width != 0; return new_width != 0;
} }
@ -164,27 +164,23 @@ init_tiles (ClutterTexture *texture)
x_pot = clutter_util_next_p2 (priv->width); x_pot = clutter_util_next_p2 (priv->width);
y_pot = clutter_util_next_p2 (priv->height); y_pot = clutter_util_next_p2 (priv->height);
if (x_pot - priv->width > priv->max_tile_waste
&& y_pot - priv->height > priv->max_tile_waste)
{
while (!(can_create (x_pot, y_pot, priv->pixel_format, priv->pixel_type)
&& (x_pot - priv->width < priv->max_tile_waste)
&& (y_pot - priv->height < priv->max_tile_waste)))
{
CLUTTER_DBG("x_pot:%i - width:%i < max_waste:%i",
x_pot, priv->width, priv->max_tile_waste);
CLUTTER_DBG("y_pot:%i - height:%i < max_waste:%i",
y_pot, priv->height, priv->max_tile_waste);
if (x_pot > y_pot)
x_pot /= 2;
else
y_pot /= 2;
}
}
while (!(can_create (x_pot, y_pot, priv->pixel_format, priv->pixel_type)
&& (x_pot - priv->width < priv->max_tile_waste)
&& (y_pot - priv->height < priv->max_tile_waste)))
{
CLUTTER_DBG("x_pot:%i - width:%i < max_waste:%i",
x_pot, priv->width, priv->max_tile_waste);
CLUTTER_DBG("y_pot:%i - height:%i < max_waste:%i",
y_pot, priv->height, priv->max_tile_waste);
if (x_pot > y_pot)
x_pot /= 2;
else
y_pot /= 2;
}
if (priv->x_tiles) if (priv->x_tiles)
g_free(priv->x_tiles); g_free(priv->x_tiles);
@ -290,11 +286,11 @@ texture_render_to_gl_quad (ClutterTexture *texture,
glTexCoord2f (tx, 0); glVertex2i (qx2, qy1); glTexCoord2f (tx, 0); glVertex2i (qx2, qy1);
glEnd (); glEnd ();
lasty += qy2 - qy1; lasty += (qy2 - qy1) ;
i++; i++;
} }
lastx += qx2 - qx1; lastx += (qx2 - qx1);
} }
} }
@ -376,11 +372,11 @@ clutter_texture_sync_pixbuf (ClutterTexture *texture)
glTexParameteri(GL_TEXTURE_2D, glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_S,
priv->repeat_x ? GL_REPEAT : GL_CLAMP); priv->repeat_x ? GL_REPEAT : GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_T, GL_TEXTURE_WRAP_T,
priv->repeat_y ? GL_REPEAT : GL_CLAMP); priv->repeat_y ? GL_REPEAT : GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
priv->filter_quality ? GL_LINEAR : GL_NEAREST); priv->filter_quality ? GL_LINEAR : GL_NEAREST);
@ -490,11 +486,11 @@ clutter_texture_sync_pixbuf (ClutterTexture *texture)
glTexParameteri(GL_TEXTURE_2D, glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_S,
priv->repeat_x ? GL_REPEAT : GL_CLAMP); priv->repeat_x ? GL_REPEAT : GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_T, GL_TEXTURE_WRAP_T,
priv->repeat_y ? GL_REPEAT : GL_CLAMP); priv->repeat_y ? GL_REPEAT : GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
priv->filter_quality ? GL_LINEAR : GL_NEAREST); priv->filter_quality ? GL_LINEAR : GL_NEAREST);
@ -876,8 +872,23 @@ clutter_texture_init (ClutterTexture *self)
ClutterTexturePrivate *priv; ClutterTexturePrivate *priv;
priv = g_new0 (ClutterTexturePrivate, 1); priv = g_new0 (ClutterTexturePrivate, 1);
/* FIXME: It seems defaults via props do not get set
* on all props for sub classes ( ie labels ).
* Should they be ?
*
* Setting them here also to be sure + safe.
*/
priv->max_tile_waste = 64;
priv->filter_quality = 0;
priv->tiled = TRUE;
priv->pixel_type = PIXEL_TYPE;
priv->pixel_format = GL_RGBA;
priv->repeat_x = FALSE;
priv->repeat_y = FALSE;
priv->pixbuf = NULL; priv->pixbuf = NULL;
self->priv = priv; self->priv = priv;
} }