We've had complaints that our Cogl code/headers are a bit "special" so
this is a first pass at tidying things up by giving them some
consistency. These changes are all consistent with how new code in Cogl
is being written, but the style isn't consistently applied across all
code yet.
There are two parts to this patch; but since each one required a large
amount of effort to maintain tidy indenting it made sense to combine the
changes to reduce the time spent re indenting the same lines.
The first change is to use a consistent style for declaring function
prototypes in headers. Cogl headers now consistently use this style for
prototypes:
return_type
cogl_function_name (CoglType arg0,
CoglType arg1);
Not everyone likes this style, but it seems that most of the currently
active Cogl developers agree on it.
The second change is to constrain the use of redundant glib data types
in Cogl. Uses of gint, guint, gfloat, glong, gulong and gchar have all
been replaced with int, unsigned int, float, long, unsigned long and char
respectively. When talking about pixel data; use of guchar has been
replaced with guint8, otherwise unsigned char can be used.
The glib types that we continue to use for portability are gboolean,
gint{8,16,32,64}, guint{8,16,32,64} and gsize.
The general intention is that Cogl should look palatable to the widest
range of C programmers including those outside the Gnome community so
- especially for the public API - we want to minimize the number of
foreign looking typedefs.
This adds three new texture backends.
- CoglTexture2D: This is a trimmed down version of CoglTexture2DSliced
which only supports a single texture and only works with the
GL_TEXTURE_2D target. The code is a lot simpler so it has a less
overheads than dealing with slices. Cogl will use this wherever
possible.
- CoglSubTexture: This is used to get a CoglHandle to represent a
subregion of another texture. The texture can be used as if it was a
standalone texture but it does not need to copy the resources.
- CoglAtlasTexture: This collects RGB and RGBA textures into a single
GL texture with the aim of reducing texture state changes and
increasing batching. The backend will try to manage the atlas and
may move the textures around to close gaps in the texture. By
default all textures will be placed in the atlas.
Commit 92a375ab4 changed the initial value of max_texcoord_attrib_unit
to -1 so that it could disable the texture coord array for the first
texture unit when there are no texture coords used in the vbo. However
max_texcoord_attrib_unit was an unsigned value so this actually became
G_MAXUINT. The disabling loop at the bottom still worked because
G_MAXUINT+1==0 but the check for whether any texture unit is greater
than max_texcoord_attrib_unit was failing so it would always end up
disabling all texture units. This is now fixed by changing
max_texcoord_attrib_unit to be signed.
When setting up the state for the vertex buffer,
enable_state_for_drawing_buffer tries to keep track of the highest
numbered texture unit in use. It then disables any texture arrays for
units that were previously enabled if they are greater than that
number. However if there is no texturing in the VBO then the max used
unit would be left at 0 which it would later think meant unit 0 is
still in use so it wouldn't disable it. To fix this it now initialises
the max used unit to -1 which it should interpret as ‘no units are in
use’ so it will later disable the arrays for all units.
Thanks to Jon Mayo for reporting the bug.
http://bugzilla.openedhand.com/show_bug.cgi?id=1957
The sub texture backend doesn't work well as a completely general
texture backend because for example when rendering with cogl_polygon
it needs to be able to tranform arbitrary texture coordinates without
reference to the other coordintes. This can't be done when the texture
coordinates are a multiple of one because sometimes the coordinate
should represent the left or top edge and sometimes it should
represent the bottom or top edge. For example if the s coordinates are
0 and 1 then 1 represents the right edge but if they are 1 and 2 then
1 represents the left edge.
Instead the sub-textures are now documented not to support coordinates
outside the range [0,1]. The coordinates for the sub-region are now
represented as integers as this helps avoid rounding issues. The
region can no longer be a super-region of the texture as this
simplifies the code quite a lot.
There are two new texture virtual functions:
transform_quad_coords_to_gl - This transforms two pairs of coordinates
representing a quad. It will return FALSE if the coordinates can
not be transformed. The sub texture backend uses this to detect
coordinates that require repeating which causes cogl-primitives
to use manual repeating.
ensure_non_quad_rendering - This is used in cogl_polygon and
cogl_vertex_buffer to inform the texture backend that
transform_quad_to_gl is going to be used. The atlas backend
migrates the texture out of the atlas when it hits this.
cogl_push_draw_buffer, cogl_set_draw_buffer and cogl_pop_draw_buffer are now
deprecated and new code should use the new cogl_framebuffer_* API instead.
Code that previously did:
cogl_push_draw_buffer ();
cogl_set_draw_buffer (COGL_OFFSCREEN_BUFFER, buffer);
/* draw */
cogl_pop_draw_buffer ();
should now be re-written as:
cogl_push_framebuffer (buffer);
/* draw */
cogl_pop_framebuffer ();
As can be seen from the example above the rename has been used as an
opportunity to remove the redundant target argument from
cogl_set_draw_buffer; it now only takes one call to redirect to an offscreen
buffer, and finally the term framebuffer may be a bit more familiar to
anyone coming from an OpenGL background.
Previously if you need to depend on a new GL feature you had to:
- Add typedefs for all of the functions in cogl-defines.h.in
- Add function pointers for each of the functions in
cogl-context-driver.h
- Add an initializer for the function pointers in
cogl-context-driver.c
- Add a check for the extension and all of the functions in
cogl_features_init. If the extension is available under multiple
names then you have to duplicate the checks.
This is quite tedious and error prone. This patch moves all of the
features and their functions into a list of macro invocations in
cogl-feature-functions.h. The macros can be redefined to implement all
of the above tasks from the same header.
The features are described in a struct with a pointer to a table of
functions. A new function takes the feature description from this
struct and checks for its availability. The feature can take a list of
extension names with a list of alternate namespaces (such as "EXT" or
"ARB"). It can also detect the feature from a particular version of
GL.
The typedefs are now gone and instead the function pointer in the Cogl
context just directly contains the type.
Some of the functions in the context were previously declared with the
'ARB' extension. This has been removed so that now all the functions
have no suffix. This makes more sense when the extension could
potentially be merged into GL core as well.
Because Cogl defines the origin for texture as top left and offscreen draw
buffers can be used to render to textures, we (internally) force all
offscreen rendering to be upside down. (because OpenGL defines the origin
to be bottom left)
By forcing the users scene to be rendered upside down though we also reverse
the winding order of all the drawn triangles which may interfere with the
users use of backface culling. This patch ensures that we reverse the
winding order for a front face (if culling is in use) while rendering
offscreen so we don't conflict with the users back face culling.
Cogl's support for offscreen rendering was originally written just to support
the clutter_texture_new_from_actor API and due to lack of documentation and
several confusing - non orthogonal - side effects of using the API it wasn't
really possible to use directly.
This commit does a number of things:
- It removes {gl,gles}/cogl-fbo.{c,h} and adds shared cogl-draw-buffer.{c,h}
files instead which should be easier to maintain.
- internally CoglFbo objects are now called CoglDrawBuffers. A
CoglDrawBuffer is an abstract base class that is inherited from to
implement CoglOnscreen and CoglOffscreen draw buffers. CoglOffscreen draw
buffers will initially be used to support the
cogl_offscreen_new_to_texture API, and CoglOnscreen draw buffers will
start to be used internally to represent windows as we aim to migrate some
of Clutter's backend code to Cogl.
- It makes draw buffer objects the owners of the following state:
- viewport
- projection matrix stack
- modelview matrix stack
- clip state
(This means when you switch between draw buffers you will automatically be
switching to their associated viewport, matrix and clip state)
Aside from hopefully making cogl_offscreen_new_to_texture be more useful
short term by having simpler and well defined semantics for
cogl_set_draw_buffer, as mentioned above this is the first step for a couple
of other things:
- Its a step toward moving ownership for windows down from Clutter backends
into Cogl, by (internally at least) introducing the CoglOnscreen draw
buffer. Note: the plan is that cogl_set_draw_buffer will accept on or
offscreen draw buffer handles, and the "target" argument will become
redundant since we will instead query the type of the given draw buffer
handle.
- Because we have a common type for on and offscreen framebuffers we can
provide a unified API for framebuffer management. Things like:
- blitting between buffers
- managing ancillary buffers (e.g. attaching depth and stencil buffers)
- size requisition
- clearing
cogl-primitives.c was previously digging right into CoglTextures so it could
manually iterate the texture slices for texturing quads and polygons and
because we were missing some state getters we were lazily just poking into
the structures directly.
This adds some extra state getter functions, and adds a higher level
_cogl_texture_foreach_slice () API that hopefully simplifies the way in
which sliced textures may be used to render primitives. This lets you
specify a rectangle in "virtual" texture coords and it will call a given
callback for each slice that intersects that rectangle giving the virtual
coords of the current slice and corresponding "real" texture coordinates for
the underlying gl texture.
At the same time a noteable bug in how we previously iterated sliced
textures was fixed, whereby we weren't correctly handling inverted texture
coordinates. E.g. with the previous code if you supplied texture coords of
tx1=100,ty1=0,tx2=0,ty2=100 (inverted along y axis) that would result in a
back-facing quad, which could be discarded if using back-face culling.
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.