Implement GPU-side dither
[blender-staging.git] / intern / opencolorio / fallback_impl.cc
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2012 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Brecht van Lommel
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 #include <string.h>
27
28 #include "MEM_guardedalloc.h"
29 #include "BLI_math_color.h"
30
31 #include "ocio_impl.h"
32
33 #define CONFIG_DEFAULT           ((OCIO_ConstConfigRcPtr*)1)
34
35 #define PROCESSOR_LINEAR_TO_SRGB ((OCIO_ConstProcessorRcPtr*)1)
36 #define PROCESSOR_SRGB_TO_LINEAR ((OCIO_ConstProcessorRcPtr*)2)
37 #define PROCESSOR_UNKNOWN        ((OCIO_ConstProcessorRcPtr*)3)
38
39 #define COLORSPACE_LINEAR        ((OCIO_ConstColorSpaceRcPtr*)1)
40 #define COLORSPACE_SRGB          ((OCIO_ConstColorSpaceRcPtr*)2)
41
42 typedef struct OCIO_PackedImageDescription {
43         float *data;
44         long width;
45         long height;
46         long numChannels;
47         long chanStrideBytes;
48         long xStrideBytes;
49         long yStrideBytes;
50 } OCIO_PackedImageDescription;
51
52 OCIO_ConstConfigRcPtr *FallbackImpl::getCurrentConfig(void)
53 {
54         return CONFIG_DEFAULT;
55 }
56
57 void FallbackImpl::setCurrentConfig(const OCIO_ConstConfigRcPtr * /*config*/)
58 {
59 }
60
61 OCIO_ConstConfigRcPtr *FallbackImpl::configCreateFromEnv(void)
62 {
63         return CONFIG_DEFAULT;
64 }
65
66 OCIO_ConstConfigRcPtr *FallbackImpl::configCreateFromFile(const char * /*filename*/)
67 {
68         return CONFIG_DEFAULT;
69 }
70
71 void FallbackImpl::configRelease(OCIO_ConstConfigRcPtr * /*config*/)
72 {
73 }
74
75 int FallbackImpl::configGetNumColorSpaces(OCIO_ConstConfigRcPtr * /*config*/)
76 {
77         return 2;
78 }
79
80 const char *FallbackImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr * /*config*/, int index)
81 {
82         if (index == 0)
83                 return "Linear";
84         else if (index == 1)
85                 return "sRGB";
86         
87         return NULL;
88 }
89
90 OCIO_ConstColorSpaceRcPtr *FallbackImpl::configGetColorSpace(OCIO_ConstConfigRcPtr * /*config*/, const char *name)
91 {
92         if (strcmp(name, "scene_linear") == 0)
93                 return COLORSPACE_LINEAR;
94         else if (strcmp(name, "color_picking") == 0)
95                 return COLORSPACE_SRGB;
96         else if (strcmp(name, "texture_paint") == 0)
97                 return COLORSPACE_LINEAR;
98         else if (strcmp(name, "default_byte") == 0)
99                 return COLORSPACE_SRGB;
100         else if (strcmp(name, "default_float") == 0)
101                 return COLORSPACE_LINEAR;
102         else if (strcmp(name, "default_sequencer") == 0)
103                 return COLORSPACE_SRGB;
104         else if (strcmp(name, "Linear") == 0)
105                 return COLORSPACE_LINEAR;
106         else if (strcmp(name, "sRGB") == 0)
107                 return COLORSPACE_SRGB;
108
109         return NULL;
110 }
111
112 int FallbackImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name)
113 {
114         OCIO_ConstColorSpaceRcPtr *cs = configGetColorSpace(config, name);
115
116         if (cs == COLORSPACE_LINEAR)
117                 return 0;
118         else if (cs == COLORSPACE_SRGB)
119                 return 1;
120
121         return -1;
122 }
123
124 const char *FallbackImpl::configGetDefaultDisplay(OCIO_ConstConfigRcPtr * /*config*/)
125 {
126         return "sRGB";
127 }
128
129 int FallbackImpl::configGetNumDisplays(OCIO_ConstConfigRcPtr * /*config*/)
130 {
131         return 1;
132 }
133
134 const char *FallbackImpl::configGetDisplay(OCIO_ConstConfigRcPtr * /*config*/, int index)
135 {
136         if (index == 0)
137                 return "sRGB";
138         
139         return NULL;
140 }
141
142 const char *FallbackImpl::configGetDefaultView(OCIO_ConstConfigRcPtr * /*config*/, const char * /*display*/)
143 {
144         return "Default";
145 }
146
147 int FallbackImpl::configGetNumViews(OCIO_ConstConfigRcPtr * /*config*/, const char * /*display*/)
148 {
149         return 1;
150 }
151
152 const char *FallbackImpl::configGetView(OCIO_ConstConfigRcPtr * /*config*/, const char * /*display*/, int index)
153 {
154         if (index == 0)
155                 return "Default";
156
157         return NULL;
158 }
159
160 const char *FallbackImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr * /*config*/, const char * /*display*/, const char * /*view*/)
161 {
162         return "sRGB";
163 }
164
165 int FallbackImpl::configGetNumLooks(OCIO_ConstConfigRcPtr * /*config*/)
166 {
167         return 0;
168 }
169
170 const char *FallbackImpl::configGetLookNameByIndex(OCIO_ConstConfigRcPtr * /*config*/, int /*index*/)
171 {
172         return "";
173 }
174
175 OCIO_ConstLookRcPtr *FallbackImpl::configGetLook(OCIO_ConstConfigRcPtr * /*config*/, const char * /*name*/)
176 {
177         return NULL;
178 }
179
180 const char *FallbackImpl::lookGetProcessSpace(OCIO_ConstLookRcPtr *look)
181 {
182         return NULL;
183 }
184
185 void FallbackImpl::lookRelease(OCIO_ConstLookRcPtr * /*look*/)
186 {
187 }
188
189 int FallbackImpl::colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr * /*cs*/)
190 {
191         return 1;
192 }
193
194 int FallbackImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr * /*cs*/)
195 {
196         return 0;
197 }
198
199 void FallbackImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr * /*cs*/)
200 {
201 }
202
203 OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName)
204 {
205         OCIO_ConstColorSpaceRcPtr *cs_src = configGetColorSpace(config, srcName);
206         OCIO_ConstColorSpaceRcPtr *cs_dst = configGetColorSpace(config, dstName);
207
208         if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB)
209                 return PROCESSOR_LINEAR_TO_SRGB;
210         else if (cs_src == COLORSPACE_SRGB && cs_dst == COLORSPACE_LINEAR)
211                 return PROCESSOR_SRGB_TO_LINEAR;
212
213         return 0;
214 }
215
216 OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessor(OCIO_ConstConfigRcPtr * /*config*/, OCIO_ConstTransformRcPtr *tfm)
217 {
218         return (OCIO_ConstProcessorRcPtr*)tfm;
219 }
220
221 void FallbackImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img)
222 {
223         /* OCIO_TODO stride not respected, channels must be 3 or 4 */
224         OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription*)img;
225         int channels = desc->numChannels;
226         float *pixels = desc->data;
227         int width = desc->width;
228         int height = desc->height;
229         int x, y;
230
231         for (y = 0; y < height; y++) {
232                 for (x = 0; x < width; x++) {
233                         float *pixel = pixels + channels * (y * width + x);
234
235                         if (channels == 4)
236                                 processorApplyRGBA(processor, pixel);
237                         else if (channels == 3)
238                                 processorApplyRGB(processor, pixel);
239                 }
240         }
241 }
242
243 void FallbackImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img)
244 {
245         /* OCIO_TODO stride not respected, channels must be 3 or 4 */
246         OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription*)img;
247         int channels = desc->numChannels;
248         float *pixels = desc->data;
249         int width = desc->width;
250         int height = desc->height;
251         int x, y;
252
253         for (y = 0; y < height; y++) {
254                 for (x = 0; x < width; x++) {
255                         float *pixel = pixels + channels * (y * width + x);
256
257                         if (channels == 4)
258                                 processorApplyRGBA_predivide(processor, pixel);
259                         else if (channels == 3)
260                                 processorApplyRGB(processor, pixel);
261                 }
262         }
263 }
264
265 void FallbackImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel)
266 {
267         if (processor == PROCESSOR_LINEAR_TO_SRGB)
268                 linearrgb_to_srgb_v3_v3(pixel, pixel);
269         else if (processor == PROCESSOR_SRGB_TO_LINEAR)
270                 srgb_to_linearrgb_v3_v3(pixel, pixel);
271 }
272
273 void FallbackImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel)
274 {
275         if (processor == PROCESSOR_LINEAR_TO_SRGB)
276                 linearrgb_to_srgb_v4(pixel, pixel);
277         else if (processor == PROCESSOR_SRGB_TO_LINEAR)
278                 srgb_to_linearrgb_v4(pixel, pixel);
279 }
280
281 void FallbackImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel)
282 {
283         if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
284                 processorApplyRGBA(processor, pixel);
285         }
286         else {
287                 float alpha, inv_alpha;
288
289                 alpha = pixel[3];
290                 inv_alpha = 1.0f / alpha;
291
292                 pixel[0] *= inv_alpha;
293                 pixel[1] *= inv_alpha;
294                 pixel[2] *= inv_alpha;
295
296                 processorApplyRGBA(processor, pixel);
297
298                 pixel[0] *= alpha;
299                 pixel[1] *= alpha;
300                 pixel[2] *= alpha;
301         }
302 }
303
304 void FallbackImpl::processorRelease(OCIO_ConstProcessorRcPtr * /*p*/)
305 {
306 }
307
308 const char *FallbackImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
309 {
310         if (cs == COLORSPACE_LINEAR)
311                 return "Linear";
312         else if (cs == COLORSPACE_SRGB)
313                 return "sRGB";
314         
315         return NULL;
316 }
317
318 const char *FallbackImpl::colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr * /*cs*/)
319 {
320         return "";
321 }
322
323 const char *FallbackImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr * /*cs*/)
324 {
325         return "";
326 }
327
328 OCIO_DisplayTransformRcPtr *FallbackImpl::createDisplayTransform(void)
329 {
330         return (OCIO_DisplayTransformRcPtr*)PROCESSOR_LINEAR_TO_SRGB;
331 }
332
333 void FallbackImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr * /*dt*/, const char * /*name*/)
334 {
335 }
336
337 void FallbackImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr * /*dt*/, const char * /*name*/)
338 {
339 }
340
341 void FallbackImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr * /*dt*/, const char * /*name*/)
342 {
343 }
344
345 void FallbackImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr * /*dt*/, OCIO_ConstTransformRcPtr * /*et*/)
346 {
347 }
348
349 void FallbackImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr * /*dt*/, OCIO_ConstTransformRcPtr * /*et*/)
350 {
351 }
352
353 void FallbackImpl::displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr * /*dt*/, const char * /*looks*/)
354 {
355 }
356
357 void FallbackImpl::displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr * /*dt*/, bool /*enabled*/)
358 {
359 }
360
361 void FallbackImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr * /*dt*/)
362 {
363 }
364
365 OCIO_PackedImageDesc *FallbackImpl::createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels,
366                                                                long chanStrideBytes, long xStrideBytes, long yStrideBytes)
367 {
368         OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription*)MEM_callocN(sizeof(OCIO_PackedImageDescription), "OCIO_PackedImageDescription");
369
370         desc->data = data;
371         desc->width = width;
372         desc->height = height;
373         desc->numChannels = numChannels;
374         desc->chanStrideBytes = chanStrideBytes;
375         desc->xStrideBytes = xStrideBytes;
376         desc->yStrideBytes = yStrideBytes;
377
378         return (OCIO_PackedImageDesc*)desc;
379 }
380
381 void FallbackImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id)
382 {
383         MEM_freeN(id);
384 }
385
386 OCIO_ExponentTransformRcPtr *FallbackImpl::createExponentTransform(void)
387 {
388         return (OCIO_ExponentTransformRcPtr*)PROCESSOR_UNKNOWN;
389 }
390
391 void FallbackImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr * /*et*/, const float * /*exponent*/)
392 {
393 }
394
395 void FallbackImpl::exponentTransformRelease(OCIO_ExponentTransformRcPtr * /*et*/)
396 {
397 }
398
399 OCIO_MatrixTransformRcPtr *FallbackImpl::createMatrixTransform(void)
400 {
401         return (OCIO_MatrixTransformRcPtr*)PROCESSOR_UNKNOWN;
402 }
403
404 void FallbackImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr * /*mt*/, const float * /*m44*/, const float * /*offset4*/)
405 {
406 }
407
408 void FallbackImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr * /*mt*/)
409 {
410 }
411
412 void FallbackImpl::matrixTransformScale(float * /*m44*/, float * /*offset44*/, const float * /*scale4*/)
413 {
414 }
415
416 bool FallbackImpl::supportGLSLDraw(void)
417 {
418         return false;
419 }
420
421 bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState ** /*state_r*/, OCIO_ConstProcessorRcPtr * /*processor*/,
422                                  OCIO_CurveMappingSettings * /*curve_mapping_settings*/,
423                                  float /*dither*/,  bool /*predivide*/)
424 {
425         return false;
426 }
427
428 void FallbackImpl::finishGLSLDraw(OCIO_GLSLDrawState * /*state*/)
429 {
430 }
431
432 void FallbackImpl::freeGLState(struct OCIO_GLSLDrawState * /*state_r*/)
433 {
434 }
435
436 const char *FallbackImpl::getVersionString(void)
437 {
438         return "fallback";
439 }
440
441 int FallbackImpl::getVersionHex(void)
442 {
443         return 0;
444 }