mirror of https://github.com/GNOME/gimp.git
added a variant of pixel_regions_process_parallel() that takes a progress
2005-02-16 Sven Neumann <sven@gimp.org> * app/base/pixel-processor.[ch]: added a variant of pixel_regions_process_parallel() that takes a progress callback and progress data. Does only work for the single-threaded case yet. * app/core/gimpdrawable-blend.c (gradient_fill_region): parallelized.
This commit is contained in:
parent
6be469171d
commit
82a5329fbf
|
@ -1,3 +1,11 @@
|
|||
2005-02-16 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/base/pixel-processor.[ch]: added a variant of
|
||||
pixel_regions_process_parallel() that takes a progress callback and
|
||||
progress data. Does only work for the single-threaded case yet.
|
||||
|
||||
* app/core/gimpdrawable-blend.c (gradient_fill_region): parallelized.
|
||||
|
||||
2005-02-16 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/core/gimpimage-contiguous-region.c
|
||||
|
|
|
@ -37,6 +37,10 @@
|
|||
#include "tile.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define PROGRESS_TIMEOUT 64
|
||||
|
||||
|
||||
static gint max_threads = 0;
|
||||
|
||||
|
||||
|
@ -60,17 +64,19 @@ typedef struct _PixelProcessor PixelProcessor;
|
|||
|
||||
struct _PixelProcessor
|
||||
{
|
||||
gpointer data;
|
||||
PixelProcessorFunc func;
|
||||
PixelRegionIterator *PRI;
|
||||
gpointer data;
|
||||
|
||||
#ifdef ENABLE_MP
|
||||
GStaticMutex mutex;
|
||||
gint threads;
|
||||
#endif
|
||||
|
||||
PixelRegionIterator *PRI;
|
||||
gint num_regions;
|
||||
PixelRegion *regions[4];
|
||||
|
||||
gulong progress;
|
||||
};
|
||||
|
||||
|
||||
|
@ -98,6 +104,9 @@ do_parallel_regions (PixelProcessor *processor)
|
|||
|
||||
do
|
||||
{
|
||||
guint pixels = (processor->PRI->portion_width *
|
||||
processor->PRI->portion_height);
|
||||
|
||||
for (i = 0; i < processor->num_regions; i++)
|
||||
if (processor->regions[i])
|
||||
{
|
||||
|
@ -141,18 +150,19 @@ do_parallel_regions (PixelProcessor *processor)
|
|||
g_warning ("do_parallel_regions: Bad number of regions %d\n",
|
||||
processor->num_regions);
|
||||
break;
|
||||
}
|
||||
|
||||
g_static_mutex_lock (&processor->mutex);
|
||||
|
||||
for (i = 0; i < processor->num_regions; i++)
|
||||
if (processor->regions[i])
|
||||
{
|
||||
if (tr[i].tiles)
|
||||
tile_release (tr[i].curtile, tr[i].dirty);
|
||||
}
|
||||
|
||||
processor->progress += pixels;
|
||||
}
|
||||
|
||||
g_static_mutex_lock (&processor->mutex);
|
||||
|
||||
for (i = 0; i < processor->num_regions; i++)
|
||||
if (processor->regions[i])
|
||||
{
|
||||
if (tr[i].tiles)
|
||||
tile_release (tr[i].curtile, tr[i].dirty);
|
||||
}
|
||||
}
|
||||
|
||||
while (processor->PRI &&
|
||||
(processor->PRI = pixel_regions_process (processor->PRI)));
|
||||
|
||||
|
@ -169,8 +179,16 @@ do_parallel_regions (PixelProcessor *processor)
|
|||
*/
|
||||
|
||||
static gpointer
|
||||
do_parallel_regions_single (PixelProcessor *processor)
|
||||
do_parallel_regions_single (PixelProcessor *processor,
|
||||
PixelProcessorProgressFunc progress_func,
|
||||
gpointer progress_data,
|
||||
gulong total)
|
||||
{
|
||||
GTimeVal last_time;
|
||||
|
||||
if (progress_func)
|
||||
g_get_current_time (&last_time);
|
||||
|
||||
do
|
||||
{
|
||||
switch (processor->num_regions)
|
||||
|
@ -205,8 +223,26 @@ do_parallel_regions_single (PixelProcessor *processor)
|
|||
g_warning ("do_parallel_regions_single: Bad number of regions %d\n",
|
||||
processor->num_regions);
|
||||
}
|
||||
}
|
||||
|
||||
if (progress_func)
|
||||
{
|
||||
GTimeVal now;
|
||||
|
||||
processor->progress += (processor->PRI->portion_width *
|
||||
processor->PRI->portion_height);
|
||||
|
||||
g_get_current_time (&now);
|
||||
|
||||
if (((now.tv_sec - last_time.tv_sec) * 1024 +
|
||||
(now.tv_usec - last_time.tv_usec) / 1024) > PROGRESS_TIMEOUT)
|
||||
{
|
||||
progress_func (progress_data,
|
||||
(gdouble) processor->progress / (gdouble) total);
|
||||
|
||||
last_time = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (processor->PRI &&
|
||||
(processor->PRI = pixel_regions_process (processor->PRI)));
|
||||
|
||||
|
@ -217,11 +253,15 @@ do_parallel_regions_single (PixelProcessor *processor)
|
|||
#define TILES_PER_THREAD 8
|
||||
|
||||
static void
|
||||
pixel_regions_do_parallel (PixelProcessor *processor)
|
||||
pixel_regions_do_parallel (PixelProcessor *processor,
|
||||
PixelProcessorProgressFunc progress_func,
|
||||
gpointer progress_data)
|
||||
{
|
||||
gulong pixels = (processor->PRI->region_width *
|
||||
processor->PRI->region_height);
|
||||
|
||||
#ifdef ENABLE_MP
|
||||
glong tiles = (processor->PRI->region_width *
|
||||
processor->PRI->region_height) / (TILE_WIDTH * TILE_HEIGHT);
|
||||
gulong tiles = pixels / (TILE_WIDTH * TILE_HEIGHT);
|
||||
|
||||
if (max_threads > 1 && tiles > TILES_PER_THREAD)
|
||||
{
|
||||
|
@ -255,15 +295,18 @@ pixel_regions_do_parallel (PixelProcessor *processor)
|
|||
else
|
||||
#endif
|
||||
{
|
||||
do_parallel_regions_single (processor);
|
||||
do_parallel_regions_single (processor,
|
||||
progress_func, progress_data, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pixel_regions_process_parallel_valist (PixelProcessorFunc func,
|
||||
gpointer data,
|
||||
gint num_regions,
|
||||
va_list ap)
|
||||
pixel_regions_process_parallel_valist (PixelProcessorFunc func,
|
||||
gpointer data,
|
||||
PixelProcessorProgressFunc progress_func,
|
||||
gpointer progress_data,
|
||||
gint num_regions,
|
||||
va_list ap)
|
||||
{
|
||||
PixelProcessor processor = { NULL, };
|
||||
gint i;
|
||||
|
@ -271,7 +314,7 @@ pixel_regions_process_parallel_valist (PixelProcessorFunc func,
|
|||
for (i = 0; i < num_regions; i++)
|
||||
processor.regions[i] = va_arg (ap, PixelRegion *);
|
||||
|
||||
switch(num_regions)
|
||||
switch (num_regions)
|
||||
{
|
||||
case 1:
|
||||
processor.PRI = pixel_regions_register (num_regions,
|
||||
|
@ -300,8 +343,8 @@ pixel_regions_process_parallel_valist (PixelProcessorFunc func,
|
|||
break;
|
||||
|
||||
default:
|
||||
g_warning ("pixel_regions_process_parallel:"
|
||||
"Bad number of regions %d\n", processor.num_regions);
|
||||
g_warning ("pixel_regions_process_parallel: "
|
||||
"bad number of regions (%d)\n", processor.num_regions);
|
||||
}
|
||||
|
||||
if (! processor.PRI)
|
||||
|
@ -317,7 +360,9 @@ pixel_regions_process_parallel_valist (PixelProcessorFunc func,
|
|||
processor.threads = 0;
|
||||
#endif
|
||||
|
||||
pixel_regions_do_parallel (&processor);
|
||||
processor.progress = 0;
|
||||
|
||||
pixel_regions_do_parallel (&processor, progress_func, progress_data);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -332,6 +377,8 @@ pixel_processor_set_num_threads (gint num_threads)
|
|||
g_return_if_fail (num_threads > 0);
|
||||
|
||||
max_threads = CLAMP (num_threads, 1, GIMP_MAX_NUM_THREADS);
|
||||
|
||||
g_printerr ("max_threads: %d\n", max_threads);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -350,7 +397,28 @@ pixel_regions_process_parallel (PixelProcessorFunc func,
|
|||
|
||||
va_start (va, num_regions);
|
||||
|
||||
pixel_regions_process_parallel_valist (func, data, num_regions, va);
|
||||
pixel_regions_process_parallel_valist (func, data,
|
||||
NULL, NULL,
|
||||
num_regions, va);
|
||||
|
||||
va_end (va);
|
||||
}
|
||||
|
||||
void
|
||||
pixel_regions_process_parallel_progress (PixelProcessorFunc func,
|
||||
gpointer data,
|
||||
PixelProcessorProgressFunc progress_func,
|
||||
gpointer progress_data,
|
||||
gint num_regions,
|
||||
...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start (va, num_regions);
|
||||
|
||||
pixel_regions_process_parallel_valist (func, data,
|
||||
progress_func, progress_data,
|
||||
num_regions, va);
|
||||
|
||||
va_end (va);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
#define GIMP_MAX_NUM_THREADS 16
|
||||
|
||||
|
||||
typedef void (* PixelProcessorFunc) (void);
|
||||
typedef void (* PixelProcessorFunc) (void);
|
||||
typedef void (* PixelProcessorProgressFunc) (gpointer progress_data,
|
||||
gdouble fraction);
|
||||
|
||||
|
||||
void pixel_processor_init (gint num_threads);
|
||||
|
@ -37,5 +39,13 @@ void pixel_regions_process_parallel (PixelProcessorFunc func,
|
|||
gint num_regions,
|
||||
...);
|
||||
|
||||
void pixel_regions_process_parallel_progress
|
||||
(PixelProcessorFunc func,
|
||||
gpointer data,
|
||||
PixelProcessorProgressFunc progress_func,
|
||||
gpointer progress_data,
|
||||
gint num_regions,
|
||||
...);
|
||||
|
||||
|
||||
#endif /* __PIXEL_PROCESSOR_H__ */
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "base/pixel-processor.h"
|
||||
#include "base/pixel-region.h"
|
||||
#include "base/tile.h"
|
||||
#include "base/tile-manager.h"
|
||||
|
@ -57,6 +58,7 @@ typedef struct
|
|||
gdouble dist;
|
||||
gdouble vec[2];
|
||||
GimpRepeatMode repeat;
|
||||
GRand *dither_rand;
|
||||
} RenderBlendData;
|
||||
|
||||
typedef struct
|
||||
|
@ -65,7 +67,6 @@ typedef struct
|
|||
guchar *row_data;
|
||||
gint bytes;
|
||||
gint width;
|
||||
gboolean dither;
|
||||
GRand *dither_rand;
|
||||
} PutPixelData;
|
||||
|
||||
|
@ -150,6 +151,11 @@ static void gradient_fill_region (GimpImage *gimage,
|
|||
gdouble ey,
|
||||
GimpProgress *progress);
|
||||
|
||||
static void gradient_fill_single_region_rgb (RenderBlendData *rbd,
|
||||
PixelRegion *PR);
|
||||
static void gradient_fill_single_region_gray (RenderBlendData *rbd,
|
||||
PixelRegion *PR);
|
||||
|
||||
|
||||
/* variables for the shapeburst algs */
|
||||
|
||||
|
@ -803,7 +809,7 @@ gradient_put_pixel (gint x,
|
|||
|
||||
if (ppd->bytes >= 3)
|
||||
{
|
||||
if (ppd->dither)
|
||||
if (ppd->dither_rand)
|
||||
{
|
||||
gdouble dither_prob;
|
||||
gdouble ftmp;
|
||||
|
@ -853,7 +859,7 @@ gradient_put_pixel (gint x,
|
|||
/* Convert to grayscale */
|
||||
gdouble gray = gimp_rgb_intensity (color);
|
||||
|
||||
if (ppd->dither)
|
||||
if (ppd->dither_rand)
|
||||
{
|
||||
gdouble dither_prob;
|
||||
gdouble ftmp;
|
||||
|
@ -910,11 +916,6 @@ gradient_fill_region (GimpImage *gimage,
|
|||
GimpProgress *progress)
|
||||
{
|
||||
RenderBlendData rbd;
|
||||
gint x, y;
|
||||
gint endx, endy;
|
||||
gpointer pr;
|
||||
guchar *data;
|
||||
GimpRGB color;
|
||||
GRand *dither_rand = NULL;
|
||||
|
||||
rbd.gradient = gimp_context_get_gradient (context);
|
||||
|
@ -1019,7 +1020,6 @@ gradient_fill_region (GimpImage *gimage,
|
|||
ppd.row_data = g_malloc (width * PR->bytes);
|
||||
ppd.bytes = PR->bytes;
|
||||
ppd.width = width;
|
||||
ppd.dither = dither;
|
||||
ppd.dither_rand = dither_rand;
|
||||
|
||||
gimp_adaptive_supersample_area (0, 0, (width - 1), (height - 1),
|
||||
|
@ -1034,116 +1034,139 @@ gradient_fill_region (GimpImage *gimage,
|
|||
}
|
||||
else
|
||||
{
|
||||
gint max_progress = PR->w * PR->h;
|
||||
gint curr_progress = 0;
|
||||
PixelProcessorFunc func;
|
||||
PixelProcessorProgressFunc progress_func = NULL;
|
||||
|
||||
for (pr = pixel_regions_register (1, PR);
|
||||
pr != NULL;
|
||||
pr = pixel_regions_process (pr))
|
||||
{
|
||||
data = PR->data;
|
||||
endx = PR->x + PR->w;
|
||||
endy = PR->y + PR->h;
|
||||
rbd.dither_rand = dither_rand;
|
||||
|
||||
for (y = PR->y; y < endy; y++)
|
||||
{
|
||||
for (x = PR->x; x < endx; x++)
|
||||
{
|
||||
gradient_render_pixel (x, y, &color, &rbd);
|
||||
if (PR->bytes >= 3)
|
||||
func = (PixelProcessorFunc) gradient_fill_single_region_rgb;
|
||||
else
|
||||
func = (PixelProcessorFunc) gradient_fill_single_region_gray;
|
||||
|
||||
if (PR->bytes >= 3)
|
||||
{
|
||||
if (dither)
|
||||
{
|
||||
gdouble dither_prob;
|
||||
gdouble ftmp;
|
||||
gint itmp;
|
||||
if (progress)
|
||||
progress_func = (PixelProcessorProgressFunc) gimp_progress_set_value;
|
||||
|
||||
ftmp = color.r * 255.0;
|
||||
itmp = ftmp;
|
||||
dither_prob = ftmp - itmp;
|
||||
|
||||
if (g_rand_double (dither_rand) < dither_prob)
|
||||
color.r += (1.0 / 255.0);
|
||||
|
||||
ftmp = color.g * 255.0;
|
||||
itmp = ftmp;
|
||||
dither_prob = ftmp - itmp;
|
||||
|
||||
if (g_rand_double (dither_rand) < dither_prob)
|
||||
color.g += (1.0 / 255.0);
|
||||
|
||||
ftmp = color.b * 255.0;
|
||||
itmp = ftmp;
|
||||
dither_prob = ftmp - itmp;
|
||||
|
||||
if (g_rand_double (dither_rand) < dither_prob)
|
||||
color.b += (1.0 / 255.0);
|
||||
|
||||
ftmp = color.a * 255.0;
|
||||
itmp = ftmp;
|
||||
dither_prob = ftmp - itmp;
|
||||
|
||||
if (g_rand_double (dither_rand) < dither_prob)
|
||||
color.a += (1.0 / 255.0);
|
||||
|
||||
if (color.r > 1.0) color.r = 1.0;
|
||||
if (color.g > 1.0) color.g = 1.0;
|
||||
if (color.b > 1.0) color.b = 1.0;
|
||||
if (color.a > 1.0) color.a = 1.0;
|
||||
}
|
||||
|
||||
*data++ = color.r * 255.0;
|
||||
*data++ = color.g * 255.0;
|
||||
*data++ = color.b * 255.0;
|
||||
*data++ = color.a * 255.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Convert to grayscale */
|
||||
gdouble gray = gimp_rgb_intensity (&color);
|
||||
|
||||
if (dither)
|
||||
{
|
||||
gdouble dither_prob;
|
||||
gdouble ftmp;
|
||||
gint itmp;
|
||||
|
||||
ftmp = gray * 255.0;
|
||||
itmp = ftmp;
|
||||
dither_prob = ftmp - itmp;
|
||||
|
||||
if (g_rand_double (dither_rand) < dither_prob)
|
||||
gray += (1.0 / 255.0);
|
||||
|
||||
ftmp = color.a * 255.0;
|
||||
itmp = ftmp;
|
||||
dither_prob = ftmp - itmp;
|
||||
|
||||
if (g_rand_double (dither_rand) < dither_prob)
|
||||
color.a += (1.0 / 255.0);
|
||||
|
||||
if (gray > 1.0) gray = 1.0;
|
||||
if (color.a > 1.0) color.a = 1.0;
|
||||
}
|
||||
|
||||
*data++ = gray * 255.0;
|
||||
*data++ = color.a * 255.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (progress)
|
||||
{
|
||||
curr_progress += PR->w * PR->h;
|
||||
|
||||
gimp_progress_set_value (progress,
|
||||
(gdouble) curr_progress /
|
||||
(gdouble) max_progress);
|
||||
}
|
||||
}
|
||||
pixel_regions_process_parallel_progress (func, &rbd,
|
||||
progress_func, progress,
|
||||
1, PR);
|
||||
}
|
||||
|
||||
if (dither)
|
||||
g_rand_free (dither_rand);
|
||||
}
|
||||
|
||||
static void
|
||||
gradient_fill_single_region_rgb (RenderBlendData *rbd,
|
||||
PixelRegion *PR)
|
||||
{
|
||||
guchar *data = PR->data;
|
||||
gint endx = PR->x + PR->w;
|
||||
gint endy = PR->y + PR->h;
|
||||
gint x, y;
|
||||
|
||||
for (y = PR->y; y < endy; y++)
|
||||
{
|
||||
for (x = PR->x; x < endx; x++)
|
||||
{
|
||||
GimpRGB color;
|
||||
|
||||
gradient_render_pixel (x, y, &color, rbd);
|
||||
|
||||
if (rbd->dither_rand)
|
||||
{
|
||||
gdouble dither_prob;
|
||||
gdouble ftmp;
|
||||
gint itmp;
|
||||
|
||||
ftmp = color.r * 255.0;
|
||||
itmp = ftmp;
|
||||
dither_prob = ftmp - itmp;
|
||||
|
||||
if (g_rand_double (rbd->dither_rand) < dither_prob)
|
||||
color.r += (1.0 / 255.0);
|
||||
|
||||
ftmp = color.g * 255.0;
|
||||
itmp = ftmp;
|
||||
dither_prob = ftmp - itmp;
|
||||
|
||||
if (g_rand_double (rbd->dither_rand) < dither_prob)
|
||||
color.g += (1.0 / 255.0);
|
||||
|
||||
ftmp = color.b * 255.0;
|
||||
itmp = ftmp;
|
||||
dither_prob = ftmp - itmp;
|
||||
|
||||
if (g_rand_double (rbd->dither_rand) < dither_prob)
|
||||
color.b += (1.0 / 255.0);
|
||||
|
||||
ftmp = color.a * 255.0;
|
||||
itmp = ftmp;
|
||||
dither_prob = ftmp - itmp;
|
||||
|
||||
if (g_rand_double (rbd->dither_rand) < dither_prob)
|
||||
color.a += (1.0 / 255.0);
|
||||
|
||||
if (color.r > 1.0) color.r = 1.0;
|
||||
if (color.g > 1.0) color.g = 1.0;
|
||||
if (color.b > 1.0) color.b = 1.0;
|
||||
if (color.a > 1.0) color.a = 1.0;
|
||||
}
|
||||
|
||||
*data++ = color.r * 255.0;
|
||||
*data++ = color.g * 255.0;
|
||||
*data++ = color.b * 255.0;
|
||||
*data++ = color.a * 255.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gradient_fill_single_region_gray (RenderBlendData *rbd,
|
||||
PixelRegion *PR)
|
||||
{
|
||||
guchar *data = PR->data;
|
||||
gint endx = PR->x + PR->w;
|
||||
gint endy = PR->y + PR->h;
|
||||
gint x, y;
|
||||
|
||||
for (y = PR->y; y < endy; y++)
|
||||
{
|
||||
for (x = PR->x; x < endx; x++)
|
||||
{
|
||||
GimpRGB color;
|
||||
gdouble gray;
|
||||
|
||||
gradient_render_pixel (x, y, &color, rbd);
|
||||
|
||||
gray = gimp_rgb_intensity (&color);
|
||||
|
||||
if (rbd->dither_rand)
|
||||
{
|
||||
gdouble dither_prob;
|
||||
gdouble ftmp;
|
||||
gint itmp;
|
||||
|
||||
ftmp = gray * 255.0;
|
||||
itmp = ftmp;
|
||||
dither_prob = ftmp - itmp;
|
||||
|
||||
if (g_rand_double (rbd->dither_rand) < dither_prob)
|
||||
gray += (1.0 / 255.0);
|
||||
|
||||
ftmp = color.a * 255.0;
|
||||
itmp = ftmp;
|
||||
dither_prob = ftmp - itmp;
|
||||
|
||||
if (g_rand_double (rbd->dither_rand) < dither_prob)
|
||||
color.a += (1.0 / 255.0);
|
||||
|
||||
if (gray > 1.0) gray = 1.0;
|
||||
if (color.a > 1.0) color.a = 1.0;
|
||||
}
|
||||
|
||||
*data++ = gray * 255.0;
|
||||
*data++ = color.a * 255.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue