new function pixel_regions_process_parallel

* app/pixel_region.c, app/pixel_region.h: new function
	pixel_regions_process_parallel

	* app/paint_funcs.c: use pixel_regions_process_parallel in
	combine_regions.  fixed bug in combine_inten_a_and_inten_a_pixels

	* app/gimprc.c, app/gimprc.h, app/preferences_dialog.c: added
	num-processors variable

	* config.h.in, configure.in, acconfig.h: add configure option
 	--with-mp and define ENABLE_MP.
This commit is contained in:
jaycox 1999-01-22 23:46:44 +00:00
parent 2bdd456f6b
commit 74fae96949
15 changed files with 1148 additions and 311 deletions

View File

@ -1,3 +1,17 @@
1999-01-22 Jay Cox <jaycox@earthlink.net>
* app/pixel_region.c, app/pixel_region.h: new function
pixel_regions_process_parallel
* app/paint_funcs.c: use pixel_regions_process_parallel in
combine_regions. fixed bug in combine_inten_a_and_inten_a_pixels
* app/gimprc.c, app/gimprc.h, app/preferences_dialog.c: added
num-processors variable
* config.h.in, configure.in, acconfig.h: add configure option
--with-mp and define ENABLE_MP.
Thu Jan 21 22:58:00 PST 1999 Manish Singh <yosh@gimp.org>
* gimp1_1_splash.ppm: new splash, from Shaw Terwilliger

View File

@ -14,6 +14,7 @@
Leave the following blank line there!! Autoheader needs it. */
#undef ENABLE_MP
#undef ENABLE_NLS
#undef HAVE_CATGETS
#undef HAVE_DIRENT_H

View File

@ -21,10 +21,24 @@
#include <string.h>
#include "appenv.h"
#include "pixel_region.h"
#include "gimprc.h"
#include "tile_manager_pvt.h"
#include "tile.h" /* ick. */
#ifdef ENABLE_MP
#include <pthread.h>
#define IF_THREAD(statement) statement
#else /* !USE_PTHREADS */
#define IF_THREAD(statement)
#endif /* !USE_PTHREADS */
typedef struct _PixelRegionHolder PixelRegionHolder;
struct _PixelRegionHolder
@ -289,6 +303,159 @@ pixel_region_set_col (PR, x, y, h, data)
}
}
typedef void (*p1_func)(void *, PixelRegion *);
typedef void (*p2_func)(void *, PixelRegion * ,PixelRegion *);
typedef void (*p3_func)(void *, PixelRegion * ,PixelRegion *, PixelRegion *);
typedef void (*p4_func)(void *, PixelRegion * ,PixelRegion *, PixelRegion *,
PixelRegion *);
struct parallel_struct
{
void *data;
p_func f;
PixelRegionIterator *PRI;
IF_THREAD(pthread_mutex_t mutex;)
int nthreads;
int n_regions;
PixelRegion *r[4];
};
static void *
do_parallel_regions(struct parallel_struct *p_s)
{
PixelRegion tr[4];
int ntiles = 0;
int i;
IF_THREAD(pthread_mutex_lock(&p_s->mutex);)
if (p_s->nthreads != 0 && p_s->PRI)
p_s->PRI = (PixelRegionIterator*)pixel_regions_process(p_s->PRI);
if (p_s->PRI == NULL)
{
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
return NULL;
}
p_s->nthreads++;
do
{
for (i = 0; i < p_s->n_regions; i++)
if (p_s->r[i])
memcpy(&tr[i], p_s->r[i], sizeof(PixelRegion));
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
ntiles++;
switch(p_s->n_regions)
{
case 1:
((p1_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL);
break;
case 2:
((p2_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL);
break;
case 3:
((p3_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL,
p_s->r[2] ? &tr[2] : NULL);
break;
case 4:
((p4_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL,
p_s->r[2] ? &tr[2] : NULL,
p_s->r[3] ? &tr[3] : NULL);
break;
default:
g_message("do_parallel_regions: Bad number of regions %d\n",
p_s->n_regions);
}
IF_THREAD(pthread_mutex_lock(&p_s->mutex);)
} while (p_s->PRI && (p_s->PRI = (PixelRegionIterator*)pixel_regions_process(p_s->PRI)));
p_s->nthreads--;
/* fprintf(stderr, "processed %d tiles\n", ntiles); */
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
return NULL;
}
#define MAX_THREADS 30
void pixel_regions_process_parallel(p_func f, void *data, int num_regions, ...)
{
int i;
PixelRegionIterator *PRI;
struct parallel_struct p_s;
IF_THREAD(pthread_t threads[MAX_THREADS];)
IF_THREAD(pthread_attr_t pthread_attr;)
int nthreads;
va_list ap;
va_start (ap, num_regions);
for (i = 0; i < num_regions; i++)
p_s.r[i] = va_arg (ap, PixelRegion *);
va_end (ap);
switch(num_regions)
{
case 1:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0]);
break;
case 2:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0],
p_s.r[1]);
break;
case 3:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0],
p_s.r[1],
p_s.r[2]);
break;
case 4:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0],
p_s.r[1],
p_s.r[2],
p_s.r[3]);
break;
default:
g_message("pixel_regions_process_parallel: Bad number of regions %d\n",
p_s.n_regions);
}
if (!p_s.PRI)
return;
p_s.f = f;
p_s.data = data;
p_s.n_regions = num_regions;
IF_THREAD(pthread_mutex_init(&p_s.mutex, NULL);)
p_s.nthreads = 0;
IF_THREAD(
nthreads = MIN(num_processors,
(p_s.PRI->region_width * p_s.PRI->region_height) /(64*64));
if (nthreads > 1)
{
pthread_attr_init (&pthread_attr);
for (i = 0; i < nthreads; i++)
{
pthread_create (&threads[i], &pthread_attr,
(void *(*)(void *)) do_parallel_regions,
&p_s);
}
for (i = 0; i < nthreads; i++)
{
pthread_join(threads[i], NULL);
}
}
else
)
do_parallel_regions(&p_s);
if (p_s.nthreads != 0)
fprintf(stderr, "Ack, we've lost a thread.");
}
void *
pixel_regions_register (int num_regions, ...)

View File

@ -36,6 +36,7 @@ struct _PixelRegion
int process_count; /* used internally */
};
typedef void (*p_func)(void);
/* PixelRegion functions */
void pixel_region_init (PixelRegion *, TileManager *, int, int, int, int, int);
@ -47,6 +48,8 @@ void pixel_region_set_row (PixelRegion *, int, int, int, unsigned char *)
void pixel_region_get_col (PixelRegion *, int, int, int, unsigned char *, int);
void pixel_region_set_col (PixelRegion *, int, int, int, unsigned char *);
void *pixel_regions_register (int, ...);
void pixel_regions_process_parallel (p_func f, void *data, int num_regions,
...);
void *pixel_regions_process (void *);
void pixel_regions_process_stop (void *);

View File

@ -107,6 +107,7 @@ static char * old_gradient_path;
static float old_monitor_xres;
static float old_monitor_yres;
static int old_using_xserver_resolution;
static int old_num_processors;
static char * edit_temp_path = NULL;
static char * edit_swap_path = NULL;
@ -120,12 +121,14 @@ static int edit_tile_cache_size;
static int edit_install_cmap;
static int edit_cycled_marching_ants;
static int edit_last_opened_size;
static int edit_num_processors;
static GtkWidget *tile_cache_size_spinbutton = NULL;
static int divided_tile_cache_size;
static int mem_size_unit;
static GtkWidget *xres_spinbutton = NULL;
static GtkWidget *yres_spinbutton = NULL;
static GtkWidget *num_processors_spinbutton = NULL;
/* Some information regarding preferences, compiled by Raph Levien 11/3/97.
@ -214,6 +217,12 @@ file_prefs_ok_callback (GtkWidget *widget,
levels_of_undo = old_levels_of_undo;
return;
}
if (num_processors < 1 || num_processors > 30)
{
g_message (_("Error: Number of processors must be between 1 and 30."));
num_processors = old_num_processors;
return;
}
if (marching_speed < 50)
{
g_message (_("Error: Marching speed must be 50 or greater."));
@ -262,6 +271,7 @@ file_prefs_save_callback (GtkWidget *widget,
GList *remove = NULL; /* options that should be commented out */
int save_stingy_memory_use;
int save_tile_cache_size;
int save_num_processors;
int save_install_cmap;
int save_cycled_marching_ants;
int save_last_opened_size;
@ -289,6 +299,7 @@ file_prefs_save_callback (GtkWidget *widget,
save_palette_path = palette_path;
save_plug_in_path = plug_in_path;
save_gradient_path = gradient_path;
save_num_processors = num_processors;
if (levels_of_undo != old_levels_of_undo)
update = g_list_append (update, "undo-levels");
@ -364,6 +375,8 @@ file_prefs_save_callback (GtkWidget *widget,
if (using_xserver_resolution != old_using_xserver_resolution ||
ABS(monitor_yres - old_monitor_yres) > 1e-5)
update = g_list_append (update, "monitor-yresolution");
if (edit_num_processors != num_processors)
update = g_list_append (update, "num-processors");
if (edit_stingy_memory_use != stingy_memory_use)
{
update = g_list_append (update, "stingy-memory-use");
@ -509,6 +522,7 @@ file_prefs_cancel_callback (GtkWidget *widget,
monitor_xres = old_monitor_xres;
monitor_yres = old_monitor_yres;
using_xserver_resolution = old_using_xserver_resolution;
num_processors = old_num_processors;
if (preview_size != old_preview_size)
{
@ -837,6 +851,8 @@ file_pref_cmd_callback (GtkWidget *widget,
old_monitor_xres = monitor_xres;
old_monitor_yres = monitor_yres;
old_using_xserver_resolution = using_xserver_resolution;
old_num_processors = num_processors;
file_prefs_strset (&old_temp_path, edit_temp_path);
file_prefs_strset (&old_swap_path, edit_swap_path);
file_prefs_strset (&old_brush_path, edit_brush_path);
@ -1283,6 +1299,31 @@ file_pref_cmd_callback (GtkWidget *widget,
if (mem_size_unit == mem_size_units[i].unit)
gtk_option_menu_set_history(GTK_OPTION_MENU (optionmenu),i);
hbox = gtk_hbox_new (FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
label = gtk_label_new (_("Number of processors to use:"));
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
adj = (GtkAdjustment *) gtk_adjustment_new (num_processors, 1,
30, 1.0,
2.0, 0.0);
num_processors_spinbutton = gtk_spin_button_new (adj, 1.0, 0.0);
gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON(num_processors_spinbutton),
GTK_SHADOW_NONE);
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(num_processors_spinbutton),
TRUE);
gtk_widget_set_usize (num_processors_spinbutton, 75, 0);
gtk_box_pack_start (GTK_BOX (hbox), num_processors_spinbutton,
FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (num_processors_spinbutton), "changed",
(GtkSignalFunc) file_prefs_spinbutton_callback,
&num_processors);
gtk_widget_show (num_processors_spinbutton);
button = gtk_check_button_new_with_label(_("Install colormap (8-bit only)"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
install_cmap);

View File

@ -134,6 +134,7 @@ int show_tool_tips = TRUE;
float monitor_xres = 72.0;
float monitor_yres = 72.0;
int using_xserver_resolution = FALSE;
int num_processors = 1;
static int get_next_token (void);
static int peek_next_token (void);
@ -255,7 +256,8 @@ static ParseFunc funcs[] =
{ "device", TT_XDEVICE, NULL, NULL },
{ "session-info", TT_XSESSIONINFO, NULL, NULL},
{ "monitor-xresolution", TT_FLOAT, &monitor_xres, NULL },
{ "monitor-yresolution", TT_FLOAT, &monitor_yres, NULL }
{ "monitor-yresolution", TT_FLOAT, &monitor_yres, NULL },
{ "num-processors", TT_INT, &num_processors, NULL }
};
static int nfuncs = sizeof (funcs) / sizeof (funcs[0]);

View File

@ -70,6 +70,7 @@ extern int show_tool_tips;
extern float monitor_xres;
extern float monitor_yres;
extern int using_xserver_resolution;
extern int num_processors;
/* function prototypes */

View File

@ -107,6 +107,7 @@ static char * old_gradient_path;
static float old_monitor_xres;
static float old_monitor_yres;
static int old_using_xserver_resolution;
static int old_num_processors;
static char * edit_temp_path = NULL;
static char * edit_swap_path = NULL;
@ -120,12 +121,14 @@ static int edit_tile_cache_size;
static int edit_install_cmap;
static int edit_cycled_marching_ants;
static int edit_last_opened_size;
static int edit_num_processors;
static GtkWidget *tile_cache_size_spinbutton = NULL;
static int divided_tile_cache_size;
static int mem_size_unit;
static GtkWidget *xres_spinbutton = NULL;
static GtkWidget *yres_spinbutton = NULL;
static GtkWidget *num_processors_spinbutton = NULL;
/* Some information regarding preferences, compiled by Raph Levien 11/3/97.
@ -214,6 +217,12 @@ file_prefs_ok_callback (GtkWidget *widget,
levels_of_undo = old_levels_of_undo;
return;
}
if (num_processors < 1 || num_processors > 30)
{
g_message (_("Error: Number of processors must be between 1 and 30."));
num_processors = old_num_processors;
return;
}
if (marching_speed < 50)
{
g_message (_("Error: Marching speed must be 50 or greater."));
@ -262,6 +271,7 @@ file_prefs_save_callback (GtkWidget *widget,
GList *remove = NULL; /* options that should be commented out */
int save_stingy_memory_use;
int save_tile_cache_size;
int save_num_processors;
int save_install_cmap;
int save_cycled_marching_ants;
int save_last_opened_size;
@ -289,6 +299,7 @@ file_prefs_save_callback (GtkWidget *widget,
save_palette_path = palette_path;
save_plug_in_path = plug_in_path;
save_gradient_path = gradient_path;
save_num_processors = num_processors;
if (levels_of_undo != old_levels_of_undo)
update = g_list_append (update, "undo-levels");
@ -364,6 +375,8 @@ file_prefs_save_callback (GtkWidget *widget,
if (using_xserver_resolution != old_using_xserver_resolution ||
ABS(monitor_yres - old_monitor_yres) > 1e-5)
update = g_list_append (update, "monitor-yresolution");
if (edit_num_processors != num_processors)
update = g_list_append (update, "num-processors");
if (edit_stingy_memory_use != stingy_memory_use)
{
update = g_list_append (update, "stingy-memory-use");
@ -509,6 +522,7 @@ file_prefs_cancel_callback (GtkWidget *widget,
monitor_xres = old_monitor_xres;
monitor_yres = old_monitor_yres;
using_xserver_resolution = old_using_xserver_resolution;
num_processors = old_num_processors;
if (preview_size != old_preview_size)
{
@ -837,6 +851,8 @@ file_pref_cmd_callback (GtkWidget *widget,
old_monitor_xres = monitor_xres;
old_monitor_yres = monitor_yres;
old_using_xserver_resolution = using_xserver_resolution;
old_num_processors = num_processors;
file_prefs_strset (&old_temp_path, edit_temp_path);
file_prefs_strset (&old_swap_path, edit_swap_path);
file_prefs_strset (&old_brush_path, edit_brush_path);
@ -1283,6 +1299,31 @@ file_pref_cmd_callback (GtkWidget *widget,
if (mem_size_unit == mem_size_units[i].unit)
gtk_option_menu_set_history(GTK_OPTION_MENU (optionmenu),i);
hbox = gtk_hbox_new (FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
label = gtk_label_new (_("Number of processors to use:"));
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
adj = (GtkAdjustment *) gtk_adjustment_new (num_processors, 1,
30, 1.0,
2.0, 0.0);
num_processors_spinbutton = gtk_spin_button_new (adj, 1.0, 0.0);
gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON(num_processors_spinbutton),
GTK_SHADOW_NONE);
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(num_processors_spinbutton),
TRUE);
gtk_widget_set_usize (num_processors_spinbutton, 75, 0);
gtk_box_pack_start (GTK_BOX (hbox), num_processors_spinbutton,
FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (num_processors_spinbutton), "changed",
(GtkSignalFunc) file_prefs_spinbutton_callback,
&num_processors);
gtk_widget_show (num_processors_spinbutton);
button = gtk_check_button_new_with_label(_("Install colormap (8-bit only)"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
install_cmap);

View File

@ -709,7 +709,6 @@ color_only_pixels (const unsigned char *src1,
}
}
void
multiply_pixels (const unsigned char *src1,
const unsigned char *src2,
@ -1002,7 +1001,7 @@ dissolve_pixels (const unsigned char *src,
rand_val = (rand() & 0xFF);
if (has_alpha)
dest[alpha] = (rand_val > opacity) ? 0 : src[alpha];
dest[alpha] = (rand_val > src[alpha]) ? 0 : src[alpha];
else
dest[alpha] = (rand_val > opacity) ? 0 : OPAQUE_OPACITY;
@ -1350,6 +1349,34 @@ initial_inten_pixels (const unsigned char *src,
*/
dest_bytes = bytes + 1;
if (bytes == 3 && affect[0] && affect[1] && affect[2])
{
if (!affect[bytes])
opacity = 0;
destp = dest + bytes;
if (mask && opacity != 0)
while(length--)
{
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = INT_MULT(opacity, *m, tmp);
src += bytes;
dest += dest_bytes;
m++;
}
else
while(length--)
{
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = opacity;
src += bytes;
dest += dest_bytes;
}
return;
}
for (b =0; b < bytes; b++)
{
destp = dest + b;
@ -1971,7 +1998,9 @@ combine_inten_a_and_inten_a_pixels (const unsigned char *src1,
int i,j;
/* HEAD */
i = ((int)m) & (sizeof(int)-1);
i = (((int)m) & (sizeof(int)-1));
if (i != 0)
i = sizeof(int) - i;
length -= i;
while (i--)
{
@ -2082,7 +2111,9 @@ combine_inten_a_and_inten_a_pixels (const unsigned char *src1,
int i,j;
/* HEAD */
i = ((int)m) & (sizeof(int)-1);
i = (((int)m) & (sizeof(int)-1));
if (i != 0)
i = sizeof(int) - i;
length -= i;
while (i--)
{
@ -4744,6 +4775,194 @@ initial_region (PixelRegion *src,
}
}
struct combine_regions_struct
{
int opacity;
int mode;
int *affect;
int type;
unsigned char *data;
int has_alpha1, has_alpha2;
};
void
combine_sub_region(struct combine_regions_struct *st,
PixelRegion *src1, PixelRegion *src2,
PixelRegion *dest, PixelRegion *mask)
{
unsigned char *data;
int opacity;
int mode;
int *affect;
int type;
int h;
int has_alpha1, has_alpha2;
int combine = 0;
int mode_affect;
unsigned char * s, * s1, * s2;
unsigned char * d, * m;
unsigned char buf[512];
/* fprintf (stderr, "combine_whack_region: %p, %p, %p, %p, %p, %p\n", */
/* (p4_func)combine_whack_region, */
/* &st, src1, src2, dest, mask); */
opacity = st->opacity;
mode = st->mode;
affect = st->affect;
type = st->type;
data = st->data;
has_alpha1 = st->has_alpha1;
has_alpha2 = st->has_alpha2;
s1 = src1->data;
s2 = src2->data;
d = dest->data;
m = (mask) ? mask->data : NULL;
if (src1->w > 128)
fprintf(stderr, "combine_sub_region::src1->w = %d\n", src1->w);
for (h = 0; h < src1->h; h++)
{
s = buf;
/* apply the paint mode based on the combination type & mode */
switch (type)
{
case COMBINE_INTEN_A_INDEXED_A:
case COMBINE_INTEN_A_CHANNEL_MASK:
case COMBINE_INTEN_A_CHANNEL_SELECTION:
combine = type;
break;
case COMBINE_INDEXED_INDEXED:
case COMBINE_INDEXED_INDEXED_A:
case COMBINE_INDEXED_A_INDEXED_A:
/* Now, apply the paint mode--for indexed images */
combine = apply_indexed_layer_mode (s1, s2, &s, mode, has_alpha1, has_alpha2);
break;
case COMBINE_INTEN_INTEN_A:
case COMBINE_INTEN_A_INTEN:
case COMBINE_INTEN_INTEN:
case COMBINE_INTEN_A_INTEN_A:
/* Now, apply the paint mode */
combine = apply_layer_mode (s1, s2, &s, src1->x, src1->y + h, opacity, src1->w, mode,
src1->bytes, src2->bytes, has_alpha1, has_alpha2, &mode_affect);
break;
default:
break;
}
/* based on the type of the initial image... */
switch (combine)
{
case COMBINE_INDEXED_INDEXED:
combine_indexed_and_indexed_pixels (s1, s2, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INDEXED_INDEXED_A:
combine_indexed_and_indexed_a_pixels (s1, s2, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INDEXED_A_INDEXED_A:
combine_indexed_a_and_indexed_a_pixels (s1, s2, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_A_INDEXED_A:
/* assume the data passed to this procedure is the
* indexed layer's colormap
*/
combine_inten_a_and_indexed_a_pixels (s1, s2, d, m, data, opacity,
src1->w, dest->bytes);
break;
case COMBINE_INTEN_A_CHANNEL_MASK:
/* assume the data passed to this procedure is the
* indexed layer's colormap
*/
combine_inten_a_and_channel_mask_pixels (s1, s2, d, data, opacity,
src1->w, dest->bytes);
break;
case COMBINE_INTEN_A_CHANNEL_SELECTION:
combine_inten_a_and_channel_selection_pixels (s1, s2, d, data, opacity,
src1->w, src1->bytes);
break;
case COMBINE_INTEN_INTEN:
combine_inten_and_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_INTEN_A:
combine_inten_and_inten_a_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_A_INTEN:
combine_inten_a_and_inten_pixels (s1, s, d, m, opacity,
affect, mode_affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_A_INTEN_A:
combine_inten_a_and_inten_a_pixels (s1, s, d, m, opacity,
affect, mode_affect, src1->w, src1->bytes);
break;
case BEHIND_INTEN:
behind_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case BEHIND_INDEXED:
behind_indexed_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case REPLACE_INTEN:
replace_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case REPLACE_INDEXED:
replace_indexed_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case ERASE_INTEN:
erase_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case ERASE_INDEXED:
erase_indexed_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case NO_COMBINATION:
break;
default:
break;
}
s1 += src1->rowstride;
s2 += src2->rowstride;
d += dest->rowstride;
if (mask)
m += mask->rowstride;
}
}
void
combine_regions (PixelRegion *src1,
@ -4758,13 +4977,12 @@ combine_regions (PixelRegion *src1,
{
int h;
int has_alpha1, has_alpha2;
int combine;
int mode_affect;
unsigned char * s, * s1, * s2;
unsigned char * d, * m;
unsigned char * buf;
void * pr;
combine = 0;
struct combine_regions_struct st;
/* Determine which sources have alpha channels */
switch (type)
@ -4790,155 +5008,15 @@ combine_regions (PixelRegion *src1,
has_alpha1 = has_alpha2 = 0;
}
buf = paint_funcs_get_buffer (src1->w * (src1->bytes + 1));
for (pr = pixel_regions_register (4, src1, src2, dest, mask); pr != NULL; pr = pixel_regions_process (pr))
{
s1 = src1->data;
s2 = src2->data;
d = dest->data;
m = (mask) ? mask->data : NULL;
for (h = 0; h < src1->h; h++)
{
s = buf;
/* apply the paint mode based on the combination type & mode */
switch (type)
{
case COMBINE_INTEN_A_INDEXED_A:
case COMBINE_INTEN_A_CHANNEL_MASK:
case COMBINE_INTEN_A_CHANNEL_SELECTION:
combine = type;
break;
case COMBINE_INDEXED_INDEXED:
case COMBINE_INDEXED_INDEXED_A:
case COMBINE_INDEXED_A_INDEXED_A:
/* Now, apply the paint mode--for indexed images */
combine = apply_indexed_layer_mode (s1, s2, &s, mode, has_alpha1, has_alpha2);
break;
case COMBINE_INTEN_INTEN_A:
case COMBINE_INTEN_A_INTEN:
case COMBINE_INTEN_INTEN:
case COMBINE_INTEN_A_INTEN_A:
/* Now, apply the paint mode */
combine = apply_layer_mode (s1, s2, &s, src1->x, src1->y + h, opacity, src1->w, mode,
src1->bytes, src2->bytes, has_alpha1, has_alpha2, &mode_affect);
break;
default:
break;
}
/* based on the type of the initial image... */
switch (combine)
{
case COMBINE_INDEXED_INDEXED:
combine_indexed_and_indexed_pixels (s1, s2, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INDEXED_INDEXED_A:
combine_indexed_and_indexed_a_pixels (s1, s2, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INDEXED_A_INDEXED_A:
combine_indexed_a_and_indexed_a_pixels (s1, s2, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_A_INDEXED_A:
/* assume the data passed to this procedure is the
* indexed layer's colormap
*/
combine_inten_a_and_indexed_a_pixels (s1, s2, d, m, data, opacity,
src1->w, dest->bytes);
break;
case COMBINE_INTEN_A_CHANNEL_MASK:
/* assume the data passed to this procedure is the
* indexed layer's colormap
*/
combine_inten_a_and_channel_mask_pixels (s1, s2, d, data, opacity,
src1->w, dest->bytes);
break;
case COMBINE_INTEN_A_CHANNEL_SELECTION:
combine_inten_a_and_channel_selection_pixels (s1, s2, d, data, opacity,
src1->w, src1->bytes);
break;
case COMBINE_INTEN_INTEN:
combine_inten_and_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_INTEN_A:
combine_inten_and_inten_a_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_A_INTEN:
combine_inten_a_and_inten_pixels (s1, s, d, m, opacity,
affect, mode_affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_A_INTEN_A:
combine_inten_a_and_inten_a_pixels (s1, s, d, m, opacity,
affect, mode_affect, src1->w, src1->bytes);
break;
case BEHIND_INTEN:
behind_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case BEHIND_INDEXED:
behind_indexed_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case REPLACE_INTEN:
replace_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case REPLACE_INDEXED:
replace_indexed_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case ERASE_INTEN:
erase_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case ERASE_INDEXED:
erase_indexed_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case NO_COMBINATION:
break;
default:
break;
}
s1 += src1->rowstride;
s2 += src2->rowstride;
d += dest->rowstride;
if (mask)
m += mask->rowstride;
}
}
st.opacity = opacity;
st.mode = mode;
st.affect = affect;
st.type = type;
st.data = data;
st.has_alpha1 = has_alpha1;
st.has_alpha2 = has_alpha2;
pixel_regions_process_parallel ((p_func)combine_sub_region, &st, 4,
src1, src2, dest, mask);
}
void

View File

@ -709,7 +709,6 @@ color_only_pixels (const unsigned char *src1,
}
}
void
multiply_pixels (const unsigned char *src1,
const unsigned char *src2,
@ -1002,7 +1001,7 @@ dissolve_pixels (const unsigned char *src,
rand_val = (rand() & 0xFF);
if (has_alpha)
dest[alpha] = (rand_val > opacity) ? 0 : src[alpha];
dest[alpha] = (rand_val > src[alpha]) ? 0 : src[alpha];
else
dest[alpha] = (rand_val > opacity) ? 0 : OPAQUE_OPACITY;
@ -1350,6 +1349,34 @@ initial_inten_pixels (const unsigned char *src,
*/
dest_bytes = bytes + 1;
if (bytes == 3 && affect[0] && affect[1] && affect[2])
{
if (!affect[bytes])
opacity = 0;
destp = dest + bytes;
if (mask && opacity != 0)
while(length--)
{
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = INT_MULT(opacity, *m, tmp);
src += bytes;
dest += dest_bytes;
m++;
}
else
while(length--)
{
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = opacity;
src += bytes;
dest += dest_bytes;
}
return;
}
for (b =0; b < bytes; b++)
{
destp = dest + b;
@ -1971,7 +1998,9 @@ combine_inten_a_and_inten_a_pixels (const unsigned char *src1,
int i,j;
/* HEAD */
i = ((int)m) & (sizeof(int)-1);
i = (((int)m) & (sizeof(int)-1));
if (i != 0)
i = sizeof(int) - i;
length -= i;
while (i--)
{
@ -2082,7 +2111,9 @@ combine_inten_a_and_inten_a_pixels (const unsigned char *src1,
int i,j;
/* HEAD */
i = ((int)m) & (sizeof(int)-1);
i = (((int)m) & (sizeof(int)-1));
if (i != 0)
i = sizeof(int) - i;
length -= i;
while (i--)
{
@ -4744,6 +4775,194 @@ initial_region (PixelRegion *src,
}
}
struct combine_regions_struct
{
int opacity;
int mode;
int *affect;
int type;
unsigned char *data;
int has_alpha1, has_alpha2;
};
void
combine_sub_region(struct combine_regions_struct *st,
PixelRegion *src1, PixelRegion *src2,
PixelRegion *dest, PixelRegion *mask)
{
unsigned char *data;
int opacity;
int mode;
int *affect;
int type;
int h;
int has_alpha1, has_alpha2;
int combine = 0;
int mode_affect;
unsigned char * s, * s1, * s2;
unsigned char * d, * m;
unsigned char buf[512];
/* fprintf (stderr, "combine_whack_region: %p, %p, %p, %p, %p, %p\n", */
/* (p4_func)combine_whack_region, */
/* &st, src1, src2, dest, mask); */
opacity = st->opacity;
mode = st->mode;
affect = st->affect;
type = st->type;
data = st->data;
has_alpha1 = st->has_alpha1;
has_alpha2 = st->has_alpha2;
s1 = src1->data;
s2 = src2->data;
d = dest->data;
m = (mask) ? mask->data : NULL;
if (src1->w > 128)
fprintf(stderr, "combine_sub_region::src1->w = %d\n", src1->w);
for (h = 0; h < src1->h; h++)
{
s = buf;
/* apply the paint mode based on the combination type & mode */
switch (type)
{
case COMBINE_INTEN_A_INDEXED_A:
case COMBINE_INTEN_A_CHANNEL_MASK:
case COMBINE_INTEN_A_CHANNEL_SELECTION:
combine = type;
break;
case COMBINE_INDEXED_INDEXED:
case COMBINE_INDEXED_INDEXED_A:
case COMBINE_INDEXED_A_INDEXED_A:
/* Now, apply the paint mode--for indexed images */
combine = apply_indexed_layer_mode (s1, s2, &s, mode, has_alpha1, has_alpha2);
break;
case COMBINE_INTEN_INTEN_A:
case COMBINE_INTEN_A_INTEN:
case COMBINE_INTEN_INTEN:
case COMBINE_INTEN_A_INTEN_A:
/* Now, apply the paint mode */
combine = apply_layer_mode (s1, s2, &s, src1->x, src1->y + h, opacity, src1->w, mode,
src1->bytes, src2->bytes, has_alpha1, has_alpha2, &mode_affect);
break;
default:
break;
}
/* based on the type of the initial image... */
switch (combine)
{
case COMBINE_INDEXED_INDEXED:
combine_indexed_and_indexed_pixels (s1, s2, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INDEXED_INDEXED_A:
combine_indexed_and_indexed_a_pixels (s1, s2, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INDEXED_A_INDEXED_A:
combine_indexed_a_and_indexed_a_pixels (s1, s2, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_A_INDEXED_A:
/* assume the data passed to this procedure is the
* indexed layer's colormap
*/
combine_inten_a_and_indexed_a_pixels (s1, s2, d, m, data, opacity,
src1->w, dest->bytes);
break;
case COMBINE_INTEN_A_CHANNEL_MASK:
/* assume the data passed to this procedure is the
* indexed layer's colormap
*/
combine_inten_a_and_channel_mask_pixels (s1, s2, d, data, opacity,
src1->w, dest->bytes);
break;
case COMBINE_INTEN_A_CHANNEL_SELECTION:
combine_inten_a_and_channel_selection_pixels (s1, s2, d, data, opacity,
src1->w, src1->bytes);
break;
case COMBINE_INTEN_INTEN:
combine_inten_and_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_INTEN_A:
combine_inten_and_inten_a_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_A_INTEN:
combine_inten_a_and_inten_pixels (s1, s, d, m, opacity,
affect, mode_affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_A_INTEN_A:
combine_inten_a_and_inten_a_pixels (s1, s, d, m, opacity,
affect, mode_affect, src1->w, src1->bytes);
break;
case BEHIND_INTEN:
behind_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case BEHIND_INDEXED:
behind_indexed_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case REPLACE_INTEN:
replace_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case REPLACE_INDEXED:
replace_indexed_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case ERASE_INTEN:
erase_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case ERASE_INDEXED:
erase_indexed_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case NO_COMBINATION:
break;
default:
break;
}
s1 += src1->rowstride;
s2 += src2->rowstride;
d += dest->rowstride;
if (mask)
m += mask->rowstride;
}
}
void
combine_regions (PixelRegion *src1,
@ -4758,13 +4977,12 @@ combine_regions (PixelRegion *src1,
{
int h;
int has_alpha1, has_alpha2;
int combine;
int mode_affect;
unsigned char * s, * s1, * s2;
unsigned char * d, * m;
unsigned char * buf;
void * pr;
combine = 0;
struct combine_regions_struct st;
/* Determine which sources have alpha channels */
switch (type)
@ -4790,155 +5008,15 @@ combine_regions (PixelRegion *src1,
has_alpha1 = has_alpha2 = 0;
}
buf = paint_funcs_get_buffer (src1->w * (src1->bytes + 1));
for (pr = pixel_regions_register (4, src1, src2, dest, mask); pr != NULL; pr = pixel_regions_process (pr))
{
s1 = src1->data;
s2 = src2->data;
d = dest->data;
m = (mask) ? mask->data : NULL;
for (h = 0; h < src1->h; h++)
{
s = buf;
/* apply the paint mode based on the combination type & mode */
switch (type)
{
case COMBINE_INTEN_A_INDEXED_A:
case COMBINE_INTEN_A_CHANNEL_MASK:
case COMBINE_INTEN_A_CHANNEL_SELECTION:
combine = type;
break;
case COMBINE_INDEXED_INDEXED:
case COMBINE_INDEXED_INDEXED_A:
case COMBINE_INDEXED_A_INDEXED_A:
/* Now, apply the paint mode--for indexed images */
combine = apply_indexed_layer_mode (s1, s2, &s, mode, has_alpha1, has_alpha2);
break;
case COMBINE_INTEN_INTEN_A:
case COMBINE_INTEN_A_INTEN:
case COMBINE_INTEN_INTEN:
case COMBINE_INTEN_A_INTEN_A:
/* Now, apply the paint mode */
combine = apply_layer_mode (s1, s2, &s, src1->x, src1->y + h, opacity, src1->w, mode,
src1->bytes, src2->bytes, has_alpha1, has_alpha2, &mode_affect);
break;
default:
break;
}
/* based on the type of the initial image... */
switch (combine)
{
case COMBINE_INDEXED_INDEXED:
combine_indexed_and_indexed_pixels (s1, s2, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INDEXED_INDEXED_A:
combine_indexed_and_indexed_a_pixels (s1, s2, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INDEXED_A_INDEXED_A:
combine_indexed_a_and_indexed_a_pixels (s1, s2, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_A_INDEXED_A:
/* assume the data passed to this procedure is the
* indexed layer's colormap
*/
combine_inten_a_and_indexed_a_pixels (s1, s2, d, m, data, opacity,
src1->w, dest->bytes);
break;
case COMBINE_INTEN_A_CHANNEL_MASK:
/* assume the data passed to this procedure is the
* indexed layer's colormap
*/
combine_inten_a_and_channel_mask_pixels (s1, s2, d, data, opacity,
src1->w, dest->bytes);
break;
case COMBINE_INTEN_A_CHANNEL_SELECTION:
combine_inten_a_and_channel_selection_pixels (s1, s2, d, data, opacity,
src1->w, src1->bytes);
break;
case COMBINE_INTEN_INTEN:
combine_inten_and_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_INTEN_A:
combine_inten_and_inten_a_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_A_INTEN:
combine_inten_a_and_inten_pixels (s1, s, d, m, opacity,
affect, mode_affect, src1->w, src1->bytes);
break;
case COMBINE_INTEN_A_INTEN_A:
combine_inten_a_and_inten_a_pixels (s1, s, d, m, opacity,
affect, mode_affect, src1->w, src1->bytes);
break;
case BEHIND_INTEN:
behind_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case BEHIND_INDEXED:
behind_indexed_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case REPLACE_INTEN:
replace_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case REPLACE_INDEXED:
replace_indexed_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes,
src2->bytes, has_alpha1, has_alpha2);
break;
case ERASE_INTEN:
erase_inten_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case ERASE_INDEXED:
erase_indexed_pixels (s1, s, d, m, opacity,
affect, src1->w, src1->bytes);
break;
case NO_COMBINATION:
break;
default:
break;
}
s1 += src1->rowstride;
s2 += src2->rowstride;
d += dest->rowstride;
if (mask)
m += mask->rowstride;
}
}
st.opacity = opacity;
st.mode = mode;
st.affect = affect;
st.type = type;
st.data = data;
st.has_alpha1 = has_alpha1;
st.has_alpha2 = has_alpha2;
pixel_regions_process_parallel ((p_func)combine_sub_region, &st, 4,
src1, src2, dest, mask);
}
void

View File

@ -21,10 +21,24 @@
#include <string.h>
#include "appenv.h"
#include "pixel_region.h"
#include "gimprc.h"
#include "tile_manager_pvt.h"
#include "tile.h" /* ick. */
#ifdef ENABLE_MP
#include <pthread.h>
#define IF_THREAD(statement) statement
#else /* !USE_PTHREADS */
#define IF_THREAD(statement)
#endif /* !USE_PTHREADS */
typedef struct _PixelRegionHolder PixelRegionHolder;
struct _PixelRegionHolder
@ -289,6 +303,159 @@ pixel_region_set_col (PR, x, y, h, data)
}
}
typedef void (*p1_func)(void *, PixelRegion *);
typedef void (*p2_func)(void *, PixelRegion * ,PixelRegion *);
typedef void (*p3_func)(void *, PixelRegion * ,PixelRegion *, PixelRegion *);
typedef void (*p4_func)(void *, PixelRegion * ,PixelRegion *, PixelRegion *,
PixelRegion *);
struct parallel_struct
{
void *data;
p_func f;
PixelRegionIterator *PRI;
IF_THREAD(pthread_mutex_t mutex;)
int nthreads;
int n_regions;
PixelRegion *r[4];
};
static void *
do_parallel_regions(struct parallel_struct *p_s)
{
PixelRegion tr[4];
int ntiles = 0;
int i;
IF_THREAD(pthread_mutex_lock(&p_s->mutex);)
if (p_s->nthreads != 0 && p_s->PRI)
p_s->PRI = (PixelRegionIterator*)pixel_regions_process(p_s->PRI);
if (p_s->PRI == NULL)
{
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
return NULL;
}
p_s->nthreads++;
do
{
for (i = 0; i < p_s->n_regions; i++)
if (p_s->r[i])
memcpy(&tr[i], p_s->r[i], sizeof(PixelRegion));
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
ntiles++;
switch(p_s->n_regions)
{
case 1:
((p1_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL);
break;
case 2:
((p2_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL);
break;
case 3:
((p3_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL,
p_s->r[2] ? &tr[2] : NULL);
break;
case 4:
((p4_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL,
p_s->r[2] ? &tr[2] : NULL,
p_s->r[3] ? &tr[3] : NULL);
break;
default:
g_message("do_parallel_regions: Bad number of regions %d\n",
p_s->n_regions);
}
IF_THREAD(pthread_mutex_lock(&p_s->mutex);)
} while (p_s->PRI && (p_s->PRI = (PixelRegionIterator*)pixel_regions_process(p_s->PRI)));
p_s->nthreads--;
/* fprintf(stderr, "processed %d tiles\n", ntiles); */
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
return NULL;
}
#define MAX_THREADS 30
void pixel_regions_process_parallel(p_func f, void *data, int num_regions, ...)
{
int i;
PixelRegionIterator *PRI;
struct parallel_struct p_s;
IF_THREAD(pthread_t threads[MAX_THREADS];)
IF_THREAD(pthread_attr_t pthread_attr;)
int nthreads;
va_list ap;
va_start (ap, num_regions);
for (i = 0; i < num_regions; i++)
p_s.r[i] = va_arg (ap, PixelRegion *);
va_end (ap);
switch(num_regions)
{
case 1:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0]);
break;
case 2:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0],
p_s.r[1]);
break;
case 3:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0],
p_s.r[1],
p_s.r[2]);
break;
case 4:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0],
p_s.r[1],
p_s.r[2],
p_s.r[3]);
break;
default:
g_message("pixel_regions_process_parallel: Bad number of regions %d\n",
p_s.n_regions);
}
if (!p_s.PRI)
return;
p_s.f = f;
p_s.data = data;
p_s.n_regions = num_regions;
IF_THREAD(pthread_mutex_init(&p_s.mutex, NULL);)
p_s.nthreads = 0;
IF_THREAD(
nthreads = MIN(num_processors,
(p_s.PRI->region_width * p_s.PRI->region_height) /(64*64));
if (nthreads > 1)
{
pthread_attr_init (&pthread_attr);
for (i = 0; i < nthreads; i++)
{
pthread_create (&threads[i], &pthread_attr,
(void *(*)(void *)) do_parallel_regions,
&p_s);
}
for (i = 0; i < nthreads; i++)
{
pthread_join(threads[i], NULL);
}
}
else
)
do_parallel_regions(&p_s);
if (p_s.nthreads != 0)
fprintf(stderr, "Ack, we've lost a thread.");
}
void *
pixel_regions_register (int num_regions, ...)

View File

@ -36,6 +36,7 @@ struct _PixelRegion
int process_count; /* used internally */
};
typedef void (*p_func)(void);
/* PixelRegion functions */
void pixel_region_init (PixelRegion *, TileManager *, int, int, int, int, int);
@ -47,6 +48,8 @@ void pixel_region_set_row (PixelRegion *, int, int, int, unsigned char *)
void pixel_region_get_col (PixelRegion *, int, int, int, unsigned char *, int);
void pixel_region_set_col (PixelRegion *, int, int, int, unsigned char *);
void *pixel_regions_register (int, ...);
void pixel_regions_process_parallel (p_func f, void *data, int num_regions,
...);
void *pixel_regions_process (void *);
void pixel_regions_process_stop (void *);

View File

@ -107,6 +107,7 @@ static char * old_gradient_path;
static float old_monitor_xres;
static float old_monitor_yres;
static int old_using_xserver_resolution;
static int old_num_processors;
static char * edit_temp_path = NULL;
static char * edit_swap_path = NULL;
@ -120,12 +121,14 @@ static int edit_tile_cache_size;
static int edit_install_cmap;
static int edit_cycled_marching_ants;
static int edit_last_opened_size;
static int edit_num_processors;
static GtkWidget *tile_cache_size_spinbutton = NULL;
static int divided_tile_cache_size;
static int mem_size_unit;
static GtkWidget *xres_spinbutton = NULL;
static GtkWidget *yres_spinbutton = NULL;
static GtkWidget *num_processors_spinbutton = NULL;
/* Some information regarding preferences, compiled by Raph Levien 11/3/97.
@ -214,6 +217,12 @@ file_prefs_ok_callback (GtkWidget *widget,
levels_of_undo = old_levels_of_undo;
return;
}
if (num_processors < 1 || num_processors > 30)
{
g_message (_("Error: Number of processors must be between 1 and 30."));
num_processors = old_num_processors;
return;
}
if (marching_speed < 50)
{
g_message (_("Error: Marching speed must be 50 or greater."));
@ -262,6 +271,7 @@ file_prefs_save_callback (GtkWidget *widget,
GList *remove = NULL; /* options that should be commented out */
int save_stingy_memory_use;
int save_tile_cache_size;
int save_num_processors;
int save_install_cmap;
int save_cycled_marching_ants;
int save_last_opened_size;
@ -289,6 +299,7 @@ file_prefs_save_callback (GtkWidget *widget,
save_palette_path = palette_path;
save_plug_in_path = plug_in_path;
save_gradient_path = gradient_path;
save_num_processors = num_processors;
if (levels_of_undo != old_levels_of_undo)
update = g_list_append (update, "undo-levels");
@ -364,6 +375,8 @@ file_prefs_save_callback (GtkWidget *widget,
if (using_xserver_resolution != old_using_xserver_resolution ||
ABS(monitor_yres - old_monitor_yres) > 1e-5)
update = g_list_append (update, "monitor-yresolution");
if (edit_num_processors != num_processors)
update = g_list_append (update, "num-processors");
if (edit_stingy_memory_use != stingy_memory_use)
{
update = g_list_append (update, "stingy-memory-use");
@ -509,6 +522,7 @@ file_prefs_cancel_callback (GtkWidget *widget,
monitor_xres = old_monitor_xres;
monitor_yres = old_monitor_yres;
using_xserver_resolution = old_using_xserver_resolution;
num_processors = old_num_processors;
if (preview_size != old_preview_size)
{
@ -837,6 +851,8 @@ file_pref_cmd_callback (GtkWidget *widget,
old_monitor_xres = monitor_xres;
old_monitor_yres = monitor_yres;
old_using_xserver_resolution = using_xserver_resolution;
old_num_processors = num_processors;
file_prefs_strset (&old_temp_path, edit_temp_path);
file_prefs_strset (&old_swap_path, edit_swap_path);
file_prefs_strset (&old_brush_path, edit_brush_path);
@ -1283,6 +1299,31 @@ file_pref_cmd_callback (GtkWidget *widget,
if (mem_size_unit == mem_size_units[i].unit)
gtk_option_menu_set_history(GTK_OPTION_MENU (optionmenu),i);
hbox = gtk_hbox_new (FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
label = gtk_label_new (_("Number of processors to use:"));
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
adj = (GtkAdjustment *) gtk_adjustment_new (num_processors, 1,
30, 1.0,
2.0, 0.0);
num_processors_spinbutton = gtk_spin_button_new (adj, 1.0, 0.0);
gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON(num_processors_spinbutton),
GTK_SHADOW_NONE);
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(num_processors_spinbutton),
TRUE);
gtk_widget_set_usize (num_processors_spinbutton, 75, 0);
gtk_box_pack_start (GTK_BOX (hbox), num_processors_spinbutton,
FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (num_processors_spinbutton), "changed",
(GtkSignalFunc) file_prefs_spinbutton_callback,
&num_processors);
gtk_widget_show (num_processors_spinbutton);
button = gtk_check_button_new_with_label(_("Install colormap (8-bit only)"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
install_cmap);

185
config.h.in Normal file
View File

@ -0,0 +1,185 @@
/* config.h.in. Generated automatically from configure.in by autoheader. */
/* Define if using alloca.c. */
#undef C_ALLOCA
/* Define to empty if the keyword does not work. */
#undef const
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
#undef CRAY_STACKSEG_END
/* Define if you have alloca, as a function or macro. */
#undef HAVE_ALLOCA
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#undef HAVE_ALLOCA_H
/* Define if you don't have vprintf but do have _doprnt. */
#undef HAVE_DOPRNT
/* Define if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define if you have <unistd.h>. */
#undef HAVE_UNISTD_H
/* Define if you have the vprintf function. */
#undef HAVE_VPRINTF
/* Define as __inline if that's what the C compiler calls it. */
#undef inline
/* Define to `long' if <sys/types.h> doesn't define. */
#undef off_t
/* Define to `int' if <sys/types.h> doesn't define. */
#undef pid_t
/* Define if you need to in order for stat and other things to work. */
#undef _POSIX_SOURCE
/* Define as the return type of signal handlers (int or void). */
#undef RETSIGTYPE
/* Define to `unsigned' if <sys/types.h> doesn't define. */
#undef size_t
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#undef STACK_DIRECTION
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
#undef ENABLE_MP
#undef ENABLE_NLS
#undef HAVE_CATGETS
#undef HAVE_DIRENT_H
#undef HAVE_DOPRNT
#undef HAVE_GETTEXT
#undef HAVE_IPC_H
#undef HAVE_LC_MESSAGES
#undef HAVE_NDIR_H
#undef HAVE_PROGRESSIVE_JPEG
#undef HAVE_PUTENV
#undef HAVE_SHM_H
#undef HAVE_STPCPY
#undef HAVE_SYS_DIR_H
#undef HAVE_SYS_NDIR_H
#undef HAVE_SYS_SELECT_H
#undef HAVE_SYS_TIME_H
#undef HAVE_UNISTD_H
#undef HAVE_VPRINTF
#undef HAVE_VSNPRINTF
#undef HAVE_XSHM_H
#undef IPC_RMID_DEFERRED_RELEASE
#undef NO_DIFFTIME
#undef NO_FD_SET
#undef RAND_FUNC
#undef SRAND_FUNC
#undef USE_PTHREADS
/* Define if you have the __argz_count function. */
#undef HAVE___ARGZ_COUNT
/* Define if you have the __argz_next function. */
#undef HAVE___ARGZ_NEXT
/* Define if you have the __argz_stringify function. */
#undef HAVE___ARGZ_STRINGIFY
/* Define if you have the dcgettext function. */
#undef HAVE_DCGETTEXT
/* Define if you have the getcwd function. */
#undef HAVE_GETCWD
/* Define if you have the getpagesize function. */
#undef HAVE_GETPAGESIZE
/* Define if you have the munmap function. */
#undef HAVE_MUNMAP
/* Define if you have the putenv function. */
#undef HAVE_PUTENV
/* Define if you have the setenv function. */
#undef HAVE_SETENV
/* Define if you have the setlocale function. */
#undef HAVE_SETLOCALE
/* Define if you have the stpcpy function. */
#undef HAVE_STPCPY
/* Define if you have the strcasecmp function. */
#undef HAVE_STRCASECMP
/* Define if you have the strchr function. */
#undef HAVE_STRCHR
/* Define if you have the strdup function. */
#undef HAVE_STRDUP
/* Define if you have the vsnprintf function. */
#undef HAVE_VSNPRINTF
/* Define if you have the <argz.h> header file. */
#undef HAVE_ARGZ_H
/* Define if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
/* Define if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
/* Define if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H
/* Define if you have the <ndir.h> header file. */
#undef HAVE_NDIR_H
/* Define if you have the <nl_types.h> header file. */
#undef HAVE_NL_TYPES_H
/* Define if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define if you have the <sys/dir.h> header file. */
#undef HAVE_SYS_DIR_H
/* Define if you have the <sys/ndir.h> header file. */
#undef HAVE_SYS_NDIR_H
/* Define if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define if you have the i library (-li). */
#undef HAVE_LIBI
/* define if compiled symbols have a leading underscore */
#undef WITH_SYMBOL_UNDERSCORE

View File

@ -425,6 +425,21 @@ if test "x$with_threads" = "xposix" || test "x$with_threads" = "xyes"; then
GIMP_THREAD_FLAGS="-D_REENTRANT -D_THREAD_SAFE"]))
fi
dnl Multi-Processor Support
AC_ARG_WITH(mp, [ --with-mp=[no] support multiple processors ])
GIMP_THREAD_LIBS=
if test "x$with_mp" = "xyes"; then
AC_CHECK_LIB(pthread, pthread_attr_init,
[AC_DEFINE(ENABLE_MP)
GIMP_THREAD_LIBS="-lpthread"
GIMP_THREAD_FLAGS="-D_REENTRANT"],
# AIX has libpthreads, cause they're special. Special friends (TM)
AC_CHECK_LIB(pthreads, pthread_attr_init,
[AC_DEFINE(ENABLE_MP)
GIMP_THREAD_LIBS="-lpthreads"
GIMP_THREAD_FLAGS="-D_REENTRANT -D_THREAD_SAFE"]))
fi
gimpdatadir=$datadir/gimp
gimpplugindir=$libdir/$PACKAGE/$GIMP_MAJOR_VERSION.$GIMP_MINOR_VERSION
localedir=$datadir/locale