Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
pixelpipe_cpu.c
Go to the documentation of this file.
1/*
2 Private CPU pixelpipe backend.
3*/
4
5#include "common/darktable.h"
6#include "common/iop_order.h"
7#include "develop/blend.h"
10
11#include <assert.h>
12#include <math.h>
13#include <stdio.h>
14
16 const dt_dev_pixelpipe_iop_t *previous_piece,
18 gboolean *const cache_output,
19 dt_pixel_cache_entry_t *input_entry, dt_pixel_cache_entry_t *output_entry)
20{
21 dt_iop_module_t *module = piece->module;
22 float *input = input_entry ? dt_pixel_cache_entry_get_data(input_entry) : NULL;
23 void *output = dt_pixel_cache_entry_get_data(output_entry);
24 float *process_input_temp = NULL;
25 float *blend_input_temp = NULL;
26 float *blend_output_temp = NULL;
27 const float *process_input = input;
28 const float *blend_input = input;
29 void *blend_output = output;
30 const dt_iop_buffer_dsc_t actual_input_dsc = previous_piece ? previous_piece->dsc_out : pipe->dev->image_storage.dsc;
31 dt_iop_buffer_dsc_t process_input_dsc = actual_input_dsc;
32 dt_iop_buffer_dsc_t blend_input_dsc = actual_input_dsc;
33 dt_iop_buffer_dsc_t blend_output_dsc = piece->dsc_out;
34 gboolean input_locked = FALSE;
35
36 if(IS_NULL_PTR(input) && !(module->flags() & IOP_FLAGS_TAKE_NO_INPUT))
37 {
38 fprintf(stdout, "[dev_pixelpipe] %s got a NULL input, report that to developers\n", module->name());
39 return 1;
40 }
41 if(IS_NULL_PTR(output))
42 output = dt_pixel_cache_alloc(darktable.pixelpipe_cache, output_entry);
43
44 if(IS_NULL_PTR(output))
45 {
46 fprintf(stdout, "[dev_pixelpipe] %s got a NULL output, report that to developers\n", module->name());
47 return 1;
48 }
49
50 const dt_iop_order_iccprofile_info_t *const work_profile
51 = (process_input_dsc.cst != IOP_CS_RAW || piece->dsc_in.cst != IOP_CS_RAW)
53 : NULL;
54
55 const int cst_before = process_input_dsc.cst;
56 if(process_input_dsc.cst != piece->dsc_in.cst
57 && !(dt_iop_colorspace_is_rgb(process_input_dsc.cst) && dt_iop_colorspace_is_rgb(piece->dsc_in.cst)))
58 {
59 process_input_temp
60 = dt_pixelpipe_cache_alloc_align_float((size_t)piece->roi_in.width * piece->roi_in.height * 4, pipe);
61 if(IS_NULL_PTR(process_input_temp))
62 return 1;
63
65 input_locked = TRUE;
66 dt_ioppr_transform_image_colorspace(module, input, process_input_temp, piece->roi_in.width,
67 piece->roi_in.height, process_input_dsc.cst, piece->dsc_in.cst,
68 &process_input_dsc.cst, work_profile);
70 input_locked = FALSE;
71 process_input = process_input_temp;
72 }
73 else if(process_input_dsc.cst != piece->dsc_in.cst)
74 {
75 process_input_dsc.cst = piece->dsc_in.cst;
76 if(input_entry)
77 {
79 input_locked = TRUE;
80 }
81 }
82 else
83 {
84 if(input_entry)
85 {
87 input_locked = TRUE;
88 }
89 }
90 const int cst_after = process_input_dsc.cst;
91
92 dt_dev_pixelpipe_debug_dump_module_io(pipe, module, "pre", FALSE, &piece->dsc_in, &piece->dsc_out,
93 &piece->roi_in, &piece->roi_out,
94 process_input_dsc.bpp, piece->dsc_out.bpp, cst_before, cst_after);
95
96 if((darktable.unmuted & DT_DEBUG_NAN) && !IS_NULL_PTR(output) && piece->dsc_out.datatype == TYPE_FLOAT)
97 {
98 const size_t ch = piece->dsc_out.channels;
99 const size_t count = (size_t)piece->roi_out.width * (size_t)piece->roi_out.height * ch;
100 float *out = (float *)output;
102 for(size_t k = 0; k < count; k++)
103 out[k] = NAN;
104 }
105
106 const gboolean fitting = dt_tiling_piece_fits_host_memory(MAX(piece->roi_in.width, piece->roi_out.width),
107 MAX(piece->roi_in.height, piece->roi_out.height),
108 MAX(process_input_dsc.bpp, piece->dsc_out.bpp),
109 tiling->factor, tiling->overhead);
110
111 int err = 0;
112 if(!fitting && piece->process_tiling_ready)
113 {
114 err = module->process_tiling(module, pipe, piece, process_input, output, process_input_dsc.bpp);
116 *pixelpipe_flow &= ~(PIXELPIPE_FLOW_PROCESSED_ON_GPU);
117 }
118 else
119 {
120 err = module->process(module, pipe, piece, process_input, output);
121 *pixelpipe_flow |= PIXELPIPE_FLOW_PROCESSED_ON_CPU;
123 }
124
125 if(err)
126 {
127 fprintf(stdout, "[pixelpipe] %s process on CPU returned with an error\n", module->name());
128 if(input_locked)
130 dt_pixelpipe_cache_free_align(process_input_temp);
131 return err;
132 }
133
134 if(module->flags() & IOP_FLAGS_SUPPORTS_BLENDING)
135 {
136 blend_input = process_input;
137 blend_input_dsc = process_input_dsc;
138 blend_output = output;
139 blend_output_dsc = piece->dsc_out;
140 const dt_dev_pixelpipe_display_mask_t request_mask_display
141 = (module->dev->gui_attached && (module == module->dev->gui_module) && (pipe == module->dev->pipe))
142 ? module->request_mask_display
143 : DT_DEV_PIXELPIPE_DISPLAY_NONE;
144
145 const dt_pixelpipe_blend_transform_t blend_transforms
146 = dt_dev_pixelpipe_transform_for_blend(module, piece, &piece->dsc_out);
147 if(blend_transforms != DT_DEV_PIXELPIPE_BLEND_TRANSFORM_NONE)
148 {
150 const int blend_in_before = blend_input_dsc.cst;
151 if(blend_transforms & DT_DEV_PIXELPIPE_BLEND_TRANSFORM_INPUT)
152 {
153 blend_input_temp
154 = dt_pixelpipe_cache_alloc_align_float((size_t)piece->roi_in.width * piece->roi_in.height * 4, pipe);
155 if(IS_NULL_PTR(blend_input_temp))
156 {
157 if(input_locked)
159 dt_pixelpipe_cache_free_align(process_input_temp);
160 return 1;
161 }
162
163 dt_ioppr_transform_image_colorspace(module, process_input, blend_input_temp, piece->roi_in.width,
164 piece->roi_in.height, blend_input_dsc.cst, blend_cst,
165 &blend_input_dsc.cst, work_profile);
166 blend_input = blend_input_temp;
167 if(input_locked)
168 {
170 input_locked = FALSE;
171 }
172 }
173 const int blend_in_after = blend_input_dsc.cst;
174
175 dt_dev_pixelpipe_debug_dump_module_io(pipe, module, "blend-in", FALSE, &process_input_dsc, &blend_input_dsc,
176 &piece->roi_in, &piece->roi_in,
177 process_input_dsc.bpp, blend_input_dsc.bpp,
178 blend_in_before, blend_in_after);
179
180 const int blend_out_before = blend_output_dsc.cst;
181 if(blend_transforms & DT_DEV_PIXELPIPE_BLEND_TRANSFORM_OUTPUT)
182 {
183 blend_output_temp
184 = dt_pixelpipe_cache_alloc_align_float((size_t)piece->roi_out.width * piece->roi_out.height * 4, pipe);
185 if(IS_NULL_PTR(blend_output_temp))
186 {
187 if(input_locked)
189 dt_pixelpipe_cache_free_align(blend_input_temp);
190 dt_pixelpipe_cache_free_align(process_input_temp);
191 return 1;
192 }
193
194 dt_ioppr_transform_image_colorspace(module, output, blend_output_temp, piece->roi_out.width,
195 piece->roi_out.height, blend_output_dsc.cst, blend_cst,
196 &blend_output_dsc.cst, work_profile);
197 blend_output = blend_output_temp;
198 }
199 const int blend_out_after = blend_output_dsc.cst;
200
201 dt_dev_pixelpipe_debug_dump_module_io(pipe, module, "blend-out", FALSE, &piece->dsc_out, &blend_output_dsc,
202 &piece->roi_out, &piece->roi_out,
203 piece->dsc_out.bpp, blend_output_dsc.bpp,
204 blend_out_before, blend_out_after);
205 }
206
207 err = dt_develop_blend_process(module, pipe, piece, blend_input, blend_output);
208 *pixelpipe_flow |= PIXELPIPE_FLOW_BLENDED_ON_CPU;
209 *pixelpipe_flow &= ~(PIXELPIPE_FLOW_BLENDED_ON_GPU);
210
211 if(!err && (blend_transforms & DT_DEV_PIXELPIPE_BLEND_TRANSFORM_OUTPUT))
212 {
213 if(request_mask_display & DT_DEV_PIXELPIPE_DISPLAY_ANY)
214 {
215 memcpy(output, blend_output,
216 (size_t)piece->roi_out.width * piece->roi_out.height * piece->dsc_out.bpp);
217 }
218 else
219 {
220 dt_ioppr_transform_image_colorspace(module, blend_output, output, piece->roi_out.width,
221 piece->roi_out.height, blend_output_dsc.cst, piece->dsc_out.cst,
222 &blend_output_dsc.cst, work_profile);
223 }
224 }
225 }
226
227 if(input_locked)
229 dt_pixelpipe_cache_free_align(blend_output_temp);
230 dt_pixelpipe_cache_free_align(blend_input_temp);
231 dt_pixelpipe_cache_free_align(process_input_temp);
232
233 return err;
234}
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
dt_iop_colorspace_type_t dt_develop_blend_colorspace(const dt_dev_pixelpipe_iop_t *const piece, dt_iop_colorspace_type_t cst)
Definition blend.c:179
int dt_develop_blend_process(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
Definition blend.c:641
dt_iop_colorspace_type_t
@ IOP_CS_RAW
const dt_colormatrix_t dt_aligned_pixel_t out
darktable_t darktable
Definition darktable.c:181
@ DT_DEBUG_NAN
Definition darktable.h:726
#define dt_pixelpipe_cache_free_align(mem)
Definition darktable.h:453
#define dt_pixelpipe_cache_alloc_align_float(pixels, pipe)
Definition darktable.h:442
#define __OMP_PARALLEL_FOR_SIMD__(...)
Definition darktable.h:259
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
dt_dev_pixelpipe_display_mask_t
Definition develop.h:116
@ DT_DEV_PIXELPIPE_DISPLAY_ANY
Definition develop.h:138
@ TYPE_FLOAT
Definition format.h:46
static gboolean dt_iop_colorspace_is_rgb(const dt_iop_colorspace_type_t cst)
Definition imageop.h:213
@ IOP_FLAGS_SUPPORTS_BLENDING
Definition imageop.h:167
@ IOP_FLAGS_TAKE_NO_INPUT
Definition imageop.h:176
void dt_ioppr_transform_image_colorspace(struct dt_iop_module_t *self, const float *const image_in, float *const image_out, const int width, const int height, const int cst_from, const int cst_to, int *converted_cst, const dt_iop_order_iccprofile_info_t *const profile_info)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_work_profile_info(const struct dt_dev_pixelpipe_t *pipe)
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
void * dt_pixel_cache_entry_get_data(dt_pixel_cache_entry_t *entry)
void * dt_pixel_cache_alloc(dt_dev_pixelpipe_cache_t *cache, dt_pixel_cache_entry_t *cache_entry)
Actually allocate the memory buffer attached to the cache entry once you create it with dt_dev_pixelp...
void dt_dev_pixelpipe_cache_rdlock_entry(dt_dev_pixelpipe_cache_t *cache, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the read lock on the entry.
int pixelpipe_process_on_CPU(dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const dt_dev_pixelpipe_iop_t *previous_piece, dt_develop_tiling_t *tiling, dt_pixelpipe_flow_t *pixelpipe_flow, gboolean *const cache_output, dt_pixel_cache_entry_t *input_entry, dt_pixel_cache_entry_t *output_entry)
dt_pixelpipe_blend_transform_t dt_dev_pixelpipe_transform_for_blend(const dt_iop_module_t *const self, const dt_dev_pixelpipe_iop_t *const piece, const dt_iop_buffer_dsc_t *const output_dsc)
void dt_dev_pixelpipe_debug_dump_module_io(dt_dev_pixelpipe_t *pipe, dt_iop_module_t *module, const char *stage, const gboolean is_cl, const dt_iop_buffer_dsc_t *in_dsc, const dt_iop_buffer_dsc_t *out_dsc, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out, const size_t in_bpp, const size_t out_bpp, const int cst_before, const int cst_after)
dt_pixelpipe_flow_t
@ PIXELPIPE_FLOW_PROCESSED_ON_CPU
@ PIXELPIPE_FLOW_PROCESSED_WITH_TILING
@ PIXELPIPE_FLOW_PROCESSED_ON_GPU
@ PIXELPIPE_FLOW_BLENDED_ON_CPU
@ PIXELPIPE_FLOW_BLENDED_ON_GPU
dt_pixelpipe_blend_transform_t
@ DT_DEV_PIXELPIPE_BLEND_TRANSFORM_INPUT
@ DT_DEV_PIXELPIPE_BLEND_TRANSFORM_NONE
@ DT_DEV_PIXELPIPE_BLEND_TRANSFORM_OUTPUT
struct dt_dev_pixelpipe_cache_t * pixelpipe_cache
Definition darktable.h:790
int32_t unmuted
Definition darktable.h:760
dt_iop_buffer_dsc_t dsc_out
dt_iop_buffer_dsc_t dsc_in
struct dt_develop_t * dev
dt_image_t image_storage
Definition develop.h:259
dt_iop_buffer_dsc_t dsc
Definition image.h:337
unsigned int channels
Definition format.h:54
dt_iop_buffer_type_t datatype
Definition format.h:56
#define MAX(a, b)
Definition thinplate.c:29
int dt_tiling_piece_fits_host_memory(const size_t width, const size_t height, const unsigned bpp, const float factor, const size_t overhead)
Definition tiling.c:1778