Commit df54426d authored by Victor Oliveira's avatar Victor Oliveira Committed by Øyvind "pippin" Kolås

Major refactoring in point-filter-cl

GeglBufferClIterator created and using it in point-filter-cl
parent e2de30ee
......@@ -20,6 +20,7 @@ libbuffer_la_SOURCES = \
gegl-buffer-share.c \
gegl-buffer-index.h \
gegl-buffer-iterator.c \
gegl-buffer-cl-iterator.c \
gegl-buffer-linear.c \
gegl-buffer-save.c \
gegl-buffer-load.c \
......@@ -48,6 +49,7 @@ libbuffer_la_SOURCES = \
gegl-buffer.h \
gegl-buffer-private.h \
gegl-buffer-iterator.h \
gegl-buffer-cl-iterator.h \
gegl-buffer-load.h \
gegl-buffer-save.h \
gegl-buffer-types.h \
......
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <glib-object.h>
#include <glib/gprintf.h>
#include "gegl.h"
#include "gegl-buffer-types.h"
#include "gegl-buffer-cl-iterator.h"
#include "gegl-buffer-private.h"
#include "gegl-tile-storage.h"
#include "gegl-utils.h"
#define CL_ERROR {g_printf("[OpenCL] Error in %s:%d@%s - %s\n", __FILE__, __LINE__, __func__, gegl_cl_errstring(errcode)); g_assert(FALSE);}
typedef struct GeglBufferClIterators
{
/* current region of interest */
gint n;
size_t size [GEGL_CL_BUFFER_MAX_ITERATORS][GEGL_CL_NTEX][2]; /* length of current data in pixels */
cl_mem tex [GEGL_CL_BUFFER_MAX_ITERATORS][GEGL_CL_NTEX];
GeglRectangle roi [GEGL_CL_BUFFER_MAX_ITERATORS][GEGL_CL_NTEX];
/* the following is private: */
cl_mem tex_aux [GEGL_CL_BUFFER_MAX_ITERATORS][GEGL_CL_NTEX];
gint iterators;
gint iteration_no;
gboolean is_finished;
guint flags [GEGL_CL_BUFFER_MAX_ITERATORS];
GeglRectangle rect [GEGL_CL_BUFFER_MAX_ITERATORS]; /* the region we iterate on. They can be
different from each other, but width
and height are the same */
const Babl *format [GEGL_CL_BUFFER_MAX_ITERATORS]; /* The format required for the data */
GeglBuffer *buffer [GEGL_CL_BUFFER_MAX_ITERATORS];
/* buffer->format */
cl_image_format buf_cl_format [GEGL_CL_BUFFER_MAX_ITERATORS];
/* format */
cl_image_format op_cl_format [GEGL_CL_BUFFER_MAX_ITERATORS];
gegl_cl_color_op conv [GEGL_CL_BUFFER_MAX_ITERATORS];
/* total iteration */
gint rois;
gint roi_no;
GeglRectangle *roi_all;
} GeglBufferClIterators;
gint
gegl_buffer_cl_iterator_add (GeglBufferClIterator *iterator,
GeglBuffer *buffer,
const GeglRectangle *result,
const Babl *format,
guint flags)
{
GeglBufferClIterators *i = (gpointer)iterator;
gint self = 0;
if (i->iterators+1 > GEGL_CL_BUFFER_MAX_ITERATORS)
{
g_error ("too many iterators (%i)", i->iterators+1);
}
if (i->iterators == 0) /* for sanity, we zero at init */
{
memset (i, 0, sizeof (GeglBufferClIterators));
}
self = i->iterators++;
if (!result)
result = self==0?&(buffer->extent):&(i->rect[0]);
i->rect[self]=*result;
i->buffer[self]= g_object_ref (buffer);
if (format)
i->format[self]=format;
else
i->format[self]=buffer->format;
i->flags[self]=flags;
if (flags == GEGL_CL_BUFFER_WRITE)
i->conv[self] = gegl_cl_color_supported (format, buffer->format);
else
i->conv[self] = gegl_cl_color_supported (buffer->format, format);
gegl_cl_color_babl (buffer->format, &i->buf_cl_format[self], NULL);
gegl_cl_color_babl (format, &i->op_cl_format [self], NULL);
if (self!=0)
{
/* we make all subsequently added iterators share the width and height of the first one */
i->rect[self].width = i->rect[0].width;
i->rect[self].height = i->rect[0].height;
}
else
{
gint x, y, j;
i->rois = 0;
for (y=result->y; y < result->y + result->height; y += cl_state.max_image_height)
for (x=result->x; x < result->x + result->width; x += cl_state.max_image_width)
i->rois++;
i->roi_no = 0;
i->roi_all = g_new0 (GeglRectangle, i->rois);
j = 0;
for (y=0; y < result->height; y += cl_state.max_image_height)
for (x=0; x < result->width; x += cl_state.max_image_width)
{
GeglRectangle r = {x, y,
MIN(cl_state.max_image_width, result->width - x),
MIN(cl_state.max_image_height, result->height - y)};
i->roi_all[j] = r;
j++;
}
}
return self;
}
gboolean
gegl_buffer_cl_iterator_next (GeglBufferClIterator *iterator)
{
GeglBufferClIterators *i = (gpointer)iterator;
gboolean result = FALSE;
gint no;
const size_t origin_zero[3] = {0, 0, 0};
if (i->is_finished)
g_error ("%s called on finished buffer iterator", G_STRFUNC);
if (i->iteration_no == 0)
{
for (no=0; no<i->iterators;no++)
{
gint j;
gboolean found = FALSE;
for (j=0; j<no; j++)
if (i->buffer[no]==i->buffer[j])
{
found = TRUE;
break;
}
if (!found)
gegl_buffer_lock (i->buffer[no]);
}
}
else
{
gint j;
cl_int errcode = 0;
/* complete pending write work */
for (no=0; no<i->iterators;no++)
{
if (i->flags[no] == GEGL_CL_BUFFER_WRITE)
{
/* Wait Processing */
errcode = gegl_clEnqueueBarrier(gegl_cl_get_command_queue());
if (errcode != CL_SUCCESS) CL_ERROR;
/* color conversion in the GPU (output) */
if (i->conv[no] == CL_COLOR_CONVERT)
for (j=0; j < i->n; j++)
{
g_assert (i->tex_aux[no][j] == NULL);
i->tex_aux[no][j] = gegl_clCreateImage2D (gegl_cl_get_context (),
CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE,
&i->buf_cl_format[no],
i->roi[no][j].width,
i->roi[no][j].height,
0, NULL, &errcode);
if (errcode != CL_SUCCESS) CL_ERROR;
errcode = gegl_cl_color_conv (&i->tex[no][j], &i->tex_aux[no][j], i->size[no][j],
i->format[no], i->buffer[no]->format);
if (errcode != CL_SUCCESS) CL_ERROR;
}
/* Wait Processing */
errcode = gegl_clEnqueueBarrier(gegl_cl_get_command_queue());
if (errcode != CL_SUCCESS) CL_ERROR;
/* GPU -> CPU */
for (j=0; j < i->n; j++)
{
gpointer data;
size_t pitch;
const size_t region[3] = {i->roi[no][j].width, i->roi[no][j].height, 1};
data = gegl_clEnqueueMapImage(gegl_cl_get_command_queue(), i->tex[no][j], CL_TRUE,
CL_MAP_READ,
origin_zero, region, &pitch, NULL,
0, NULL, NULL, &errcode);
if (errcode != CL_SUCCESS) CL_ERROR;
/* tile-ize */
if (i->conv[no] == CL_COLOR_NOT_SUPPORTED)
/* color conversion using BABL */
gegl_buffer_set (i->buffer[no], &i->roi[no][j], i->format[no], data, pitch);
else
/* color conversion has already been performed in the GPU */
gegl_buffer_set (i->buffer[no], &i->roi[no][j], i->buffer[no]->format, data, pitch);
errcode = gegl_clEnqueueUnmapMemObject (gegl_cl_get_command_queue(), i->tex[no][j], data,
0, NULL, NULL);
if (errcode != CL_SUCCESS) CL_ERROR;
}
}
}
/* Run! */
errcode = gegl_clFinish(gegl_cl_get_command_queue());
if (errcode != CL_SUCCESS) CL_ERROR;
for (no=0; no < i->iterators; no++)
for (j=0; j < i->n; j++)
{
if (i->tex_aux[no][j]) gegl_clReleaseMemObject (i->tex_aux[no][j]);
gegl_clReleaseMemObject (i->tex[no][j]);
i->tex_aux[no][j] = NULL;
i->tex[no][j] = NULL;
}
}
g_assert (i->iterators > 0);
result = (i->roi_no >= i->rois)? FALSE : TRUE;
i->n = MIN(GEGL_CL_NTEX, i->rois - i->roi_no);
/* then we iterate all */
for (no=0; no<i->iterators;no++)
{
int j;
int errcode = 0;
for (j = 0; j < i->n; j++)
{
GeglRectangle r = {i->rect[no].x + i->roi_all[i->roi_no+j].x,
i->rect[no].y + i->roi_all[i->roi_no+j].y,
i->roi_all[i->roi_no+j].width,
i->roi_all[i->roi_no+j].height};
i->roi [no][j] = r;
i->size[no][j][0] = r.width;
i->size[no][j][1] = r.height;
}
if (i->flags[no] == GEGL_CL_BUFFER_READ)
{
for (j=0; j < i->n; j++)
{
gpointer data;
size_t pitch;
const size_t region[3] = {i->roi[no][j].width, i->roi[no][j].height, 1};
g_assert (i->tex[no][j] == NULL);
i->tex[no][j] = gegl_clCreateImage2D (gegl_cl_get_context (),
CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE,
(i->conv[no] == CL_COLOR_CONVERT)?
&i->buf_cl_format[no] :
&i->op_cl_format [no],
i->roi[no][j].width,
i->roi[no][j].height,
0, NULL, &errcode);
if (errcode != CL_SUCCESS) CL_ERROR;
/* pre-pinned memory */
data = gegl_clEnqueueMapImage(gegl_cl_get_command_queue(), i->tex[no][j], CL_TRUE,
CL_MAP_WRITE,
origin_zero, region, &pitch, NULL,
0, NULL, NULL, &errcode);
if (errcode != CL_SUCCESS) CL_ERROR;
/* un-tile */
if (i->conv[no] == CL_COLOR_NOT_SUPPORTED)
/* color conversion using BABL */
gegl_buffer_get (i->buffer[no], 1.0, &i->roi[no][j], i->format[no], data, pitch);
else
/* color conversion will be performed in the GPU later */
gegl_buffer_get (i->buffer[no], 1.0, &i->roi[no][j], i->buffer[no]->format, data, pitch);
errcode = gegl_clEnqueueUnmapMemObject (gegl_cl_get_command_queue(), i->tex[no][j], data,
0, NULL, NULL);
if (errcode != CL_SUCCESS) CL_ERROR;
}
errcode = gegl_clEnqueueBarrier(gegl_cl_get_command_queue());
if (errcode != CL_SUCCESS) CL_ERROR;
/* color conversion in the GPU (input) */
if (i->conv[no] == CL_COLOR_CONVERT)
for (j = 0; j < i->n; j++)
{
g_assert (i->tex_aux[no][j] == NULL);
i->tex_aux[no][j] = gegl_clCreateImage2D (gegl_cl_get_context (),
CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE,
&i->op_cl_format[no],
i->roi[no][j].width,
i->roi[no][j].height,
0, NULL, &errcode);
if (errcode != CL_SUCCESS) CL_ERROR;
errcode = gegl_cl_color_conv (&i->tex[no][j], &i->tex_aux[no][j], i->size[no][j],
i->buffer[no]->format, i->format[no]);
if (errcode == FALSE) CL_ERROR;
}
}
else if (i->flags[no] == GEGL_CL_BUFFER_WRITE)
{
for (j=0; j < i->n; j++)
{
g_assert (i->tex[no][j] == NULL);
i->tex[no][j] = gegl_clCreateImage2D (gegl_cl_get_context (),
CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE,
&i->op_cl_format [no],
i->roi[no][j].width,
i->roi[no][j].height,
0, NULL, &errcode);
if (errcode != CL_SUCCESS) CL_ERROR;
}
}
else
{
g_assert (FALSE);
}
}
i->roi_no += i->n;
i->iteration_no++;
if (result == FALSE)
{
for (no=0; no<i->iterators;no++)
{
gint j;
gboolean found = FALSE;
for (j=0; j<no; j++)
if (i->buffer[no]==i->buffer[j])
{
found = TRUE;
break;
}
if (!found)
gegl_buffer_unlock (i->buffer[no]);
}
for (no=0; no<i->iterators;no++)
{
g_object_unref (i->buffer[no]);
}
i->is_finished = TRUE;
g_free (i->roi_all);
g_slice_free (GeglBufferClIterators, i);
}
return result;
}
GeglBufferClIterator *
gegl_buffer_cl_iterator_new (GeglBuffer *buffer,
const GeglRectangle *roi,
const Babl *format,
guint flags)
{
GeglBufferClIterator *i = (gpointer)g_slice_new0 (GeglBufferClIterators);
/* Because the iterator is nulled above, we can forgo explicitly setting
* i->is_finished to FALSE. */
gegl_buffer_cl_iterator_add (i, buffer, roi, format, flags);
return i;
}
#undef CL_ERROR
#ifndef __GEGL_BUFFER_CL_ITERATOR_H__
#define __GEGL_BUFFER_CL_ITERATOR_H__
#include "gegl-buffer.h"
#include "opencl/gegl-cl.h"
#define GEGL_CL_NTEX 16
#define GEGL_CL_BUFFER_MAX_ITERATORS 6
enum
{
GEGL_CL_BUFFER_READ = 1,
GEGL_CL_BUFFER_WRITE = 2
};
typedef struct GeglBufferClIterator
{
gint n;
size_t size [GEGL_CL_BUFFER_MAX_ITERATORS][GEGL_CL_NTEX][2]; /* length of current data in pixels */
cl_mem tex [GEGL_CL_BUFFER_MAX_ITERATORS][GEGL_CL_NTEX];
GeglRectangle roi [GEGL_CL_BUFFER_MAX_ITERATORS][GEGL_CL_NTEX];
} GeglBufferClIterator;
gint gegl_buffer_cl_iterator_add (GeglBufferClIterator *iterator,
GeglBuffer *buffer,
const GeglRectangle *roi,
const Babl *format,
guint flags);
gboolean gegl_buffer_cl_iterator_next (GeglBufferClIterator *iterator);
GeglBufferClIterator *gegl_buffer_cl_iterator_new (GeglBuffer *buffer,
const GeglRectangle *roi,
const Babl *format,
guint flags);
#endif
......@@ -24,6 +24,7 @@
#include "gegl-buffer.h"
#include "gegl-tile-handler.h"
#include "gegl-buffer-iterator.h"
#include "gegl-buffer-cl-iterator.h"
#define GEGL_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEGL_TYPE_BUFFER, GeglBufferClass))
#define GEGL_IS_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEGL_TYPE_BUFFER))
......
......@@ -30,10 +30,10 @@ gegl_cl_texture_manager_request (cl_mem_flags flags,
for (i=0; i<tex_pool->len; i++)
{
TextureInfo *info = &g_array_index (tex_pool, TextureInfo, i);
if (info->flags == flags &&
if ((flags & info->flags) &&
info->format.image_channel_order == format.image_channel_order &&
info->format.image_channel_data_type == format.image_channel_data_type &&
info->width >= width && info->height >= height &&
info->width == width && info->height == height &&
info->used == 0)
{
info->used ++;
......
......@@ -33,7 +33,6 @@
#include "gegl-tile-storage.h"
#include "opencl/gegl-cl.h"
#include "opencl/gegl-cl-texture-manager.h"
static gboolean gegl_operation_point_filter_process
(GeglOperation *operation,
......@@ -73,45 +72,22 @@ gegl_operation_point_filter_init (GeglOperationPointFilter *self)
{
}
struct buf_tex
{
GeglBuffer *buf;
GeglRectangle *region;
cl_mem *tex;
};
//#define CL_ERROR {g_assert(0);}
#define CL_ERROR {g_printf("[OpenCL] Error in %s:%d@%s - %s\n", __FILE__, __LINE__, __func__, gegl_cl_errstring(errcode)); goto error;}
static gboolean
gegl_operation_point_filter_cl_process_full (GeglOperation *operation,
GeglBuffer *input,
GeglBuffer *output,
const GeglRectangle *result)
gegl_operation_point_filter_cl_process (GeglOperation *operation,
GeglBuffer *input,
GeglBuffer *output,
const GeglRectangle *result)
{
const Babl *in_format = gegl_operation_get_format (operation, "input");
const Babl *out_format = gegl_operation_get_format (operation, "output");
GeglOperationPointFilterClass *point_filter_class = GEGL_OPERATION_POINT_FILTER_GET_CLASS (operation);
int y, x, i;
int errcode = 0;
gfloat** out_data = NULL;
int ntex = 0;
struct buf_tex input_tex;
struct buf_tex output_tex;
const size_t origin_zero[3] = {0, 0, 0};
gegl_cl_color_op conv_in;
gegl_cl_color_op conv_out;
cl_image_format in_image_format;
cl_image_format out_image_format;
size_t bpp;
gint j;
cl_int errcode = 0;
/* non-texturizable format! */
if (!gegl_cl_color_babl (in_format, NULL, NULL) ||
......@@ -121,178 +97,30 @@ gegl_operation_point_filter_cl_process_full (GeglOperation *operation,
return FALSE;
}
if (!gegl_cl_color_babl (input->format, &in_image_format, &bpp))
gegl_cl_color_babl (in_format, &in_image_format, &bpp);
if (!gegl_cl_color_babl (output->format, &out_image_format, &bpp))
gegl_cl_color_babl (out_format, &out_image_format, &bpp);
conv_in = gegl_cl_color_supported (input->format, in_format);
conv_out = gegl_cl_color_supported (out_format, output->format);
g_printf("[OpenCL] BABL formats: (%s,%s:%d) (%s,%s:%d)\n \t Tile Size:(%d, %d)\n",
g_printf("[OpenCL] BABL formats: (%s,%s) (%s,%s)\n \t Tile Size:(%d, %d)\n",
babl_get_name(input->format),
babl_get_name(in_format),
conv_in,
babl_get_name(out_format),
babl_get_name(output->format),
conv_out,
input->tile_storage->tile_width,
input->tile_storage->tile_height);
for (y=result->y; y < result->y + result->height; y += cl_state.max_image_height)
for (x=result->x; x < result->x + result->width; x += cl_state.max_image_width)
ntex++;
input_tex.region = (GeglRectangle *) g_new0 (GeglRectangle, ntex);
output_tex.region = (GeglRectangle *) g_new0 (GeglRectangle, ntex);
input_tex.tex = (cl_mem *) g_new0 (cl_mem, ntex);
output_tex.tex = (cl_mem *) g_new0 (cl_mem, ntex);
i = 0;
for (y=result->y; y < result->y + result->height; y += cl_state.max_image_height)
for (x=result->x; x < result->x + result->width; x += cl_state.max_image_width)
{
const size_t region[3] = {MIN(cl_state.max_image_width, result->x + result->width - x),
MIN(cl_state.max_image_height, result->y + result->height - y),
1};
GeglRectangle r = {x, y, region[0], region[1]};
input_tex.region[i] = output_tex.region[i] = r;
input_tex.tex[i] = gegl_cl_texture_manager_request (CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE,
in_image_format,
region[0], region[1]);
if (input_tex.tex[i] == NULL) CL_ERROR;
output_tex.tex[i] = gegl_cl_texture_manager_request (CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE,
out_image_format,
region[0], region[1]);
if (output_tex.tex[i] == NULL) CL_ERROR;
i++;
}
for (i=0; i < ntex; i++)
{
gpointer data;
size_t pitch;
const size_t region[3] = {input_tex.region[i].width, input_tex.region[i].height, 1};
/* pre-pinned memory */
data = gegl_clEnqueueMapImage(gegl_cl_get_command_queue(), input_tex.tex[i], CL_TRUE,
CL_MAP_WRITE,
origin_zero, region, &pitch, NULL,
0, NULL, NULL, &errcode);
if (errcode != CL_SUCCESS) CL_ERROR;
/* un-tile */
if (conv_in == CL_COLOR_NOT_SUPPORTED)
/* color conversion using BABL */
gegl_buffer_get (input, 1.0, &input_tex.region[i], in_format, data, pitch);
else
/* color conversion will be performed in the GPU later */
gegl_buffer_get (input, 1.0, &input_tex.region[i], input->format, data, pitch);
errcode = gegl_clEnqueueUnmapMemObject (gegl_cl_get_command_queue(), input_tex.tex[i], data,
0, NULL, NULL);
if (errcode != CL_SUCCESS) CL_ERROR;
}
errcode = gegl_clEnqueueBarrier(gegl_cl_get_command_queue());
if (errcode != CL_SUCCESS) CL_ERROR;
/* color conversion in the GPU (input) */
if (conv_in == CL_COLOR_CONVERT)
for (i=0; i < ntex; i++)
{
const size_t size[2] = {input_tex.region[i].width, input_tex.region[i].height};
errcode = gegl_cl_color_conv (&input_tex.tex[i], &output_tex.tex[i], size, input->format, in_format);
if (errcode == FALSE) CL_ERROR;
}
/* Process */
for (i=0; i < ntex; i++)
{
const size_t region[3] = {input_tex.region[i].width, input_tex.region[i].height, 1};
const size_t global_worksize[2] = {region[0], region[1]};
errcode = point_filter_class->cl_process(operation, input_tex.tex[i], output_tex.tex[i], global_worksize, &input_tex.region[i]);
if (errcode != CL_SUCCESS) CL_ERROR;
}
/* Wait Processing */
errcode = gegl_clEnqueueBarrier(gegl_cl_get_command_queue());
if (errcode != CL_SUCCESS) CL_ERROR;
/* color conversion in the GPU (output) */
if (conv_out == CL_COLOR_CONVERT)
for (i=0; i < ntex; i++)
{
const size_t size[2] = {output_tex.region[i].width, output_tex.region[i].height};
errcode = gegl_cl_color_conv (&output_tex.tex[i], &input_tex.tex[i], size, out_format, output->format);
}
/* Wait Processing */
errcode = gegl_clEnqueueBarrier(gegl_cl_get_command_queue());
if (errcode != CL_SUCCESS) CL_ERROR;
/* GPU -> CPU */
for (i=0; i < ntex; i++)
{
gpointer data;
size_t pitch;
const size_t region[3] = {output_tex.region[i].width, output_tex.region[i].height, 1};
data = gegl_clEnqueueMapImage(gegl_cl_get_command_queue(), output_tex.tex[i], CL_TRUE,
CL_MAP_READ,
origin_zero, region, &pitch, NULL,
0, NULL, NULL, &errcode);
if (errcode != CL_SUCCESS) CL_ERROR;
/* tile-ize */
if (conv_out == CL_COLOR_NOT_SUPPORTED)
/* color conversion using BABL */
gegl_buffer_set (output, &output_tex.region[i], out_format, data, pitch);
else
/* color conversion has already been be performed in the GPU */
gegl_buffer_set (output, &output_tex.region[i], output->format, data, pitch);
errcode = gegl_clEnqueueUnmapMemObject (gegl_cl_get_command_queue(), output_tex.tex[i], data,
0, NULL, NULL);
if (errcode != CL_SUCCESS) CL_ERROR;
}
/* Run! */
errcode = gegl_clFinish(gegl_cl_get_command_queue());
if (errcode != CL_SUCCESS) CL_ERROR;
for (i=0; i < ntex; i++)
{
gegl_cl_texture_manager_give (input_tex.tex[i]);
gegl_cl_texture_manager_give (output_tex.tex[i]);
}
g_free(input_tex.tex);
g_free(output_tex.tex);
g_free(input_tex.region);
g_free(output_tex.region);
{
GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (output, result, out_format, GEGL_CL_BUFFER_WRITE);
gint read = gegl_buffer_cl_iterator_add (i, input, result, in_format, GEGL_CL_BUFFER_READ);
while (gegl_buffer_cl_iterator_next (i))
for (j=0; j < i->n; j++)
{
errcode = point_filter_class->cl_process(operation, i->tex[read][j], i->tex[0][j],
i->size[0][j], &i->roi[0][j]);
if (errcode != CL_SUCCESS) CL_ERROR;
}
}
return TRUE;
error:
for (i=0; i < ntex;