This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git.
The branch, master has been updated via 274f579cdeaeeb021e9650e6022c01bb874f7fed (commit) via 5355f8de46d21c12f260b08c4774a13993db9701 (commit) from 00460e85d190a282d97009977cecdc5a6b9c101a (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- http://repo.or.cz/w/gfxprim.git/commit/274f579cdeaeeb021e9650e6022c01bb874f7...
commit 274f579cdeaeeb021e9650e6022c01bb874f7fed Author: Cyril Hrubis metan@ucw.cz Date: Sun Jul 8 23:24:44 2012 +0200
filters,core: Update in the threads interface.
diff --git a/include/core/GP_ProgressCallback.h b/include/core/GP_ProgressCallback.h index 818bafa..e944154 100644 --- a/include/core/GP_ProgressCallback.h +++ b/include/core/GP_ProgressCallback.h @@ -24,10 +24,11 @@
Progress callback implementation.
- Progress callbacks serves two purposes + Progress callbacks serves following purposes:
- ability to visibly show algorithm progress - ability to correctly abort operation in the middle of processing + - ability to override default number of threads to use for the operation
*/
@@ -42,8 +43,20 @@ */ typedef struct GP_ProgressCallback { float percentage; + int (*callback)(struct GP_ProgressCallback *self); void *priv; + + /* + * Number of threads to use (if supported). This setting could be used + * to override the default number of threads as returned by + * GP_NrThreads(). + * + * 0 == use number returned from GP_NrThreads(). + * + * >= 1 use exactly n threads + */ + unsigned int threads; } GP_ProgressCallback;
static inline int GP_ProgressCallbackReport(GP_ProgressCallback *callback, diff --git a/include/core/GP_Threads.h b/include/core/GP_Threads.h index 948f278..185ce06 100644 --- a/include/core/GP_Threads.h +++ b/include/core/GP_Threads.h @@ -35,12 +35,31 @@ #include "GP_Types.h"
/* - * Returns an optimal number of threads for a given image size on a particular - * machine. Most of the time, if the image is not too small, this function - * returns number of processors as seen by the operating system. + * Sets default number of threads the library uses + * (changes the behavior of GP_NrThreads()). + * + * 0 == auto + * Most of the time, if the image is not too small, this makes + * the filter run number of processors (as seen by the operating system) + * threads. + * + * 1 == one thread + * Everything runs in exactly one thread. This is default value. + * + * >= 2 + * Runs exactly n threads unless the image is too small. + * + * This value may also be overriden by GP_THREADS enviroment variable. + * + * Moreover the value may changed for a single call by settings in progres + * callback structure. */ -unsigned int GP_NrThreads(GP_Size w, GP_Size h); +void GP_NrThreadsSet(unsigned int nr);
+/* + * Returns a number of threads to use. + */ +unsigned int GP_NrThreads(GP_Size w, GP_Size h, GP_ProgressCallback *callback);
/* * Multithreaded progress callback priv data guarded by a mutex. diff --git a/libs/core/GP_Threads.c b/libs/core/GP_Threads.c index 638f27b..ff59d75 100644 --- a/libs/core/GP_Threads.c +++ b/libs/core/GP_Threads.c @@ -21,26 +21,63 @@ *****************************************************************************/
#include <unistd.h> +#include <stdlib.h>
#include "GP_Common.h" #include "GP_Debug.h"
#include "GP_Threads.h"
-unsigned int GP_NrThreads(GP_Size w, GP_Size h) +static unsigned int nr_threads = 1; + +unsigned int GP_NrThreads(GP_Size w, GP_Size h, GP_ProgressCallback *callback) { - int count = sysconf(_SC_NPROCESSORS_ONLN); - int threads = GP_MIN(count, (int)(w * h / 1024) + 1); + int count, threads; + char *env; + + /* Try to override nr_threads from the callback first */ + if (callback != NULL && callback->threads) { + GP_DEBUG(1, "Overriding nr_threads from callback to %i", + callback->threads); + nr_threads = callback->threads; + } else { + /* Then try to override it from the enviroment variable */ + env = getenv("GP_THREADS"); + + if (env) { + nr_threads = atoi(env); + GP_DEBUG(1, "Using GP_THREADS=%u from enviroment " + "variable", nr_threads); + } + }
- if (count < -1) + if (nr_threads == 0) { + count = sysconf(_SC_NPROCESSORS_ONLN); + GP_DEBUG(1, "Found %i CPUs", count); + } else { + count = nr_threads; + GP_DEBUG(1, "Using nr_threads=%i", count); + } + + threads = GP_MIN(count, (int)(w * h / 1024) + 1); + + /* Call to the sysconf may return -1 if unsupported */ + if (threads < -1) threads = 1;
- GP_DEBUG(1, "Found %u CPUs size %ux%u runnig %u threads", + GP_DEBUG(1, "Max threads %i image size %ux%u runnig %u threads", count, w, h, threads);
return threads; }
+void GP_NrThreadsSet(unsigned int nr) +{ + nr_threads = nr; + + GP_DEBUG(1, "Setting default number of threads to %u", nr); +} + int GP_ProgressCallbackMP(GP_ProgressCallback *self) { struct GP_ProgressCallbackMPPriv *priv = self->priv; diff --git a/libs/filters/GP_LinearThreads.c b/libs/filters/GP_LinearThreads.c index 9a2aa43..2ab625e 100644 --- a/libs/filters/GP_LinearThreads.c +++ b/libs/filters/GP_LinearThreads.c @@ -60,11 +60,14 @@ static void *linear_convolution(void *arg)
int GP_FilterHConvolutionMP_Raw(const GP_ConvolutionParams *params) { - int i, t = GP_NrThreads(params->w_src, params->h_src); + int i, t = GP_NrThreads(params->w_src, params->h_src, params->callback);
if (t == 1) return GP_FilterHConvolution_Raw(params);
+ GP_ASSERT(params->src != params->dst, + "Multithreaded convolution can't work in-place"); + GP_PROGRESS_CALLBACK_MP(callback_mp, params->callback);
/* Run t threads */ @@ -105,11 +108,14 @@ int GP_FilterHConvolutionMP_Raw(const GP_ConvolutionParams *params)
int GP_FilterVConvolutionMP_Raw(const GP_ConvolutionParams *params) { - int i, t = GP_NrThreads(params->w_src, params->h_src); + int i, t = GP_NrThreads(params->w_src, params->h_src, params->callback);
if (t == 1) return GP_FilterVConvolution_Raw(params); + GP_ASSERT(params->src != params->dst, + "Multithreaded convolution can't work in-place"); + GP_PROGRESS_CALLBACK_MP(callback_mp, params->callback); /* Run t threads */ @@ -149,10 +155,13 @@ int GP_FilterVConvolutionMP_Raw(const GP_ConvolutionParams *params)
int GP_FilterConvolutionMP_Raw(const GP_ConvolutionParams *params) { - int i, t = GP_NrThreads(params->w_src, params->h_src); + int i, t = GP_NrThreads(params->w_src, params->h_src, params->callback);
if (t == 1) return GP_FilterConvolution_Raw(params); + + GP_ASSERT(params->src != params->dst, + "Multithreaded convolution can't work in-place");
GP_PROGRESS_CALLBACK_MP(callback_mp, params->callback);
http://repo.or.cz/w/gfxprim.git/commit/5355f8de46d21c12f260b08c4774a13993db9...
commit 5355f8de46d21c12f260b08c4774a13993db9701 Author: Cyril Hrubis metan@ucw.cz Date: Sun Jul 8 13:12:52 2012 +0200
filters: Simplify multithreaded filters.
* Move the common code to the core
* Pack the linear convolution paraters into the structure by default.
diff --git a/include/core/GP_ProgressCallback.h b/include/core/GP_ProgressCallback.h index 72857ce..818bafa 100644 --- a/include/core/GP_ProgressCallback.h +++ b/include/core/GP_ProgressCallback.h @@ -69,4 +69,10 @@ static inline void GP_ProgressCallbackDone(GP_ProgressCallback *callback) callback->callback(callback); }
+#define GP_PROGRESS_CALLBACK(name, pcallback, ppriv) + GP_ProgressCallback name = { + .callback = pcallback, + .priv = ppriv, + }; + #endif /* CORE_GP_PROGRESSCALBACK_H */ diff --git a/include/filters/GP_LinearThreads.h b/include/core/GP_Threads.h similarity index 51% copy from include/filters/GP_LinearThreads.h copy to include/core/GP_Threads.h index 76c46db..948f278 100644 --- a/include/filters/GP_LinearThreads.h +++ b/include/core/GP_Threads.h @@ -20,33 +20,62 @@ * * *****************************************************************************/
-#ifndef FILTERS_GP_LINEAR_THREADS_H -#define FILTERS_GP_LINEAR_THREADS_H - -#include "GP_Filter.h" - -int GP_FilterLinearConvolutionMP_Raw(const GP_Context *src, - GP_Coord x_src, GP_Coord y_src, - GP_Size w_src, GP_Size h_src, - GP_Context *dst, - GP_Coord x_dst, GP_Coord y_dst, - float kernel[], uint32_t kw, uint32_t kh, - float kern_div, GP_ProgressCallback *callback); - -int GP_FilterHLinearConvolutionMP_Raw(const GP_Context *src, - GP_Coord x_src, GP_Coord y_src, - GP_Size w_src, GP_Size h_src, - GP_Context *dst, - GP_Coord x_dst, GP_Coord y_dst, - float kernel[], uint32_t kw, float kern_div, - GP_ProgressCallback *callback); - -int GP_FilterVLinearConvolutionMP_Raw(const GP_Context *src, - GP_Coord x_src, GP_Coord y_src, - GP_Size w_src, GP_Size h_src, - GP_Context *dst, - GP_Coord x_dst, GP_Coord y_dst, - float kernel[], uint32_t kh, float kern_div, - GP_ProgressCallback *callback); - -#endif /* FILTERS_GP_LINEAR_THREADS_H */ + /* + + A code to ease multithreaded filters and more. + + */ + +#ifndef GP_THREADS_H +#define GP_THREADS_H + +#include <pthread.h> + +#include "GP_ProgressCallback.h" +#include "GP_Types.h" + +/* + * Returns an optimal number of threads for a given image size on a particular + * machine. Most of the time, if the image is not too small, this function + * returns number of processors as seen by the operating system. + */ +unsigned int GP_NrThreads(GP_Size w, GP_Size h); + + +/* + * Multithreaded progress callback priv data guarded by a mutex. + */ +struct GP_ProgressCallbackMPPriv { + float max; + int abort; + pthread_mutex_t mutex; + GP_ProgressCallback *orig_callback; +}; + +/* + * Creates and initalizes a on-the-stack progress callback + * + * The intended usage is: + * + * GP_PROGRESS_CALLBACK(callback_mp, orig_callback); + * + * ... + * + * for n threads: + * run_filter(..., callback ? &callback_mp : NULL); + */ +#define GP_PROGRESS_CALLBACK_MP(name, callback) + struct GP_ProgressCallbackMPPriv name_priv = { + .max = 0, + .abort = 0, + .mutex = PTHREAD_MUTEX_INITIALIZER, + .orig_callback = callback, + }; + GP_PROGRESS_CALLBACK(name, GP_ProgressCallbackMP, &name_priv); + +/* + * Multithreaded callback function itself. + */ +int GP_ProgressCallbackMP(GP_ProgressCallback *self); + +#endif /* GP_THREADS_H */ diff --git a/include/filters/GP_Linear.h b/include/filters/GP_Linear.h index ae96e34..fe938f5 100644 --- a/include/filters/GP_Linear.h +++ b/include/filters/GP_Linear.h @@ -53,8 +53,6 @@ * kw = kh = 3 * * kern_div = 9 - * - * This function works also in-place. */ int GP_FilterLinearConvolution_Raw(const GP_Context *src, GP_Coord x_src, GP_Coord y_src, @@ -109,4 +107,59 @@ int GP_FilterVHLinearConvolution_Raw(const GP_Context *src, */ void GP_FilterKernelPrint_Raw(float kernel[], int kw, int kh, float kern_div);
+ + +typedef struct GP_ConvolutionParams { + const GP_Context *src; + GP_Coord x_src; + GP_Coord y_src; + GP_Size w_src; + GP_Size h_src; + + GP_Context *dst; + GP_Coord x_dst; + GP_Coord y_dst; + + float *kernel; + unsigned int kw; + unsigned int kh; + float kern_div; + + GP_ProgressCallback *callback; +} GP_ConvolutionParams; + +static inline int GP_FilterConvolution_Raw(const struct GP_ConvolutionParams *params) +{ + return GP_FilterLinearConvolution_Raw(params->src, params->x_src, + params->y_src, params->w_src, + params->h_src, params->dst, + params->x_dst, params->y_dst, + params->kernel, params->kw, + params->kh, params->kern_div, + params->callback); +} + +static inline int GP_FilterVConvolution_Raw(const struct GP_ConvolutionParams *params) +{ + + return GP_FilterVLinearConvolution_Raw(params->src, params->x_src, + params->y_src, params->w_src, + params->h_src, params->dst, + params->x_dst, params->y_dst, + params->kernel, params->kh, + params->kern_div, + params->callback); +} + +static inline int GP_FilterHConvolution_Raw(const struct GP_ConvolutionParams *params) +{ + return GP_FilterHLinearConvolution_Raw(params->src, params->x_src, + params->y_src, params->w_src, + params->h_src, params->dst, + params->x_dst, params->y_dst, + params->kernel, params->kw, + params->kern_div, + params->callback); +} + #endif /* FILTERS_GP_LINEAR_H */ diff --git a/include/filters/GP_LinearThreads.h b/include/filters/GP_LinearThreads.h index 76c46db..ee4d0fc 100644 --- a/include/filters/GP_LinearThreads.h +++ b/include/filters/GP_LinearThreads.h @@ -24,29 +24,13 @@ #define FILTERS_GP_LINEAR_THREADS_H
#include "GP_Filter.h" +#include "GP_Linear.h"
-int GP_FilterLinearConvolutionMP_Raw(const GP_Context *src, - GP_Coord x_src, GP_Coord y_src, - GP_Size w_src, GP_Size h_src, - GP_Context *dst, - GP_Coord x_dst, GP_Coord y_dst, - float kernel[], uint32_t kw, uint32_t kh, - float kern_div, GP_ProgressCallback *callback); +int GP_FilterConvolutionMP_Raw(const GP_ConvolutionParams *params);
-int GP_FilterHLinearConvolutionMP_Raw(const GP_Context *src, - GP_Coord x_src, GP_Coord y_src, - GP_Size w_src, GP_Size h_src, - GP_Context *dst, - GP_Coord x_dst, GP_Coord y_dst, - float kernel[], uint32_t kw, float kern_div, - GP_ProgressCallback *callback); +int GP_FilterVConvolutionMP_Raw(const GP_ConvolutionParams *params); + +int GP_FilterHConvolutionMP_Raw(const GP_ConvolutionParams *params);
-int GP_FilterVLinearConvolutionMP_Raw(const GP_Context *src, - GP_Coord x_src, GP_Coord y_src, - GP_Size w_src, GP_Size h_src, - GP_Context *dst, - GP_Coord x_dst, GP_Coord y_dst, - float kernel[], uint32_t kh, float kern_div, - GP_ProgressCallback *callback);
#endif /* FILTERS_GP_LINEAR_THREADS_H */ diff --git a/include/core/GP_ProgressCallback.h b/libs/core/GP_Threads.c similarity index 58% copy from include/core/GP_ProgressCallback.h copy to libs/core/GP_Threads.c index 72857ce..638f27b 100644 --- a/include/core/GP_ProgressCallback.h +++ b/libs/core/GP_Threads.c @@ -16,57 +16,58 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2011 Cyril Hrubis metan@ucw.cz * + * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
-/* +#include <unistd.h>
- Progress callback implementation. +#include "GP_Common.h" +#include "GP_Debug.h"
- Progress callbacks serves two purposes +#include "GP_Threads.h"
- - ability to visibly show algorithm progress - - ability to correctly abort operation in the middle of processing +unsigned int GP_NrThreads(GP_Size w, GP_Size h) +{ + int count = sysconf(_SC_NPROCESSORS_ONLN); + int threads = GP_MIN(count, (int)(w * h / 1024) + 1);
- */ + if (count < -1) + threads = 1;
-#ifndef CORE_GP_PROGRESSCALLBACK_H -#define CORE_GP_PROGRESSCALLBACK_H + GP_DEBUG(1, "Found %u CPUs size %ux%u runnig %u threads", + count, w, h, threads);
-/* - * Progress callback - * - * Non zero return value from callback will abort current operation - * free memory and return NULL from filter/loader... - */ -typedef struct GP_ProgressCallback { - float percentage; - int (*callback)(struct GP_ProgressCallback *self); - void *priv; -} GP_ProgressCallback; + return threads; +}
-static inline int GP_ProgressCallbackReport(GP_ProgressCallback *callback, - unsigned int val, unsigned int max, - unsigned int mul __attribute__((unused))) +int GP_ProgressCallbackMP(GP_ProgressCallback *self) { - if (callback == NULL) - return 0; + struct GP_ProgressCallbackMPPriv *priv = self->priv;
- if (val % 100) + /* + * If any thread got non-zero return value from a callback abort all. + */ + if (priv->abort) + return 1; + + if (pthread_mutex_trylock(&priv->mutex)) { + GP_DEBUG(1, "Mutex locked, skipping calllback."); return 0; + }
- callback->percentage = 100.00 * val / max; - return callback->callback(callback); -} + /* Compute max value for the percentage */ + priv->orig_callback->percentage = GP_MAX(self->percentage, priv->max); + priv->max = priv->orig_callback->percentage;
-static inline void GP_ProgressCallbackDone(GP_ProgressCallback *callback) -{ - if (callback == NULL) - return; + /* Call the original callback */ + int ret = priv->orig_callback->callback(priv->orig_callback); - callback->percentage = 100; - callback->callback(callback); -} + /* Turn on abort flag if callback returned nonzero */ + if (ret) + priv->abort = 1;
-#endif /* CORE_GP_PROGRESSCALBACK_H */ + pthread_mutex_unlock(&priv->mutex); + + return ret; +} diff --git a/libs/filters/GP_Blur.c b/libs/filters/GP_Blur.c index 22b99fd..21aa315 100644 --- a/libs/filters/GP_Blur.c +++ b/libs/filters/GP_Blur.c @@ -25,6 +25,7 @@ #include "core/GP_Debug.h"
#include "GP_Linear.h" +#include "GP_LinearThreads.h"
#include "GP_Blur.h"
@@ -92,10 +93,24 @@ int GP_FilterGaussianBlur_Raw(const GP_Context *src, GP_Context *dst, if (sigma_x > 0) { float kernel_x[size_x]; float sum = gaussian_kernel_init(sigma_x, kernel_x); - - if (GP_FilterHLinearConvolution_Raw(src, 0, 0, src->w, src->h, - dst, 0, 0, kernel_x, size_x, - sum, new_callback)) + + GP_ConvolutionParams params = { + .src = src, + .x_src = 0, + .y_src = 0, + .w_src = src->w, + .h_src = src->h, + .dst = dst, + .x_dst = 0, + .y_dst = 0, + .kernel = kernel_x, + .kw = size_x, + .kh = 1, + .kern_div = sum, + .callback = new_callback, + }; + + if (GP_FilterHConvolutionMP_Raw(¶ms)) return 1; } @@ -107,9 +122,23 @@ int GP_FilterGaussianBlur_Raw(const GP_Context *src, GP_Context *dst, float kernel_y[size_y]; float sum = gaussian_kernel_init(sigma_y, kernel_y); - if (GP_FilterVLinearConvolution_Raw(dst, 0, 0, src->w, src->h, - dst, 0, 0, kernel_y, size_y, - sum, new_callback)) + GP_ConvolutionParams params = { + .src = src, + .x_src = 0, + .y_src = 0, + .w_src = src->w, + .h_src = src->h, + .dst = dst, + .x_dst = 0, + .y_dst = 0, + .kernel = kernel_y, + .kw = 1, + .kh = size_y, + .kern_div = sum, + .callback = new_callback, + }; + + if (GP_FilterVConvolutionMP_Raw(¶ms)) return 1; }
diff --git a/libs/filters/GP_Edge.c b/libs/filters/GP_Edge.c index a9a42a6..349c36b 100644 --- a/libs/filters/GP_Edge.c +++ b/libs/filters/GP_Edge.c @@ -57,24 +57,54 @@ static int prewitt(const GP_Context *src, GP_Context *dx, GP_Context *dy, static int sobel(const GP_Context *src, GP_Context *dx, GP_Context *dy, GP_ProgressCallback *callback) { - float x_kern[] = { + float dx_kern[] = { -1, 0, 1, -2, 0, 2, -1, 0, 1, };
- if (GP_FilterLinearConvolution_Raw(src, 0, 0, src->w, src->h, - dx, 0, 0, x_kern, 3, 3, 32, callback)) + GP_ConvolutionParams dx_conv = { + .src = src, + .x_src = 0, + .y_src = 0, + .w_src = src->w, + .h_src = src->h, + .dst = dx, + .x_dst = 0, + .y_dst = 0, + .kernel = dx_kern, + .kw = 3, + .kh = 3, + .kern_div = 1, + .callback = callback, + }; + + if (GP_FilterConvolution_Raw(&dx_conv)) return 1; - float y_kern[] = { + float dy_kern[] = { -1, -2, -1, 0, 0, 0, 1, 2, 1, }; + + GP_ConvolutionParams dy_conv = { + .src = src, + .x_src = 0, + .y_src = 0, + .w_src = src->w, + .h_src = src->h, + .dst = dy, + .x_dst = 0, + .y_dst = 0, + .kernel = dy_kern, + .kw = 3, + .kh = 3, + .kern_div = 1, + .callback = callback, + };
- if (GP_FilterLinearConvolution_Raw(src, 0, 0, src->w, src->h, - dy, 0, 0, y_kern, 3, 3, 32, callback)) + if (GP_FilterConvolution_Raw(&dy_conv)) return 1;
return 0; @@ -133,7 +163,7 @@ static int edge_detect(const GP_Context *src, GP_PutPixel_Raw_24BPP(dx, i, j, GP_Pixel_CREATE_RGB888(RE, GE, BE)); - + if (Rx != 0 && Ry != 0) RPhi = ((atan2(Rx, Ry) + M_PI) * 255)/(2*M_PI); else diff --git a/libs/filters/GP_LinearThreads.c b/libs/filters/GP_LinearThreads.c index 5ccdebc..9a2aa43 100644 --- a/libs/filters/GP_LinearThreads.c +++ b/libs/filters/GP_LinearThreads.c @@ -26,189 +26,65 @@
#include "core/GP_Common.h" #include "core/GP_Debug.h" +#include "core/GP_Threads.h"
#include "GP_Linear.h" #include "GP_LinearThreads.h"
-static int nr_threads(GP_Size w, GP_Size h) -{ - int count = sysconf(_SC_NPROCESSORS_ONLN); - int threads = GP_MIN(count, (int)(w * h / 1024) + 1); - - if (count < -1) - threads = 1; - - GP_DEBUG(1, "Found %u CPUs size %ux%u runnig %u threads", - count, w, h, threads); - - return threads; -} - -/* - * Multithreaded callback wrapper. - */ -struct callback_priv { - float max; - int abort; - unsigned int nr_threads; - pthread_mutex_t mutex; - GP_ProgressCallback *orig_callback; -}; - -static int progress_callback_mp(GP_ProgressCallback *self) +static void *h_linear_convolution(void *arg) { - struct callback_priv *priv = self->priv; + struct GP_ConvolutionParams *params = arg;
- /* If any thread got non-zero return value from a callback, abort all */ - if (priv->abort) - return 1; - - if (pthread_mutex_trylock(&priv->mutex)) { - GP_DEBUG(1, "Mutex locked, skipping calllback."); - return 0; - } - - /* Compute max value for the percentage */ - priv->orig_callback->percentage = GP_MAX(self->percentage, priv->max); - priv->max = priv->orig_callback->percentage; - - /* Call the original callback */ - int ret = priv->orig_callback->callback(priv->orig_callback); + long ret = GP_FilterHConvolution_Raw(params); - /* Turn on abort flag if callback returned nonzero */ - if (ret) - priv->abort = 1; - - pthread_mutex_unlock(&priv->mutex); - - return ret; -} - -static void callback_priv_init(struct callback_priv *priv, int nr_threads, - GP_ProgressCallback *orig_callback) -{ - priv->nr_threads = nr_threads; - priv->orig_callback = orig_callback; - priv->max = 0; - priv->abort = 0; - pthread_mutex_init(&priv->mutex, NULL); + return (void*)ret; }
-static void callback_priv_exit(struct callback_priv *priv) +static void *v_linear_convolution(void *arg) { - pthread_mutex_destroy(&priv->mutex); -} - -/* - * This code just packs and unpacks convolution parameters. - */ -struct convolution { - const GP_Context *src; - GP_Coord x_src; - GP_Coord y_src; - GP_Size w_src; - GP_Size h_src; + struct GP_ConvolutionParams *params = arg; - GP_Context *dst; - GP_Coord x_dst; - GP_Coord y_dst; - - float *kernel; - unsigned int ks; - float kern_div; - - GP_ProgressCallback *callback; -}; - -static void convolution_init(struct convolution *conv, const GP_Context *src, - GP_Coord x_src, GP_Coord y_src, - GP_Size w_src, GP_Size h_src, - GP_Context *dst, GP_Coord x_dst, GP_Coord y_dst, - float kernel[], unsigned int ks, float kern_div, - GP_ProgressCallback *callback) -{ - conv->src = src; - conv->x_src = x_src; - conv->y_src = y_src; - conv->w_src = w_src; - conv->h_src = h_src; - conv->dst = dst; - conv->x_dst = x_dst; - conv->y_dst = y_dst; - conv->kernel = kernel; - conv->ks = ks; - conv->kern_div = kern_div; - conv->callback = callback; -} - -static void *h_linear_convolution(void *arg) -{ - struct convolution *conv = arg; - - long ret; + long ret = GP_FilterVConvolution_Raw(params);
- ret = GP_FilterHLinearConvolution_Raw(conv->src, conv->x_src, conv->y_src, - conv->w_src, conv->h_src, conv->dst, - conv->x_dst, conv->y_dst, conv->kernel, - conv->ks, conv->kern_div, conv->callback); return (void*)ret; }
-static void *v_linear_convolution(void *arg) +static void *linear_convolution(void *arg) { - struct convolution *conv = arg; - - long ret; + struct GP_ConvolutionParams *params = arg; + + long ret = GP_FilterConvolution_Raw(params);
- ret = GP_FilterVLinearConvolution_Raw(conv->src, conv->x_src, conv->y_src, - conv->w_src, conv->h_src, conv->dst, - conv->x_dst, conv->y_dst, conv->kernel, - conv->ks, conv->kern_div, conv->callback); return (void*)ret; }
- -int GP_FilterHLinearConvolutionMP_Raw(const GP_Context *src, - GP_Coord x_src, GP_Coord y_src, - GP_Size w_src, GP_Size h_src, - GP_Context *dst, - GP_Coord x_dst, GP_Coord y_dst, - float kernel[], uint32_t kw, float kern_div, - GP_ProgressCallback *callback) +int GP_FilterHConvolutionMP_Raw(const GP_ConvolutionParams *params) { - int t = nr_threads(w_src, h_src); - - if (t == 1) { - return GP_FilterHLinearConvolution_Raw(src, x_src, y_src, - w_src, h_src, - dst, x_dst, y_dst, - kernel, kw, kern_div, - callback); - } + int i, t = GP_NrThreads(params->w_src, params->h_src); + + if (t == 1) + return GP_FilterHConvolution_Raw(params);
- /* Create multithreaded safe callback on the stack */ - struct callback_priv priv; - callback_priv_init(&priv, t, callback); - GP_ProgressCallback callback_mp = {0, progress_callback_mp, &priv}; + GP_PROGRESS_CALLBACK_MP(callback_mp, params->callback);
/* Run t threads */ - int i; pthread_t threads[t]; - struct convolution convs[t]; - GP_Size h = h_src/t; + struct GP_ConvolutionParams convs[t]; + GP_Size h = params->h_src/t;
for (i = 0; i < t; i++) { - GP_Coord y_src_2 = y_src + i * h; - GP_Coord y_dst_2 = y_dst + i * h; + GP_Coord y_src_2 = params->y_src + i * h; + GP_Coord y_dst_2 = params->y_dst + i * h; GP_Size h_src_2 = h; if (i == t - 1) - h_src_2 = h_src - i * h; + h_src_2 = params->h_src - i * h;
- /* Pack convolution parameters into the structure */ - convolution_init(&convs[i], src, x_src, y_src_2, w_src, h_src_2, - dst, x_dst, y_dst_2, kernel, kw, kern_div, - callback ? &callback_mp : NULL); + convs[i] = *params; + convs[i].y_src = y_src_2; + convs[i].h_src = h_src_2; + convs[i].y_dst = y_dst_2; + convs[i].callback = params->callback ? &callback_mp : NULL;
pthread_create(&threads[i], NULL, h_linear_convolution, &convs[i]); } @@ -223,52 +99,37 @@ int GP_FilterHLinearConvolutionMP_Raw(const GP_Context *src, ret |= (int)r; } - callback_priv_exit(&priv); - return ret; }
-int GP_FilterVLinearConvolutionMP_Raw(const GP_Context *src, - GP_Coord x_src, GP_Coord y_src, - GP_Size w_src, GP_Size h_src, - GP_Context *dst, - GP_Coord x_dst, GP_Coord y_dst, - float kernel[], uint32_t kh, float kern_div, - GP_ProgressCallback *callback) +int GP_FilterVConvolutionMP_Raw(const GP_ConvolutionParams *params) { - int t = nr_threads(w_src, h_src); - - if (t == 1) { - return GP_FilterVLinearConvolution_Raw(src, x_src, y_src, - w_src, h_src, - dst, x_dst, y_dst, - kernel, kh, kern_div, - callback); - } + int i, t = GP_NrThreads(params->w_src, params->h_src); + + if (t == 1) + return GP_FilterVConvolution_Raw(params); - /* Create multithreaded safe callback on the stack */ - struct callback_priv priv; - callback_priv_init(&priv, t, callback); - GP_ProgressCallback callback_mp = {0, progress_callback_mp, &priv}; + GP_PROGRESS_CALLBACK_MP(callback_mp, params->callback); - int i; + /* Run t threads */ pthread_t threads[t]; - struct convolution convs[t]; - GP_Size h = h_src/t; + struct GP_ConvolutionParams convs[t]; + GP_Size h = params->h_src/t;
for (i = 0; i < t; i++) { - GP_Coord y_src_2 = y_src + i * h; - GP_Coord y_dst_2 = y_dst + i * h; + GP_Coord y_src_2 = params->y_src + i * h; + GP_Coord y_dst_2 = params->y_dst + i * h; GP_Size h_src_2 = h; if (i == t - 1) - h_src_2 = h_src - i * h; - - /* Pack convolution parameters into the structure */ - convolution_init(&convs[i], src, x_src, y_src_2, w_src, h_src_2, - dst, x_dst, y_dst_2, kernel, kh, kern_div, - callback ? &callback_mp : NULL); + h_src_2 = params->h_src - i * h; + + convs[i] = *params; + convs[i].y_src = y_src_2; + convs[i].h_src = h_src_2; + convs[i].y_dst = y_dst_2; + convs[i].callback = params->callback ? &callback_mp : NULL; pthread_create(&threads[i], NULL, v_linear_convolution, &convs[i]); } @@ -282,19 +143,49 @@ int GP_FilterVLinearConvolutionMP_Raw(const GP_Context *src, ret |= (int)r; } - callback_priv_exit(&priv); - return ret; }
-/* -int GP_FilterLinearConvolutionMP_Raw(const GP_Context *src, - GP_Coord x_src, GP_Coord y_src, - GP_Size w_src, GP_Size h_src, - GP_Context *dst, - GP_Coord x_dst, GP_Coord y_dst, - float kernel[], uint32_t kw, uint32_t kh, - float kern_div, GP_ProgressCallback *callback) + +int GP_FilterConvolutionMP_Raw(const GP_ConvolutionParams *params) { + int i, t = GP_NrThreads(params->w_src, params->h_src); + + if (t == 1) + return GP_FilterConvolution_Raw(params); + + GP_PROGRESS_CALLBACK_MP(callback_mp, params->callback); + + /* Run t threads */ + pthread_t threads[t]; + struct GP_ConvolutionParams convs[t]; + GP_Size h = params->h_src/t; + + for (i = 0; i < t; i++) { + GP_Coord y_src_2 = params->y_src + i * h; + GP_Coord y_dst_2 = params->y_dst + i * h; + GP_Size h_src_2 = h; + + if (i == t - 1) + h_src_2 = params->h_src - i * h; + + convs[i] = *params; + convs[i].y_src = y_src_2; + convs[i].h_src = h_src_2; + convs[i].y_dst = y_dst_2; + convs[i].callback = params->callback ? &callback_mp : NULL; + + pthread_create(&threads[i], NULL, linear_convolution, &convs[i]); + } + + int ret = 0; + + for (i = 0; i < t; i++) { + long r; + pthread_join(threads[i], (void*)&r); + + ret |= (int)r; + } + + return ret; } -*/
-----------------------------------------------------------------------
Summary of changes: include/core/GP_ProgressCallback.h | 21 +++- include/core/GP_Threads.h | 100 ++++++++++++ include/filters/GP_Linear.h | 57 +++++++- include/filters/GP_LinearThreads.h | 26 +--- libs/core/GP_Threads.c | 110 ++++++++++++++ libs/filters/GP_Blur.c | 43 +++++- libs/filters/GP_Edge.c | 44 +++++- libs/filters/GP_LinearThreads.c | 290 ++++++++++++------------------------ 8 files changed, 458 insertions(+), 233 deletions(-) create mode 100644 include/core/GP_Threads.h create mode 100644 libs/core/GP_Threads.c
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos@gmail.com if you want to unsubscribe, or site admin admin@repo.or.cz if you receive no reply.