diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index dfb54b2dd..3181ff81e 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -79,7 +79,6 @@ struct _ClutterTexturePrivate { gfloat width; gfloat height; - ClutterTextureQuality filter_quality; CoglHandle material; gboolean no_slice; @@ -176,36 +175,35 @@ clutter_texture_error_quark (void) return g_quark_from_static_string ("clutter-texture-error-quark"); } +static const struct +{ + gint min_filter; + gint mag_filter; +} +clutter_texture_quality_filters[] = + { + /* CLUTTER_TEXTURE_QUALITY_LOW */ + { COGL_MATERIAL_FILTER_NEAREST, COGL_MATERIAL_FILTER_NEAREST }, + + /* CLUTTER_TEXTURE_QUALITY_MEDIUM */ + { COGL_MATERIAL_FILTER_LINEAR, COGL_MATERIAL_FILTER_LINEAR }, + + /* CLUTTER_TEXTURE_QUALITY_HIGH */ + { COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR, COGL_MATERIAL_FILTER_LINEAR } + }; + static inline void clutter_texture_quality_to_filters (ClutterTextureQuality quality, gint *min_filter_p, gint *mag_filter_p) { - gint min_filter, mag_filter; - - switch (quality) - { - case CLUTTER_TEXTURE_QUALITY_LOW: - min_filter = COGL_TEXTURE_FILTER_NEAREST; - mag_filter = COGL_TEXTURE_FILTER_NEAREST; - break; - - case CLUTTER_TEXTURE_QUALITY_MEDIUM: - min_filter = COGL_TEXTURE_FILTER_LINEAR; - mag_filter = COGL_TEXTURE_FILTER_LINEAR; - break; - - case CLUTTER_TEXTURE_QUALITY_HIGH: - min_filter = COGL_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR; - mag_filter = COGL_TEXTURE_FILTER_LINEAR; - break; - } + g_return_if_fail (quality < G_N_ELEMENTS (clutter_texture_quality_filters)); if (min_filter_p) - *min_filter_p = min_filter; + *min_filter_p = clutter_texture_quality_filters[quality].min_filter; if (mag_filter_p) - *mag_filter_p = mag_filter; + *mag_filter_p = clutter_texture_quality_filters[quality].mag_filter; } static void @@ -216,7 +214,10 @@ texture_free_gl_resources (ClutterTexture *texture) CLUTTER_MARK(); if (priv->material != COGL_INVALID_HANDLE) - cogl_material_remove_layer (priv->material, 0); + /* We want to keep the layer so that the filter settings will + remain but we want to free its resources so we clear the + texture handle */ + cogl_material_set_layer (priv->material, 0, COGL_INVALID_HANDLE); } static void @@ -285,7 +286,6 @@ clutter_texture_realize (ClutterActor *actor) if (priv->fbo_source) { CoglTextureFlags flags = COGL_TEXTURE_NONE; - gint min_filter, mag_filter; CoglHandle tex; /* Handle FBO's */ @@ -293,9 +293,6 @@ clutter_texture_realize (ClutterActor *actor) if (priv->no_slice) flags |= COGL_TEXTURE_NO_SLICING; - if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH) - flags |= COGL_TEXTURE_AUTO_MIPMAP; - tex = cogl_texture_new_with_size (priv->width, priv->height, flags, @@ -303,12 +300,6 @@ clutter_texture_realize (ClutterActor *actor) cogl_material_set_layer (priv->material, 0, tex); - clutter_texture_quality_to_filters (priv->filter_quality, - &min_filter, - &mag_filter); - - cogl_texture_set_filters (tex, min_filter, mag_filter); - priv->fbo_handle = cogl_offscreen_new_to_texture (tex); /* The material now has a reference to the texture so it will @@ -1189,7 +1180,6 @@ clutter_texture_init (ClutterTexture *self) self->priv = priv = CLUTTER_TEXTURE_GET_PRIVATE (self); - priv->filter_quality = CLUTTER_TEXTURE_QUALITY_MEDIUM; priv->repeat_x = FALSE; priv->repeat_y = FALSE; priv->sync_actor_size = TRUE; @@ -1229,11 +1219,6 @@ clutter_texture_save_to_local_data (ClutterTexture *texture) /* Align to 4 bytes */ priv->local_data_rowstride = (priv->local_data_width * bpp + 3) & ~3; - /* Store the filter quality from the texture properties so that - * they will be restored the data is loaded again - */ - priv->filter_quality = clutter_texture_get_filter_quality (texture); - priv->local_data = g_malloc (priv->local_data_rowstride * priv->local_data_height); @@ -1465,14 +1450,10 @@ clutter_texture_set_from_data (ClutterTexture *texture, ClutterTexturePrivate *priv = texture->priv; CoglHandle new_texture = COGL_INVALID_HANDLE; CoglTextureFlags flags = COGL_TEXTURE_NONE; - gint min_filter, mag_filter; if (priv->no_slice) flags |= COGL_TEXTURE_NO_SLICING; - if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH) - flags |= COGL_TEXTURE_AUTO_MIPMAP; - /* FIXME if we are not realized, we should store the data * for future use, instead of creating the texture. */ @@ -1493,12 +1474,6 @@ clutter_texture_set_from_data (ClutterTexture *texture, return FALSE; } - clutter_texture_quality_to_filters (priv->filter_quality, - &min_filter, - &mag_filter); - - cogl_texture_set_filters (new_texture, min_filter, mag_filter); - clutter_texture_set_cogl_texture (texture, new_texture); cogl_handle_unref (new_texture); @@ -1669,9 +1644,6 @@ clutter_texture_async_load_complete (ClutterTexture *self, if (priv->no_slice) flags |= COGL_TEXTURE_NO_SLICING; - if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH) - flags |= COGL_TEXTURE_AUTO_MIPMAP; - handle = cogl_texture_new_from_bitmap (bitmap, flags, COGL_PIXEL_FORMAT_ANY); @@ -1905,7 +1877,6 @@ clutter_texture_set_from_file (ClutterTexture *texture, CoglHandle new_texture = COGL_INVALID_HANDLE; GError *internal_error = NULL; CoglTextureFlags flags = COGL_TEXTURE_NONE; - gint min_filter, mag_filter; priv = texture->priv; @@ -1917,9 +1888,6 @@ clutter_texture_set_from_file (ClutterTexture *texture, if (priv->no_slice) flags |= COGL_TEXTURE_NO_SLICING; - if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH) - flags |= COGL_TEXTURE_AUTO_MIPMAP; - new_texture = cogl_texture_new_from_file (filename, flags, COGL_PIXEL_FORMAT_ANY, @@ -1941,12 +1909,6 @@ clutter_texture_set_from_file (ClutterTexture *texture, return FALSE; } - clutter_texture_quality_to_filters (priv->filter_quality, - &min_filter, - &mag_filter); - - cogl_texture_set_filters (new_texture, min_filter, mag_filter); - clutter_texture_set_cogl_texture (texture, new_texture); cogl_handle_unref (new_texture); @@ -1987,26 +1949,14 @@ clutter_texture_set_filter_quality (ClutterTexture *texture, if (filter_quality != old_quality) { - CoglHandle cogl_texture = clutter_texture_get_cogl_texture (texture); gint min_filter, mag_filter; - priv->filter_quality = filter_quality; - - clutter_texture_quality_to_filters (priv->filter_quality, + clutter_texture_quality_to_filters (filter_quality, &min_filter, &mag_filter); - /* Is this actually needed - causes problems with TFP mipmaps */ - if (cogl_texture != COGL_INVALID_HANDLE) - cogl_texture_set_filters (cogl_texture, min_filter, mag_filter); - - if ((old_quality == CLUTTER_TEXTURE_QUALITY_HIGH || - filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH) && - CLUTTER_ACTOR_IS_REALIZED (texture)) - { - _clutter_actor_rerealize (CLUTTER_ACTOR (texture), - NULL, NULL); - } + cogl_material_set_layer_filters (priv->material, 0, + min_filter, mag_filter); g_object_notify (G_OBJECT (texture), "filter-quality"); @@ -2029,12 +1979,28 @@ ClutterTextureQuality clutter_texture_get_filter_quality (ClutterTexture *texture) { ClutterTexturePrivate *priv; + const GList *layers; + CoglMaterialFilter min_filter, mag_filter; + int i; g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), 0); priv = texture->priv; - return priv->filter_quality; + layers = cogl_material_get_layers (priv->material); + if (layers == NULL) + return CLUTTER_TEXTURE_QUALITY_MEDIUM; + + min_filter = cogl_material_layer_get_min_filter (layers->data); + mag_filter = cogl_material_layer_get_mag_filter (layers->data); + + for (i = 0; i < G_N_ELEMENTS (clutter_texture_quality_filters); i++) + if (clutter_texture_quality_filters[i].min_filter == min_filter + && clutter_texture_quality_filters[i].mag_filter == mag_filter) + return i; + + /* Unknown filter combination */ + return CLUTTER_TEXTURE_QUALITY_LOW; } /** @@ -2255,7 +2221,6 @@ on_fbo_source_size_change (GObject *object, if (w != priv->width || h != priv->height) { CoglTextureFlags flags = COGL_TEXTURE_NONE; - gint min_filter, mag_filter; CoglHandle tex; /* tear down the FBO */ @@ -2269,9 +2234,6 @@ on_fbo_source_size_change (GObject *object, flags |= COGL_TEXTURE_NO_SLICING; - if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH) - flags |= COGL_TEXTURE_AUTO_MIPMAP; - tex = cogl_texture_new_with_size (MAX (priv->width, 1), MAX (priv->height, 1), flags, @@ -2279,12 +2241,6 @@ on_fbo_source_size_change (GObject *object, cogl_material_set_layer (priv->material, 0, tex); - clutter_texture_quality_to_filters (priv->filter_quality, - &min_filter, - &mag_filter); - - cogl_texture_set_filters (tex, min_filter, mag_filter); - priv->fbo_handle = cogl_offscreen_new_to_texture (tex); /* The material now has a reference to the texture so it will diff --git a/clutter/cogl/cogl-material.h b/clutter/cogl/cogl-material.h index 504c173fa..66fbd8d5c 100644 --- a/clutter/cogl/cogl-material.h +++ b/clutter/cogl/cogl-material.h @@ -43,6 +43,52 @@ G_BEGIN_DECLS * blended together. */ +/** + * CoglMaterialFilter: + * @COGL_MATERIAL_FILTER_NEAREST: Measuring in manhatten distance from the, + * current pixel center, use the nearest texture + * texel. + * @COGL_MATERIAL_FILTER_LINEAR: Use the weighted average of the 4 texels + * nearest the current pixel center. + * @COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST: Select the mimap level whose + * texel size most closely matches + * the current pixel, and use the + * COGL_MATERIAL_FILTER_NEAREST + * criterion. + * @COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST: Select the mimap level whose + * texel size most closely matches + * the current pixel, and use the + * COGL_MATERIAL_FILTER_LINEAR + * criterion. + * @COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR: Select the two mimap levels + * whose texel size most closely + * matches the current pixel, use + * the COGL_MATERIAL_FILTER_NEAREST + * criterion on each one and take + * their weighted average. + * @COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR: Select the two mimap levels + * whose texel size most closely + * matches the current pixel, use + * the COGL_MATERIAL_FILTER_LINEAR + * criterion on each one and take + * their weighted average. + * + * Texture filtering is used whenever the current pixel maps either to more + * than one texture element (texel) or less than one. These filter enums + * correspond to different strategies used to come up with a pixel color, by + * possibly referring to multiple neighbouring texels and taking a weighted + * average or simply using the nearest texel. + */ +typedef enum _CoglMaterialFilter +{ + COGL_MATERIAL_FILTER_NEAREST = GL_NEAREST, + COGL_MATERIAL_FILTER_LINEAR = GL_LINEAR, + COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST, + COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST, + COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR, + COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR +} CoglMaterialFilter; + /** * cogl_material_new: * @@ -660,6 +706,40 @@ CoglMaterialLayerType cogl_material_layer_get_type (CoglHandle layer_handle); */ CoglHandle cogl_material_layer_get_texture (CoglHandle layer_handle); +/** + * cogl_material_layer_get_min_filter: + * @layer_handle: a #CoglHandle for a material layer. + * + * Query the currently set downscaling filter for a cogl material layer. + * + * Returns: the current downscaling filter for a cogl material layer. + */ +CoglMaterialFilter cogl_material_layer_get_min_filter (CoglHandle layer_handle); + +/** + * cogl_material_layer_get_mag_filter: + * @layer_handle: a #CoglHandle for a material layer. + * + * Query the currently set downscaling filter for a cogl material layer. + * + * Returns: the current downscaling filter for a cogl material layer. + */ +CoglMaterialFilter cogl_material_layer_get_mag_filter (CoglHandle layer_handle); + +/** + * cogl_material_set_layer_filters: + * @handle: a #CoglHandle to a material. + * @layer_index: the layer number to change. + * @min_filter: the filter used when scaling a texture down. + * @mag_filter: the filter used when magnifying a texture. + * + * Changes the decimation and interpolation filters used when a texture is + * drawn at other scales than 100%. + */ +void cogl_material_set_layer_filters (CoglHandle handle, + gint layer_index, + CoglMaterialFilter min_filter, + CoglMaterialFilter mag_filter); G_END_DECLS diff --git a/clutter/cogl/cogl-texture.h b/clutter/cogl/cogl-texture.h index d4cc4e812..15cadc879 100644 --- a/clutter/cogl/cogl-texture.h +++ b/clutter/cogl/cogl-texture.h @@ -218,72 +218,6 @@ guint cogl_texture_get_rowstride (CoglHandle handle); */ gint cogl_texture_get_max_waste (CoglHandle handle); -/** - * CoglTextureFilter: - * @COGL_TEXTURE_FILTER_NEAREST: Measuring in manhatten distance from the, - * current pixel center, use the nearest texture - * texel. - * @COGL_TEXTURE_FILTER_LINEAR: Use the weighted average of the 4 texels - * nearest the current pixel center. - * @COGL_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST: Select the mimap level whose - * texel size most closely matches - * the current pixel, and use the - * COGL_TEXTURE_FILTER_NEAREST - * criterion. - * @COGL_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST: Select the mimap level whose - * texel size most closely matches - * the current pixel, and use the - * COGL_TEXTURE_FILTER_LINEAR - * criterion. - * @COGL_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR: Select the two mimap levels - * whose texel size most closely - * matches the current pixel, use - * the COGL_TEXTURE_FILTER_NEAREST - * criterion on each one and take - * their weighted average. - * @COGL_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR: Select the two mimap levels - * whose texel size most closely - * matches the current pixel, use - * the COGL_TEXTURE_FILTER_LINEAR - * criterion on each one and take - * their weighted average. - * - * Texture filtering is used whenever the current pixel maps either to more - * than one texture element (texel) or less than one. These filter enums - * correspond to different strategies used to come up with a pixel color, by - * possibly referring to multiple neighbouring texels and taking a weighted - * average or simply using the nearest texel. - */ -typedef enum _CoglTextureFilter -{ - COGL_TEXTURE_FILTER_NEAREST = GL_NEAREST, - COGL_TEXTURE_FILTER_LINEAR = GL_LINEAR, - COGL_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST, - COGL_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST, - COGL_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR, - COGL_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR -} CoglTextureFilter; - -/** - * cogl_texture_get_min_filter: - * @handle: a #CoglHandle for a texture. - * - * Query the currently set downscaling filter for a cogl texture. - * - * Returns: the current downscaling filter for a cogl texture. - */ -CoglTextureFilter cogl_texture_get_min_filter (CoglHandle handle); - -/** - * cogl_texture_get_mag_filter: - * @handle: a #CoglHandle for a texture. - * - * Query the currently set downscaling filter for a cogl texture. - * - * Returns: the current downscaling filter for a cogl texture. - */ -CoglTextureFilter cogl_texture_get_mag_filter (CoglHandle handle); - /** * cogl_texture_is_sliced: * @handle: a #CoglHandle for a texture. @@ -333,20 +267,6 @@ gint cogl_texture_get_data (CoglHandle handle, guint rowstride, guchar *data); -/** - * cogl_texture_set_filters: - * @handle: a #CoglHandle. - * @min_filter: the filter used when scaling the texture down. - * @mag_filter: the filter used when magnifying the texture. - * - * Changes the decimation and interpolation filters used when the texture is - * drawn at other scales than 100%. - */ -void cogl_texture_set_filters (CoglHandle handle, - CoglTextureFilter min_filter, - CoglTextureFilter mag_filter); - - /** * cogl_texture_set_region: * @handle: a #CoglHandle. diff --git a/clutter/cogl/cogl-types.h b/clutter/cogl/cogl-types.h index 3aa6f5c3c..0a1360dde 100644 --- a/clutter/cogl/cogl-types.h +++ b/clutter/cogl/cogl-types.h @@ -244,8 +244,11 @@ struct _CoglTextureVertex /** * CoglTextureFlags: * @COGL_TEXTURE_NONE: No flags specified - * @COGL_TEXTURE_AUTO_MIPMAP: Enables the automatic generation of the - * mipmap pyramid from the base level image whenever it is updated + * @COGL_TEXTURE_NO_AUTO_MIPMAP: Disables the automatic generation of + * the mipmap pyramid from the base level image whenever it is + * updated. The mipmaps are only generated when the texture is + * rendered with a mipmap filter so it should be free to leave out + * this flag when using other filtering modes. * @COGL_TEXTURE_NO_SLICING: Disables the slicing of the texture * * Flags to pass to the cogl_texture_new_* family of functions. @@ -253,9 +256,9 @@ struct _CoglTextureVertex * Since: 1.0 */ typedef enum { - COGL_TEXTURE_NONE = 0, - COGL_TEXTURE_AUTO_MIPMAP = 1 << 0, - COGL_TEXTURE_NO_SLICING = 1 << 1 + COGL_TEXTURE_NONE = 0, + COGL_TEXTURE_NO_AUTO_MIPMAP = 1 << 0, + COGL_TEXTURE_NO_SLICING = 1 << 1 } CoglTextureFlags; /** diff --git a/clutter/cogl/common/cogl-material-private.h b/clutter/cogl/common/cogl-material-private.h index 9b2170ecf..e61ab97bd 100644 --- a/clutter/cogl/common/cogl-material-private.h +++ b/clutter/cogl/common/cogl-material-private.h @@ -68,6 +68,9 @@ struct _CoglMaterialLayer CoglHandle texture; /*!< The texture for this layer, or COGL_INVALID_HANDLE for an empty layer */ + CoglMaterialFilter mag_filter; + CoglMaterialFilter min_filter; + /* Determines how the color of individual texture fragments * are calculated. */ GLint texture_combine_rgb_func; diff --git a/clutter/cogl/common/cogl-material.c b/clutter/cogl/common/cogl-material.c index f3e7bb417..66a4b0c96 100644 --- a/clutter/cogl/common/cogl-material.c +++ b/clutter/cogl/common/cogl-material.c @@ -637,6 +637,8 @@ _cogl_material_get_layer (CoglMaterial *material, layer_handle = _cogl_material_layer_handle_new (layer); layer->index = index_; layer->flags = COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE; + layer->mag_filter = COGL_MATERIAL_FILTER_LINEAR; + layer->min_filter = COGL_MATERIAL_FILTER_LINEAR; layer->texture = COGL_INVALID_HANDLE; /* Choose the same default combine mode as OpenGL: @@ -1014,6 +1016,15 @@ get_n_args_for_combine_func (GLint func) return 0; } +static gboolean +is_mipmap_filter (CoglMaterialFilter filter) +{ + return (filter == COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST + || filter == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST + || filter == COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR + || filter == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR); +} + static void _cogl_material_layer_flush_gl_sampler_state (CoglMaterialLayer *layer, CoglLayerInfo *gl_layer_info) @@ -1214,6 +1225,13 @@ _cogl_material_flush_layers_gl_state (CoglMaterial *material, GE (glActiveTexture (GL_TEXTURE0 + i)); + _cogl_texture_set_filters (layer->texture, + layer->min_filter, + layer->mag_filter); + if (is_mipmap_filter (layer->min_filter) + || is_mipmap_filter (layer->mag_filter)) + _cogl_texture_ensure_mipmaps (layer->texture); + /* FIXME: We could be more clever here and only bind the texture if it is different from gl_layer_info->gl_texture to avoid redundant GL calls. However a few other places in Cogl and @@ -1474,3 +1492,44 @@ cogl_set_source_texture (CoglHandle texture_handle) cogl_set_source (ctx->default_material); } +CoglMaterialFilter +cogl_material_layer_get_min_filter (CoglHandle layer_handle) +{ + CoglMaterialLayer *layer; + + g_return_val_if_fail (cogl_is_material_layer (layer_handle), 0); + + layer = _cogl_material_layer_pointer_from_handle (layer_handle); + + return layer->min_filter; +} + +CoglMaterialFilter +cogl_material_layer_get_mag_filter (CoglHandle layer_handle) +{ + CoglMaterialLayer *layer; + + g_return_val_if_fail (cogl_is_material_layer (layer_handle), 0); + + layer = _cogl_material_layer_pointer_from_handle (layer_handle); + + return layer->mag_filter; +} + +void +cogl_material_set_layer_filters (CoglHandle handle, + gint layer_index, + CoglMaterialFilter min_filter, + CoglMaterialFilter mag_filter) +{ + CoglMaterial *material; + CoglMaterialLayer *layer; + + g_return_if_fail (cogl_is_material (handle)); + + material = _cogl_material_pointer_from_handle (handle); + layer = _cogl_material_get_layer (material, layer_index, TRUE); + + layer->min_filter = min_filter; + layer->mag_filter = mag_filter; +} diff --git a/clutter/cogl/common/cogl-primitives.c b/clutter/cogl/common/cogl-primitives.c index c43fbde49..03fe43180 100644 --- a/clutter/cogl/common/cogl-primitives.c +++ b/clutter/cogl/common/cogl-primitives.c @@ -1186,7 +1186,8 @@ cogl_polygon (CoglTextureVertex *vertices, use_sliced_polygon_fallback = TRUE; n_layers = 1; - if (tex->min_filter != GL_NEAREST || tex->mag_filter != GL_NEAREST) + if (cogl_material_layer_get_min_filter (layer) != GL_NEAREST + || cogl_material_layer_get_mag_filter (layer) != GL_NEAREST) { static gboolean warning_seen = FALSE; if (!warning_seen) diff --git a/clutter/cogl/gl/cogl-context.h b/clutter/cogl/gl/cogl-context.h index 3db4c0e9e..d845a6c12 100644 --- a/clutter/cogl/gl/cogl-context.h +++ b/clutter/cogl/gl/cogl-context.h @@ -120,6 +120,7 @@ typedef struct COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC pf_glDeleteFramebuffersEXT; COGL_PFNGLBLITFRAMEBUFFEREXTPROC pf_glBlitFramebufferEXT; COGL_PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC pf_glRenderbufferStorageMultisampleEXT; + COGL_PFNGLGENERATEMIPMAPEXTPROC pf_glGenerateMipmapEXT; COGL_PFNGLCREATEPROGRAMOBJECTARBPROC pf_glCreateProgramObjectARB; COGL_PFNGLCREATESHADEROBJECTARBPROC pf_glCreateShaderObjectARB; diff --git a/clutter/cogl/gl/cogl-defines.h.in b/clutter/cogl/gl/cogl-defines.h.in index 4805ea5b3..025b4cad0 100644 --- a/clutter/cogl/gl/cogl-defines.h.in +++ b/clutter/cogl/gl/cogl-defines.h.in @@ -773,6 +773,10 @@ typedef void GLsizei width, GLsizei height); +typedef void + (APIENTRYP COGL_PFNGLGENERATEMIPMAPEXTPROC) + (GLenum target); + typedef GLhandleARB (APIENTRYP COGL_PFNGLCREATEPROGRAMOBJECTARBPROC) (void); diff --git a/clutter/cogl/gl/cogl-texture-private.h b/clutter/cogl/gl/cogl-texture-private.h index 7cf6fe951..365a47921 100644 --- a/clutter/cogl/gl/cogl-texture-private.h +++ b/clutter/cogl/gl/cogl-texture-private.h @@ -30,6 +30,7 @@ typedef struct _CoglTexture CoglTexture; typedef struct _CoglTexSliceSpan CoglTexSliceSpan; typedef struct _CoglSpanIter CoglSpanIter; +typedef struct _CoglTexturePixel CoglTexturePixel; struct _CoglTexSliceSpan { @@ -55,6 +56,18 @@ struct _CoglSpanIter gboolean intersects; }; +/* This is used to store the first pixel of each slice. This is only + used when glGenerateMipmap is not available */ +struct _CoglTexturePixel +{ + /* We need to store the format of the pixel because we store the + data in the source format which might end up being different for + each slice if a subregion is updated with a different format */ + GLenum gl_format; + GLenum gl_type; + guint8 data[4]; +}; + struct _CoglTexture { CoglHandleObject _parent; @@ -68,11 +81,17 @@ struct _CoglTexture GArray *slice_y_spans; GArray *slice_gl_handles; gint max_waste; - CoglTextureFilter min_filter; - CoglTextureFilter mag_filter; + GLenum min_filter; + GLenum mag_filter; gboolean is_foreign; GLint wrap_mode; gboolean auto_mipmap; + gboolean mipmaps_dirty; + + /* This holds a copy of the first pixel in each slice. It is only + used to force an automatic update of the mipmaps when + glGenerateMipmap is not available. */ + CoglTexturePixel *first_pixels; }; /* To improve batching of geometry when submitting vertices to OpenGL we @@ -93,6 +112,14 @@ void _cogl_texture_set_wrap_mode_parameter (CoglTexture *tex, GLenum wrap_mode); +void +_cogl_texture_set_filters (CoglHandle handle, + GLenum min_filter, + GLenum mag_filter); + +void +_cogl_texture_ensure_mipmaps (CoglHandle handle); + gboolean _cogl_texture_span_has_waste (CoglTexture *tex, gint x_span_index, diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c index 80e428eba..e2c6c264f 100644 --- a/clutter/cogl/gl/cogl-texture.c +++ b/clutter/cogl/gl/cogl-texture.c @@ -49,6 +49,7 @@ #define glDrawRangeElements ctx->pf_glDrawRangeElements #define glActiveTexture ctx->pf_glActiveTexture #define glClientActiveTexture ctx->pf_glClientActiveTexture +#define glGenerateMipmap ctx->pf_glGenerateMipmapEXT #else @@ -247,11 +248,12 @@ _cogl_texture_upload_to_gl (CoglTexture *tex) /* Iterate horizontal slices */ for (x = 0; x < tex->slice_x_spans->len; ++x) { + gint slice_num = y * tex->slice_x_spans->len + x; + x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x); /* Pick the gl texture object handle */ - gl_handle = g_array_index (tex->slice_gl_handles, GLuint, - y * tex->slice_x_spans->len + x); + gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num); /* Setup gl alignment to match rowstride and top-left corner */ prep_for_gl_pixels_upload (tex->bitmap.rowstride, @@ -259,6 +261,17 @@ _cogl_texture_upload_to_gl (CoglTexture *tex) y_span->start, bpp); + /* Keep a copy of the first pixel if needed */ + if (tex->first_pixels) + { + memcpy (tex->first_pixels[slice_num].data, + tex->bitmap.data + x_span->start * bpp + + y_span->start * tex->bitmap.rowstride, + bpp); + tex->first_pixels[slice_num].gl_format = tex->gl_format; + tex->first_pixels[slice_num].gl_type = tex->gl_type; + } + /* Upload new image data */ GE( glBindTexture (tex->gl_target, gl_handle) ); @@ -343,6 +356,8 @@ _cogl_texture_upload_to_gl (CoglTexture *tex) if (waste_buf) g_free (waste_buf); + tex->mipmaps_dirty = TRUE; + return TRUE; } @@ -494,6 +509,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, _cogl_span_iter_next (&x_iter), source_x += inter_w ) { + gint slice_num; + /* Discard slices out of the subregion early */ if (!x_iter.intersects) { @@ -516,10 +533,10 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, local_y = (y_iter.intersect_start - y_iter.pos); + slice_num = y_iter.index * tex->slice_x_spans->len + x_iter.index; + /* Pick slice GL handle */ - gl_handle = g_array_index (tex->slice_gl_handles, GLuint, - y_iter.index * tex->slice_x_spans->len + - x_iter.index); + gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num); /* Setup gl alignment to match rowstride and top-left corner */ prep_for_gl_pixels_upload (source_bmp->rowstride, @@ -527,6 +544,17 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, source_y, bpp); + /* Keep a copy of the first pixel if needed */ + if (tex->first_pixels && local_x == 0 && local_y == 0) + { + memcpy (tex->first_pixels[slice_num].data, + source_bmp->data + source_x * bpp + + source_y * source_bmp->rowstride, + bpp); + tex->first_pixels[slice_num].gl_format = source_gl_format; + tex->first_pixels[slice_num].gl_type = source_gl_type; + } + /* Upload new image data */ GE( glBindTexture (tex->gl_target, gl_handle) ); @@ -640,6 +668,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, if (waste_buf) g_free (waste_buf); + tex->mipmaps_dirty = TRUE; + return TRUE; } @@ -913,6 +943,14 @@ _cogl_texture_slices_create (CoglTexture *tex) g_array_set_size (tex->slice_gl_handles, n_slices); + /* Allocate some space to store a copy of the first pixel of each + slice. This is only needed to glGenerateMipmap (which is part of + the FBO extension) is not available */ + if (cogl_features_available (COGL_FEATURE_OFFSCREEN)) + tex->first_pixels = NULL; + else + tex->first_pixels = g_new (CoglTexturePixel, n_slices); + /* Wrap mode not yet set */ tex->wrap_mode = GL_FALSE; @@ -941,14 +979,6 @@ _cogl_texture_slices_create (CoglTexture *tex) /* Setup texture parameters */ GE( glBindTexture (tex->gl_target, gl_handles[y * n_x_slices + x]) ); - GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER, - tex->mag_filter) ); - GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER, - tex->min_filter) ); - - if (tex->auto_mipmap) - GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, - GL_TRUE) ); /* Use a transparent border color so that we can leave the color buffer alone when using texture co-ordinates @@ -985,6 +1015,9 @@ _cogl_texture_slices_free (CoglTexture *tex) g_array_free (tex->slice_gl_handles, TRUE); } + + if (tex->first_pixels != NULL) + g_free (tex->first_pixels); } gboolean @@ -1221,7 +1254,8 @@ cogl_texture_new_with_size (guint width, tex = (CoglTexture*) g_malloc (sizeof (CoglTexture)); tex->is_foreign = FALSE; - tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0); + tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0; + tex->mipmaps_dirty = TRUE; tex->bitmap.width = width; tex->bitmap.height = height; @@ -1239,8 +1273,9 @@ cogl_texture_new_with_size (guint width, else tex->max_waste = COGL_TEXTURE_MAX_WASTE; - tex->min_filter = COGL_TEXTURE_FILTER_NEAREST; - tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST; + /* Unknown filter */ + tex->min_filter = GL_FALSE; + tex->mag_filter = GL_FALSE; /* Find closest GL format match */ tex->bitmap.format = @@ -1285,7 +1320,8 @@ cogl_texture_new_from_data (guint width, tex = (CoglTexture*) g_malloc (sizeof (CoglTexture)); tex->is_foreign = FALSE; - tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0); + tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0; + tex->mipmaps_dirty = TRUE; tex->bitmap.width = width; tex->bitmap.height = height; @@ -1303,8 +1339,9 @@ cogl_texture_new_from_data (guint width, else tex->max_waste = COGL_TEXTURE_MAX_WASTE; - tex->min_filter = COGL_TEXTURE_FILTER_NEAREST; - tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST; + /* Unknown filter */ + tex->min_filter = GL_FALSE; + tex->mag_filter = GL_FALSE; /* FIXME: If upload fails we should set some kind of * error flag but still return texture handle (this @@ -1348,7 +1385,8 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle, tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture)); tex->is_foreign = FALSE; - tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0); + tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0; + tex->mipmaps_dirty = TRUE; tex->bitmap = *bmp; tex->bitmap_owner = TRUE; @@ -1363,8 +1401,9 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle, else tex->max_waste = COGL_TEXTURE_MAX_WASTE; - tex->min_filter = COGL_TEXTURE_FILTER_NEAREST; - tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST; + /* Unknown filter */ + tex->min_filter = GL_FALSE; + tex->mag_filter = GL_FALSE; /* FIXME: If upload fails we should set some kind of * error flag but still return texture handle if the @@ -1440,8 +1479,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle, GLint gl_int_format = 0; GLint gl_width = 0; GLint gl_height = 0; - GLint gl_min_filter; - GLint gl_mag_filter; GLint gl_gen_mipmap; guint bpp; CoglTexture *tex; @@ -1489,14 +1526,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle, GL_TEXTURE_HEIGHT, &gl_height) ); - GE( glGetTexParameteriv (gl_target, - GL_TEXTURE_MIN_FILTER, - &gl_min_filter) ); - - GE( glGetTexParameteriv (gl_target, - GL_TEXTURE_MAG_FILTER, - &gl_mag_filter) ); - GE( glGetTexParameteriv (gl_target, GL_GENERATE_MIPMAP, &gl_gen_mipmap) ); @@ -1524,6 +1553,7 @@ cogl_texture_new_from_foreign (GLuint gl_handle, /* Setup bitmap info */ tex->is_foreign = TRUE; tex->auto_mipmap = (gl_gen_mipmap == GL_TRUE) ? TRUE : FALSE; + tex->mipmaps_dirty = TRUE; bpp = _cogl_get_format_bpp (format); tex->bitmap.format = format; @@ -1537,8 +1567,9 @@ cogl_texture_new_from_foreign (GLuint gl_handle, tex->gl_format = gl_int_format; tex->gl_type = GL_UNSIGNED_BYTE; - tex->min_filter = gl_min_filter; - tex->mag_filter = gl_mag_filter; + /* Unknown filter */ + tex->min_filter = GL_FALSE; + tex->mag_filter = GL_FALSE; tex->max_waste = 0; /* Wrap mode not yet set */ @@ -1684,36 +1715,10 @@ cogl_texture_get_gl_texture (CoglHandle handle, return TRUE; } -CoglTextureFilter -cogl_texture_get_min_filter (CoglHandle handle) -{ - CoglTexture *tex; - - if (!cogl_is_texture (handle)) - return 0; - - tex = _cogl_texture_pointer_from_handle (handle); - - return tex->min_filter; -} - -CoglTextureFilter -cogl_texture_get_mag_filter (CoglHandle handle) -{ - CoglTexture *tex; - - if (!cogl_is_texture (handle)) - return 0; - - tex = _cogl_texture_pointer_from_handle (handle); - - return tex->mag_filter; -} - void -cogl_texture_set_filters (CoglHandle handle, - CoglTextureFilter min_filter, - CoglTextureFilter mag_filter) +_cogl_texture_set_filters (CoglHandle handle, + GLenum min_filter, + GLenum mag_filter) { CoglTexture *tex; GLuint gl_handle; @@ -1724,14 +1729,18 @@ cogl_texture_set_filters (CoglHandle handle, tex = _cogl_texture_pointer_from_handle (handle); - /* Store new values */ - tex->min_filter = min_filter; - tex->mag_filter = mag_filter; - /* Make sure slices were created */ if (tex->slice_gl_handles == NULL) return; + if (min_filter == tex->min_filter + && mag_filter == tex->mag_filter) + return; + + /* Store new values */ + tex->min_filter = min_filter; + tex->mag_filter = mag_filter; + /* Apply new filters to every slice */ for (i=0; islice_gl_handles->len; ++i) { @@ -1744,6 +1753,52 @@ cogl_texture_set_filters (CoglHandle handle, } } +void +_cogl_texture_ensure_mipmaps (CoglHandle handle) +{ + CoglTexture *tex; + int i; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!cogl_is_texture (handle)) + return; + + tex = _cogl_texture_pointer_from_handle (handle); + + /* Only update if the mipmaps are dirty */ + if (!tex->auto_mipmap || !tex->mipmaps_dirty) + return; + + /* Make sure slices were created */ + if (tex->slice_gl_handles == NULL) + return; + + /* Regenerate the mipmaps on every slice */ + for (i = 0; i < tex->slice_gl_handles->len; i++) + { + GLuint gl_handle = g_array_index (tex->slice_gl_handles, GLuint, i); + GE( glBindTexture (tex->gl_target, gl_handle) ); + + /* glGenerateMipmap is defined in the FBO extension */ + if (cogl_features_available (COGL_FEATURE_OFFSCREEN)) + GE( glGenerateMipmap (tex->gl_target) ); + else + { + CoglTexturePixel *pixel = tex->first_pixels + i; + /* Temporarily enable automatic mipmap generation and + re-upload the first pixel to cause a regeneration */ + GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_TRUE) ); + GE( glTexSubImage2D (tex->gl_target, 0, 0, 0, 1, 1, + pixel->gl_format, pixel->gl_type, + pixel->data) ); + GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_FALSE) ); + } + } + + tex->mipmaps_dirty = FALSE; +} + gboolean cogl_texture_set_region (CoglHandle handle, gint src_x, diff --git a/clutter/cogl/gl/cogl.c b/clutter/cogl/gl/cogl.c index 608bc364e..748c082ac 100644 --- a/clutter/cogl/gl/cogl.c +++ b/clutter/cogl/gl/cogl.c @@ -399,6 +399,10 @@ _cogl_features_init (void) (COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC) cogl_get_proc_address ("glDeleteFramebuffersEXT"); + ctx->pf_glGenerateMipmapEXT = + (COGL_PFNGLGENERATEMIPMAPEXTPROC) + cogl_get_proc_address ("glGenerateMipmapEXT"); + if (ctx->pf_glGenRenderbuffersEXT && ctx->pf_glBindRenderbufferEXT && ctx->pf_glRenderbufferStorageEXT && @@ -407,7 +411,8 @@ _cogl_features_init (void) ctx->pf_glFramebufferTexture2DEXT && ctx->pf_glFramebufferRenderbufferEXT && ctx->pf_glCheckFramebufferStatusEXT && - ctx->pf_glDeleteFramebuffersEXT) + ctx->pf_glDeleteFramebuffersEXT && + ctx->pf_glGenerateMipmapEXT) flags |= COGL_FEATURE_OFFSCREEN; } diff --git a/clutter/glx/clutter-glx-texture-pixmap.c b/clutter/glx/clutter-glx-texture-pixmap.c index b6a677a84..366643021 100644 --- a/clutter/glx/clutter-glx-texture-pixmap.c +++ b/clutter/glx/clutter-glx-texture-pixmap.c @@ -135,14 +135,6 @@ texture_bind (ClutterGLXTexturePixmap *tex) /* FIXME: fire off an error here? */ glBindTexture (target, handle); - if (clutter_texture_get_filter_quality (CLUTTER_TEXTURE (tex)) - == CLUTTER_TEXTURE_QUALITY_HIGH && tex->priv->can_mipmap) - { - cogl_texture_set_filters (cogl_tex, - COGL_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR, - COGL_TEXTURE_FILTER_LINEAR); - } - return TRUE; } @@ -167,6 +159,18 @@ on_glx_texture_pixmap_pre_paint (ClutterGLXTexturePixmap *texture, texture->priv->mipmap_generate_queued = 0; } + /* Disable mipmaps if we can't support them */ + if (clutter_texture_get_filter_quality (CLUTTER_TEXTURE (texture)) + == CLUTTER_TEXTURE_QUALITY_HIGH + && !texture->priv->can_mipmap) + { + CoglHandle material + = clutter_texture_get_cogl_material (CLUTTER_TEXTURE (texture)); + + cogl_material_set_layer_filters (material, 0, + COGL_MATERIAL_FILTER_LINEAR, + COGL_MATERIAL_FILTER_LINEAR); + } } static void diff --git a/clutter/pango/cogl-pango-glyph-cache.c b/clutter/pango/cogl-pango-glyph-cache.c index 9be1e83b8..df26f672f 100644 --- a/clutter/pango/cogl-pango-glyph-cache.c +++ b/clutter/pango/cogl-pango-glyph-cache.c @@ -51,10 +51,6 @@ struct _CoglPangoGlyphCache /* List of horizontal bands of glyphs */ CoglPangoGlyphCacheBand *bands; - - /* If TRUE all of the textures will be created with automatic mipmap - generation enabled */ - gboolean use_mipmapping; }; struct _CoglPangoGlyphCacheKey @@ -177,7 +173,7 @@ cogl_pango_glyph_cache_free_bands (CoglPangoGlyphCacheBand *node) } CoglPangoGlyphCache * -cogl_pango_glyph_cache_new (gboolean use_mipmapping) +cogl_pango_glyph_cache_new (void) { CoglPangoGlyphCache *cache; @@ -191,7 +187,6 @@ cogl_pango_glyph_cache_new (gboolean use_mipmapping) cache->textures = NULL; cache->bands = NULL; - cache->use_mipmapping = use_mipmapping; return cache; } @@ -272,7 +267,6 @@ cogl_pango_glyph_cache_set (CoglPangoGlyphCache *cache, texture = texture->next); if (texture == NULL) { - CoglTextureFlags flags = COGL_TEXTURE_NONE; guchar *clear_data; /* Allocate a new texture that is the nearest power of two @@ -291,13 +285,10 @@ cogl_pango_glyph_cache_set (CoglPangoGlyphCache *cache, clear_data = g_malloc0 (texture->texture_size * texture->texture_size); - if (cache->use_mipmapping) - flags |= COGL_TEXTURE_AUTO_MIPMAP; - texture->texture = cogl_texture_new_from_data (texture->texture_size, texture->texture_size, - flags, + COGL_TEXTURE_NONE, COGL_PIXEL_FORMAT_A_8, COGL_PIXEL_FORMAT_A_8, texture->texture_size, @@ -308,15 +299,6 @@ cogl_pango_glyph_cache_set (CoglPangoGlyphCache *cache, texture->space_remaining = texture->texture_size; texture->next = cache->textures; cache->textures = texture; - - if (cache->use_mipmapping) - cogl_texture_set_filters (texture->texture, - COGL_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR, - COGL_TEXTURE_FILTER_LINEAR); - else - cogl_texture_set_filters (texture->texture, - COGL_TEXTURE_FILTER_LINEAR, - COGL_TEXTURE_FILTER_LINEAR); } band = g_slice_new (CoglPangoGlyphCacheBand); diff --git a/clutter/pango/cogl-pango-glyph-cache.h b/clutter/pango/cogl-pango-glyph-cache.h index 33364e1c7..ab5265afa 100644 --- a/clutter/pango/cogl-pango-glyph-cache.h +++ b/clutter/pango/cogl-pango-glyph-cache.h @@ -49,7 +49,7 @@ struct _CoglPangoGlyphCacheValue }; CoglPangoGlyphCache * -cogl_pango_glyph_cache_new (gboolean use_mipmapping); +cogl_pango_glyph_cache_new (void); void cogl_pango_glyph_cache_free (CoglPangoGlyphCache *cache); diff --git a/clutter/pango/cogl-pango-render.c b/clutter/pango/cogl-pango-render.c index 898c11ee3..89c89c481 100644 --- a/clutter/pango/cogl-pango-render.c +++ b/clutter/pango/cogl-pango-render.c @@ -49,12 +49,8 @@ struct _CoglPangoRenderer /* The material used for solid fills. (boxes, rectangles + trapezoids) */ CoglHandle solid_material; - /* Two caches of glyphs as textures, one with mipmapped textures and - one without */ + /* Caches of glyphs as textures */ CoglPangoGlyphCache *glyph_cache; - CoglPangoGlyphCache *mipmapped_glyph_cache; - - gboolean use_mipmapping; /* The current display list that is being built */ CoglPangoDisplayList *display_list; @@ -144,9 +140,9 @@ cogl_pango_renderer_init (CoglPangoRenderer *priv) priv->solid_material = cogl_material_new (); - priv->glyph_cache = cogl_pango_glyph_cache_new (FALSE); - priv->mipmapped_glyph_cache = cogl_pango_glyph_cache_new (TRUE); - priv->use_mipmapping = FALSE; + priv->glyph_cache = cogl_pango_glyph_cache_new (); + + _cogl_pango_renderer_set_use_mipmapping (priv, FALSE); } static void @@ -167,7 +163,6 @@ cogl_pango_renderer_finalize (GObject *object) { CoglPangoRenderer *priv = COGL_PANGO_RENDERER (object); - cogl_pango_glyph_cache_free (priv->mipmapped_glyph_cache); cogl_pango_glyph_cache_free (priv->glyph_cache); G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->finalize (object); @@ -363,20 +358,31 @@ void _cogl_pango_renderer_clear_glyph_cache (CoglPangoRenderer *renderer) { cogl_pango_glyph_cache_clear (renderer->glyph_cache); - cogl_pango_glyph_cache_clear (renderer->mipmapped_glyph_cache); } void _cogl_pango_renderer_set_use_mipmapping (CoglPangoRenderer *renderer, - gboolean value) + gboolean value) { - renderer->use_mipmapping = value; + if (value) + cogl_material_set_layer_filters (renderer->glyph_material, 0, + COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR, + COGL_MATERIAL_FILTER_LINEAR); + else + cogl_material_set_layer_filters (renderer->glyph_material, 0, + COGL_MATERIAL_FILTER_LINEAR, + COGL_MATERIAL_FILTER_LINEAR); } gboolean _cogl_pango_renderer_get_use_mipmapping (CoglPangoRenderer *renderer) { - return renderer->use_mipmapping; + const GList *layers = cogl_material_get_layers (renderer->glyph_material); + + g_return_val_if_fail (layers != NULL, FALSE); + + return (cogl_material_layer_get_min_filter (layers->data) + == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR); } static CoglPangoGlyphCacheValue * @@ -386,12 +392,8 @@ cogl_pango_renderer_get_cached_glyph (PangoRenderer *renderer, { CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer); CoglPangoGlyphCacheValue *value; - CoglPangoGlyphCache *glyph_cache; - glyph_cache = priv->use_mipmapping ? priv->mipmapped_glyph_cache - : priv->glyph_cache; - - value = cogl_pango_glyph_cache_lookup (glyph_cache, font, glyph); + value = cogl_pango_glyph_cache_lookup (priv->glyph_cache, font, glyph); if (value == NULL) { cairo_surface_t *surface; @@ -423,7 +425,7 @@ cogl_pango_renderer_get_cached_glyph (PangoRenderer *renderer, /* Copy the glyph to the cache */ value = - cogl_pango_glyph_cache_set (glyph_cache, font, glyph, + cogl_pango_glyph_cache_set (priv->glyph_cache, font, glyph, cairo_image_surface_get_data (surface), cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface), diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index f596ee042..872e02d11 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -132,12 +132,9 @@ cogl_texture_get_height cogl_texture_get_format cogl_texture_get_rowstride cogl_texture_get_max_waste -cogl_texture_get_min_filter -cogl_texture_get_mag_filter cogl_texture_is_sliced cogl_texture_get_gl_texture cogl_texture_get_data -cogl_texture_set_filters cogl_texture_set_region @@ -366,8 +363,12 @@ cogl_material_set_layer_combine cogl_material_set_layer_combine_constant cogl_material_set_layer_matrix cogl_material_get_layers +CoglMaterialFilter +cogl_material_set_layer_filters cogl_material_layer_get_type cogl_material_layer_get_texture +cogl_material_layer_get_min_filter +cogl_material_layer_get_mag_filter CoglMaterial CoglMaterialFlags diff --git a/tests/conform/test-backface-culling.c b/tests/conform/test-backface-culling.c index bfddcf105..5d8b7ba62 100644 --- a/tests/conform/test-backface-culling.c +++ b/tests/conform/test-backface-culling.c @@ -107,6 +107,11 @@ on_paint (ClutterActor *actor, TestState *state) { int i; int frame_num; + CoglHandle material = cogl_material_new (); + + cogl_material_set_layer_filters (material, 0, + COGL_MATERIAL_FILTER_NEAREST, + COGL_MATERIAL_FILTER_NEAREST); cogl_set_backface_culling_enabled (TRUE); @@ -120,24 +125,21 @@ on_paint (ClutterActor *actor, TestState *state) float x1 = 0, x2, y1 = 0, y2 = (float)(TEXTURE_RENDER_SIZE); CoglTextureVertex verts[4]; - memset (verts, 0, sizeof (verts)); + cogl_set_source (material); - /* Set the color to white so that all the textures will be drawn - at their own color */ - cogl_set_source_color4f (1.0, 1.0, - 1.0, 1.0); + memset (verts, 0, sizeof (verts)); x2 = x1 + (float)(TEXTURE_RENDER_SIZE); /* Draw a front-facing texture */ - cogl_set_source_texture (state->texture); + cogl_material_set_layer (material, 0, state->texture); cogl_rectangle (x1, y1, x2, y2); x1 = x2; x2 = x1 + (float)(TEXTURE_RENDER_SIZE); /* Draw a back-facing texture */ - cogl_set_source_texture (state->texture); + cogl_material_set_layer (material, 0, state->texture); cogl_rectangle (x2, y1, x1, y2); x1 = x2; @@ -152,7 +154,7 @@ on_paint (ClutterActor *actor, TestState *state) verts[1].tx = 1.0; verts[1].ty = 0; verts[2].tx = 1.0; verts[2].ty = 1.0; verts[3].tx = 0; verts[3].ty = 1.0; - cogl_set_source_texture (state->texture); + cogl_material_set_layer (material, 0, state->texture); cogl_polygon (verts, 4, FALSE); x1 = x2; @@ -167,7 +169,7 @@ on_paint (ClutterActor *actor, TestState *state) verts[1].tx = 1.0; verts[1].ty = 0; verts[2].tx = 1.0; verts[2].ty = 1.0; verts[3].tx = 0; verts[3].ty = 1.0; - cogl_set_source_texture (state->texture); + cogl_material_set_layer (material, 0, state->texture); cogl_polygon (verts, 4, FALSE); x1 = x2; @@ -185,6 +187,8 @@ on_paint (ClutterActor *actor, TestState *state) cogl_pop_matrix (); + cogl_handle_unref (material); + /* XXX: Experiments have shown that for some buggy drivers, when using * glReadPixels there is some kind of race, so we delay our test for a * few frames and a few seconds: diff --git a/tests/interactive/test-cogl-multitexture.c b/tests/interactive/test-cogl-multitexture.c index df7360260..c10182760 100644 --- a/tests/interactive/test-cogl-multitexture.c +++ b/tests/interactive/test-cogl-multitexture.c @@ -87,20 +87,17 @@ test_cogl_multitexture_main (int argc, char *argv[]) state->alpha_tex = cogl_texture_new_from_file ("redhand_alpha.png", - COGL_TEXTURE_NO_SLICING | - COGL_TEXTURE_AUTO_MIPMAP, + COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_ANY, NULL); state->redhand_tex = cogl_texture_new_from_file ("redhand.png", - COGL_TEXTURE_NO_SLICING | - COGL_TEXTURE_AUTO_MIPMAP, + COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_ANY, NULL); state->light_tex0 = cogl_texture_new_from_file ("light0.png", - COGL_TEXTURE_NO_SLICING | - COGL_TEXTURE_AUTO_MIPMAP, + COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_ANY, NULL); diff --git a/tests/interactive/test-cogl-tex-polygon.c b/tests/interactive/test-cogl-tex-polygon.c index b7252b50a..4378a7bd0 100644 --- a/tests/interactive/test-cogl-tex-polygon.c +++ b/tests/interactive/test-cogl-tex-polygon.c @@ -173,14 +173,17 @@ test_coglbox_paint (ClutterActor *self) : priv->not_sliced_tex; int tex_width = cogl_texture_get_width (tex_handle); int tex_height = cogl_texture_get_height (tex_handle); + CoglHandle material = cogl_material_new (); - cogl_texture_set_filters (tex_handle, - priv->use_linear_filtering - ? COGL_TEXTURE_FILTER_LINEAR : - COGL_TEXTURE_FILTER_NEAREST, - priv->use_linear_filtering - ? COGL_TEXTURE_FILTER_LINEAR : - COGL_TEXTURE_FILTER_NEAREST); + cogl_material_set_layer (material, 0, tex_handle); + + cogl_material_set_layer_filters (material, 0, + priv->use_linear_filtering + ? COGL_MATERIAL_FILTER_LINEAR : + COGL_MATERIAL_FILTER_NEAREST, + priv->use_linear_filtering + ? COGL_MATERIAL_FILTER_LINEAR : + COGL_MATERIAL_FILTER_NEAREST); cogl_push_matrix (); cogl_translate (tex_width / 2, 0, 0); @@ -188,7 +191,7 @@ test_coglbox_paint (ClutterActor *self) cogl_translate (-tex_width / 2, 0, 0); /* Draw a hand and refect it */ - cogl_set_source_texture (tex_handle); + cogl_set_source (material); cogl_rectangle_with_texture_coords (0, 0, tex_width, tex_height, 0, 0, 1, 1); test_coglbox_fade_texture (tex_handle, @@ -217,6 +220,8 @@ test_coglbox_paint (ClutterActor *self) 1, 1); cogl_pop_matrix (); + + cogl_handle_unref (material); } static void diff --git a/tests/interactive/test-cogl-tex-tile.c b/tests/interactive/test-cogl-tex-tile.c index 07f395db6..2c700b533 100644 --- a/tests/interactive/test-cogl-tex-tile.c +++ b/tests/interactive/test-cogl-tex-tile.c @@ -147,10 +147,6 @@ test_coglbox_init (TestCoglbox *self) COGL_TEXTURE_NONE, COGL_PIXEL_FORMAT_ANY, NULL); - - cogl_texture_set_filters (priv->cogl_tex_id, - COGL_TEXTURE_FILTER_LINEAR, - COGL_TEXTURE_FILTER_LINEAR); } static void