Code refactor: don't expose UpdateObjectTransformState in header.
[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 <algorithm>
27 #include <cstring>
28
29 #include "MEM_guardedalloc.h"
30 #include "BLI_math_color.h"
31 #include "BLI_math_vector.h"
32
33 #include "ocio_impl.h"
34
35 using std::max;
36
37 #define CONFIG_DEFAULT           ((OCIO_ConstConfigRcPtr*)1)
38
39 enum TransformType {
40         TRANSFORM_LINEAR_TO_SRGB,
41         TRANSFORM_SRGB_TO_LINEAR,
42         TRANSFORM_MATRIX,
43         TRANSFORM_EXPONENT,
44         TRANSFORM_UNKNOWN,
45 };
46
47 #define COLORSPACE_LINEAR        ((OCIO_ConstColorSpaceRcPtr*)1)
48 #define COLORSPACE_SRGB          ((OCIO_ConstColorSpaceRcPtr*)2)
49
50 typedef struct OCIO_PackedImageDescription {
51         float *data;
52         long width;
53         long height;
54         long numChannels;
55         long chanStrideBytes;
56         long xStrideBytes;
57         long yStrideBytes;
58 } OCIO_PackedImageDescription;
59
60 struct FallbackTransform {
61         FallbackTransform()
62                 : type(TRANSFORM_UNKNOWN),
63                   linear_transform(NULL),
64                   display_transform(NULL)
65         {
66         }
67
68         ~FallbackTransform()
69         {
70                 delete linear_transform;
71                 delete display_transform;
72         }
73
74         void applyRGB(float *pixel)
75         {
76                 if (type == TRANSFORM_LINEAR_TO_SRGB) {
77                         applyLinearRGB(pixel);
78                         linearrgb_to_srgb_v3_v3(pixel, pixel);
79                         applyDisplayRGB(pixel);
80                 }
81                 else if (type == TRANSFORM_SRGB_TO_LINEAR) {
82                         srgb_to_linearrgb_v3_v3(pixel, pixel);
83                 }
84                 else if (type == TRANSFORM_EXPONENT) {
85                         pixel[0] = powf(max(0.0f, pixel[0]), exponent[0]);
86                         pixel[1] = powf(max(0.0f, pixel[1]), exponent[1]);
87                         pixel[2] = powf(max(0.0f, pixel[2]), exponent[2]);
88                 }
89                 else if (type == TRANSFORM_MATRIX) {
90                         float r = pixel[0];
91                         float g = pixel[1];
92                         float b = pixel[2];
93                         pixel[0] = r*matrix[0] + g*matrix[1] + b*matrix[2];
94                         pixel[1] = r*matrix[4] + g*matrix[5] + b*matrix[6];
95                         pixel[2] = r*matrix[8] + g*matrix[9] + b*matrix[10];
96                         pixel[0] += offset[0];
97                         pixel[1] += offset[1];
98                         pixel[2] += offset[2];
99                 }
100         }
101
102         void applyRGBA(float *pixel)
103         {
104                 if (type == TRANSFORM_LINEAR_TO_SRGB) {
105                         applyLinearRGBA(pixel);
106                         linearrgb_to_srgb_v4(pixel, pixel);
107                         applyDisplayRGBA(pixel);
108                 }
109                 else if (type == TRANSFORM_SRGB_TO_LINEAR) {
110                         srgb_to_linearrgb_v4(pixel, pixel);
111                 }
112                 else if (type == TRANSFORM_EXPONENT) {
113                         pixel[0] = powf(max(0.0f, pixel[0]), exponent[0]);
114                         pixel[1] = powf(max(0.0f, pixel[1]), exponent[1]);
115                         pixel[2] = powf(max(0.0f, pixel[2]), exponent[2]);
116                         pixel[3] = powf(max(0.0f, pixel[3]), exponent[3]);
117                 }
118                 else if (type == TRANSFORM_MATRIX) {
119                         float r = pixel[0];
120                         float g = pixel[1];
121                         float b = pixel[2];
122                         float a = pixel[3];
123                         pixel[0] = r*matrix[0] + g*matrix[1] + b*matrix[2] + a*matrix[3];
124                         pixel[1] = r*matrix[4] + g*matrix[5] + b*matrix[6] + a*matrix[7];
125                         pixel[2] = r*matrix[8] + g*matrix[9] + b*matrix[10] + a*matrix[11];
126                         pixel[3] = r*matrix[12] + g*matrix[13] + b*matrix[14] + a*matrix[15];
127                         pixel[0] += offset[0];
128                         pixel[1] += offset[1];
129                         pixel[2] += offset[2];
130                         pixel[3] += offset[3];
131                 }
132         }
133
134         void applyLinearRGB(float *pixel)
135         {
136                 if (linear_transform != NULL) {
137                         linear_transform->applyRGB(pixel);
138                 }
139         }
140
141         void applyLinearRGBA(float *pixel)
142         {
143                 if (linear_transform != NULL) {
144                         linear_transform->applyRGBA(pixel);
145                 }
146         }
147
148         void applyDisplayRGB(float *pixel)
149         {
150                 if (display_transform != NULL) {
151                         display_transform->applyRGB(pixel);
152                 }
153         }
154
155         void applyDisplayRGBA(float *pixel)
156         {
157                 if (display_transform != NULL) {
158                         display_transform->applyRGBA(pixel);
159                 }
160         }
161
162         TransformType type;
163         FallbackTransform *linear_transform;
164         FallbackTransform *display_transform;
165         /* Exponent transform. */
166         float exponent[4];
167         /* Matrix transform. */
168         float matrix[16];
169         float offset[4];
170
171         MEM_CXX_CLASS_ALLOC_FUNCS("FallbackProcessor");
172 };
173
174 struct FallbackProcessor {
175         FallbackProcessor()
176                 : transform(NULL)
177         {
178         }
179
180         ~FallbackProcessor() {
181                 delete transform;
182         }
183
184         void applyRGB(float *pixel)
185         {
186                 transform->applyRGB(pixel);
187         }
188
189         void applyRGBA(float *pixel)
190         {
191                 transform->applyRGBA(pixel);
192         }
193
194         FallbackTransform *transform;
195
196         MEM_CXX_CLASS_ALLOC_FUNCS("FallbackProcessor");
197 };
198
199 OCIO_ConstConfigRcPtr *FallbackImpl::getCurrentConfig(void)
200 {
201         return CONFIG_DEFAULT;
202 }
203
204 void FallbackImpl::setCurrentConfig(const OCIO_ConstConfigRcPtr * /*config*/)
205 {
206 }
207
208 OCIO_ConstConfigRcPtr *FallbackImpl::configCreateFromEnv(void)
209 {
210         return NULL;
211 }
212
213 OCIO_ConstConfigRcPtr *FallbackImpl::configCreateFromFile(const char * /*filename*/)
214 {
215         return CONFIG_DEFAULT;
216 }
217
218 void FallbackImpl::configRelease(OCIO_ConstConfigRcPtr * /*config*/)
219 {
220 }
221
222 int FallbackImpl::configGetNumColorSpaces(OCIO_ConstConfigRcPtr * /*config*/)
223 {
224         return 2;
225 }
226
227 const char *FallbackImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr * /*config*/,
228                                                          int index)
229 {
230         if (index == 0)
231                 return "Linear";
232         else if (index == 1)
233                 return "sRGB";
234         
235         return NULL;
236 }
237
238 OCIO_ConstColorSpaceRcPtr *FallbackImpl::configGetColorSpace(OCIO_ConstConfigRcPtr * /*config*/,
239                                                              const char *name)
240 {
241         if (strcmp(name, "scene_linear") == 0)
242                 return COLORSPACE_LINEAR;
243         else if (strcmp(name, "color_picking") == 0)
244                 return COLORSPACE_SRGB;
245         else if (strcmp(name, "texture_paint") == 0)
246                 return COLORSPACE_LINEAR;
247         else if (strcmp(name, "default_byte") == 0)
248                 return COLORSPACE_SRGB;
249         else if (strcmp(name, "default_float") == 0)
250                 return COLORSPACE_LINEAR;
251         else if (strcmp(name, "default_sequencer") == 0)
252                 return COLORSPACE_SRGB;
253         else if (strcmp(name, "Linear") == 0)
254                 return COLORSPACE_LINEAR;
255         else if (strcmp(name, "sRGB") == 0)
256                 return COLORSPACE_SRGB;
257
258         return NULL;
259 }
260
261 int FallbackImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config,
262                                               const char *name)
263 {
264         OCIO_ConstColorSpaceRcPtr *cs = configGetColorSpace(config, name);
265
266         if (cs == COLORSPACE_LINEAR) {
267                 return 0;
268         }
269         else if (cs == COLORSPACE_SRGB) {
270                 return 1;
271         }
272         return -1;
273 }
274
275 const char *FallbackImpl::configGetDefaultDisplay(OCIO_ConstConfigRcPtr * /*config*/)
276 {
277         return "sRGB";
278 }
279
280 int FallbackImpl::configGetNumDisplays(OCIO_ConstConfigRcPtr * /*config*/)
281 {
282         return 1;
283 }
284
285 const char *FallbackImpl::configGetDisplay(OCIO_ConstConfigRcPtr * /*config*/,
286                                            int index)
287 {
288         if (index == 0) {
289                 return "sRGB";
290         }
291         return NULL;
292 }
293
294 const char *FallbackImpl::configGetDefaultView(OCIO_ConstConfigRcPtr * /*config*/,
295                                                const char * /*display*/)
296 {
297         return "Default";
298 }
299
300 int FallbackImpl::configGetNumViews(OCIO_ConstConfigRcPtr * /*config*/,
301                                     const char * /*display*/)
302 {
303         return 1;
304 }
305
306 const char *FallbackImpl::configGetView(OCIO_ConstConfigRcPtr * /*config*/,
307                                         const char * /*display*/, int index)
308 {
309         if (index == 0) {
310                 return "Default";
311         }
312         return NULL;
313 }
314
315 const char *FallbackImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr * /*config*/,
316                                                          const char * /*display*/,
317                                                          const char * /*view*/)
318 {
319         return "sRGB";
320 }
321
322 void FallbackImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr * /*config*/,
323                                              float *rgb)
324 {
325         /* Here we simply use the older Blender assumed primaries of
326          * ITU-BT.709 / sRGB, or 0.2126729 0.7151522 0.0721750. Brute
327          * force stupid, but only plausible option given no color management
328          * system in place.
329          */
330
331         rgb[0] = 0.2126f;
332         rgb[1] = 0.7152f;
333         rgb[2] = 0.0722f;
334 }
335
336 int FallbackImpl::configGetNumLooks(OCIO_ConstConfigRcPtr * /*config*/)
337 {
338         return 0;
339 }
340
341 const char *FallbackImpl::configGetLookNameByIndex(OCIO_ConstConfigRcPtr * /*config*/,
342                                                    int /*index*/)
343 {
344         return "";
345 }
346
347 OCIO_ConstLookRcPtr *FallbackImpl::configGetLook(OCIO_ConstConfigRcPtr * /*config*/,
348                                                  const char * /*name*/)
349 {
350         return NULL;
351 }
352
353 const char *FallbackImpl::lookGetProcessSpace(OCIO_ConstLookRcPtr * /*look*/)
354 {
355         return NULL;
356 }
357
358 void FallbackImpl::lookRelease(OCIO_ConstLookRcPtr * /*look*/)
359 {
360 }
361
362 int FallbackImpl::colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr * /*cs*/)
363 {
364         return 1;
365 }
366
367 int FallbackImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr * /*cs*/)
368 {
369         return 0;
370 }
371
372 void FallbackImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr * /*cs*/)
373 {
374 }
375
376 OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessorWithNames(
377         OCIO_ConstConfigRcPtr *config,
378         const char *srcName,
379         const char *dstName)
380 {
381         OCIO_ConstColorSpaceRcPtr *cs_src = configGetColorSpace(config, srcName);
382         OCIO_ConstColorSpaceRcPtr *cs_dst = configGetColorSpace(config, dstName);
383         FallbackTransform *transform = new FallbackTransform();
384         if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB) {
385                 transform->type = TRANSFORM_LINEAR_TO_SRGB;
386         }
387         else if (cs_src == COLORSPACE_SRGB && cs_dst == COLORSPACE_LINEAR) {
388                 transform->type = TRANSFORM_SRGB_TO_LINEAR;
389         }
390         else {
391                 transform->type = TRANSFORM_UNKNOWN;
392         }
393         FallbackProcessor *processor = new FallbackProcessor();
394         processor->transform = transform;
395         return (OCIO_ConstProcessorRcPtr *)processor;
396 }
397
398 OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessor(OCIO_ConstConfigRcPtr * /*config*/,
399                                                            OCIO_ConstTransformRcPtr *transform)
400 {
401         FallbackProcessor *processor = new FallbackProcessor();
402         processor->transform = (FallbackTransform *)transform;
403         return (OCIO_ConstProcessorRcPtr *)processor;
404 }
405
406 void FallbackImpl::processorApply(OCIO_ConstProcessorRcPtr *processor,
407                                   OCIO_PackedImageDesc *img)
408 {
409         /* OCIO_TODO stride not respected, channels must be 3 or 4 */
410         OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription*)img;
411         int channels = desc->numChannels;
412         float *pixels = desc->data;
413         int width = desc->width;
414         int height = desc->height;
415         int x, y;
416
417         for (y = 0; y < height; y++) {
418                 for (x = 0; x < width; x++) {
419                         float *pixel = pixels + channels * (y * width + x);
420
421                         if (channels == 4)
422                                 processorApplyRGBA(processor, pixel);
423                         else if (channels == 3)
424                                 processorApplyRGB(processor, pixel);
425                 }
426         }
427 }
428
429 void FallbackImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor,
430                                             OCIO_PackedImageDesc *img)
431 {
432         /* OCIO_TODO stride not respected, channels must be 3 or 4 */
433         OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription*)img;
434         int channels = desc->numChannels;
435         float *pixels = desc->data;
436         int width = desc->width;
437         int height = desc->height;
438         int x, y;
439
440         for (y = 0; y < height; y++) {
441                 for (x = 0; x < width; x++) {
442                         float *pixel = pixels + channels * (y * width + x);
443
444                         if (channels == 4)
445                                 processorApplyRGBA_predivide(processor, pixel);
446                         else if (channels == 3)
447                                 processorApplyRGB(processor, pixel);
448                 }
449         }
450 }
451
452 void FallbackImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor,
453                                      float *pixel)
454 {
455         ((FallbackProcessor *)processor)->applyRGB(pixel);
456 }
457
458 void FallbackImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor,
459                                       float *pixel)
460 {
461         ((FallbackProcessor *)processor)->applyRGBA(pixel);
462 }
463
464 void FallbackImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor,
465                                                 float *pixel)
466 {
467         if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
468                 processorApplyRGBA(processor, pixel);
469         }
470         else {
471                 float alpha, inv_alpha;
472
473                 alpha = pixel[3];
474                 inv_alpha = 1.0f / alpha;
475
476                 pixel[0] *= inv_alpha;
477                 pixel[1] *= inv_alpha;
478                 pixel[2] *= inv_alpha;
479
480                 processorApplyRGBA(processor, pixel);
481
482                 pixel[0] *= alpha;
483                 pixel[1] *= alpha;
484                 pixel[2] *= alpha;
485         }
486 }
487
488 void FallbackImpl::processorRelease(OCIO_ConstProcessorRcPtr *processor)
489 {
490         delete (FallbackProcessor*)(processor);
491 }
492
493 const char *FallbackImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
494 {
495         if (cs == COLORSPACE_LINEAR) {
496                 return "Linear";
497         }
498         else if (cs == COLORSPACE_SRGB) {
499                 return "sRGB";
500         }
501         return NULL;
502 }
503
504 const char *FallbackImpl::colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr * /*cs*/)
505 {
506         return "";
507 }
508
509 const char *FallbackImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr * /*cs*/)
510 {
511         return "";
512 }
513
514 OCIO_DisplayTransformRcPtr *FallbackImpl::createDisplayTransform(void)
515 {
516         FallbackTransform *transform = new FallbackTransform();
517         transform->type = TRANSFORM_LINEAR_TO_SRGB;
518         return (OCIO_DisplayTransformRcPtr*)transform;
519 }
520
521 void FallbackImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr * /*dt*/,
522                                                           const char * /*name*/)
523 {
524 }
525
526 void FallbackImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr * /*dt*/,
527                                               const char * /*name*/)
528 {
529 }
530
531 void FallbackImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr * /*dt*/,
532                                            const char * /*name*/)
533 {
534 }
535
536 void FallbackImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt,
537                                                 OCIO_ConstTransformRcPtr *et)
538 {
539         FallbackTransform *transform = (FallbackTransform *)dt;
540         transform->display_transform = (FallbackTransform *)et;
541 }
542
543 void FallbackImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt,
544                                                OCIO_ConstTransformRcPtr *et)
545 {
546         FallbackTransform *transform = (FallbackTransform *)dt;
547         transform->linear_transform = (FallbackTransform *)et;
548 }
549
550 void FallbackImpl::displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr * /*dt*/,
551                                                     const char * /*looks*/)
552 {
553 }
554
555 void FallbackImpl::displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr * /*dt*/,
556                                                            bool /*enabled*/)
557 {
558 }
559
560 void FallbackImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr * /*dt*/)
561 {
562 }
563
564 OCIO_PackedImageDesc *FallbackImpl::createOCIO_PackedImageDesc(
565         float *data,
566         long width, long height, long numChannels,
567         long chanStrideBytes, long xStrideBytes, long yStrideBytes)
568 {
569         OCIO_PackedImageDescription *desc =
570                 (OCIO_PackedImageDescription*)MEM_callocN(sizeof(OCIO_PackedImageDescription),
571                                                           "OCIO_PackedImageDescription");
572         desc->data = data;
573         desc->width = width;
574         desc->height = height;
575         desc->numChannels = numChannels;
576         desc->chanStrideBytes = chanStrideBytes;
577         desc->xStrideBytes = xStrideBytes;
578         desc->yStrideBytes = yStrideBytes;
579         return (OCIO_PackedImageDesc*)desc;
580 }
581
582 void FallbackImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id)
583 {
584         MEM_freeN(id);
585 }
586
587 OCIO_ExponentTransformRcPtr *FallbackImpl::createExponentTransform(void)
588 {
589         FallbackTransform *transform = new FallbackTransform();
590         transform->type = TRANSFORM_EXPONENT;
591         return (OCIO_ExponentTransformRcPtr *)transform;
592 }
593
594 void FallbackImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et,
595                                              const float *exponent)
596 {
597         FallbackTransform *transform = (FallbackTransform *)et;
598         copy_v4_v4(transform->exponent, exponent);
599 }
600
601 void FallbackImpl::exponentTransformRelease(OCIO_ExponentTransformRcPtr * /*et*/)
602 {
603 }
604
605 OCIO_MatrixTransformRcPtr *FallbackImpl::createMatrixTransform(void)
606 {
607         FallbackTransform *transform = new FallbackTransform();
608         transform->type = TRANSFORM_MATRIX;
609         return (OCIO_MatrixTransformRcPtr *)transform;
610 }
611
612 void FallbackImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt,
613                                            const float *m44,
614                                            const float *offset4)
615 {
616         FallbackTransform *transform = (FallbackTransform *)mt;
617         copy_m4_m4((float (*)[4])transform->matrix, (float (*)[4])m44);
618         copy_v4_v4(transform->offset, offset4);
619 }
620
621 void FallbackImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr * /*mt*/)
622 {
623 }
624
625 void FallbackImpl::matrixTransformScale(float *m44,
626                                         float *offset4,
627                                         const float *scale4)
628 {
629         if (scale4 == NULL) {
630                 return;
631         }
632         if (m44 != NULL) {
633                 memset(m44, 0, 16*sizeof(float));
634                 m44[0] = scale4[0];
635                 m44[5] = scale4[1];
636                 m44[10] = scale4[2];
637                 m44[15] = scale4[3];
638         }
639         if (offset4 != NULL) {
640                 offset4[0] = 0.0f;
641                 offset4[1] = 0.0f;
642                 offset4[2] = 0.0f;
643                 offset4[3] = 0.0f;
644         }
645 }
646
647 bool FallbackImpl::supportGLSLDraw(void)
648 {
649         return false;
650 }
651
652 bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState ** /*state_r*/,
653                                  OCIO_ConstProcessorRcPtr * /*processor*/,
654                                  OCIO_CurveMappingSettings * /*curve_mapping_settings*/,
655                                  float /*dither*/,
656                                  bool /*predivide*/)
657 {
658         return false;
659 }
660
661 void FallbackImpl::finishGLSLDraw(OCIO_GLSLDrawState * /*state*/)
662 {
663 }
664
665 void FallbackImpl::freeGLState(struct OCIO_GLSLDrawState * /*state_r*/)
666 {
667 }
668
669 const char *FallbackImpl::getVersionString(void)
670 {
671         return "fallback";
672 }
673
674 int FallbackImpl::getVersionHex(void)
675 {
676         return 0;
677 }