static void get_tile (GeglBufferIterator *iter, int index) { GeglBufferIteratorPriv *priv = iter->priv; SubIterState *sub = &priv->sub_iter[index]; GeglBuffer *buf = priv->sub_iter[index].buffer; if (sub->linear_tile) { sub->current_tile = sub->linear_tile; sub->real_roi = buf->extent; sub->current_tile_mode = GeglIteratorTileMode_LinearTile; } else { int shift_x = buf->shift_x; int shift_y = buf->shift_y; int tile_width = buf->tile_width; int tile_height = buf->tile_height; int tile_x = gegl_tile_indice (iter->roi[index].x + shift_x, tile_width); int tile_y = gegl_tile_indice (iter->roi[index].y + shift_y, tile_height); sub->current_tile = gegl_tile_source_get_tile ((GeglTileSource *)(buf), tile_x, tile_y, 0); if (sub->flags & GEGL_BUFFER_WRITE) gegl_tile_lock (sub->current_tile); sub->real_roi.x = (tile_x * tile_width) - shift_x; sub->real_roi.y = (tile_y * tile_height) - shift_y; sub->real_roi.width = tile_width; sub->real_roi.height = tile_height; sub->current_tile_mode = GeglIteratorTileMode_DirectTile; } sub->row_stride = buf->tile_width * sub->format_bpp; iter->data[index] = gegl_tile_get_data (sub->current_tile); }
static void retile_subs (GeglBufferIterator *iter, int x, int y) { GeglBufferIteratorPriv *priv = iter->priv; GeglRectangle real_roi; int index; int shift_x = priv->origin_tile.x; int shift_y = priv->origin_tile.y; int tile_x = gegl_tile_indice (x + shift_x, priv->origin_tile.width); int tile_y = gegl_tile_indice (y + shift_y, priv->origin_tile.height); /* Reset tile size */ real_roi.x = (tile_x * priv->origin_tile.width) - shift_x; real_roi.y = (tile_y * priv->origin_tile.height) - shift_y; real_roi.width = priv->origin_tile.width; real_roi.height = priv->origin_tile.height; /* Trim tile down to the iteration roi */ gegl_rectangle_intersect (&iter->roi[0], &real_roi, &priv->sub_iter[0].full_rect); priv->sub_iter[0].real_roi = iter->roi[0]; for (index = 1; index < priv->num_buffers; index++) { SubIterState *lead_sub = &priv->sub_iter[0]; SubIterState *sub = &priv->sub_iter[index]; int roi_offset_x = sub->full_rect.x - lead_sub->full_rect.x; int roi_offset_y = sub->full_rect.y - lead_sub->full_rect.y; iter->roi[index].x = iter->roi[0].x + roi_offset_x; iter->roi[index].y = iter->roi[0].y + roi_offset_y; iter->roi[index].width = iter->roi[0].width; iter->roi[index].height = iter->roi[0].height; sub->real_roi = iter->roi[index]; } }
static gboolean gegl_buffer_tile_iterator_next (GeglBufferTileIterator *i) { GeglBuffer *buffer = i->buffer; gint tile_width = buffer->tile_storage->tile_width; gint tile_height = buffer->tile_storage->tile_height; gint buffer_shift_x = buffer->shift_x; gint buffer_shift_y = buffer->shift_y; gint buffer_x = i->roi.x + buffer_shift_x; gint buffer_y = i->roi.y + buffer_shift_y; if (i->roi.width == 0 || i->roi.height == 0) return FALSE; gulp: /* unref previously held tile */ if (i->tile) { if (i->write && i->subrect.width == tile_width && i->same_format) { gegl_tile_unlock (i->tile); } gegl_tile_unref (i->tile); i->tile = NULL; } if (i->next_col < i->roi.width) { /* return tile on this row */ gint tiledx = buffer_x + i->next_col; gint tiledy = buffer_y + i->next_row; gint offsetx = gegl_tile_offset (tiledx, tile_width); gint offsety = gegl_tile_offset (tiledy, tile_height); { i->subrect.x = offsetx; i->subrect.y = offsety; if (i->roi.width + offsetx - i->next_col < tile_width) i->subrect.width = (i->roi.width + offsetx - i->next_col) - offsetx; else i->subrect.width = tile_width - offsetx; if (i->roi.height + offsety - i->next_row < tile_height) i->subrect.height = (i->roi.height + offsety - i->next_row) - offsety; else i->subrect.height = tile_height - offsety; i->tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer), gegl_tile_indice (tiledx, tile_width), gegl_tile_indice (tiledy, tile_height), 0); if (i->write && i->subrect.width == tile_width && i->same_format) { gegl_tile_lock (i->tile); } i->data = gegl_tile_get_data (i->tile); { gint bpp = babl_format_get_bytes_per_pixel (i->buffer->soft_format); i->rowstride = bpp * tile_width; i->sub_data = (guchar*)(i->data) + bpp * (i->subrect.y * tile_width + i->subrect.x); } i->col = i->next_col; i->row = i->next_row; i->next_col += tile_width - offsetx; i->roi2.x = i->roi.x + i->col; i->roi2.y = i->roi.y + i->row; i->roi2.width = i->subrect.width; i->roi2.height = i->subrect.height; return TRUE; } } else /* move down to next row */ { gint tiledy; gint offsety; i->row = i->next_row; i->col = i->next_col; tiledy = buffer_y + i->next_row; offsety = gegl_tile_offset (tiledy, tile_height); i->next_row += tile_height - offsety; i->next_col=0; if (i->next_row < i->roi.height) { goto gulp; /* return the first tile in the next row */ } return FALSE; } return FALSE; }
static void inline gegl_sampler_get_pixel (GeglSampler *sampler, gint x, gint y, gpointer data, GeglAbyssPolicy repeat_mode) { GeglSamplerNearest *nearest_sampler = (GeglSamplerNearest*)(sampler); GeglBuffer *buffer = sampler->buffer; const GeglRectangle *abyss = &buffer->abyss; guchar *buf = data; if (y < abyss->y || x < abyss->x || y >= abyss->y + abyss->height || x >= abyss->x + abyss->width) { switch (repeat_mode) { case GEGL_ABYSS_CLAMP: x = CLAMP (x, abyss->x, abyss->x+abyss->width-1); y = CLAMP (y, abyss->y, abyss->y+abyss->height-1); break; case GEGL_ABYSS_LOOP: x = abyss->x + GEGL_REMAINDER (x - abyss->x, abyss->width); y = abyss->y + GEGL_REMAINDER (y - abyss->y, abyss->height); break; case GEGL_ABYSS_BLACK: { gfloat color[4] = {0.0, 0.0, 0.0, 1.0}; babl_process (babl_fish (gegl_babl_rgba_linear_float (), sampler->format), color, buf, 1); return; } case GEGL_ABYSS_WHITE: { gfloat color[4] = {1.0, 1.0, 1.0, 1.0}; babl_process (babl_fish (gegl_babl_rgba_linear_float (), sampler->format), color, buf, 1); return; } default: case GEGL_ABYSS_NONE: memset (buf, 0x00, babl_format_get_bytes_per_pixel (sampler->format)); return; } } gegl_buffer_lock (sampler->buffer); { gint tile_width = buffer->tile_width; gint tile_height = buffer->tile_height; gint tiledy = y + buffer->shift_y; gint tiledx = x + buffer->shift_x; gint indice_x = gegl_tile_indice (tiledx, tile_width); gint indice_y = gegl_tile_indice (tiledy, tile_height); GeglTile *tile = nearest_sampler->hot_tile; if (!(tile && tile->x == indice_x && tile->y == indice_y)) { if (gegl_config_threads()>1) g_rec_mutex_lock (&buffer->tile_storage->mutex); if (tile) gegl_tile_unref (tile); tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer), indice_x, indice_y, 0); nearest_sampler->hot_tile = tile; if (gegl_config_threads()>1) g_rec_mutex_unlock (&buffer->tile_storage->mutex); } if (tile) { gint tile_origin_x = indice_x * tile_width; gint tile_origin_y = indice_y * tile_height; gint offsetx = tiledx - tile_origin_x; gint offsety = tiledy - tile_origin_y; guchar *tp = gegl_tile_get_data (tile) + (offsety * tile_width + offsetx) * nearest_sampler->buffer_bpp; babl_process (sampler->fish, tp, buf, 1); } } gegl_buffer_unlock (sampler->buffer); }