gegl r2958 - in trunk: . gegl/process
- From: neo svn gnome org
- To: svn-commits-list gnome org
- Subject: gegl r2958 - in trunk: . gegl/process
- Date: Thu, 12 Mar 2009 18:29:33 +0000 (UTC)
Author: neo
Date: Thu Mar 12 18:29:33 2009
New Revision: 2958
URL: http://svn.gnome.org/viewvc/gegl?rev=2958&view=rev
Log:
2009-03-12 Sven Neumann <sven gimp org>
* gegl/process/gegl-processor.c: applied patch from Henrik
Akesson.
Cleans up the code and comments it.
Modified:
trunk/ChangeLog
trunk/gegl/process/gegl-processor.c
Modified: trunk/gegl/process/gegl-processor.c
==============================================================================
--- trunk/gegl/process/gegl-processor.c (original)
+++ trunk/gegl/process/gegl-processor.c Thu Mar 12 18:29:33 2009
@@ -57,6 +57,7 @@
guint n_params,
GObjectConstructParam *params);
static gdouble gegl_processor_progress (GeglProcessor *processor);
+static gint gegl_processor_get_band_size(gint size) G_GNUC_CONST;
struct _GeglProcessor
@@ -132,6 +133,9 @@
processor->chunk_size = 128 * 128;
}
+/* Initialises the fields processor->input, processor->valid_region
+ * and processor->queued_region.
+ */
static GObject *
gegl_processor_constructor (GType type,
guint n_params,
@@ -143,6 +147,8 @@
object = G_OBJECT_CLASS (gegl_processor_parent_class)->constructor (type, n_params, params);
processor = GEGL_PROCESSOR (object);
+ /* if the processor's node is a sink operation then get the producer node
+ * and set up the region (unless all is going to be needed) */
if (processor->node->operation &&
g_type_is_a (G_OBJECT_TYPE (processor->node->operation),
GEGL_TYPE_OPERATION_SINK))
@@ -157,6 +163,8 @@
processor->valid_region = NULL;
}
}
+ /* If the processor's node is not a sink operation, then just use it as
+ * an input, and set the region to NULL */
else
{
processor->input = processor->node;
@@ -261,6 +269,8 @@
}
}
+/* Sets the processor->rectangle to the given rectangle (or the node bounding
+ * box if rectangle is NULL) and removes any dirty_rectangles */
void
gegl_processor_set_rectangle (GeglProcessor *processor,
const GeglRectangle *rectangle)
@@ -274,6 +284,8 @@
rectangle = &input_bounding_box;
}
+ /* if the processor's rectangle isn't already set to the node's bounding box,
+ * then set it and remove processor->dirty_rectangles (set to NULL) */
if (! gegl_rectangle_equal (&processor->rectangle, rectangle))
{
@@ -299,6 +311,8 @@
}
}
+/* creates a new processor and sets up it's context (if the node is
+ * a operation sink wich needs the full content */
GeglProcessor *
gegl_node_new_processor (GeglNode *node,
const GeglRectangle *rectangle)
@@ -315,6 +329,10 @@
/* FIXME: Look for what pads that are available rather than looking
* at what type of operation we are dealing with
*/
+
+ /* if the node's operation is a sink and it needs the full content then
+ * a context will be set up together with a cache and
+ * needed and result rectangles */
if (node->operation &&
GEGL_IS_OPERATION_SINK (node->operation) &&
gegl_operation_sink_needs_full (node->operation))
@@ -341,7 +359,37 @@
return processor;
}
-/* returns TRUE if there is more work */
+/* Will generate band_sizes that are adapted to the size of the tiles */
+static gint
+gegl_processor_get_band_size (gint size)
+{
+ gint band_size;
+
+ band_size = size / 2;
+
+ /* try to make the rects generated match better with potential 2^n sized
+ * tiles, XXX: should be improved to make the next slice fit as well. */
+ if (band_size <= 256)
+ {
+ band_size = MIN(band_size, 128); /* prefer a band_size of 128,
+ hoping to hit tiles */
+ }
+ else if (band_size <= 512)
+ {
+ band_size = MIN(band_size, 256); /* prefer a band_size of 128,
+ hoping to hit tiles */
+ }
+
+ if (band_size < 1)
+ band_size = 1;
+
+ return band_size;
+}
+
+/* If the processor's dirty rectangle is too big then it will be cut, added
+ * to the processor's list of dirty rectangles and TRUE will be returned.
+ * If the rectangle is small enough it will be processed, using a buffer or
+ * not as appropriate, and will return TRUE if there is more work */
static gboolean
render_rectangle (GeglProcessor *processor)
{
@@ -350,6 +398,8 @@
GeglCache *cache = NULL;
gint pxsize;
+ /* Retreive the cache if the processor's node is not buffered if it's
+ * operation is a sink and it doesn't use the full area */
buffered = !(GEGL_IS_OPERATION_SINK(processor->node->operation) &&
!gegl_operation_sink_needs_full (processor->node->operation));
if (buffered)
@@ -362,76 +412,46 @@
{
GeglRectangle *dr = processor->dirty_rectangles->data;
+ /* If a dirty rectangle is bigger than the max area, then cut it
+ * to smaller pieces */
if (dr->height * dr->width > max_area && 1)
{
gint band_size;
- if (dr->width > dr->height)
- {
- GeglRectangle *fragment;
-
-/* try to make the rects generated match better with potential 2^n sized
- * tiles, XXX: should be improved to make the next slice fit as well.
- */
- band_size = dr->width / 2;
-#if 1
- if (band_size <= 256)
- {
- band_size = MIN(band_size, 128); /* prefer a band_size of 128,
- hoping to hit tiles */
- }
- else if (band_size <= 512)
- {
- band_size = MIN(band_size, 256); /* prefer a band_size of 128,
- hoping to hit tiles */
- }
-#endif
-
- if (band_size < 1)
- band_size = 1;
+ g_debug( "{%s:%u} rectangle (%ux%u) too big (> %u)",
+ __FILE__, __LINE__, dr->height, dr->width, max_area );
- fragment = g_slice_dup (GeglRectangle, dr);
-
- fragment->width = band_size;
- dr->width -= band_size;
- dr->x += band_size;
-
- processor->dirty_rectangles = g_slist_prepend (processor->dirty_rectangles, fragment);
-
- return TRUE;
- }
- else
- {
- GeglRectangle *fragment;
-
- band_size = dr->height / 2;
-
-
- if (band_size <= 256)
- {
- band_size = MIN(band_size, 128); /* prefer a band_size of 128,
- hoping to hit tiles */
- }
- else if (band_size <= 512)
- {
- band_size = MIN(band_size, 256); /* prefer a band_size of 128,
- hoping to hit tiles */
- }
-
- if (band_size < 1)
- band_size = 1;
+ {
+ GeglRectangle *fragment;
- fragment = g_slice_dup (GeglRectangle, dr);
+ fragment = g_slice_dup (GeglRectangle, dr);
- fragment->height = band_size;
- dr->height -= band_size;
- dr->y += band_size;
+ /* When splitting a rectangle, we'll do it on the biggest side */
+ if (dr->width > dr->height)
+ {
+ band_size = gegl_processor_get_band_size ( dr->width );
+
+ fragment->width = band_size;
+ dr->width -= band_size;
+ dr->x += band_size;
+ }
+ else
+ {
+ band_size = gegl_processor_get_band_size (dr->height);
- processor->dirty_rectangles = g_slist_prepend (processor->dirty_rectangles, fragment);
+ fragment->height = band_size;
+ dr->height -= band_size;
+ dr->y += band_size;
+ }
+ processor->dirty_rectangles = g_slist_prepend (processor->dirty_rectangles, fragment);
- return TRUE;
- }
+ g_debug ("{%s:%u} rectangle split to (%ux%u) and (%ux%u)\n",
+ __FILE__, __LINE__, dr->height, dr->width,
+ fragment->height, fragment->width);
+ }
+ return TRUE;
}
+ /* remove the rectangle that will be processed from the list of dirty ones */
processor->dirty_rectangles = g_slist_remove (processor->dirty_rectangles, dr);
if (!dr->width || !dr->height)
@@ -444,27 +464,30 @@
if (buffered)
{
/* only do work if the rectangle is not completely inside the valid
- * region of the cache
- */
+ * region of the cache */
if (gegl_region_rect_in (cache->valid_region, dr) !=
GEGL_OVERLAP_RECTANGLE_IN)
{
+ /* create a buffer and initialise it */
guchar *buf;
gegl_region_union_with_rect (cache->valid_region, dr);
buf = g_malloc (dr->width * dr->height * pxsize);
g_assert (buf);
+ /* do the image calculations using the buffer */
gegl_node_blit (cache->node, 1.0, dr, cache->format, buf,
GEGL_AUTO_ROWSTRIDE, GEGL_BLIT_DEFAULT);
- /* check that we haven't been recently */
+ /* copy the buffer data into the cache */
gegl_buffer_set (GEGL_BUFFER (cache), dr, cache->format, buf,
GEGL_AUTO_ROWSTRIDE);
+ /* tells the cache that the rectangle (dr) has been computed */
gegl_cache_computed (cache, dr);
+ /* release the buffer */
g_free (buf);
}
}
@@ -487,6 +510,7 @@
return rectangle->width * rectangle->height;
}
+/* returns the total area covered by a region */
static gint
region_area (GeglRegion *region)
{
@@ -506,6 +530,7 @@
return sum;
}
+/* returns the area not covered by the rectangle */
static gint
area_left (GeglRegion *area,
GeglRectangle *rectangle)
@@ -520,6 +545,7 @@
return sum;
}
+/* returns true if everything is rendered */
static gboolean
gegl_processor_is_rendered (GeglProcessor *processor)
{
@@ -567,6 +593,8 @@
return ret;
}
+/* Processes the rectangle (might be only splitting it to smaller ones) and
+ * updates the progress indicator */
static gboolean
gegl_processor_render (GeglProcessor *processor,
GeglRectangle *rectangle,
@@ -686,6 +714,8 @@
return !gegl_processor_is_rendered (processor);
}
+/* Will call gegl_processor_render and when there is no more work to be done,
+ * it will write the result to the destination */
gboolean
gegl_processor_work (GeglProcessor *processor,
gdouble *progress)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]