Compare commits
	
		
			1 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					2b8e75ad48 | 
@@ -65,8 +65,6 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	compositor/meta-shaped-texture.c	\
 | 
			
		||||
	compositor/meta-texture-rectangle.c	\
 | 
			
		||||
	compositor/meta-texture-rectangle.h	\
 | 
			
		||||
	compositor/meta-texture-tower.c		\
 | 
			
		||||
	compositor/meta-texture-tower.h		\
 | 
			
		||||
	compositor/meta-window-actor.c		\
 | 
			
		||||
	compositor/meta-window-actor-private.h	\
 | 
			
		||||
	compositor/meta-window-group.c		\
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
Intro
 | 
			
		||||
=====
 | 
			
		||||
 | 
			
		||||
Fix me.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Env Vars
 | 
			
		||||
========
 | 
			
		||||
 | 
			
		||||
MUTTER_DISABLE_MIPMAPS - set to disable use of mipmaped windows.
 | 
			
		||||
@@ -31,7 +31,6 @@ struct _MetaCompositor
 | 
			
		||||
  guint           server_time_is_monotonic_time : 1;
 | 
			
		||||
  guint           show_redraw : 1;
 | 
			
		||||
  guint           debug       : 1;
 | 
			
		||||
  guint           no_mipmaps  : 1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaCompScreen
 | 
			
		||||
 
 | 
			
		||||
@@ -1532,9 +1532,6 @@ meta_compositor_new (MetaDisplay *display)
 | 
			
		||||
 | 
			
		||||
  compositor->display = display;
 | 
			
		||||
 | 
			
		||||
  if (g_getenv("META_DISABLE_MIPMAPS"))
 | 
			
		||||
    compositor->no_mipmaps = TRUE;
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
 | 
			
		||||
  XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
 | 
			
		||||
                False, atoms);
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,6 @@
 | 
			
		||||
#include <config.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/meta-shaped-texture.h>
 | 
			
		||||
#include "meta-texture-tower.h"
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <cogl/cogl.h>
 | 
			
		||||
@@ -64,7 +63,6 @@ G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
 | 
			
		||||
 | 
			
		||||
struct _MetaShapedTexturePrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaTextureTower *paint_tower;
 | 
			
		||||
  Pixmap pixmap;
 | 
			
		||||
  CoglTexturePixmapX11 *texture;
 | 
			
		||||
  CoglTexture *mask_texture;
 | 
			
		||||
@@ -74,8 +72,6 @@ struct _MetaShapedTexturePrivate
 | 
			
		||||
  cairo_region_t *clip_region;
 | 
			
		||||
 | 
			
		||||
  guint tex_width, tex_height;
 | 
			
		||||
 | 
			
		||||
  guint create_mipmaps : 1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -102,10 +98,8 @@ meta_shaped_texture_init (MetaShapedTexture *self)
 | 
			
		||||
 | 
			
		||||
  priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self);
 | 
			
		||||
 | 
			
		||||
  priv->paint_tower = meta_texture_tower_new ();
 | 
			
		||||
  priv->texture = NULL;
 | 
			
		||||
  priv->mask_texture = NULL;
 | 
			
		||||
  priv->create_mipmaps = TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -114,10 +108,6 @@ meta_shaped_texture_dispose (GObject *object)
 | 
			
		||||
  MetaShapedTexture *self = (MetaShapedTexture *) object;
 | 
			
		||||
  MetaShapedTexturePrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  if (priv->paint_tower)
 | 
			
		||||
    meta_texture_tower_free (priv->paint_tower);
 | 
			
		||||
  priv->paint_tower = NULL;
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer (&priv->pipeline, cogl_object_unref);
 | 
			
		||||
  g_clear_pointer (&priv->pipeline_unshaped, cogl_object_unref);
 | 
			
		||||
  g_clear_pointer (&priv->texture, cogl_object_unref);
 | 
			
		||||
@@ -133,7 +123,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
 | 
			
		||||
{
 | 
			
		||||
  MetaShapedTexture *stex = (MetaShapedTexture *) actor;
 | 
			
		||||
  MetaShapedTexturePrivate *priv = stex->priv;
 | 
			
		||||
  CoglTexture *paint_tex;
 | 
			
		||||
  guint tex_width, tex_height;
 | 
			
		||||
  ClutterActorBox alloc;
 | 
			
		||||
 | 
			
		||||
@@ -148,29 +137,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
 | 
			
		||||
  if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
 | 
			
		||||
    clutter_actor_realize (CLUTTER_ACTOR (stex));
 | 
			
		||||
 | 
			
		||||
  /* The GL EXT_texture_from_pixmap extension does allow for it to be
 | 
			
		||||
   * used together with SGIS_generate_mipmap, however this is very
 | 
			
		||||
   * rarely supported. Also, even when it is supported there
 | 
			
		||||
   * are distinct performance implications from:
 | 
			
		||||
   *
 | 
			
		||||
   *  - Updating mipmaps that we don't need
 | 
			
		||||
   *  - Having to reallocate pixmaps on the server into larger buffers
 | 
			
		||||
   *
 | 
			
		||||
   * So, we just unconditionally use our mipmap emulation code. If we
 | 
			
		||||
   * wanted to use SGIS_generate_mipmap, we'd have to  query COGL to
 | 
			
		||||
   * see if it was supported (no API currently), and then if and only
 | 
			
		||||
   * if that was the case, set the clutter texture quality to HIGH.
 | 
			
		||||
   * Setting the texture quality to high without SGIS_generate_mipmap
 | 
			
		||||
   * support for TFP textures will result in fallbacks to XGetImage.
 | 
			
		||||
   */
 | 
			
		||||
  if (priv->create_mipmaps)
 | 
			
		||||
    paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
 | 
			
		||||
  else
 | 
			
		||||
    paint_tex = COGL_TEXTURE (priv->texture);
 | 
			
		||||
 | 
			
		||||
  if (paint_tex == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  tex_width = priv->tex_width;
 | 
			
		||||
  tex_height = priv->tex_height;
 | 
			
		||||
 | 
			
		||||
@@ -212,7 +178,10 @@ meta_shaped_texture_paint (ClutterActor *actor)
 | 
			
		||||
      cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  cogl_pipeline_set_layer_texture (pipeline, 0, paint_tex);
 | 
			
		||||
  cogl_pipeline_set_layer_filters (pipeline, 0,
 | 
			
		||||
                                   COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR,
 | 
			
		||||
                                   COGL_PIPELINE_FILTER_LINEAR);
 | 
			
		||||
  cogl_pipeline_set_layer_texture (pipeline, 0, priv->texture);
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    CoglColor color;
 | 
			
		||||
@@ -373,28 +342,6 @@ meta_shaped_texture_new (void)
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
 | 
			
		||||
					gboolean           create_mipmaps)
 | 
			
		||||
{
 | 
			
		||||
  MetaShapedTexturePrivate *priv;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
 | 
			
		||||
 | 
			
		||||
  priv = stex->priv;
 | 
			
		||||
 | 
			
		||||
  create_mipmaps = create_mipmaps != FALSE;
 | 
			
		||||
 | 
			
		||||
  if (create_mipmaps != priv->create_mipmaps)
 | 
			
		||||
    {
 | 
			
		||||
      CoglTexture *base_texture;
 | 
			
		||||
      priv->create_mipmaps = create_mipmaps;
 | 
			
		||||
      base_texture = create_mipmaps ?
 | 
			
		||||
        COGL_TEXTURE (priv->texture) : NULL;
 | 
			
		||||
      meta_texture_tower_set_base_texture (priv->paint_tower, base_texture);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
 | 
			
		||||
                                      CoglTexture       *mask_texture)
 | 
			
		||||
@@ -434,8 +381,6 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
 | 
			
		||||
  cogl_texture_pixmap_x11_update_area (priv->texture,
 | 
			
		||||
                                       x, y, width, height);
 | 
			
		||||
 | 
			
		||||
  meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -514,10 +459,6 @@ meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    set_cogl_texture (stex, NULL);
 | 
			
		||||
 | 
			
		||||
  if (priv->create_mipmaps)
 | 
			
		||||
    meta_texture_tower_set_base_texture (priv->paint_tower,
 | 
			
		||||
                                         COGL_TEXTURE (priv->texture));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -1,624 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * MetaTextureTower
 | 
			
		||||
 *
 | 
			
		||||
 * Mipmap emulation by creation of scaled down images
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2009 Red Hat, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-texture-tower.h"
 | 
			
		||||
#include "meta-texture-rectangle.h"
 | 
			
		||||
 | 
			
		||||
#ifndef M_LOG2E
 | 
			
		||||
#define M_LOG2E 1.4426950408889634074
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MAX_TEXTURE_LEVELS 12
 | 
			
		||||
 | 
			
		||||
/* If the texture format in memory doesn't match this, then Mesa
 | 
			
		||||
 * will do the conversion, so things will still work, but it might
 | 
			
		||||
 * be slow depending on how efficient Mesa is. These should be the
 | 
			
		||||
 * native formats unless the display is 16bpp. If conversions
 | 
			
		||||
 * here are a bottleneck, investigate whether we are converting when
 | 
			
		||||
 * storing window data *into* the texture before adding extra code
 | 
			
		||||
 * to handle multiple texture formats.
 | 
			
		||||
 */
 | 
			
		||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
 | 
			
		||||
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_BGRA_8888_PRE
 | 
			
		||||
#else
 | 
			
		||||
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_ARGB_8888_PRE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  guint16 x1;
 | 
			
		||||
  guint16 y1;
 | 
			
		||||
  guint16 x2;
 | 
			
		||||
  guint16 y2;
 | 
			
		||||
} Box;
 | 
			
		||||
 | 
			
		||||
struct _MetaTextureTower
 | 
			
		||||
{
 | 
			
		||||
  int n_levels;
 | 
			
		||||
  CoglTexture *textures[MAX_TEXTURE_LEVELS];
 | 
			
		||||
  CoglOffscreen *fbos[MAX_TEXTURE_LEVELS];
 | 
			
		||||
  Box invalid[MAX_TEXTURE_LEVELS];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_texture_tower_new:
 | 
			
		||||
 *
 | 
			
		||||
 * Creates a new texture tower. The base texture has to be set with
 | 
			
		||||
 * meta_texture_tower_set_base_texture() before use.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: the new texture tower. Free with meta_texture_tower_free()
 | 
			
		||||
 */
 | 
			
		||||
MetaTextureTower *
 | 
			
		||||
meta_texture_tower_new (void)
 | 
			
		||||
{
 | 
			
		||||
  MetaTextureTower *tower;
 | 
			
		||||
 | 
			
		||||
  tower = g_slice_new0 (MetaTextureTower);
 | 
			
		||||
 | 
			
		||||
  return tower;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_texture_tower_free:
 | 
			
		||||
 * @tower: a #MetaTextureTower
 | 
			
		||||
 *
 | 
			
		||||
 * Frees a texture tower created with meta_texture_tower_new().
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
meta_texture_tower_free (MetaTextureTower *tower)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (tower != NULL);
 | 
			
		||||
 | 
			
		||||
  meta_texture_tower_set_base_texture (tower, NULL);
 | 
			
		||||
 | 
			
		||||
  g_slice_free (MetaTextureTower, tower);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_texture_tower_set_base_texture:
 | 
			
		||||
 * @tower: a #MetaTextureTower
 | 
			
		||||
 * @texture: the new texture used as a base for scaled down versions
 | 
			
		||||
 *
 | 
			
		||||
 * Sets the base texture that is the scaled texture that the
 | 
			
		||||
 * scaled textures of the tower are derived from. The texture itself
 | 
			
		||||
 * will be used as level 0 of the tower and will be referenced until
 | 
			
		||||
 * unset or until the tower is freed.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
meta_texture_tower_set_base_texture (MetaTextureTower *tower,
 | 
			
		||||
                                     CoglTexture      *texture)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (tower != NULL);
 | 
			
		||||
 | 
			
		||||
  if (texture == tower->textures[0])
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (tower->textures[0] != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      for (i = 1; i < tower->n_levels; i++)
 | 
			
		||||
        {
 | 
			
		||||
          if (tower->textures[i] != NULL)
 | 
			
		||||
            {
 | 
			
		||||
              cogl_object_unref (tower->textures[i]);
 | 
			
		||||
              tower->textures[i] = NULL;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          if (tower->fbos[i] != NULL)
 | 
			
		||||
            {
 | 
			
		||||
              cogl_object_unref (tower->fbos[i]);
 | 
			
		||||
              tower->fbos[i] = NULL;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      cogl_object_unref (tower->textures[0]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  tower->textures[0] = texture;
 | 
			
		||||
 | 
			
		||||
  if (tower->textures[0] != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      int width, height;
 | 
			
		||||
 | 
			
		||||
      cogl_object_ref (tower->textures[0]);
 | 
			
		||||
 | 
			
		||||
      width = cogl_texture_get_width (tower->textures[0]);
 | 
			
		||||
      height = cogl_texture_get_height (tower->textures[0]);
 | 
			
		||||
 | 
			
		||||
      tower->n_levels = 1 + MAX ((int)(M_LOG2E * log (width)), (int)(M_LOG2E * log (height)));
 | 
			
		||||
      tower->n_levels = MIN(tower->n_levels, MAX_TEXTURE_LEVELS);
 | 
			
		||||
 | 
			
		||||
      meta_texture_tower_update_area (tower, 0, 0, width, height);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      tower->n_levels = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_texture_tower_update_area:
 | 
			
		||||
 * @tower: a #MetaTextureTower
 | 
			
		||||
 * @x: X coordinate of upper left of rectangle that changed
 | 
			
		||||
 * @y: Y coordinate of upper left of rectangle that changed
 | 
			
		||||
 * @width: width of rectangle that changed
 | 
			
		||||
 * @height: height rectangle that changed
 | 
			
		||||
 *
 | 
			
		||||
 * Mark a region of the base texture as having changed; the next
 | 
			
		||||
 * time a scaled down version of the base texture is retrieved,
 | 
			
		||||
 * the appropriate area of the scaled down texture will be updated.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
meta_texture_tower_update_area (MetaTextureTower *tower,
 | 
			
		||||
                                int               x,
 | 
			
		||||
                                int               y,
 | 
			
		||||
                                int               width,
 | 
			
		||||
                                int               height)
 | 
			
		||||
{
 | 
			
		||||
  int texture_width, texture_height;
 | 
			
		||||
  Box invalid;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (tower != NULL);
 | 
			
		||||
 | 
			
		||||
  if (tower->textures[0] == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  texture_width = cogl_texture_get_width (tower->textures[0]);
 | 
			
		||||
  texture_height = cogl_texture_get_height (tower->textures[0]);
 | 
			
		||||
 | 
			
		||||
  invalid.x1 = x;
 | 
			
		||||
  invalid.y1 = y;
 | 
			
		||||
  invalid.x2 = x + width;
 | 
			
		||||
  invalid.y2 = y + height;
 | 
			
		||||
 | 
			
		||||
  for (i = 1; i < tower->n_levels; i++)
 | 
			
		||||
    {
 | 
			
		||||
      texture_width = MAX (1, texture_width / 2);
 | 
			
		||||
      texture_height = MAX (1, texture_height / 2);
 | 
			
		||||
 | 
			
		||||
      invalid.x1 = invalid.x1 / 2;
 | 
			
		||||
      invalid.y1 = invalid.y1 / 2;
 | 
			
		||||
      invalid.x2 = MIN (texture_width, (invalid.x2 + 1) / 2);
 | 
			
		||||
      invalid.y2 = MIN (texture_height, (invalid.y2 + 1) / 2);
 | 
			
		||||
 | 
			
		||||
      if (tower->invalid[i].x1 == tower->invalid[i].x2 ||
 | 
			
		||||
          tower->invalid[i].y1 == tower->invalid[i].y2)
 | 
			
		||||
        {
 | 
			
		||||
          tower->invalid[i] = invalid;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          tower->invalid[i].x1 = MIN (tower->invalid[i].x1, invalid.x1);
 | 
			
		||||
          tower->invalid[i].y1 = MIN (tower->invalid[i].y1, invalid.y1);
 | 
			
		||||
          tower->invalid[i].x2 = MAX (tower->invalid[i].x2, invalid.x2);
 | 
			
		||||
          tower->invalid[i].y2 = MAX (tower->invalid[i].y2, invalid.y2);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* It generally looks worse if we scale up a window texture by even a
 | 
			
		||||
 * small amount than if we scale it down using bilinear filtering, so
 | 
			
		||||
 * we always pick the *larger* adjacent level. */
 | 
			
		||||
#define LOD_BIAS (-0.49)
 | 
			
		||||
 | 
			
		||||
/* This determines the appropriate level of detail to use when drawing the
 | 
			
		||||
 * texture, in a way that corresponds to what the GL specification does
 | 
			
		||||
 * when mip-mapping. This is probably fancier and slower than what we need,
 | 
			
		||||
 * but we do the computation only once each time we paint a window, and
 | 
			
		||||
 * its easier to just use the equations from the specification than to
 | 
			
		||||
 * come up with something simpler.
 | 
			
		||||
 *
 | 
			
		||||
 * If window is being painted at an angle from the viewer, then we have to
 | 
			
		||||
 * pick a point in the texture; we use the middle of the texture (which is
 | 
			
		||||
 * why the width/height are passed in.) This is not the normal case for
 | 
			
		||||
 * Meta.
 | 
			
		||||
 */
 | 
			
		||||
static int
 | 
			
		||||
get_paint_level (int width, int height)
 | 
			
		||||
{
 | 
			
		||||
  CoglMatrix projection, modelview, pm;
 | 
			
		||||
  float v[4];
 | 
			
		||||
  double viewport_width, viewport_height;
 | 
			
		||||
  double u0, v0;
 | 
			
		||||
  double xc, yc, wc;
 | 
			
		||||
  double dxdu_, dxdv_, dydu_, dydv_;
 | 
			
		||||
  double det_, det_sq;
 | 
			
		||||
  double rho_sq;
 | 
			
		||||
  double lambda;
 | 
			
		||||
 | 
			
		||||
  /* See
 | 
			
		||||
   * http://www.opengl.org/registry/doc/glspec32.core.20090803.pdf
 | 
			
		||||
   * Section 3.8.9, p. 1.6.2. Here we have
 | 
			
		||||
   *
 | 
			
		||||
   *  u(x,y) = x_o;
 | 
			
		||||
   *  v(x,y) = y_o;
 | 
			
		||||
   *
 | 
			
		||||
   * Since we are mapping 1:1 from object coordinates into pixel
 | 
			
		||||
   * texture coordinates, the clip coordinates are:
 | 
			
		||||
   *
 | 
			
		||||
   *  (x_c)                               (x_o)        (u)
 | 
			
		||||
   *  (y_c) = (M_projection)(M_modelview) (y_o) = (PM) (v)
 | 
			
		||||
   *  (z_c)                               (z_o)        (0)
 | 
			
		||||
   *  (w_c)                               (w_o)        (1)
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  cogl_get_projection_matrix (&projection);
 | 
			
		||||
  cogl_get_modelview_matrix (&modelview);
 | 
			
		||||
 | 
			
		||||
  cogl_matrix_multiply (&pm, &projection, &modelview);
 | 
			
		||||
 | 
			
		||||
  cogl_get_viewport (v);
 | 
			
		||||
  viewport_width = v[2];
 | 
			
		||||
  viewport_height = v[3];
 | 
			
		||||
 | 
			
		||||
  u0 = width / 2.;
 | 
			
		||||
  v0 = height / 2.;
 | 
			
		||||
 | 
			
		||||
  xc = pm.xx * u0 + pm.xy * v0 + pm.xw;
 | 
			
		||||
  yc = pm.yx * u0 + pm.yy * v0 + pm.yw;
 | 
			
		||||
  wc = pm.wx * u0 + pm.wy * v0 + pm.ww;
 | 
			
		||||
 | 
			
		||||
  /* We'll simplify the equations below for a bit of micro-optimization.
 | 
			
		||||
   * The commented out code is the unsimplified version.
 | 
			
		||||
 | 
			
		||||
  // Partial derivates of window coordinates:
 | 
			
		||||
  //
 | 
			
		||||
  //  x_w = 0.5 * viewport_width * x_c / w_c + viewport_center_x
 | 
			
		||||
  //  y_w = 0.5 * viewport_height * y_c / w_c + viewport_center_y
 | 
			
		||||
  //
 | 
			
		||||
  // with respect to u, v, using
 | 
			
		||||
  // d(a/b)/dx = da/dx * (1/b) - a * db/dx / (b^2)
 | 
			
		||||
 | 
			
		||||
  dxdu = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc)) / wc;
 | 
			
		||||
  dxdv = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc)) / wc;
 | 
			
		||||
  dydu = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc)) / wc;
 | 
			
		||||
  dydv = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc)) / wc;
 | 
			
		||||
 | 
			
		||||
  // Compute the inverse partials as the matrix inverse
 | 
			
		||||
  det = dxdu * dydv - dxdv * dydu;
 | 
			
		||||
 | 
			
		||||
  dudx =   dydv / det;
 | 
			
		||||
  dudy = - dxdv / det;
 | 
			
		||||
  dvdx = - dydu / det;
 | 
			
		||||
  dvdy =   dvdu / det;
 | 
			
		||||
 | 
			
		||||
  // Scale factor; maximum of the distance in texels for a change of 1 pixel
 | 
			
		||||
  // in the X direction or 1 pixel in the Y direction
 | 
			
		||||
  rho = MAX (sqrt (dudx * dudx + dvdx * dvdx), sqrt(dudy * dudy + dvdy * dvdy));
 | 
			
		||||
 | 
			
		||||
  // Level of detail
 | 
			
		||||
  lambda = log2 (rho) + LOD_BIAS;
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  /* dxdu * wc, etc */
 | 
			
		||||
  dxdu_ = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc));
 | 
			
		||||
  dxdv_ = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc));
 | 
			
		||||
  dydu_ = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc));
 | 
			
		||||
  dydv_ = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc));
 | 
			
		||||
 | 
			
		||||
  /* det * wc^2 */
 | 
			
		||||
  det_ = dxdu_ * dydv_ - dxdv_ * dydu_;
 | 
			
		||||
  det_sq = det_ * det_;
 | 
			
		||||
  if (det_sq == 0.0)
 | 
			
		||||
    return -1;
 | 
			
		||||
 | 
			
		||||
  /* (rho * det * wc)^2 */
 | 
			
		||||
  rho_sq = MAX (dydv_ * dydv_ + dydu_ * dydu_, dxdv_ * dxdv_ + dxdu_ * dxdu_);
 | 
			
		||||
  lambda = 0.5 * M_LOG2E * log (rho_sq * wc * wc / det_sq) + LOD_BIAS;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  g_print ("%g %g %g\n", 0.5 * viewport_width * pm.xx / pm.ww, 0.5 * viewport_height * pm.yy / pm.ww, lambda);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (lambda <= 0.)
 | 
			
		||||
    return 0;
 | 
			
		||||
  else
 | 
			
		||||
    return (int)(0.5 + lambda);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_power_of_two (int x)
 | 
			
		||||
{
 | 
			
		||||
  return (x & (x - 1)) == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
texture_tower_create_texture (MetaTextureTower *tower,
 | 
			
		||||
                              int               level,
 | 
			
		||||
                              int               width,
 | 
			
		||||
                              int               height)
 | 
			
		||||
{
 | 
			
		||||
  if ((!is_power_of_two (width) || !is_power_of_two (height)) &&
 | 
			
		||||
      meta_texture_rectangle_check (tower->textures[level - 1]))
 | 
			
		||||
    {
 | 
			
		||||
      tower->textures[level] =
 | 
			
		||||
        meta_texture_rectangle_new (width, height,
 | 
			
		||||
                                    /* data format */
 | 
			
		||||
                                    TEXTURE_FORMAT,
 | 
			
		||||
                                    /* internal cogl format */
 | 
			
		||||
                                    TEXTURE_FORMAT,
 | 
			
		||||
                                    /* rowstride */
 | 
			
		||||
                                    width * 4,
 | 
			
		||||
                                    /* data */
 | 
			
		||||
                                    NULL,
 | 
			
		||||
                                    /* error */
 | 
			
		||||
                                    NULL);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      tower->textures[level] = cogl_texture_new_with_size (width, height,
 | 
			
		||||
                                                           COGL_TEXTURE_NO_AUTO_MIPMAP,
 | 
			
		||||
                                                           TEXTURE_FORMAT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  tower->invalid[level].x1 = 0;
 | 
			
		||||
  tower->invalid[level].y1 = 0;
 | 
			
		||||
  tower->invalid[level].x2 = width;
 | 
			
		||||
  tower->invalid[level].y2 = height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
texture_tower_revalidate_fbo (MetaTextureTower *tower,
 | 
			
		||||
                              int               level)
 | 
			
		||||
{
 | 
			
		||||
  CoglTexture *source_texture = tower->textures[level - 1];
 | 
			
		||||
  int source_texture_width = cogl_texture_get_width (source_texture);
 | 
			
		||||
  int source_texture_height = cogl_texture_get_height (source_texture);
 | 
			
		||||
  CoglTexture *dest_texture = tower->textures[level];
 | 
			
		||||
  int dest_texture_width = cogl_texture_get_width (dest_texture);
 | 
			
		||||
  int dest_texture_height = cogl_texture_get_height (dest_texture);
 | 
			
		||||
  Box *invalid = &tower->invalid[level];
 | 
			
		||||
  CoglMatrix modelview;
 | 
			
		||||
 | 
			
		||||
  if (tower->fbos[level] == NULL)
 | 
			
		||||
    tower->fbos[level] = cogl_offscreen_new_to_texture (dest_texture);
 | 
			
		||||
 | 
			
		||||
  if (tower->fbos[level] == NULL)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  cogl_push_framebuffer (COGL_FRAMEBUFFER (tower->fbos[level]));
 | 
			
		||||
 | 
			
		||||
  cogl_ortho (0, dest_texture_width, dest_texture_height, 0, -1., 1.);
 | 
			
		||||
 | 
			
		||||
  cogl_matrix_init_identity (&modelview);
 | 
			
		||||
  cogl_set_modelview_matrix (&modelview);
 | 
			
		||||
 | 
			
		||||
  cogl_set_source_texture (tower->textures[level - 1]);
 | 
			
		||||
  cogl_rectangle_with_texture_coords (invalid->x1, invalid->y1,
 | 
			
		||||
                                      invalid->x2, invalid->y2,
 | 
			
		||||
                                      (2. * invalid->x1) / source_texture_width,
 | 
			
		||||
                                      (2. * invalid->y1) / source_texture_height,
 | 
			
		||||
                                      (2. * invalid->x2) / source_texture_width,
 | 
			
		||||
                                      (2. * invalid->y2) / source_texture_height);
 | 
			
		||||
 | 
			
		||||
  cogl_pop_framebuffer ();
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
fill_copy (guchar       *buf,
 | 
			
		||||
           const guchar *source,
 | 
			
		||||
           int           width)
 | 
			
		||||
{
 | 
			
		||||
  memcpy (buf, source, width * 4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
fill_scale_down (guchar       *buf,
 | 
			
		||||
                 const guchar *source,
 | 
			
		||||
                 int           width)
 | 
			
		||||
{
 | 
			
		||||
  while (width > 1)
 | 
			
		||||
    {
 | 
			
		||||
      buf[0] = (source[0] + source[4]) / 2;
 | 
			
		||||
      buf[1] = (source[1] + source[5]) / 2;
 | 
			
		||||
      buf[2] = (source[2] + source[6]) / 2;
 | 
			
		||||
      buf[3] = (source[3] + source[7]) / 2;
 | 
			
		||||
 | 
			
		||||
      buf += 4;
 | 
			
		||||
      source += 8;
 | 
			
		||||
      width -= 2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (width > 0)
 | 
			
		||||
    {
 | 
			
		||||
      buf[0] = source[0] / 2;
 | 
			
		||||
      buf[1] = source[1] / 2;
 | 
			
		||||
      buf[2] = source[2] / 2;
 | 
			
		||||
      buf[3] = source[3] / 2;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
texture_tower_revalidate_client (MetaTextureTower *tower,
 | 
			
		||||
                                 int               level)
 | 
			
		||||
{
 | 
			
		||||
  CoglTexture *source_texture = tower->textures[level - 1];
 | 
			
		||||
  int source_texture_width = cogl_texture_get_width (source_texture);
 | 
			
		||||
  int source_texture_height = cogl_texture_get_height (source_texture);
 | 
			
		||||
  guint source_rowstride;
 | 
			
		||||
  guchar *source_data;
 | 
			
		||||
  CoglTexture *dest_texture = tower->textures[level];
 | 
			
		||||
  int dest_texture_width = cogl_texture_get_width (dest_texture);
 | 
			
		||||
  int dest_texture_height = cogl_texture_get_height (dest_texture);
 | 
			
		||||
  int dest_x = tower->invalid[level].x1;
 | 
			
		||||
  int dest_y = tower->invalid[level].y1;
 | 
			
		||||
  int dest_width = tower->invalid[level].x2 - tower->invalid[level].x1;
 | 
			
		||||
  int dest_height = tower->invalid[level].y2 - tower->invalid[level].y1;
 | 
			
		||||
  guchar *dest_data;
 | 
			
		||||
  guchar *source_tmp1 = NULL, *source_tmp2 = NULL;
 | 
			
		||||
  int i, j;
 | 
			
		||||
 | 
			
		||||
  source_rowstride = source_texture_width * 4;
 | 
			
		||||
 | 
			
		||||
  source_data = g_malloc (source_texture_height * source_rowstride);
 | 
			
		||||
  cogl_texture_get_data (source_texture, TEXTURE_FORMAT, source_rowstride,
 | 
			
		||||
                         source_data);
 | 
			
		||||
 | 
			
		||||
  dest_data = g_malloc (dest_height * dest_width * 4);
 | 
			
		||||
 | 
			
		||||
  if (dest_texture_height < source_texture_height)
 | 
			
		||||
    {
 | 
			
		||||
      source_tmp1 = g_malloc (dest_width * 4);
 | 
			
		||||
      source_tmp2 = g_malloc (dest_width * 4);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < dest_height; i++)
 | 
			
		||||
    {
 | 
			
		||||
      guchar *dest_row = dest_data + i * dest_width * 4;
 | 
			
		||||
      if (dest_texture_height < source_texture_height)
 | 
			
		||||
        {
 | 
			
		||||
          guchar *source1, *source2;
 | 
			
		||||
          guchar *dest;
 | 
			
		||||
 | 
			
		||||
          if (dest_texture_width < source_texture_width)
 | 
			
		||||
            {
 | 
			
		||||
              fill_scale_down (source_tmp1,
 | 
			
		||||
                               source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 2 * 4,
 | 
			
		||||
                               dest_width * 2);
 | 
			
		||||
              fill_scale_down (source_tmp2,
 | 
			
		||||
                               source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 2 * 4,
 | 
			
		||||
                               dest_width * 2);
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              fill_copy (source_tmp1,
 | 
			
		||||
                         source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 4,
 | 
			
		||||
                         dest_width);
 | 
			
		||||
              fill_copy (source_tmp2,
 | 
			
		||||
                         source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 4,
 | 
			
		||||
                         dest_width);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          source1 = source_tmp1;
 | 
			
		||||
          source2 = source_tmp2;
 | 
			
		||||
 | 
			
		||||
          dest = dest_row;
 | 
			
		||||
          for (j = 0; j < dest_width * 4; j++)
 | 
			
		||||
            *(dest++) = (*(source1++) + *(source2++)) / 2;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          if (dest_texture_width < source_texture_width)
 | 
			
		||||
            fill_scale_down (dest_row,
 | 
			
		||||
                             source_data + (i + dest_y) * source_rowstride + dest_x * 2 * 4,
 | 
			
		||||
                             dest_width * 2);
 | 
			
		||||
          else
 | 
			
		||||
            fill_copy (dest_row,
 | 
			
		||||
                       source_data + (i + dest_y) * source_rowstride,
 | 
			
		||||
                       dest_width);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  cogl_texture_set_region (dest_texture,
 | 
			
		||||
                           0, 0,
 | 
			
		||||
                           dest_x, dest_y,
 | 
			
		||||
                           dest_width, dest_height,
 | 
			
		||||
                           dest_width, dest_height,
 | 
			
		||||
                           TEXTURE_FORMAT,
 | 
			
		||||
                           4 * dest_width,
 | 
			
		||||
                           dest_data);
 | 
			
		||||
 | 
			
		||||
  if (dest_texture_height < source_texture_height)
 | 
			
		||||
    {
 | 
			
		||||
      g_free (source_tmp1);
 | 
			
		||||
      g_free (source_tmp2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_free (source_data);
 | 
			
		||||
  g_free (dest_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
texture_tower_revalidate (MetaTextureTower *tower,
 | 
			
		||||
                          int               level)
 | 
			
		||||
{
 | 
			
		||||
  if (!texture_tower_revalidate_fbo (tower, level))
 | 
			
		||||
    texture_tower_revalidate_client (tower, level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_texture_tower_get_paint_texture:
 | 
			
		||||
 * @tower: a #MetaTextureTower
 | 
			
		||||
 *
 | 
			
		||||
 * Gets the texture from the tower that best matches the current
 | 
			
		||||
 * rendering scale. (On the assumption here the texture is going to
 | 
			
		||||
 * be rendered with vertex coordinates that correspond to its
 | 
			
		||||
 * size in pixels, so a 200x200 texture will be rendered on the
 | 
			
		||||
 * rectangle (0, 0, 200, 200).
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: the COGL texture handle to use for painting, or
 | 
			
		||||
 *  %NULL if no base texture has yet been set.
 | 
			
		||||
 */
 | 
			
		||||
CoglTexture *
 | 
			
		||||
meta_texture_tower_get_paint_texture (MetaTextureTower *tower)
 | 
			
		||||
{
 | 
			
		||||
  int texture_width, texture_height;
 | 
			
		||||
  int level;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (tower != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  if (tower->textures[0] == NULL)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  texture_width = cogl_texture_get_width (tower->textures[0]);
 | 
			
		||||
  texture_height = cogl_texture_get_height (tower->textures[0]);
 | 
			
		||||
 | 
			
		||||
  level = get_paint_level(texture_width, texture_height);
 | 
			
		||||
  if (level < 0) /* singular paint matrix, scaled to nothing */
 | 
			
		||||
    return NULL;
 | 
			
		||||
  level = MIN (level, tower->n_levels - 1);
 | 
			
		||||
 | 
			
		||||
  if (tower->textures[level] == NULL ||
 | 
			
		||||
      (tower->invalid[level].x2 != tower->invalid[level].x1 &&
 | 
			
		||||
       tower->invalid[level].y2 != tower->invalid[level].y1))
 | 
			
		||||
    {
 | 
			
		||||
      int i;
 | 
			
		||||
 | 
			
		||||
      for (i = 1; i <= level; i++)
 | 
			
		||||
       {
 | 
			
		||||
         /* Use "floor" convention here to be consistent with the NPOT texture extension */
 | 
			
		||||
         texture_width = MAX (1, texture_width / 2);
 | 
			
		||||
         texture_height = MAX (1, texture_height / 2);
 | 
			
		||||
 | 
			
		||||
         if (tower->textures[i] == NULL)
 | 
			
		||||
           texture_tower_create_texture (tower, i, texture_width, texture_height);
 | 
			
		||||
       }
 | 
			
		||||
 | 
			
		||||
      for (i = 1; i <= level; i++)
 | 
			
		||||
       {
 | 
			
		||||
         if (tower->invalid[level].x2 != tower->invalid[level].x1 &&
 | 
			
		||||
             tower->invalid[level].y2 != tower->invalid[level].y1)
 | 
			
		||||
           texture_tower_revalidate (tower, i);
 | 
			
		||||
       }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
  return tower->textures[level];
 | 
			
		||||
}
 | 
			
		||||
@@ -1,69 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * MetaTextureTower
 | 
			
		||||
 *
 | 
			
		||||
 * Mipmap emulation by creation of scaled down images
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2009 Red Hat, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __META_TEXTURE_TOWER_H__
 | 
			
		||||
#define __META_TEXTURE_TOWER_H__
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:MetaTextureTower
 | 
			
		||||
 * @short_description: mipmap emulation by creation of scaled down images
 | 
			
		||||
 *
 | 
			
		||||
 * A #MetaTextureTower is used to get good looking scaled down images when
 | 
			
		||||
 * we can't use the GL drivers mipmap support. There are two separate reasons
 | 
			
		||||
 *
 | 
			
		||||
 *  - Some cards (including radeon cards <= r5xx) only support
 | 
			
		||||
 *    TEXTURE_RECTANGLE_ARB and not NPOT textures. Rectangular textures
 | 
			
		||||
 *    are defined not to support mipmapping.
 | 
			
		||||
 *  - Even when NPOT textures are available, the combination of NPOT
 | 
			
		||||
 *    textures, texture_from_pixmap, and mipmapping doesn't typically
 | 
			
		||||
 *    work, since the X server doesn't allocate pixmaps in the right
 | 
			
		||||
 *    layout for mipmapping.
 | 
			
		||||
 *
 | 
			
		||||
 * So, what we do is create the "mipmap" levels ourselves by successive
 | 
			
		||||
 * power-of-two scaledowns, and when rendering pick the single texture
 | 
			
		||||
 * that best matches the scale we are rendering at. (Since we aren't
 | 
			
		||||
 * typically using perspective transforms, we'll frequently have a single
 | 
			
		||||
 * scale for the entire texture.)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaTextureTower MetaTextureTower;
 | 
			
		||||
 | 
			
		||||
MetaTextureTower *meta_texture_tower_new               (void);
 | 
			
		||||
void              meta_texture_tower_free              (MetaTextureTower *tower);
 | 
			
		||||
void              meta_texture_tower_set_base_texture  (MetaTextureTower *tower,
 | 
			
		||||
                                                        CoglTexture      *texture);
 | 
			
		||||
void              meta_texture_tower_update_area       (MetaTextureTower *tower,
 | 
			
		||||
                                                        int               x,
 | 
			
		||||
                                                        int               y,
 | 
			
		||||
                                                        int               width,
 | 
			
		||||
                                                        int               height);
 | 
			
		||||
CoglTexture      *meta_texture_tower_get_paint_texture (MetaTextureTower *tower);
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __META_TEXTURE_TOWER_H__ */
 | 
			
		||||
@@ -1782,10 +1782,6 @@ check_needs_pixmap (MetaWindowActor *self)
 | 
			
		||||
          goto out;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (compositor->no_mipmaps)
 | 
			
		||||
        meta_shaped_texture_set_create_mipmaps (META_SHAPED_TEXTURE (priv->actor),
 | 
			
		||||
                                                FALSE);
 | 
			
		||||
 | 
			
		||||
      meta_shaped_texture_set_pixmap (META_SHAPED_TEXTURE (priv->actor),
 | 
			
		||||
                                      priv->back_pixmap);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -66,9 +66,6 @@ GType meta_shaped_texture_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
ClutterActor *meta_shaped_texture_new (void);
 | 
			
		||||
 | 
			
		||||
void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
 | 
			
		||||
					     gboolean           create_mipmaps);
 | 
			
		||||
 | 
			
		||||
void meta_shaped_texture_update_area (MetaShapedTexture *stex,
 | 
			
		||||
                                      int                x,
 | 
			
		||||
                                      int                y,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user