~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to app/base/pixel-processor.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* The GIMP -- an image manipulation program
 
1
/* GIMP - The GNU Image Manipulation Program
2
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
3
 *
4
 
 * pixel_processor.c: Copyright (C) 1999 Jay Cox <jaycox@earthlink.net>
 
4
 * pixel_processor.c: Copyright (C) 1999 Jay Cox <jaycox@gimp.org>
5
5
 *
6
6
 * This program is free software; you can redistribute it and/or modify
7
7
 * it under the terms of the GNU General Public License as published by
21
21
#include "config.h"
22
22
 
23
23
#ifdef ENABLE_MP
24
 
#include <pthread.h>
25
 
#endif
26
 
 
27
24
#include <string.h>
 
25
#endif
28
26
 
29
27
#include <glib-object.h>
30
28
 
35
33
#include "pixel-processor.h"
36
34
#include "pixel-region.h"
37
35
 
38
 
#ifdef ENABLE_MP
39
36
#include "tile.h"
40
 
#endif
41
 
 
42
 
#ifdef __GNUC__
43
 
#warning FIXME: extern GimpBaseConfig *base_config;
44
 
#endif
45
 
extern GimpBaseConfig *base_config;
46
 
 
47
 
 
48
 
typedef void (* p1_func) (gpointer     ,
49
 
                          PixelRegion *);
50
 
typedef void (* p2_func) (gpointer     ,
51
 
                          PixelRegion * ,
52
 
                          PixelRegion *);
53
 
typedef void (* p3_func) (gpointer     ,
54
 
                          PixelRegion *,
55
 
                          PixelRegion *,
56
 
                          PixelRegion *);
57
 
typedef void (* p4_func) (gpointer     ,
58
 
                          PixelRegion *,
59
 
                          PixelRegion *,
60
 
                          PixelRegion *,
61
 
                          PixelRegion *);
62
 
 
 
37
 
 
38
 
 
39
#define TILES_PER_THREAD  8
 
40
#define PROGRESS_TIMEOUT  64
 
41
 
 
42
 
 
43
static GThreadPool *pool       = NULL;
 
44
static GMutex      *pool_mutex = NULL;
 
45
static GCond       *pool_cond  = NULL;
 
46
 
 
47
 
 
48
typedef void  (* p1_func) (gpointer      data,
 
49
                           PixelRegion  *region1);
 
50
typedef void  (* p2_func) (gpointer      data,
 
51
                           PixelRegion  *region1,
 
52
                           PixelRegion  *region2);
 
53
typedef void  (* p3_func) (gpointer      data,
 
54
                           PixelRegion  *region1,
 
55
                           PixelRegion  *region2,
 
56
                           PixelRegion  *region3);
 
57
typedef void  (* p4_func) (gpointer      data,
 
58
                           PixelRegion  *region1,
 
59
                           PixelRegion  *region2,
 
60
                           PixelRegion  *region3,
 
61
                           PixelRegion  *region4);
 
62
 
 
63
 
 
64
typedef struct _PixelProcessor PixelProcessor;
63
65
 
64
66
struct _PixelProcessor
65
67
{
 
68
  PixelProcessorFunc   func;
66
69
  gpointer             data;
67
 
  p_func               f;
 
70
 
 
71
#ifdef ENABLE_MP
 
72
  GMutex              *mutex;
 
73
  gint                 threads;
 
74
  gboolean             first;
 
75
#endif
 
76
 
68
77
  PixelRegionIterator *PRI;
69
 
 
70
 
#ifdef ENABLE_MP
71
 
  pthread_mutex_t      mutex;
72
 
  gint                 nthreads;
73
 
#endif
74
 
 
75
 
  gint                 n_regions;
76
 
  PixelRegion         *r[4];
77
 
 
78
 
  void                *progress_report_data;
79
 
  ProgressReportFunc   progress_report_func;
 
78
  gint                 num_regions;
 
79
  PixelRegion         *regions[4];
 
80
 
 
81
  gulong               progress;
80
82
};
81
83
 
82
84
 
83
85
#ifdef ENABLE_MP
84
 
static void *
85
 
do_parallel_regions (PixelProcessor *p_s)
 
86
static void
 
87
do_parallel_regions (PixelProcessor *processor)
86
88
{
87
89
  PixelRegion tr[4];
88
 
  gint        n_tiles = 0;
89
90
  gint        i;
90
 
  gint        cont = 1;
91
 
 
92
 
  pthread_mutex_lock (&p_s->mutex);
93
 
 
94
 
  if (p_s->nthreads != 0 && p_s->PRI)
95
 
    p_s->PRI = pixel_regions_process (p_s->PRI);
96
 
 
97
 
  if (p_s->PRI == NULL)
98
 
    {
99
 
      pthread_mutex_unlock (&p_s->mutex);
100
 
      return NULL;
101
 
    }
102
 
 
103
 
  p_s->nthreads++;
104
 
 
105
 
  do
106
 
    {
107
 
      for (i = 0; i < p_s->n_regions; i++)
108
 
        if (p_s->r[i])
109
 
          {
110
 
            memcpy(&tr[i], p_s->r[i], sizeof(PixelRegion));
111
 
            if (tr[i].tiles)
112
 
              tile_lock(tr[i].curtile);
113
 
          }
114
 
 
115
 
      pthread_mutex_unlock (&p_s->mutex);
116
 
      n_tiles++;
117
 
 
118
 
      switch(p_s->n_regions)
119
 
        {
120
 
        case 1:
121
 
          ((p1_func) p_s->f) (p_s->data,
122
 
                              p_s->r[0] ? &tr[0] : NULL);
123
 
          break;
124
 
 
125
 
        case 2:
126
 
          ((p2_func) p_s->f) (p_s->data,
127
 
                              p_s->r[0] ? &tr[0] : NULL,
128
 
                              p_s->r[1] ? &tr[1] : NULL);
129
 
          break;
130
 
 
131
 
        case 3:
132
 
          ((p3_func) p_s->f) (p_s->data,
133
 
                              p_s->r[0] ? &tr[0] : NULL,
134
 
                              p_s->r[1] ? &tr[1] : NULL,
135
 
                              p_s->r[2] ? &tr[2] : NULL);
136
 
          break;
137
 
 
138
 
        case 4:
139
 
          ((p4_func) p_s->f) (p_s->data,
140
 
                              p_s->r[0] ? &tr[0] : NULL,
141
 
                              p_s->r[1] ? &tr[1] : NULL,
142
 
                              p_s->r[2] ? &tr[2] : NULL,
143
 
                              p_s->r[3] ? &tr[3] : NULL);
144
 
          break;
145
 
 
146
 
        default:
147
 
          g_warning ("do_parallel_regions: Bad number of regions %d\n",
148
 
                     p_s->n_regions);
149
 
          break;
150
 
    }
151
 
 
152
 
    pthread_mutex_lock (&p_s->mutex);
153
 
 
154
 
    for (i = 0; i < p_s->n_regions; i++)
155
 
      if (p_s->r[i])
156
 
        {
157
 
          if (tr[i].tiles)
158
 
            tile_release (tr[i].curtile, tr[i].dirty);
159
 
        }
160
 
 
161
 
    if (p_s->progress_report_func && 
162
 
        !p_s->progress_report_func (p_s->progress_report_data,
163
 
                                    p_s->r[0]->x, p_s->r[0]->y, 
164
 
                                    p_s->r[0]->w, p_s->r[0]->h))
165
 
      cont = 0;
166
 
 
167
 
    } 
168
 
 
169
 
  while (cont && p_s->PRI &&
170
 
         (p_s->PRI = pixel_regions_process (p_s->PRI)));
171
 
 
172
 
  p_s->nthreads--;
173
 
 
174
 
  pthread_mutex_unlock (&p_s->mutex);
175
 
 
176
 
  return NULL;
 
91
 
 
92
  g_mutex_lock (processor->mutex);
 
93
 
 
94
  /*  the first thread getting here must not call pixel_regions_process()  */
 
95
  if (!processor->first && processor->PRI)
 
96
    processor->PRI = pixel_regions_process (processor->PRI);
 
97
  else
 
98
    processor->first = FALSE;
 
99
 
 
100
  while (processor->PRI)
 
101
    {
 
102
      guint pixels = (processor->PRI->portion_width *
 
103
                      processor->PRI->portion_height);
 
104
 
 
105
      for (i = 0; i < processor->num_regions; i++)
 
106
        if (processor->regions[i])
 
107
          {
 
108
            memcpy (&tr[i], processor->regions[i], sizeof (PixelRegion));
 
109
            if (tr[i].tiles)
 
110
              tile_lock (tr[i].curtile);
 
111
          }
 
112
 
 
113
      g_mutex_unlock (processor->mutex);
 
114
 
 
115
      switch (processor->num_regions)
 
116
        {
 
117
        case 1:
 
118
          ((p1_func) processor->func) (processor->data,
 
119
                                       processor->regions[0] ? &tr[0] : NULL);
 
120
          break;
 
121
 
 
122
        case 2:
 
123
          ((p2_func) processor->func) (processor->data,
 
124
                                       processor->regions[0] ? &tr[0] : NULL,
 
125
                                       processor->regions[1] ? &tr[1] : NULL);
 
126
          break;
 
127
 
 
128
        case 3:
 
129
          ((p3_func) processor->func) (processor->data,
 
130
                                       processor->regions[0] ? &tr[0] : NULL,
 
131
                                       processor->regions[1] ? &tr[1] : NULL,
 
132
                                       processor->regions[2] ? &tr[2] : NULL);
 
133
          break;
 
134
 
 
135
        case 4:
 
136
          ((p4_func) processor->func) (processor->data,
 
137
                                       processor->regions[0] ? &tr[0] : NULL,
 
138
                                       processor->regions[1] ? &tr[1] : NULL,
 
139
                                       processor->regions[2] ? &tr[2] : NULL,
 
140
                                       processor->regions[3] ? &tr[3] : NULL);
 
141
          break;
 
142
 
 
143
        default:
 
144
          g_warning ("do_parallel_regions: Bad number of regions %d\n",
 
145
                     processor->num_regions);
 
146
          break;
 
147
        }
 
148
 
 
149
      g_mutex_lock (processor->mutex);
 
150
 
 
151
      for (i = 0; i < processor->num_regions; i++)
 
152
        if (processor->regions[i])
 
153
          {
 
154
            if (tr[i].tiles)
 
155
              tile_release (tr[i].curtile, tr[i].dirty);
 
156
          }
 
157
 
 
158
      processor->progress += pixels;
 
159
 
 
160
      if (processor->PRI)
 
161
        processor->PRI = pixel_regions_process (processor->PRI);
 
162
    }
 
163
 
 
164
  processor->threads--;
 
165
 
 
166
  if (processor->threads == 0)
 
167
    {
 
168
      g_mutex_unlock (processor->mutex);
 
169
 
 
170
      g_mutex_lock (pool_mutex);
 
171
      g_cond_signal  (pool_cond);
 
172
      g_mutex_unlock (pool_mutex);
 
173
    }
 
174
  else
 
175
    {
 
176
      g_mutex_unlock (processor->mutex);
 
177
    }
177
178
}
178
179
#endif
179
180
 
180
 
/*  do_parallel_regions_single is just like do_parallel_regions 
 
181
/*  do_parallel_regions_single is just like do_parallel_regions
181
182
 *   except that all the mutex and tile locks have been removed
182
183
 *
183
 
 * If we are processing with only a single thread we don't need to do the
184
 
 * mutex locks etc. and aditional tile locks even if we were
 
184
 * If we are processing with only a single thread we don't need to do
 
185
 * the mutex locks etc. and aditional tile locks even if we were
185
186
 * configured --with-mp
186
187
 */
187
188
 
188
189
static gpointer
189
 
do_parallel_regions_single (PixelProcessor *p_s)
 
190
do_parallel_regions_single (PixelProcessor             *processor,
 
191
                            PixelProcessorProgressFunc  progress_func,
 
192
                            gpointer                    progress_data,
 
193
                            gulong                      total)
190
194
{
191
 
  gint cont = 1;
 
195
  GTimeVal  last_time;
 
196
 
 
197
  if (progress_func)
 
198
    g_get_current_time (&last_time);
192
199
 
193
200
  do
194
201
    {
195
 
      switch (p_s->n_regions)
 
202
      switch (processor->num_regions)
196
203
        {
197
204
        case 1:
198
 
          ((p1_func) p_s->f) (p_s->data,
199
 
                              p_s->r[0]);
 
205
          ((p1_func) processor->func) (processor->data,
 
206
                                       processor->regions[0]);
200
207
          break;
201
 
          
 
208
 
202
209
        case 2:
203
 
          ((p2_func) p_s->f) (p_s->data,
204
 
                              p_s->r[0],
205
 
                              p_s->r[1]);
 
210
          ((p2_func) processor->func) (processor->data,
 
211
                                       processor->regions[0],
 
212
                                       processor->regions[1]);
206
213
          break;
207
214
 
208
215
        case 3:
209
 
          ((p3_func) p_s->f) (p_s->data,
210
 
                              p_s->r[0],
211
 
                              p_s->r[1],
212
 
                              p_s->r[2]);
 
216
          ((p3_func) processor->func) (processor->data,
 
217
                                       processor->regions[0],
 
218
                                       processor->regions[1],
 
219
                                       processor->regions[2]);
213
220
          break;
214
 
          
 
221
 
215
222
        case 4:
216
 
          ((p4_func) p_s->f) (p_s->data,
217
 
                              p_s->r[0],
218
 
                              p_s->r[1],
219
 
                              p_s->r[2],
220
 
                              p_s->r[3]);
 
223
          ((p4_func) processor->func) (processor->data,
 
224
                                       processor->regions[0],
 
225
                                       processor->regions[1],
 
226
                                       processor->regions[2],
 
227
                                       processor->regions[3]);
221
228
          break;
222
229
 
223
230
        default:
224
231
          g_warning ("do_parallel_regions_single: Bad number of regions %d\n",
225
 
                     p_s->n_regions);
226
 
        }
227
 
 
228
 
      if (p_s->progress_report_func && 
229
 
          !p_s->progress_report_func (p_s->progress_report_data,
230
 
                                      p_s->r[0]->x, p_s->r[0]->y, 
231
 
                                      p_s->r[0]->w, p_s->r[0]->h))
232
 
        cont = 0;
 
232
                     processor->num_regions);
 
233
          break;
 
234
        }
 
235
 
 
236
      if (progress_func)
 
237
        {
 
238
          GTimeVal  now;
 
239
 
 
240
          processor->progress += (processor->PRI->portion_width *
 
241
                                  processor->PRI->portion_height);
 
242
 
 
243
          g_get_current_time (&now);
 
244
 
 
245
          if (((now.tv_sec - last_time.tv_sec) * 1024 +
 
246
               (now.tv_usec - last_time.tv_usec) / 1024) > PROGRESS_TIMEOUT)
 
247
            {
 
248
              progress_func (progress_data,
 
249
                             (gdouble) processor->progress / (gdouble) total);
 
250
 
 
251
              last_time = now;
 
252
            }
 
253
        }
233
254
    }
234
 
 
235
 
  while (cont && p_s->PRI &&
236
 
         (p_s->PRI = pixel_regions_process (p_s->PRI)));
 
255
  while (processor->PRI &&
 
256
         (processor->PRI = pixel_regions_process (processor->PRI)));
237
257
 
238
258
  return NULL;
239
259
}
240
260
 
241
 
#define MAX_THREADS 30
242
 
 
243
261
static void
244
 
pixel_regions_do_parallel (PixelProcessor *p_s)
 
262
pixel_regions_do_parallel (PixelProcessor             *processor,
 
263
                           PixelProcessorProgressFunc  progress_func,
 
264
                           gpointer                    progress_data)
245
265
{
 
266
  gulong pixels = (processor->PRI->region_width *
 
267
                   processor->PRI->region_height);
 
268
  gulong tiles  = pixels / (TILE_WIDTH * TILE_HEIGHT);
 
269
 
246
270
#ifdef ENABLE_MP
247
 
  gint nthreads;
248
 
 
249
 
  nthreads = MIN (base_config->num_processors, MAX_THREADS);
250
 
 
251
 
  /* make sure we have at least one tile per thread */
252
 
  nthreads = MIN (nthreads,
253
 
                  (p_s->PRI->region_width * p_s->PRI->region_height)
254
 
                  / (TILE_WIDTH * TILE_HEIGHT));
255
 
 
256
 
  if (nthreads > 1)
 
271
  if (pool && tiles > TILES_PER_THREAD)
257
272
    {
258
 
      gint           i;
259
 
      pthread_t      threads[MAX_THREADS];
260
 
      pthread_attr_t pthread_attr;
261
 
 
262
 
      pthread_attr_init (&pthread_attr);
263
 
 
264
 
      for (i = 0; i < nthreads; i++)
265
 
        {
266
 
          pthread_create (&threads[i], &pthread_attr,
267
 
                          (void *(*)(void *)) do_parallel_regions,
268
 
                          p_s);
269
 
        }
270
 
      for (i = 0; i < nthreads; i++)
271
 
        {
272
 
          gint ret;
273
 
 
274
 
          if ((ret = pthread_join (threads[i], NULL)))
275
 
            {
276
 
              g_printerr ("pixel_regions_do_parallel: "
277
 
                          "pthread_join returned: %d\n", ret);
278
 
            }
279
 
        }
280
 
 
281
 
      if (p_s->nthreads != 0)
282
 
        g_printerr ("pixel_regions_do_prarallel: we lost a thread\n");
 
273
      GError *error = NULL;
 
274
      gint    tasks = MIN (tiles / TILES_PER_THREAD,
 
275
                           g_thread_pool_get_max_threads (pool));
 
276
 
 
277
      /*
 
278
       * g_printerr ("pushing %d tasks into the thread pool (for %lu tiles)\n",
 
279
       *             tasks, tiles);
 
280
       */
 
281
 
 
282
      processor->first   = TRUE;
 
283
      processor->threads = tasks;
 
284
      processor->mutex   = g_mutex_new();
 
285
 
 
286
      g_mutex_lock (pool_mutex);
 
287
 
 
288
      while (tasks--)
 
289
        {
 
290
          g_thread_pool_push (pool, processor, &error);
 
291
 
 
292
          if (G_UNLIKELY (error))
 
293
            {
 
294
              g_warning ("thread creation failed: %s", error->message);
 
295
              g_clear_error (&error);
 
296
              processor->threads--;
 
297
            }
 
298
        }
 
299
 
 
300
      if (progress_func)
 
301
        {
 
302
          while (processor->threads != 0)
 
303
            {
 
304
              GTimeVal timeout;
 
305
              gulong   progress;
 
306
 
 
307
              g_get_current_time (&timeout);
 
308
              g_time_val_add (&timeout, PROGRESS_TIMEOUT * 1024);
 
309
 
 
310
              g_cond_timed_wait (pool_cond, pool_mutex, &timeout);
 
311
 
 
312
              g_mutex_lock (processor->mutex);
 
313
              progress = processor->progress;
 
314
              g_mutex_unlock (processor->mutex);
 
315
 
 
316
              progress_func (progress_data,
 
317
                             (gdouble) progress / (gdouble) pixels);
 
318
            }
 
319
        }
 
320
      else
 
321
        {
 
322
          while (processor->threads != 0)
 
323
            g_cond_wait (pool_cond, pool_mutex);
 
324
        }
 
325
 
 
326
      g_mutex_unlock (pool_mutex);
 
327
 
 
328
      g_mutex_free (processor->mutex);
283
329
    }
284
330
  else
285
331
#endif
 
332
    {
 
333
      do_parallel_regions_single (processor,
 
334
                                  progress_func, progress_data, pixels);
 
335
    }
286
336
 
287
 
    do_parallel_regions_single (p_s);
 
337
  if (progress_func)
 
338
    progress_func (progress_data, 1.0);
288
339
}
289
340
 
290
 
static PixelProcessor *
291
 
pixel_regions_real_process_parallel (p_func             f, 
292
 
                                     gpointer           data,
293
 
                                     ProgressReportFunc report_func,
294
 
                                     gpointer           report_data,
295
 
                                     gint               num_regions, 
296
 
                                     va_list            ap)
 
341
static void
 
342
pixel_regions_process_parallel_valist (PixelProcessorFunc         func,
 
343
                                       gpointer                   data,
 
344
                                       PixelProcessorProgressFunc progress_func,
 
345
                                       gpointer                   progress_data,
 
346
                                       gint                       num_regions,
 
347
                                       va_list                    ap)
297
348
{
 
349
  PixelProcessor  processor = { NULL, };
298
350
  gint            i;
299
 
  PixelProcessor *p_s;
300
 
 
301
 
  p_s = g_new (PixelProcessor, 1);
302
351
 
303
352
  for (i = 0; i < num_regions; i++)
304
 
    p_s->r[i] = va_arg (ap, PixelRegion *);
 
353
    processor.regions[i] = va_arg (ap, PixelRegion *);
305
354
 
306
 
  switch(num_regions)
 
355
  switch (num_regions)
307
356
    {
308
357
    case 1:
309
 
      p_s->PRI = pixel_regions_register (num_regions,
310
 
                                         p_s->r[0]);
 
358
      processor.PRI = pixel_regions_register (num_regions,
 
359
                                              processor.regions[0]);
311
360
      break;
312
361
 
313
362
    case 2:
314
 
      p_s->PRI = pixel_regions_register (num_regions,
315
 
                                         p_s->r[0],
316
 
                                         p_s->r[1]);
 
363
      processor.PRI = pixel_regions_register (num_regions,
 
364
                                              processor.regions[0],
 
365
                                              processor.regions[1]);
317
366
      break;
318
367
 
319
368
    case 3:
320
 
      p_s->PRI = pixel_regions_register (num_regions,
321
 
                                         p_s->r[0],
322
 
                                         p_s->r[1],
323
 
                                         p_s->r[2]);
 
369
      processor.PRI = pixel_regions_register (num_regions,
 
370
                                              processor.regions[0],
 
371
                                              processor.regions[1],
 
372
                                              processor.regions[2]);
324
373
      break;
325
374
 
326
375
    case 4:
327
 
      p_s->PRI = pixel_regions_register (num_regions,
328
 
                                         p_s->r[0],
329
 
                                         p_s->r[1],
330
 
                                         p_s->r[2],
331
 
                                         p_s->r[3]);
 
376
      processor.PRI = pixel_regions_register (num_regions,
 
377
                                              processor.regions[0],
 
378
                                              processor.regions[1],
 
379
                                              processor.regions[2],
 
380
                                              processor.regions[3]);
332
381
      break;
333
382
 
334
383
    default:
335
 
      g_warning ("pixel_regions_real_process_parallel:"
336
 
                 "Bad number of regions %d\n", p_s->n_regions);
337
 
  }
338
 
 
339
 
  if (!p_s->PRI)
340
 
    {
341
 
      pixel_processor_free (p_s);
342
 
      return NULL;
 
384
      g_warning ("pixel_regions_process_parallel: "
 
385
                 "bad number of regions (%d)", processor.num_regions);
 
386
      break;
343
387
    }
344
388
 
345
 
  p_s->f = f;
346
 
  p_s->data = data;
347
 
  p_s->n_regions = num_regions;
348
 
 
349
 
#ifdef ENABLE_MP
350
 
  pthread_mutex_init (&p_s->mutex, NULL);
351
 
  p_s->nthreads = 0;
352
 
#endif
353
 
 
354
 
  p_s->progress_report_data = report_data;
355
 
  p_s->progress_report_func = report_func;
356
 
 
357
 
  pixel_regions_do_parallel (p_s);
358
 
 
359
 
  if (p_s->PRI)
360
 
    return p_s;
361
 
 
362
 
#ifdef ENABLE_MP
363
 
  pthread_mutex_destroy (&p_s->mutex);
364
 
#endif
365
 
 
366
 
  pixel_processor_free (p_s);
367
 
 
368
 
  return NULL;
369
 
}
370
 
 
371
 
void
372
 
pixel_regions_process_parallel (p_func   f, 
373
 
                                gpointer data, 
374
 
                                gint     num_regions, 
375
 
                                ...)
376
 
{
377
 
  va_list va;
378
 
 
379
 
  va_start (va, num_regions);
380
 
 
381
 
  pixel_regions_real_process_parallel (f, data, NULL, NULL, num_regions, va);
382
 
 
383
 
  va_end (va);
384
 
}
385
 
 
386
 
PixelProcessor *
387
 
pixel_regions_process_parallel_progress (p_func             f, 
388
 
                                         gpointer           data,
389
 
                                         ProgressReportFunc progress_func,
390
 
                                         gpointer           progress_data, 
391
 
                                         gint               num_regions,
392
 
                                         ...)
393
 
{
394
 
  PixelProcessor *ret;
395
 
  va_list         va;
396
 
 
397
 
  va_start (va, num_regions);
398
 
 
399
 
  ret = pixel_regions_real_process_parallel (f, data,
400
 
                                             progress_func, progress_data,
401
 
                                             num_regions, va);
402
 
 
403
 
  va_end (va);
404
 
 
405
 
  return ret;
406
 
}
407
 
 
408
 
void
409
 
pixel_processor_stop (PixelProcessor *pp)
410
 
{
411
 
  if (!pp)
 
389
  if (! processor.PRI)
412
390
    return;
413
391
 
414
 
  if (pp->PRI)
 
392
  processor.func        = func;
 
393
  processor.data        = data;
 
394
  processor.num_regions = num_regions;
 
395
 
 
396
#ifdef ENABLE_MP
 
397
  processor.threads     = 0;
 
398
#endif
 
399
 
 
400
  processor.progress    = 0;
 
401
 
 
402
  pixel_regions_do_parallel (&processor, progress_func, progress_data);
 
403
}
 
404
 
 
405
void
 
406
pixel_processor_init (gint num_threads)
 
407
{
 
408
  pixel_processor_set_num_threads (num_threads);
 
409
}
 
410
 
 
411
void
 
412
pixel_processor_set_num_threads (gint num_threads)
 
413
{
 
414
#ifdef ENABLE_MP
 
415
 
 
416
  g_return_if_fail (num_threads > 0 && num_threads <= GIMP_MAX_NUM_THREADS);
 
417
 
 
418
  if (num_threads < 2)
415
419
    {
416
 
      pixel_regions_process_stop (pp->PRI);
417
 
      pp->PRI = NULL;
 
420
      if (pool)
 
421
        {
 
422
          g_thread_pool_free (pool, TRUE, TRUE);
 
423
          pool = NULL;
 
424
 
 
425
          g_cond_free (pool_cond);
 
426
          pool_cond = NULL;
 
427
 
 
428
          g_mutex_free (pool_mutex);
 
429
          pool_mutex = NULL;
 
430
        }
418
431
    }
419
 
 
420
 
  pixel_processor_free (pp);
421
 
}
422
 
 
423
 
PixelProcessor *
424
 
pixel_processor_cont (PixelProcessor *pp)
425
 
{
426
 
  pixel_regions_do_parallel (pp);
427
 
 
428
 
  if (pp->PRI)
429
 
    return pp;
430
 
 
431
 
  pixel_processor_free (pp);
432
 
 
433
 
  return NULL;
434
 
}
435
 
 
436
 
void
437
 
pixel_processor_free (PixelProcessor *pp)
438
 
{
439
 
  if (pp->PRI)
440
 
    pixel_processor_stop (pp);
441
432
  else
442
 
    g_free(pp);
 
433
    {
 
434
      GError *error = NULL;
 
435
 
 
436
      if (pool)
 
437
        {
 
438
          g_thread_pool_set_max_threads (pool, num_threads, &error);
 
439
        }
 
440
      else
 
441
        {
 
442
          pool = g_thread_pool_new ((GFunc) do_parallel_regions, NULL,
 
443
                                    num_threads, TRUE, &error);
 
444
 
 
445
          pool_mutex = g_mutex_new ();
 
446
          pool_cond  = g_cond_new ();
 
447
        }
 
448
 
 
449
      if (G_UNLIKELY (error))
 
450
        {
 
451
          g_warning ("changing the number of threads to %d failed: %s",
 
452
                     num_threads, error->message);
 
453
          g_clear_error (&error);
 
454
        }
 
455
    }
 
456
#endif
 
457
}
 
458
 
 
459
void
 
460
pixel_processor_exit (void)
 
461
{
 
462
  pixel_processor_set_num_threads (1);
 
463
}
 
464
 
 
465
void
 
466
pixel_regions_process_parallel (PixelProcessorFunc  func,
 
467
                                gpointer            data,
 
468
                                gint                num_regions,
 
469
                                ...)
 
470
{
 
471
  va_list va;
 
472
 
 
473
  va_start (va, num_regions);
 
474
 
 
475
  pixel_regions_process_parallel_valist (func, data,
 
476
                                         NULL, NULL,
 
477
                                         num_regions, va);
 
478
 
 
479
  va_end (va);
 
480
}
 
481
 
 
482
void
 
483
pixel_regions_process_parallel_progress (PixelProcessorFunc          func,
 
484
                                         gpointer                    data,
 
485
                                         PixelProcessorProgressFunc  progress_func,
 
486
                                         gpointer                    progress_data,
 
487
                                         gint                        num_regions,
 
488
                                         ...)
 
489
{
 
490
  va_list va;
 
491
 
 
492
  va_start (va, num_regions);
 
493
 
 
494
  pixel_regions_process_parallel_valist (func, data,
 
495
                                         progress_func, progress_data,
 
496
                                         num_regions, va);
 
497
 
 
498
  va_end (va);
443
499
}