Commit Graph

2263 Commits

Author SHA1 Message Date
Neil Roberts
0927f35e7a cogl: Use the GL_EXT_blend_{func,equation}_separate extensions
We should use these extensions to check for glBlendFuncSeparate and
glBlendEquationSeparate as well as checking the GL version number.
2009-11-17 18:06:31 +00:00
Neil Roberts
2a53b84d18 cogl: Don't bother checking for NPOTs or VBOs on later GLs
For VBOs, we don't need to check for the extension if the GL version
is greater than 1.5. Non-power-of-two textures are given in 2.0.

We could also assume shader support in GL 2.0 except that the function
names are different from those in the extension so it wouldn't work
well with the current mechanism.
2009-11-17 17:22:22 +00:00
Neil Roberts
058d79dce2 cogl: Make it easier to add checks for GL extensions
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.
2009-11-17 15:11:26 +00:00
Neil Roberts
8b4a861093 Use the GL_ARB_multitexture extension on GL 1.2
Cogl requires multi-texturing support. This is only available as an
extension in GL 1.2 so we should check for it before accepting the
driver.

http://bugzilla.openedhand.com/show_bug.cgi?id=1875
2009-11-13 15:56:01 +00:00
Neil Roberts
6b0b07a8a6 cogl-material: Fallback to BlendFunc if BlendFuncSeparate is unavailable
glBlendFuncSeparate is only available in OpenGL 1.4. If we
conditionally check for this then Clutter will work with OpenGL 1.2.

http://bugzilla.openedhand.com/show_bug.cgi?id=1875
2009-11-13 15:55:55 +00:00
Neil Roberts
a50907848f Validate that the GL version is >= 1.2
There is a new internal Cogl function called _cogl_check_driver_valid
which looks at the value of the GL_VERSION string to determine whether
the driver is supported. Clutter now calls this after the stage is
realized. If it fails then the stage is marked as unrealized and a
warning is shown.

_cogl_features_init now also checks the version number before getting
the function pointers for glBlendFuncSeparate and
glBlendEquationSeparate. It is not safe to just check for the presence
of the functions because some drivers may define the function without
fully implementing the spec.

The GLES version of _cogl_check_driver_valid just always returns TRUE
because there are no version requirements yet.

Eventually the function could also check for mandatory extensions if
there were any.

http://bugzilla.openedhand.com/show_bug.cgi?id=1875
2009-11-13 15:55:48 +00:00
Neil Roberts
d309272901 [cogl-primitives] Don't clear the whole stencil buffer
When _cogl_add_path_to_stencil_buffer is used to draw a path we don't
need to clear the entire stencil buffer. Instead it can clear just the
bounding box of the path. This adds an extra parameter called
'need_clear' which is only set if the stencil buffer is being used for
clipping.

http://bugzilla.openedhand.com/show_bug.cgi?id=1829
2009-11-13 10:51:47 +00:00
Neil Roberts
c49edf0097 Remove _cogl_flush_matrix_stacks from cogl-internal.h
The definition for this function was removed in f7d64e5abvoid so it
should be removed from the header too.
2009-11-12 17:01:44 +00:00
Emmanuele Bassi
57d9c3c668 cogl: Declare cogl_is_bitmap()
The function is automatically defined by the CoglHandle type
definition macro, but it still requires to be declared in the
header file to be used.
2009-11-11 10:32:39 +00:00
Neil Roberts
6c5110cb4b cogl: Add an initialiser for enable_flags in cogl_begin_gl
This fixes a warning about an uninitialised value. It could also
potentially fix some crashes for example if the enable_flags value
happened to include a bit for enabling a vertex array if no vertex
buffer pointer was set.
2009-11-09 11:50:16 +00:00
Emmanuele Bassi
2fca6087e9 Clean up cogl.h template
The inclusion order is mostly random, and it should really be
in alphabetic order, just like clutter.h.

Also, cogl-vertex-buffer.h is included twice.
2009-11-06 15:06:39 +00:00
Tim Horton
544543e249 osx: CGBitmapContextCreate can't make 24bpp, alphaless offscreen pixmaps
While loading a JPEG from disk (with clutter_texture_new_from_file),
I got the following:

<Error>: CGBitmapContextCreate: unsupported parameter combination: 8
integer bits/component; 24 bits/pixel; 3-component colorspace;
kCGImageAlphaNone; 3072 bytes/row.
<Error>: CGContextDrawImage: invalid context

Looking around, I found that CGBitmapContextCreate can't make 24bpp
offscreen pixmaps without an alpha channel...

This fixes the bug, and seems to not break other things...

http://bugzilla.openedhand.com/show_bug.cgi?id=1159

Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>
2009-11-06 14:10:41 +00:00
Emmanuele Bassi
339b447075 Do not pass flags to g_module_open(NULL)
The flags are ignored when opening the main module, so we
should pass 0 to avoid confusion when reading the source.
2009-11-06 14:06:18 +00:00
Emmanuele Bassi
eb0adfe2bc Merge branch 'josh-osx-fixes'
* josh-osx-fixes:
  osx: Fix a warning on Snow Leopard
  docs: Fix OS X docs to install Ports in correct order
  osx: Implement the updated ClutterStageWindow interface
2009-11-06 11:50:22 +00:00
Robert Bragg
b0c60ce77a [clip-stack] stop using deprecated cogl_clip_push_window_rect API
try_pushing_rect_as_window_rect now uses the new
cogl_clip_push_window_rectangle API.
2009-11-05 21:10:17 +00:00
Robert Bragg
2e0e441031 [cogl-clip] deprecate parts and cleanup the API
cogl_clip_push() which accepts a rectangle in model space shouldn't have
been defined to take x,y,width,height arguments because this isn't consistant
with other Cogl API dealing with model space rectangles.  If you are using a
coordinate system with the origin at the center and the y+ extending up,
then x,y,width,height isn't as natural as (x0,y0)(x1,y1). This API has
now been replace with cogl_clip_push_rectangle()

(As a general note: the Cogl API should only use the x,y,width,height style
when the appropriate coordinate space is defined by Cogl to have a top left
origin.  E.g.  window coordinates, or potentially texture coordinates)

cogl_clip_push_window_rect() shouldn't have been defined to take float
arguments since we only clip with integral pixel precision. We also
shouldn't have abbreviated "rectangle". This API has been replaced with
cogl_clip_push_window_rectangle()

cogl_clip_ensure() wasn't documented at all in Clutter 1.0 and probably
no one even knew it existed. This API isn't useful, and so it's now
deprecated. If no one complains we may remove the API altogether for
Clutter 1.2.

cogl_clip_stack_save() and cogl_clip_stack_restore() were originally added
to allow us to save/restore the clip when switching to/from offscreen
rendering.  Now that offscreen draw buffers are defined to own their clip
state and the state will be automatically saved and restored this API is now
redundant and so deprecated.
2009-11-05 21:10:17 +00:00
Robert Bragg
1af8be2f70 [clip-stack] Internally track model space clip rects as (x0,y0)(x1,y1) pairs
Don't track the rectangles as x0,y0,width,height. This is in preparation
for some API tidy up.
2009-11-05 21:10:17 +00:00
Robert Bragg
6ca49145f4 [clip-stack] move lots of supporting code from cogl.c to cogl-clip-stack.c
There was quite a bit of code in cogl.c that was only used to support
cogl-clip-stack.c, so this has now been moved to cogl-clip-stack.c
2009-11-05 21:10:16 +00:00
Robert Bragg
d4ffa2f819 [debug] Adds a COGL_DEBUG=force-scanline-paths
For a long time now the GLES driver for Cogl has supported a fallback
scanline rasterizer for filling paths when no stencil buffer is available,
but now that we build the same cogl-primitives code for GL and GLES I
thought it may sometimes be useful for debugging to force Cogl to use the
scanline rasterizer instead of the current stencil buffer approach.
2009-11-05 21:10:16 +00:00
Robert Bragg
b49f90acb6 [cogl-primitives] Get rid of driver specific cogl-primitives code
These files were practically identical, except the gles code had additional
support for filling paths without a stencil buffer.  All the driver code has
now been moved into cogl/cogl-primitives.c
2009-11-04 16:02:34 +00:00
Robert Bragg
9cfc8acb77 Merge commit 'cogl-reorg-draw-buffers'
* cogl-reorg-draw-buffers: (38 commits)
  [test-fbo] greatly simplify the test
  [tests] test-backface-culling: test culling with offscreen rendering
  [tests] Adds test-cogl-readpixels.c for very basic cogl_read_pixels testing
  [tests] Adds test-cogl-offscreen to validate offscreen draw buffer
  [tests] test-cogl-viewport tests semantics of over/under size viewports
  [test-texture-fbo] comment the colors defined in corner_colors
  Add a conformance test for clutter_texture_new_from_actor
  [cogl-texture-2d-sliced] allow COGL_FORMAT_ANY with _new_with_size()
  [texture] fix rounding when calculating update_fbo viewport offset
  [texture] switch to a new design for handling offscreen rendering
  [texture] split out fbo update code from cluter_texture_paint
  [texture] push/pop draw buffer when painting actors to a texture
  [texture] Avoid redundant use of cogl_clip_stack_save when drawing offscreen
  [cogl-draw-buffer] fix Cogl -> GL viewport coord conversion
  [cogl_clip_push_window_rect] fix Cogl -> GL coordinate conversion
  [matrix] Adds cogl_matrix_get_inverse API
  [debug] Adds a COGL_DEBUG=matrices debug option
  [cogl-matrix] Import Mesa's matrix manipulation code
  [cogl] avoid any state changes when cogl_set_backface_culling_enable is a nop
  [cogl] Use clockwise face winding for offscreen buffers with culling enabled
  ...
2009-11-04 03:47:36 +00:00
Robert Bragg
61654a9ab4 [cogl-texture-2d-sliced] allow COGL_FORMAT_ANY with _new_with_size()
It's useful when initialzing offscreen draw buffers to be able to ask
Cogl to create a texture of a given size and with the default internal
pixel format.
2009-11-04 03:34:07 +00:00
Robert Bragg
f910ce2ee5 [cogl-draw-buffer] fix Cogl -> GL viewport coord conversion
Before we call glViewport we need to convert Cogl viewport coordinates
(where the origin is defined to be top left) to OpenGL coordinates
(where the origin is defined to be bottom left)

We weren't considering that offscreen rendering is always upside down
and in this case Cogl coordinates == OpenGL coordinates.
2009-11-04 03:34:05 +00:00
Robert Bragg
57bd250a71 [cogl_clip_push_window_rect] fix Cogl -> GL coordinate conversion
Firstly this now uses the draw buffer height not the viewport height
when we need to perform a y = height - y conversion, since (as the
name suggests) we are dealing with window coordinates not viewport
coordinates.

Secondly this skips any conversion when the current draw buffer is an
offscreen draw buffer since offscreen rendering is always forced to be
upside down and in this case Cogl window coordinates == GL window
coordinates.
2009-11-04 03:34:05 +00:00
Robert Bragg
28c7e940bf [matrix] Adds cogl_matrix_get_inverse API
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.
2009-11-04 03:34:05 +00:00
Robert Bragg
2126bf60fd [debug] Adds a COGL_DEBUG=matrices debug option
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.
2009-11-04 03:34:04 +00:00
Robert Bragg
0a1db7c4d8 [cogl-matrix] Import Mesa's matrix manipulation code
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)
2009-11-04 03:34:04 +00:00
Robert Bragg
8ca17f5262 [cogl] avoid any state changes when cogl_set_backface_culling_enable is a nop
This is a simple optimization to bail out of cogl_set_backface_culling_enable
if it's not resulting in a change of state.
2009-11-04 03:34:04 +00:00
Robert Bragg
181bf92086 [cogl] Use clockwise face winding for offscreen buffers with culling enabled
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.
2009-11-04 03:34:03 +00:00
Robert Bragg
1acf5cc36f [cogl_read_pixels] don't force a 4 byte pack alignment
Technically this change shouldn't make a difference since we are
calling glReadPixels with GL_RGBA GL_UNSIGNED_BYTE which is a 4
byte format and it should always result in the same value according
to how OpenGL calculates the location of sequential rows.

i.e. k  = a/s * ceil(snl/a) where:
 a = alignment
 s = component size (1)
 n = number of components per pixel (4)
 l = number of pixels in a row
gives:
k = 4/1 * ceil(4l/4) and k = 1/1 * ceil(4l/1) which are equivalent

I'm changing it because I've seen i915 driver code that bails out of
hardware accelerated paths if the alignment isn't 1, and because
conceptually we have no alignment constraints here so even if the current
value has no effect, when we start reading back other formats it may upset
things.
2009-11-04 03:34:03 +00:00
Robert Bragg
f59180d073 [cogl_read_pixels] call cogl_flush() before changing glPixelStore state
We were previously calling cogl_flush() after setting up the glPixelStore
state for calling glReadPixels, but flushing the journal could itself
change the glPixelStore state.
2009-11-04 03:34:02 +00:00
Robert Bragg
d1de286109 [cogl_read_pixels] ensure we flush the current draw buffer state before reading
Make sure we call _cogl_draw_buffer_flush_state() before glReadPixels() to
be sure we have bound the correct framebuffer.
2009-11-04 03:34:02 +00:00
Robert Bragg
b8fe310b6d [cogl_read_pixels] fixes for calculating the y offset when rendering offscreen
Since offscreen rendering is forced to be upside down we don't need to do
any conversion of the users coordinates to go from Cogl window coordinates
to OpenGL window coordinates.
2009-11-04 03:34:02 +00:00
Robert Bragg
800d18bc19 [read-pixels] don't flip data when reading from offscreen draw buffers
Since we do all offscreen rendering upside down (so that we can have the
origin for texture coordinates be the top left of textures for the cases
where offscreen draw buffers are bound to textures) we don't need to flip
data read back from an offscreen framebuffer before we we return it to the
user.
2009-11-04 03:34:01 +00:00
Robert Bragg
0f86470eef [clip-stack] tidy up transform_point() code
I was originally expecting the code not to handle offset viewports or
viewports with a different size to the framebuffer, but it turns out the
code worked fine.  In the process though I think I made the code slightly
more readable.
2009-11-04 03:32:52 +00:00
Robert Bragg
78ee3f71b2 [cogl] deprecate cogl_viewport() in favour of cogl_set_viewport()
cogl_viewport only accepted a viewport width and height, but there are times
when it's also desireable to have a viewport offset so that a scene can be
translated after projection but before hitting the framebuffer.
2009-11-04 03:23:21 +00:00
Robert Bragg
c2a982cf9c [cogl_read_pixels] use buffer not viewport height to calculate y offset
glReadPixel takes window coordinates not viewport coordinates so we
shouldn't have been assuming that the viewport height == window height.
2009-11-04 03:23:20 +00:00
Robert Bragg
e4fe655521 [draw-buffer] Adds cogl_draw_buffer_get_{width,height} API
Simply adds missing API to query the width and height of any Cogl draw buffer.
2009-11-04 03:23:20 +00:00
Robert Bragg
b4770c1e9b [cogl] Make sure Cogl always knows the current window geometry
Because Cogl defines the origin of viewport and window coordinates to be
top-left it always needs to know the size of the current window so that Cogl
window/viewport coordinates can be transformed into OpenGL coordinates.

This also fixes cogl_read_pixels to use the current draw buffer height
instead of the viewport height to determine the OpenGL y coordinate to use
for glReadPixels.
2009-11-04 03:23:20 +00:00
Robert Bragg
2d610c2300 [cogl] Make sure we draw upside down to offscreen draw buffers
First a few notes about Cogl coordinate systems:
- Cogl defines the window origin, viewport origin and texture coordinates
origin to be top left unlike OpenGL which defines them as bottom left.
- Cogl defines the modelview and projection identity matrices in exactly the
same way as OpenGL.
- I.e. we believe that for 2D centric constructs: windows/framebuffers,
viewports and textures developers are more used to dealing with a top left
origin, but when modeling objects in 3D; an origin at the center with y
going up is quite natural.

The way Cogl handles textures is by uploading data upside down in OpenGL
terms so that bottom left becomes top left.  (Note: This also has the
benefit that we don't need to flip the data we get from image decoding
libraries since they typically also consider top left to be the image
origin.)

The viewport and window coords are mostly handled with various y =
height - y tweaks before we pass y coordinates to OpenGL.

Generally speaking though the handling of coordinate spaces in Cogl is a bit
fragile.  I guess partly because none of it was design to be, it just
evolved from how Clutter defines its coordinates without much consideration
or testing.  I hope to improve this over a number of commits; starting here.

This commit deals with the fact that offscreen draw buffers may be bound to
textures but we don't "upload" the texture data upside down, and so if you
texture from an offscreen draw buffer you need to manually flip the texture
coordinates to get it the right way around.  We now force offscreen
rendering to be flipped upside down by tweaking the projection matrix right
before we submit it to OpenGL to scale y by -1.  The tweak is entirely
hidden from the user such that if you call cogl_get_projection you will not
see this scale.
2009-11-04 03:23:19 +00:00
Robert Bragg
4bc947cfcc [cogl] Ensure features are initialized first in cogl_create_context
Previously some context initializing was being done without valid feature
flags.
2009-11-04 03:23:19 +00:00
Robert Bragg
49db9f4f77 [clip-stack] Handle flipped rectangles in try_pushing_rect_as_window_rect()
We were ignoring the possibility that the current modelview matrix may flip
the incoming rectangle in which case we didn't calculate a valid scissor
rectangle for clipping.

This fixes: http://bugzilla.o-hand.com/show_bug.cgi?id=1809
(Clipping doesn't work within an FBO)
2009-11-04 03:23:19 +00:00
Robert Bragg
bb3a008318 [draw-buffers] First pass at overhauling Cogl's framebuffer management
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
2009-11-03 17:23:03 +00:00
Robert Bragg
6b2ff320ca [cogl-fbo] Bring the gles code more in line with gl code
Over time the two cogl-fbo.c files have needlessly diverged as bug fixes or
cleanups went into one version but not the other.  This tries to bring them
back in line with each other.  It should actually be simple enough to move
cogl-fbo.c to be a common file, and simply not build it for GLES 1.1, so
maybe I'll follow up with such a patch soon.
2009-11-02 16:55:02 +00:00
Robert Bragg
cc0af441f2 [cogl-fbo] Remove poorly documented workaround for unknown driver/hardware
The comment just said: "Some implementation require a clear before drawing
to an fbo.  Luckily it is affected by scissor test." and did a scissored
clear, which is clearly a driver bug workaround, but for what driver?  The
fact that it was copied into the gles backend (or vica versa is also
suspicious since it seems unlikely that the workaround is necessary for both
backends.)

We can easily restore the workaround with a better comment if this problem
really still exists on current drivers, but for now I'd rather minimize
hand-wavey workaround code that can't be tested.
2009-11-02 16:55:02 +00:00
Emmanuele Bassi
df920a42df build: Add missing gles/cogl-context-driver.h to dist
The gles/cogl-context-driver.h header file is missing from the
dist target, which means it's not in the tarballs.
2009-10-30 12:11:19 +00:00
Neil Roberts
435d415a45 [cogl_polygon] Enable COGL_ENABLE_BLEND when use_color is set
Otherwise you can't use the alpha channel of the vertex colors unless
the material has a texture with alpha or the material's color has
alpha less than 255.
2009-10-27 13:18:51 +00:00
Neil Roberts
67a896e5df build: Add $(top_buiddir)/clutter/cogl to the include path in clutter/cogl/cogl
Some files try to include "cogl/cogl-defines-gl.h" so
$(top_builddir)/clutter/cogl needs to be in the include path for out of
tree builds to work.
2009-10-27 12:53:57 +00:00
Emmanuele Bassi
be06fe0b75 cogl: Avoid C99-isms
Do not declare variables after statements.
2009-10-23 16:44:28 +01:00
Emmanuele Bassi
edeca915cd cogl: Remove cogl-current-matrix.c
The cogl-current-matrix.c file is unused since commit
5e5d94dfbe and it's not compiled
or distributed anymore.
2009-10-23 15:46:25 +01:00