Instead of unconditionally combining the modelview and projection
matrices and then iterating each of the vertices to call
cogl_matrix_transform_point for each one in turn we now only combine the
matrices if there are more than 4 vertices (with less than 4 vertices
its less work to transform them separately) and we use the new
cogl_vertex_{transform,project}_points APIs which can hopefully
vectorize the transformations.
Finally the perspective divide and viewport scale is done in a separate
loop at the end and we don't do the spurious perspective divide and
viewport scale for the z component.
This adds two new experimental functions to cogl-matrix.c:
cogl_matrix_view_2d_in_perspective and cogl_matrix_view_2d_in_frustum
which can be used to setup a view transform that maps a 2D coordinate
system (0,0) top left and (width,height) bottom right to the current
viewport.
Toolkits such as Clutter that want to mix 2D and 3D drawing can use
these APIs to position a 2D coordinate system at an arbitrary depth
inside a 3D perspective projected viewing frustum.
cogl_matrix_project_points and cogl_matrix_transform_points had an
optimization for the common case where the stride parameters exactly
match the size of the corresponding structures. The code for both when
generated by gcc with -O2 on x86-64 use two registers to hold the
addresses of the input and output arrays. In the strided version these
pointers are incremented by adding the value of a register and in the
packed version they are incremented by adding an immediate value. I
think the difference in cost here would be negligible and it may even
be faster to add a register.
Also GCC appears to retain the loop counter in a register for the
strided version but in the packed version it can optimize it out and
directly use the input pointer as the counter. I think it would be
possible to reorder the code a bit to explicitly use the input pointer
as the counter if this were a problem.
Getting rid of the packed versions tidies up the code a bit and it
could potentially be faster if the code differences are small and we
get to avoid an extra conditional in cogl_matrix_transform_points.
Both cogl_matrix_transform_points and _project_points take points_in and
points_out arguments and explicitly allow pointing to the same array
(i.e. to transform in-place) The implementation of the various internal
transform functions though were not handling this possability and so it
was possible the reference partially transformed vertex values as if
they were original input values leading to incorrect results. This patch
ensures we take a temporary copy of the current input point when
transforming.
To allow us to have gobject properties that accept a CoglMatrix value we
need to register a GType. This adds a cogl_gtype_matrix_get_type function
that will register a static boxed type called "CoglMatrix".
This adds a new section to the reference manual for GType integration
functions.
As a pre-requisite for being able to register a boxed GType for
CoglMatrix (enabling us to define gobject properties that accept a
CoglMatrix) this adds cogl_matrix_copy and _free functions.
This add two new function that allows us to transform or project an
array of points instead of only transforming one point at a time. Recent
benchmarking has shown cogl_matrix_transform_point to be a bottleneck
sometimes, so this should allow us to reduce the overhead when
transforming lots of vertices at the same time, and also reduce the cost
of 3 component, non-projective transforms.
For now they are marked as experimental (you have to define
COGL_ENABLE_EXPERIMENTAL_API) because there is some concern that it
introduces some inconsistent naming. cogl_matrix_transform_point would
have to be renamed cogl_matrix_project_point to be consistent, but that
would be an API break.
This adds a way to compare two CoglMatrix structures to see if they
represent the same transformations. memcmp can't be used because a
CoglMatrix contains private flags and padding.
Since using addresses that might change is something that finally
the FSF acknowledge as a plausible scenario (after changing address
twice), the license blurb in the source files should use the URI
for getting the license in case the library did not come with it.
Not that URIs cannot possibly change, but at least it's easier to
set up a redirection at the same place.
As a side note: this commit closes the oldes bug in Clutter's bug
report tool.
http://bugzilla.openedhand.com/show_bug.cgi?id=521
This new API takes advantage of the recently imported Mesa code to support
inverse matrix calculation. The matrix code keeps track (via internal
flags) of the transformations a matrix represents so that it can select an
optimized inversion function.
Note: although other aspects of the Cogl matrix API have followed a similar
style to Cairo's matrix API we haven't added a cogl_matrix_invert API
because the inverse of a CoglMatrix is actually cached as part of the
CoglMatrix structure meaning a destructive API like cogl_matrix_invert
doesn't let users take advantage of this caching design.
This adds a COGL_DEBUG=matrices debug option that can be used to trace all
matrix manipulation done using the Cogl API. This can be handy when you
break something in such a way that a trace is still comparable with a
previous working version since you can simply diff a log of the broken
version vs the working version to home in on the bug.
This pulls in code from Mesa to improve our matrix manipulation support. It
includes support for calculating the inverse of matrices based on top of a
matrix categorizing system that allows optimizing certain matrix types.
(the main thing we were after) but also adds some optimisations for
rotations.
Changes compared to the original code from Mesa:
- Coding style is consistent with the rest of Cogl
- Instead of allocating matrix->m and matrix->inv using malloc, our public
CoglMatrix typedef is large enough to directly contain the matrix, its
inverse, a type and a set of flags.
- Instead of having a _math_matrix_analyse which updates the type, flags and
inverse, we have _math_matrix_update_inverse which essentially does the
same thing (internally making use of _math_matrix_update_type_and_flags())
but with additional guards in place to bail out when the inverse matrix is
still valid.
- When initializing a matrix with the identity matrix we don't immediately
initialize the inverse matrix; rather we just set the dirty flag for the
inverse (since it's likely the user won't request the inverse of the
identity matrix)
As part of an incremental process to have Cogl be a standalone project we
want to re-consider how we organise the Cogl source code.
Currently this is the structure I'm aiming for:
cogl/
cogl/
<put common source here>
winsys/
cogl-glx.c
cogl-wgl.c
driver/
gl/
gles/
os/ ?
utils/
cogl-fixed
cogl-matrix-stack?
cogl-journal?
cogl-primitives?
pango/
The new winsys component is a starting point for migrating window system
code (i.e. x11,glx,wgl,osx,egl etc) from Clutter to Cogl.
The utils/ and pango/ directories aren't added by this commit, but they are
noted because I plan to add them soon.
Overview of the planned structure:
* The winsys/ API is the API that binds OpenGL to a specific window system,
be that X11 or win32 etc. Example are glx, wgl and egl. Much of the logic
under clutter/{glx,osx,win32 etc} should migrate here.
* Note there is also the idea of a winsys-base that may represent a window
system for which there are multiple winsys APIs. An example of this is
x11, since glx and egl may both be used with x11. (currently only Clutter
has the idea of a winsys-base)
* The driver/ represents a specific varient of OpenGL. Currently we have "gl"
representing OpenGL 1.4-2.1 (mostly fixed function) and "gles" representing
GLES 1.1 (fixed funciton) and 2.0 (fully shader based)
* Everything under cogl/ should fundamentally be supporting access to the
GPU. Essentially Cogl's most basic requirement is to provide a nice GPU
Graphics API and drawing a line between this and the utility functionality
we add to support Clutter should help keep this lean and maintainable.
* Code under utils/ as suggested builds on cogl/ adding more convenient
APIs or mechanism to optimize special cases. Broadly speaking you can
compare cogl/ to OpenGL and utils/ to GLU.
* clutter/pango will be moved to clutter/cogl/pango
How some of the internal configure.ac/pkg-config terminology has changed:
backendextra -> CLUTTER_WINSYS_BASE # e.g. "x11"
backendextralib -> CLUTTER_WINSYS_BASE_LIB # e.g. "x11/libclutter-x11.la"
clutterbackend -> {CLUTTER,COGL}_WINSYS # e.g. "glx"
CLUTTER_FLAVOUR -> {CLUTTER,COGL}_WINSYS
clutterbackendlib -> CLUTTER_WINSYS_LIB
CLUTTER_COGL -> COGL_DRIVER # e.g. "gl"
Note: The CLUTTER_FLAVOUR and CLUTTER_COGL defines are kept for apps
As the first thing to take advantage of the new winsys component in Cogl;
cogl_get_proc_address() has been moved from cogl/{gl,gles}/cogl.c into
cogl/common/cogl.c and this common implementation first trys
_cogl_winsys_get_proc_address() but if that fails then it falls back to
gmodule.