Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
basebuffer.c
Go to the documentation of this file.
1/*
2 This file is part of Ansel.
3 Copyright (C) 2026 Guillaume Stutin.
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22#include "develop/imageop_gui.h"
23
24#include "system/openmp.h"
26#include "system/mem_alloc.h"
28#include "caches/mipmap_cache.h"
29#include "develop/develop.h"
31#include "develop/imageop.h"
32#include "iop/iop_api.h"
33
34#include <string.h>
35
37
42
44
45const char *name()
46{
47 return _("base buffer");
48}
49
51{
53}
54
59
61{
62 return pipe->dev->image_storage.dsc.cst;
63}
64
65// Full-size RAW in and out
67 const dt_iop_roi_t *const roi_out, dt_iop_roi_t *roi_in)
68{
69 *roi_in = (dt_iop_roi_t){ 0, 0, pipe->iwidth, pipe->iheight, 1.f };
70}
71
73 dt_iop_roi_t *roi_out, const dt_iop_roi_t *const roi_in)
74{
75 *roi_out = (dt_iop_roi_t){ 0, 0, pipe->iwidth, pipe->iheight, 1.f };
76}
77
78/* --- the geometry service's view of this module (develop/geometry/geometry.h) ---------
79 *
80 * basebuffer is the first module in the pipe and asserts the full sensor frame at scale 1,
81 * ignoring whatever roi_in it is handed. The geometry chain seeds its fold with exactly that
82 * -- the raw dimensions at scale 1 -- so re-asserting the input rect here reproduces the
83 * callback above for every position this module can occupy. It moves no points.
84 */
85
86static void _basebuffer_geometry_map_size(const void *data, const dt_iop_roi_t *const in, dt_iop_roi_t *out)
87{
88 *out = (dt_iop_roi_t){ 0, 0, in->width, in->height, 1.f };
89}
90
93 .transform = NULL,
94 .backtransform = NULL,
95};
96
97gboolean geometry_record(dt_iop_module_t *self, const void *params, dt_geometry_record_t *record)
98{
100 return TRUE;
101}
102
103
106{
107 memcpy(dsc, &pipe->dev->image_storage.dsc, sizeof(dt_iop_buffer_dsc_t));
108}
109
110
113{
114 memcpy(dsc, &pipe->dev->image_storage.dsc, sizeof(dt_iop_buffer_dsc_t));
115}
116
117
120 const void *const ivoid, void *const ovoid)
121{
122 const dt_iop_roi_t *const roi_out = &piece->roi_out;
124
125 dt_mipmap_cache_get(&buf, pipe->imgid, pipe->size, DT_MIPMAP_BLOCKING, 'r');
126
127 // Catch out-of-bounds here because roi_in -> roi_out conversions
128 // use float scaling that may not always respect initial size.
129
130 // Crop rectangle offset. roi_in is always the full sensor buffer here (modify_roi_in()
131 // always requests it whole, so basebuffer can crop any region from it) : the region
132 // actually requested downstream lives in roi_out.
133 const size_t x = MAX(roi_out->x, 0);
134 const size_t y = MAX(roi_out->y, 0);
135
136 // Crop rectangle size, and stride of the full source buffer we are cropping from
137 const size_t in_width = MIN((size_t)roi_out->width, pipe->iwidth - x);
138 const size_t in_height = MIN((size_t)roi_out->height, pipe->iheight - y);
139 const size_t in_stride = pipe->iwidth * piece->dsc_in.bpp;
140 const size_t out_stride = roi_out->width * piece->dsc_out.bpp;
141 const size_t row_bytes = in_width * piece->dsc_in.bpp;
142
143 // Crop offset translated in memory sizes
144 const size_t y_offset = y * in_stride;
145 const size_t x_offset = x * piece->dsc_in.bpp;
146
147 /* This stage copies the immutable mipmap-cache payload into the pixelpipe cacheline that will
148 * be consumed by the first real processing stage. Keeping the source copy local here makes the
149 * cache ownership and lifetime visible in the recursion instead of in a hidden bootstrap path. */
150 const void *const restrict input = buf.buf;
151
153 for(size_t j = 0; j < in_height; j++)
154 memcpy(ovoid + j * out_stride, input + x_offset + y_offset + j * in_stride, MIN(row_bytes, out_stride));
155
157
158 return 0;
159}
160
161#ifdef HAVE_OPENCL
162int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out)
163{
164 const dt_iop_roi_t *const roi_out = &piece->roi_out;
166
167 dt_mipmap_cache_get(&buf, pipe->imgid, pipe->size, DT_MIPMAP_BLOCKING, 'r');
168
169 // Catch out-of-bounds here because roi_in -> roi_out conversions
170 // use float scaling that may not always respect initial size.
171
172 // Crop rectangle offset. roi_in is always the full sensor buffer here (modify_roi_in()
173 // always requests it whole, so basebuffer can crop any region from it) : the region
174 // actually requested downstream lives in roi_out.
175 const size_t x = MAX(roi_out->x, 0);
176 const size_t y = MAX(roi_out->y, 0);
177
178 // Stride of the full source buffer we are cropping from
179 const size_t in_stride = pipe->iwidth * piece->dsc_in.bpp;
180
181 // Crop offset translated in memory sizes
182 const size_t y_offset = y * in_stride;
183 const size_t x_offset = x * piece->dsc_in.bpp;
184
185 /* This stage copies the immutable mipmap-cache payload into the pixelpipe cacheline that will
186 * be consumed by the first real processing stage. Keeping the source copy local here makes the
187 * cache ownership and lifetime visible in the recursion instead of in a hidden bootstrap path. */
188 const void *const restrict input = buf.buf;
189
190 // dev_out is a fresh, roi_out-sized device buffer: the write always starts at its own origin.
191 // The crop offset only applies to where we start reading from the host-side full buffer above.
192 size_t origin[] = { 0, 0, 0 };
193 size_t region[] = { MIN((size_t)roi_out->width, pipe->iwidth - x), MIN((size_t)roi_out->height, pipe->iheight - y), 1 };
194
195 int err = dt_opencl_write_host_to_device_raw(pipe->devid, input + x_offset + y_offset, dev_out, origin,
196 region, in_stride, CL_TRUE);
197
198
200
201 return err == CL_SUCCESS;
202}
203#endif
204
205
211
213{
214 dt_free_align(piece->data);
215 piece->data = NULL;
216}
217
219{
220 self->params = calloc(1, sizeof(dt_iop_basebuffer_params_t));
221 self->default_params = calloc(1, sizeof(dt_iop_basebuffer_params_t));
222 self->default_enabled = 1;
223 self->hide_enable_button = 1;
225}
226
228{
229 dt_free(self->params);
230 dt_free(self->default_params);
231}
232
233// clang-format off
234// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
235// vim: shiftwidth=2 expandtab tabstop=2 cindent
236// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
237// clang-format on
#define TRUE
Definition ashift_lsd.c:162
void modify_roi_out(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_roi_t *roi_out, const dt_iop_roi_t *const roi_in)
Definition basebuffer.c:72
int default_group()
Definition basebuffer.c:50
static void _basebuffer_geometry_map_size(const void *data, const dt_iop_roi_t *const in, dt_iop_roi_t *out)
Definition basebuffer.c:86
__DT_CLONE_TARGETS__ int process(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
Definition basebuffer.c:119
void modify_roi_in(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *const roi_out, dt_iop_roi_t *roi_in)
Definition basebuffer.c:66
static const dt_geometry_vtable_t _basebuffer_geometry_vtable
Definition basebuffer.c:91
const char * name()
Definition basebuffer.c:45
void output_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
Definition basebuffer.c:104
gboolean geometry_record(dt_iop_module_t *self, const void *params, dt_geometry_record_t *record)
Definition basebuffer.c:97
void cleanup_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition basebuffer.c:212
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition basebuffer.c:60
void input_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
Definition basebuffer.c:111
int flags()
Definition basebuffer.c:55
void init(dt_iop_module_t *self)
Definition basebuffer.c:218
void init_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition basebuffer.c:206
dt_iop_basebuffer_params_t dt_iop_basebuffer_data_t
Definition basebuffer.c:43
int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out)
Definition basebuffer.c:162
void cleanup(dt_iop_module_t *self)
Definition basebuffer.c:227
static const float x
const dt_colormatrix_t dt_aligned_pixel_t out
Where things are on the image, answered without a pipeline.
@ IOP_FLAGS_HIDDEN
Definition imageop.h:189
@ IOP_FLAGS_TAKE_NO_INPUT
Definition imageop.h:195
@ IOP_FLAGS_UNSAFE_COPY
Definition imageop.h:196
@ IOP_FLAGS_ONE_INSTANCE
Definition imageop.h:191
@ IOP_FLAGS_CPU_WRITES_OPENCL
Definition imageop.h:199
@ IOP_FLAGS_NO_HISTORY_STACK
Definition imageop.h:193
@ IOP_GROUP_TECHNICAL
Definition imageop.h:162
void *const ovoid
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
Definition mem_alloc.h:214
static void * dt_calloc_align(size_t size)
dt_alloc_align() followed by a zero fill.
Definition mem_alloc.h:225
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
@ DT_MIPMAP_BLOCKING
#define dt_mipmap_cache_get(B, C, D, E, F)
#define dt_mipmap_cache_release(B)
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
int dt_opencl_write_host_to_device_raw(const int devid, const void *host, void *device, const size_t *origin, const size_t *region, const int rowpitch, const int blocking)
Definition opencl.c:2667
#define __OMP_PARALLEL_FOR__(...)
Definition openmp.h:95
dt_iop_buffer_dsc_t dsc_out
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
dt_mipmap_size_t size
struct dt_develop_t * dev
dt_image_t image_storage
Definition develop.h:225
One module instance's contribution, as data.
Definition geometry.h:99
const dt_geometry_vtable_t * vtable
Definition geometry.h:110
A module's geometry, evaluated. Pure functions of the record's own data.
Definition geometry.h:75
void(* map_size)(const void *data, const dt_iop_roi_t *const in, dt_iop_roi_t *out)
Full-resolution input rect -> output rect. Mirrors modify_roi_out() at scale 1.
Definition geometry.h:77
dt_iop_buffer_dsc_t dsc
Definition image.h:419
int32_t hide_enable_button
Definition imageop.h:270
dt_iop_params_t * default_params
Definition imageop.h:333
gboolean default_enabled
Definition imageop.h:318
int32_t params_size
Definition imageop.h:335
dt_iop_params_t * params
Definition imageop.h:333
Region of interest passed through the pixelpipe.
Definition format.h:49
int width
Definition format.h:50
int height
Definition format.h:50
#define __DT_CLONE_TARGETS__
#define MIN(a, b)
Definition thinplate.c:32
#define MAX(a, b)
Definition thinplate.c:29