static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); GeglRectangle compute; if (o->blur_radius >= 1.0 && gegl_cl_is_accelerated ()) if (cl_process (operation, input, output, result)) return TRUE; compute = gegl_operation_get_required_for_output (operation, "input",result); if (o->blur_radius < 1.0) { gegl_buffer_copy (input, result, output, result); } else { bilateral_filter (input, &compute, output, result, o->blur_radius, o->edge_preservation); } return TRUE; }
static void gegl_buffer_dispose (GObject *object) { GeglBuffer *buffer = GEGL_BUFFER (object); GeglTileHandler *handler = GEGL_TILE_HANDLER (object); gegl_buffer_sample_cleanup (buffer); if (gegl_cl_is_accelerated ()) gegl_buffer_cl_cache_invalidate (GEGL_BUFFER (object), NULL); if (handler->source && GEGL_IS_TILE_STORAGE (handler->source)) { GeglTileBackend *backend = gegl_buffer_backend (buffer); /* only flush non-internal backends,. */ if (!(GEGL_IS_TILE_BACKEND_FILE (backend) || GEGL_IS_TILE_BACKEND_RAM (backend) || GEGL_IS_TILE_BACKEND_TILE_DIR (backend))) gegl_buffer_flush (buffer); gegl_tile_source_reinit (GEGL_TILE_SOURCE (handler->source)); #if 0 g_object_unref (handler->source); handler->source = NULL; /* this might be a dangerous way of marking that we have already voided */ #endif } _gegl_buffer_drop_hot_tile (buffer); G_OBJECT_CLASS (parent_class)->dispose (object); }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); GeglBuffer *temp_in; GeglRectangle compute; if (gegl_cl_is_accelerated ()) if (cl_process (operation, input, output, result)) return TRUE; compute = gegl_operation_get_required_for_output ( operation, "input", result); if (o->radius < 1.0) { output = g_object_ref (input); } else { temp_in = gegl_buffer_create_sub_buffer (input, &compute); snn_mean (temp_in, output, result, o->radius, o->pairs); g_object_unref (temp_in); } return TRUE; }
void gegl_sampler_get (GeglSampler *self, gdouble x, gdouble y, GeglMatrix2 *scale, void *output, GeglAbyssPolicy repeat_mode) { if (G_UNLIKELY(!isfinite (x))) x = 0.0; if (G_UNLIKELY(!isfinite (y))) y = 0.0; if (self->lvel) { double factor = 1.0 / (1 << self->lvel); GeglRectangle rect={floorf (x * factor), floorf (y * factor),1,1}; gegl_buffer_get (self->buffer, &rect, factor, self->format, output, GEGL_AUTO_ROWSTRIDE, repeat_mode); return; } if (gegl_cl_is_accelerated ()) { GeglRectangle rect={x,y,1,1}; gegl_buffer_cl_cache_flush (self->buffer, &rect); } self->get (self, x, y, scale, output, repeat_mode); }
static void gegl_config_use_opencl_notify (GObject *gobject, GParamSpec *pspec, gpointer user_data) { GeglConfig *cfg = GEGL_CONFIG (gobject); g_signal_handlers_block_by_func (gobject, gegl_config_use_opencl_notify, NULL); if (cfg->use_opencl) { gegl_cl_init (NULL); } else { gegl_cl_disable (); } cfg->use_opencl = gegl_cl_is_accelerated(); g_signal_handlers_unblock_by_func (gobject, gegl_config_use_opencl_notify, NULL); }
gboolean gegl_cl_has_extension (const char *extension_name) { if (!gegl_cl_is_accelerated () || !extension_name) return FALSE; return gegl_cl_device_has_extension (cl_state.device, extension_name); }
GeglSamplerGetFun gegl_sampler_get_fun (GeglSampler *sampler) { /* this flushes the buffer in preparation for the use of the sampler, * thus one can consider the handed out sampler function only temporarily * available*/ if (gegl_cl_is_accelerated ()) gegl_buffer_cl_cache_flush (sampler->buffer, NULL); return sampler->get; }
static void gegl_config_get_property (GObject *gobject, guint property_id, GValue *value, GParamSpec *pspec) { GeglConfig *config = GEGL_CONFIG (gobject); switch (property_id) { case PROP_TILE_CACHE_SIZE: g_value_set_uint64 (value, config->tile_cache_size); break; case PROP_CHUNK_SIZE: g_value_set_int (value, config->chunk_size); break; case PROP_TILE_WIDTH: g_value_set_int (value, config->tile_width); break; case PROP_TILE_HEIGHT: g_value_set_int (value, config->tile_height); break; case PROP_QUALITY: g_value_set_double (value, config->quality); break; case PROP_BABL_TOLERANCE: g_value_set_double (value, config->babl_tolerance); break; case PROP_SWAP: g_value_set_string (value, config->swap); break; case PROP_THREADS: g_value_set_int (value, config->threads); break; case PROP_USE_OPENCL: g_value_set_boolean (value, gegl_cl_is_accelerated()); break; case PROP_QUEUE_SIZE: g_value_set_int (value, config->queue_size); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec); break; } }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); gfloat red = o->red; gfloat green = o->green; gfloat blue = o->blue; gfloat *in_buf; gfloat *out_buf; if (gegl_cl_is_accelerated ()) if (cl_process (operation, input, output, result)) return TRUE; if ((result->width > 0) && (result->height > 0)) { gint num_pixels = result->width * result->height; gint i; gfloat *in_pixel, *out_pixel; in_buf = g_new (gfloat, 4 * num_pixels); out_buf = g_new (gfloat, 2 * num_pixels); gegl_buffer_get (input, result, 1.0, babl_format ("RGBA float"), in_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); in_pixel = in_buf; out_pixel = out_buf; for (i = 0; i < num_pixels; ++i) { out_pixel[0] = in_pixel[0] * red + in_pixel[1] * green + in_pixel[2] * blue; out_pixel[1] = in_pixel[3]; in_pixel += 4; out_pixel += 2; } gegl_buffer_set (output, result, 0, babl_format ("YA float"), out_buf, GEGL_AUTO_ROWSTRIDE); g_free (in_buf); g_free (out_buf); } return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglRectangle compute; if (gegl_cl_is_accelerated ()) if (cl_process (operation, input, output, result)) return TRUE; compute = gegl_operation_get_required_for_output (operation, "input", result); edge_laplace (input, &compute, output, result); return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); GeglRectangle input_rect = gegl_operation_get_required_for_output (operation, "input", result); if (gegl_cl_is_accelerated ()) if (cl_process (operation, input, output, result)) return TRUE; hor_min ( input, &input_rect, output, result, o->radius); ver_min (output, result, output, result, o->radius); return TRUE; }
void gegl_buffer_sample_at_level (GeglBuffer *buffer, gdouble x, gdouble y, GeglMatrix2 *scale, gpointer dest, const Babl *format, gint level, GeglSamplerType sampler_type, GeglAbyssPolicy repeat_mode) { /* if (sampler_type == GEGL_SAMPLER_NEAREST && format == buffer->soft_format) { GeglRectangle rect = {floorf (x), floorf(y), 1, 1}; gegl_buffer_get (buffer, &rect, 1, NULL, dest, GEGL_AUTO_ROWSTRIDE, repeat_mode); return; }*/ if (!format) format = buffer->soft_format; if (gegl_cl_is_accelerated ()) { GeglRectangle rect = {floorf (x), floorf(y), 1, 1}; gegl_buffer_cl_cache_flush (buffer, &rect); } /* unset the cached sampler if it dosn't match the needs */ if (buffer->sampler == NULL || (buffer->sampler != NULL && (buffer->sampler_type != sampler_type || buffer->sampler_format != format))) { gboolean threaded = gegl_config_threads () > 1; GType desired_type = gegl_sampler_gtype_from_enum (sampler_type); if (threaded) g_mutex_lock (&gegl_buffer_sampler_mutex); if (buffer->sampler) { g_object_unref (buffer->sampler); buffer->sampler = NULL; buffer->sampler_type = 0; } buffer->sampler_type = sampler_type; buffer->sampler = g_object_new (desired_type, "buffer", buffer, "format", format, "level", level, NULL); buffer->sampler_format = format; gegl_sampler_prepare (buffer->sampler); if (threaded) g_mutex_unlock (&gegl_buffer_sampler_mutex); } buffer->sampler->get(buffer->sampler, x, y, scale, dest, repeat_mode); }
gfloat * gegl_sampler_get_from_mipmap (GeglSampler *sampler, gint x, gint y, gint level_no, GeglAbyssPolicy repeat_mode) { GeglSamplerLevel *level = &sampler->level[level_no]; guchar *buffer_ptr; gint dx; gint dy; gint sof; const gdouble scale = 1. / ((gdouble) (1 << level_no)); const gint maximum_width = GEGL_SAMPLER_MAXIMUM_WIDTH; const gint maximum_height = GEGL_SAMPLER_MAXIMUM_HEIGHT; if (gegl_cl_is_accelerated ()) { GeglRectangle rect = {x, y, 1, 1}; gegl_buffer_cl_cache_flush (sampler->buffer, &rect); } g_assert (level_no >= 0 && level_no < GEGL_SAMPLER_MIPMAP_LEVELS); g_assert (level->context_rect.width <= maximum_width); g_assert (level->context_rect.height <= maximum_height); if ((level->sampler_buffer == NULL) || (x + level->context_rect.x < level->sampler_rectangle.x) || (y + level->context_rect.y < level->sampler_rectangle.y) || (x + level->context_rect.x + level->context_rect.width > level->sampler_rectangle.x + level->sampler_rectangle.width) || (y + level->context_rect.y + level->context_rect.height > level->sampler_rectangle.y + level->sampler_rectangle.height)) { /* * fetch_rectangle will become the value of * sampler->sampler_rectangle[level]: */ level->sampler_rectangle = _gegl_sampler_compute_rectangle (sampler, x, y, level_no); if (!level->sampler_buffer) level->sampler_buffer = g_malloc (GEGL_SAMPLER_ROWSTRIDE * GEGL_SAMPLER_MAXIMUM_HEIGHT); gegl_buffer_get (sampler->buffer, &level->sampler_rectangle, scale, sampler->interpolate_format, level->sampler_buffer, GEGL_SAMPLER_ROWSTRIDE, repeat_mode); } dx = x - level->sampler_rectangle.x; dy = y - level->sampler_rectangle.y; buffer_ptr = (guchar *) level->sampler_buffer; sof = (dx + dy * GEGL_SAMPLER_MAXIMUM_WIDTH) * GEGL_SAMPLER_BPP; return (gfloat*) (buffer_ptr + sof); }
gboolean gegl_cl_has_gl_sharing (void) { return cl_state.have_opengl && gegl_cl_is_accelerated (); }
gboolean gegl_buffer_iterator_next (GeglBufferIterator *iter) { GeglBufferIteratorPriv *priv = iter->priv; if (priv->state == GeglIteratorState_Start) { int index; prepare_iteration (iter); if (gegl_cl_is_accelerated ()) for (index = 0; index < priv->num_buffers; index++) { SubIterState *sub = &priv->sub_iter[index]; gegl_buffer_cl_cache_flush (sub->buffer, &sub->full_rect); } initialize_rects (iter); load_rects (iter); return TRUE; } else if (priv->state == GeglIteratorState_InRows) { int index; for (index = 0; index < priv->num_buffers; index++) { iter->data[index] = ((char *)iter->data[index]) + priv->sub_iter[index].row_stride; iter->roi[index].y += 1; } priv->remaining_rows -= 1; if (priv->remaining_rows == 0) priv->state = GeglIteratorState_InTile; return TRUE; } else if (priv->state == GeglIteratorState_InTile) { int index; for (index = 0; index < priv->num_buffers; index++) { release_tile (iter, index); } if (increment_rects (iter) == FALSE) { gegl_buffer_iterator_stop (iter); return FALSE; } load_rects (iter); return TRUE; } else { gegl_buffer_iterator_stop (iter); return FALSE; } }
gboolean gegl_buffer_iterator_next (GeglBufferIterator *iterator) { GeglBufferIterators *i = (gpointer)iterator; gboolean result = FALSE; gint no; 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]); if (gegl_cl_is_accelerated ()) gegl_buffer_cl_cache_flush (i->buffer[no], &i->rect[no]); } } else { /* complete pending write work */ for (no=0; no<i->iterators;no++) { if (i->flags[no] & GEGL_BUFFER_WRITE) { if (i->flags[no] & GEGL_BUFFER_SCAN_COMPATIBLE && i->flags[no] & GEGL_BUFFER_FORMAT_COMPATIBLE && i->roi[no].width == i->i[no].buffer->tile_storage->tile_width && (i->flags[no] & GEGL_BUFFER_FORMAT_COMPATIBLE)) { /* direct access, don't need to do anything */ #if DEBUG_DIRECT direct_write += i->roi[no].width * i->roi[no].height; #endif } else { #if DEBUG_DIRECT in_direct_write += i->roi[no].width * i->roi[no].height; #endif ensure_buf (i, no); /* XXX: should perhaps use _set_unlocked, and keep the lock in the * iterator. */ gegl_buffer_set (i->buffer[no], &(i->roi[no]), 0, i->format[no], i->buf[no], GEGL_AUTO_ROWSTRIDE); /* XXX: use correct level */ } } } } g_assert (i->iterators > 0); /* then we iterate all */ for (no=0; no<i->iterators;no++) { if (i->flags[no] & GEGL_BUFFER_SCAN_COMPATIBLE) { gboolean res; res = gegl_buffer_tile_iterator_next (&i->i[no]); if (no == 0) { result = res; } i->roi[no] = i->i[no].roi2; /* since they were scan compatible this should be true */ if (res != result) { g_print ("%i==%i != 0==%i\n", no, res, result); } g_assert (res == result); if ((i->flags[no] & GEGL_BUFFER_FORMAT_COMPATIBLE) && i->roi[no].width == i->i[no].buffer->tile_storage->tile_width ) { /* direct access */ i->data[no]=i->i[no].sub_data; #if DEBUG_DIRECT direct_read += i->roi[no].width * i->roi[no].height; #endif } else { ensure_buf (i, no); if (i->flags[no] & GEGL_BUFFER_READ) { gegl_buffer_get_unlocked (i->buffer[no], 1.0, &(i->roi[no]), i->format[no], i->buf[no], GEGL_AUTO_ROWSTRIDE); } i->data[no]=i->buf[no]; #if DEBUG_DIRECT in_direct_read += i->roi[no].width * i->roi[no].height; #endif } } else { /* we copy the roi from iterator 0 */ i->roi[no] = i->roi[0]; i->roi[no].x += (i->rect[no].x-i->rect[0].x); i->roi[no].y += (i->rect[no].y-i->rect[0].y); ensure_buf (i, no); if (i->flags[no] & GEGL_BUFFER_READ) { gegl_buffer_get_unlocked (i->buffer[no], 1.0, &(i->roi[no]), i->format[no], i->buf[no], GEGL_AUTO_ROWSTRIDE); } i->data[no]=i->buf[no]; #if DEBUG_DIRECT in_direct_read += i->roi[no].width * i->roi[no].height; #endif } i->length = i->roi[no].width * i->roi[no].height; } i->iteration_no++; if (result == FALSE) gegl_buffer_iterator_stop (iterator); return result; }
gboolean gegl_buffer_iterator_next (GeglBufferIterator *iter) { GeglBufferIteratorPriv *priv = iter->priv; if (priv->state == GeglIteratorState_Start) { int index; GeglBuffer *primary = priv->sub_iter[0].buffer; if (primary->tile_width == primary->extent.width && primary->tile_height == primary->extent.height && priv->sub_iter[0].full_rect.width == primary->tile_width && priv->sub_iter[0].full_rect.height == primary->tile_height && priv->sub_iter[0].full_rect.x == primary->extent.x && priv->sub_iter[0].full_rect.y == primary->extent.y && priv->sub_iter[0].buffer->extent.x == iter->roi[0].x && priv->sub_iter[0].buffer->extent.y == iter->roi[0].y && FALSE) /* XXX: conditions are not strict enough, GIMPs TIFF plug-in fails; but GEGLs buffer test suite passes */ { if (gegl_cl_is_accelerated ()) for (index = 0; index < priv->num_buffers; index++) { SubIterState *sub = &priv->sub_iter[index]; gegl_buffer_cl_cache_flush (sub->buffer, &sub->full_rect); } linear_shortcut (iter); return TRUE; } prepare_iteration (iter); if (gegl_cl_is_accelerated ()) for (index = 0; index < priv->num_buffers; index++) { SubIterState *sub = &priv->sub_iter[index]; gegl_buffer_cl_cache_flush (sub->buffer, &sub->full_rect); } initialize_rects (iter); load_rects (iter); return TRUE; } else if (priv->state == GeglIteratorState_InRows) { int index; for (index = 0; index < priv->num_buffers; index++) { iter->data[index] = ((char *)iter->data[index]) + priv->sub_iter[index].row_stride; iter->roi[index].y += 1; } priv->remaining_rows -= 1; if (priv->remaining_rows == 0) priv->state = GeglIteratorState_InTile; return TRUE; } else if (priv->state == GeglIteratorState_InTile) { int index; for (index = 0; index < priv->num_buffers; index++) { release_tile (iter, index); } if (increment_rects (iter) == FALSE) { gegl_buffer_iterator_stop (iter); return FALSE; } load_rects (iter); return TRUE; } else { gegl_buffer_iterator_stop (iter); return FALSE; } }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { gfloat min[3], max[3], diff[3]; GeglBufferIterator *gi; GeglProperties *o; gint c; if (gegl_cl_is_accelerated ()) if (cl_process (operation, input, output, result)) return TRUE; o = GEGL_PROPERTIES (operation); buffer_get_min_max (input, min, max); if (o->keep_colors) reduce_min_max_global (min, max); for (c = 0; c < 3; c++) { diff[c] = max[c] - min[c]; /* Avoid a divide by zero error if the image is a solid color */ if (diff[c] < 1e-3) { min[c] = 0.0; diff[c] = 1.0; } } gi = gegl_buffer_iterator_new (input, result, 0, babl_format ("RGBA float"), GEGL_ACCESS_READ, GEGL_ABYSS_NONE); gegl_buffer_iterator_add (gi, output, result, 0, babl_format ("RGBA float"), GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (gi)) { gfloat *in = gi->data[0]; gfloat *out = gi->data[1]; gint o; for (o = 0; o < gi->length; o++) { for (c = 0; c < 3; c++) out[c] = (in[c] - min[c]) / diff[c]; out[3] = in[3]; in += 4; out += 4; } } return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *roi, gint level) { GeglRectangle src_rect; GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); GeglOperationAreaFilter *op_area; gfloat* in_buf; gfloat* out_buf; gfloat* out_pixel; gint x,y; gdouble theta = o->angle * G_PI / 180.0; gdouble offset_x = o->length * cos(theta); gdouble offset_y = o->length * sin(theta); gint num_steps = (gint)ceil(o->length) + 1; gfloat inv_num_steps = 1.0f / num_steps; op_area = GEGL_OPERATION_AREA_FILTER (operation); src_rect = *roi; src_rect.x -= op_area->left; src_rect.y -= op_area->top; src_rect.width += op_area->left + op_area->right; src_rect.height += op_area->top + op_area->bottom; if (gegl_cl_is_accelerated ()) if (cl_process (operation, input, output, roi, &src_rect)) return TRUE; in_buf = g_new (gfloat, src_rect.width * src_rect.height * 4); out_buf = g_new0 (gfloat, roi->width * roi->height * 4); out_pixel = out_buf; gegl_buffer_get (input, &src_rect, 1.0, babl_format ("RaGaBaA float"), in_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); for (y=0; y<roi->height; ++y) { for (x=0; x<roi->width; ++x) { gint step; gint c; gint px = x+roi->x; gint py = y+roi->y; gfloat sum[4] = {0,0,0,0}; for (step=0; step<num_steps; ++step) { gdouble t = num_steps == 1 ? 0.0 : step / (gdouble)(num_steps-1) - 0.5; /* get the interpolated pixel position for this step */ gdouble xx = px + t*offset_x; gdouble yy = py + t*offset_y; gint ix = (gint)floor(xx); gint iy = (gint)floor(yy); gdouble dx = xx - floor(xx); gdouble dy = yy - floor(yy); /* do bilinear interpolation to get a nice smooth result */ gfloat *pix0, *pix1, *pix2, *pix3; gfloat mixy0[4]; gfloat mixy1[4]; pix0 = get_pixel_color(in_buf, &src_rect, ix, iy); pix1 = get_pixel_color(in_buf, &src_rect, ix+1, iy); pix2 = get_pixel_color(in_buf, &src_rect, ix, iy+1); pix3 = get_pixel_color(in_buf, &src_rect, ix+1, iy+1); for (c=0; c<4; ++c) { mixy0[c] = dy*(pix2[c] - pix0[c]) + pix0[c]; mixy1[c] = dy*(pix3[c] - pix1[c]) + pix1[c]; sum[c] += dx*(mixy1[c] - mixy0[c]) + mixy0[c]; } } for (c=0; c<4; ++c) *out_pixel++ = sum[c] * inv_num_steps; } } gegl_buffer_set (output, roi, 0, babl_format ("RaGaBaA float"), out_buf, GEGL_AUTO_ROWSTRIDE); g_free (in_buf); g_free (out_buf); return TRUE; }