CoglAtlas chooses a fairly large default initial size of either
512x512 or 1024x1024 depending on the texture format. There is a
chance that this size will not be supported on some platforms which
would be catastrophic for the glyph cache because it would mean that
it would always fail to put any glyphs in the cache so text wouldn't
work. To fix this the atlas code now checks whether the chosen initial
size is supported by the texture driver and if not it will get halved
until it is supported.
Previously when creating a new rectangle map it would try increasingly
larger texture sizes until GL_MAX_TEXTURE_SIZE is reached. This is bad
because it queries state which should really be owned by the texture
driver. Also GL_MAX_TEXTURE_SIZE is often a conservative estimate so
larger texture sizes can be used if the proxy texture is queried
instead.
Previously each node in the rectangle map tree would store the total
remaining space in all of its children to use as an optimization when
adding nodes. With this it could skip an entire branch of the tree if
it knew there could never be enough space for the new node in the
branch. This modifies that slightly to instead store the largest
single gap. This allows it to skip a branch earlier because often
there would be a lot of small gaps which would add up to enough a
space for the new rectangle, but the space can't be used unless it is
in a single node.
The rectangle map still needs to keep track of the total remaining
space for the whole map for the debugging output so this has been
added back in to the CoglRectangleMap struct. There is a separate
debugging function to verify this value.
Previously when the atlas needs to be migrated it would start by
trying with the same size as the existing atlas if there is enough
space for the new texture. However even if the atlas is completely
sorted there will always be some amount of waste so when the atlas
needs to grow it would usually end up redundantly trying the same size
when it is very unlikely to fit. This patch changes it so that there
must be at least 6% waste available after the new texture is added
otherwise it will start with the next atlas size.
When iterating over the rectangle map a stack is used to implement a
recursive algorithm. Previously this was slice allocating a linked
list. Now it uses a GArray which is retained with the rectangle map to
avoid frequent allocations which is a little bit faster.
Previously the remaining space was managed as part of the
CoglRectangleMap struct. Now it is stored per node so that at any
point in the hierarchy we can quickly determine how much space is
remaining in all of the node's children. That way when adding a
rectangle we can miss out entire branches more quickly if we know that
there is no way the new rectangle would fit in that branch.
This also adds a function to recursively verify the cached state in
the nodes such as the remaining space and the number of
rectangles. This function is only called when the dump-atlas-image
debug flag is set because it is potentially quite slow.
The glyph cache is now stored in a CoglAtlas structure instead of the
custom atlasing code. This has the advantage that it can share code
with the main texture atlas and that it supports reorganizing the
atlas when it becomes full. Unlike the texture atlas, the glyph cache
can use multiple atlases which would be neccessary if the maximum
texture size is reached and we need to create a second
texture. Whenever a display list is created it now has to register a
callback with the glyph cache so that the display list can be
recreated whenever any of the atlases are reorganized. This is needed
because the display list directly stores texture coordinates within
the atlas texture and they would become invalid when the texture is
moved.
The ensure_glyphs_for_layout now works in two steps. First it reserves
space in the atlas for all of the glyphs. The atlas is created with
the DISABLE_MIGRATION flag so that it won't actually copy any textures
if any rearranging is needed. Whenever the position is updated for a
glyph then it is marked as dirty. After space for all of the glyphs
has been reserved it will iterate over all dirty glyphs and redraw
them using Cairo. The rendered glyph is then stored in the texture
with a sub texture update.
The glyphs need to all be set at the right location before starting to
create the display list because the display list stores the texture
coordinates of the glyph. If any of the glyphs were moved around then
the parts of the display list that was created already would become
invalid. To make this work, ensure_glyphs_for_layout is now always
called before rendering a layout or a layout line.
_cogl_atlas_new now has two extra parameters to specify the format of
the textures it creates as well as a set of flags to modify the
behavious of the atlas. One of the flags causes the new textures to be
cleared and the other causes migration to avoid actually copying the
textures. This is needed to use CoglAtlas from the pango glyph cache
because it needs to use COGL_PIXEL_A_8 and to clear the textures as it
does not fill in the gaps between glyphs. It needs to avoid copying
the textures so that it can work on GL implementations without FBO
support.
Instead of storing a pointer to the CoglRectangleMap and a handle to
the atlas texture in the context, there is a now a separate data
structure called a CoglAtlas to manage these two. The context just
contains a pointer to this. The code to reorganise the atlas has been
moved from cogl-atlas-texture.c to cogl-atlas.c
This adds an internal CoglCallbackList type which is just a GSList of
of function pointers along with a data pointer to form a
closure. There are functions to add and remove items and to invoke the
list of functions. This could be used in a number of places in Cogl.
This simply renames CoglAtlas to CoglRectangleMap without making any
functional changes. The old 'CoglAtlas' is just a data structure for
managing unused areas of a rectangle and it doesn't neccessarily have
to be used for an atlas so it wasn't a very good name.
If the font size or the number of characters causes the label not to
fit on the stage, instead of aborting it will now scale the labels so
that it fits within one of the dimensions. This makes it easier to
test with large glyph sizes.
Textures within a layer were compared for equality by comparing their
texture handle. However this means that sub textures and atlas
textures which may be internally using the same GL handle would not be
batched together. Instead it now tries to determine the underlying GL
handle using either the slice override or _cogl_texture_get_gl_texture
and then compares those.
Added some extra explanation, referencing the sample code, to
try to make the scrollable actor example easier to follow. Basically
demonstrates the principles described in the paragraph about
setting the y coordinate for the scrollable actor, but using actual
numbers.
When filtering on allowed formats for atlas textures, it now masks out
the BGR and AFIRST bits in addition to the premult bit. That way it
will accept RGB and RGBA formats in any component order.
In theory it could also accept luminance and alpha-only textures but I
haven't added this because presumably if the application has requested
these formats then it has some reason not to use a full RGB or RGBA
texture and we should respect that.
See commits:
7daeb217 blur-effect: Do not inherit from ShaderEffect
1ec57743 desaturate-effect: Do not inherit from ShaderEffect
We might avoid using shaders at all in the future for simple effects.
Since BlurEffect and DesaturateEffect are using the shader API
implicitly and not using ClutterShaderEffect, we need to check if the
underlying GL implementation supports the GLSL shading language and warn
if not.
Hide the fact that we're using a fragment shader, in case we're able in
the future to use a material layer combine function when painting the
offscreen target texture.
We might want to switch the BlurEffect from a box-blur to a
super-sampling of the texture target, in order to make it cheap(er).
If we inherit from ShaderEffect, though, we're setting in stone the
fact that we are going to use a fragment shader for blurring.
Since there is not parametrization of the blur, the code necessary
to implement effect is pretty small, and we can use the Cogl API
directly.
Instead of calling cogl_program_use() around the paint_target()
chain-up, we can use the newly added API in CoglMaterial to attach
user-defined shaders to the offscreen target material.
* wip/table-layout:
Add ClutterTableLayout, a layout showing children in rows and columns
box-layout: Use allocate_align_fill()
bin-layout: Migrate to allocate_align_fill()
actor: Add allocate_align_fill()
test-flow-layout: Use BindConstraints
A TableLayout is a layout manager that allocates its children in rows
and columns. Each child is assigned to a cell (or more if a cell span
is set).
The supported child properties are:
• x-expand and y-expand: if this cell with try to allocate the
available extra space for the table.
• x-fill and y-fill: if the child will get all the space available in
the cell.
• x-align and y-align: if the child does not fill the cell, then
where the child will be aligned inside the cell.
• row-span and col-span: number of cells the child will allocate for
itself.
Also, the TableLayout has row-spacing and col-spacing for specifying
the space in pixels between rows and between columns.
We also include a simple test of the layout manager, and the
documentation updates.
The TableLayout was implemented starting from MxTable and
ClutterBoxLayout.
http://bugzilla.clutter-project.org/show_bug.cgi?id=2038
Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>
Layout managers are using the same code to allocate a child while taking
into consideration:
• horizontal and vertical alignment
• horizontal and vertical fill
• the preferred minimum and natural size, depending
on the :request-mode property
• the text direction for the horizontal alignment
• an offset given by the fixed position properties
Given the amount of code involved, and the amount of details that can go
horribly wrong while copy and pasting such code in various classes - let
alone various projects - Clutter should provide an allocate() variant
that does the right thing in the right way. This way, we have a single
point of failure.