Fixed typo in OCIO GLSL module, was using address to a pointer..
[blender.git] / intern / opencolorio / ocio_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): Xavier Thomas
22  *                 Lukas Toene,
23  *                 Sergey Sharybin
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <iostream>
29 #include <sstream>
30 #include <string.h>
31
32 #ifdef __APPLE__
33 #include <OpenGL/gl.h>
34 #include <OpenGL/glu.h>
35 #else
36 #include <GL/glew.h>
37 #endif
38
39 #include <OpenColorIO/OpenColorIO.h>
40
41 using namespace OCIO_NAMESPACE;
42
43 #include "MEM_guardedalloc.h"
44
45 #include "ocio_impl.h"
46
47 #if !defined(WITH_ASSERT_ABORT)
48 #  define OCIO_abort()
49 #else
50 #  include <stdlib.h>
51 #  define OCIO_abort() abort()
52 #endif
53
54 #if defined(_MSC_VER)
55 #  define __func__ __FUNCTION__
56 #endif
57
58 #define MEM_NEW(type) new(MEM_mallocN(sizeof(type), __func__)) type()
59 #define MEM_DELETE(what, type) if(what) { ((type*)(what))->~type(); MEM_freeN(what); } (void)0
60
61 static const int LUT3D_EDGE_SIZE = 32;
62
63 static void OCIO_reportError(const char *err)
64 {
65         std::cerr << "OpenColorIO Error: " << err << std::endl;
66
67         OCIO_abort();
68 }
69
70 static void OCIO_reportException(Exception &exception)
71 {
72         OCIO_reportError(exception.what());
73 }
74
75 OCIO_ConstConfigRcPtr *OCIOImpl::getCurrentConfig(void)
76 {
77         ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
78
79         try {
80                 *config = GetCurrentConfig();
81
82                 if (*config)
83                         return (OCIO_ConstConfigRcPtr *) config;
84         }
85         catch (Exception &exception) {
86                 OCIO_reportException(exception);
87         }
88
89         MEM_DELETE(config, ConstConfigRcPtr);
90
91         return NULL;
92 }
93
94 void OCIOImpl::setCurrentConfig(const OCIO_ConstConfigRcPtr *config)
95 {
96         try {
97                 SetCurrentConfig(*(ConstConfigRcPtr *) config);
98         }
99         catch (Exception &exception) {
100                 OCIO_reportException(exception);
101         }
102 }
103
104 OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromEnv(void)
105 {
106         ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
107
108         try {
109                 *config = Config::CreateFromEnv();
110
111                 if (*config)
112                         return (OCIO_ConstConfigRcPtr *) config;
113         }
114         catch (Exception &exception) {
115                 OCIO_reportException(exception);
116         }
117
118         MEM_DELETE(config, ConstConfigRcPtr);
119
120         return NULL;
121 }
122
123
124 OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromFile(const char *filename)
125 {
126         ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
127
128         try {
129                 *config = Config::CreateFromFile(filename);
130
131                 if (*config)
132                         return (OCIO_ConstConfigRcPtr *) config;
133         }
134         catch (Exception &exception) {
135                 OCIO_reportException(exception);
136         }
137
138         MEM_DELETE(config, ConstConfigRcPtr);
139
140         return NULL;
141 }
142
143 void OCIOImpl::configRelease(OCIO_ConstConfigRcPtr *config)
144 {
145         MEM_DELETE((ConstConfigRcPtr *) config, ConstConfigRcPtr);
146 }
147
148 int OCIOImpl::configGetNumColorSpaces(OCIO_ConstConfigRcPtr *config)
149 {
150         try {
151                 return (*(ConstConfigRcPtr *) config)->getNumColorSpaces();
152         }
153         catch (Exception &exception) {
154                 OCIO_reportException(exception);
155         }
156
157         return 0;
158 }
159
160 const char *OCIOImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *config, int index)
161 {
162         try {
163                 return (*(ConstConfigRcPtr *) config)->getColorSpaceNameByIndex(index);
164         }
165         catch (Exception &exception) {
166                 OCIO_reportException(exception);
167         }
168
169         return NULL;
170 }
171
172 OCIO_ConstColorSpaceRcPtr *OCIOImpl::configGetColorSpace(OCIO_ConstConfigRcPtr *config, const char *name)
173 {
174         ConstColorSpaceRcPtr *cs = MEM_NEW(ConstColorSpaceRcPtr);
175
176         try {
177                 *cs = (*(ConstConfigRcPtr *) config)->getColorSpace(name);
178
179                 if (*cs)
180                         return (OCIO_ConstColorSpaceRcPtr *) cs;
181         }
182         catch (Exception &exception) {
183                 OCIO_reportException(exception);
184         }
185
186         MEM_DELETE(cs, ConstColorSpaceRcPtr);
187
188         return NULL;
189 }
190
191 int OCIOImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name)
192 {
193         try {
194                 return (*(ConstConfigRcPtr *) config)->getIndexForColorSpace(name);
195         }
196         catch (Exception &exception) {
197                 OCIO_reportException(exception);
198         }
199
200         return -1;
201 }
202
203 const char *OCIOImpl::configGetDefaultDisplay(OCIO_ConstConfigRcPtr *config)
204 {
205         try {
206                 return (*(ConstConfigRcPtr *) config)->getDefaultDisplay();
207         }
208         catch (Exception &exception) {
209                 OCIO_reportException(exception);
210         }
211
212         return NULL;
213 }
214
215 int OCIOImpl::configGetNumDisplays(OCIO_ConstConfigRcPtr* config)
216 {
217         try {
218                 return (*(ConstConfigRcPtr *) config)->getNumDisplays();
219         }
220         catch (Exception &exception) {
221                 OCIO_reportException(exception);
222         }
223
224         return 0;
225 }
226
227 const char *OCIOImpl::configGetDisplay(OCIO_ConstConfigRcPtr *config, int index)
228 {
229         try {
230                 return (*(ConstConfigRcPtr *) config)->getDisplay(index);
231         }
232         catch (Exception &exception) {
233                 OCIO_reportException(exception);
234         }
235
236         return NULL;
237 }
238
239 const char *OCIOImpl::configGetDefaultView(OCIO_ConstConfigRcPtr *config, const char *display)
240 {
241         try {
242                 return (*(ConstConfigRcPtr *) config)->getDefaultView(display);
243         }
244         catch (Exception &exception) {
245                 OCIO_reportException(exception);
246         }
247
248         return NULL;
249 }
250
251 int OCIOImpl::configGetNumViews(OCIO_ConstConfigRcPtr *config, const char *display)
252 {
253         try {
254                 return (*(ConstConfigRcPtr *) config)->getNumViews(display);
255         }
256         catch (Exception &exception) {
257                 OCIO_reportException(exception);
258         }
259
260         return 0;
261 }
262
263 const char *OCIOImpl::configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index)
264 {
265         try {
266                 return (*(ConstConfigRcPtr *) config)->getView(display, index);
267         }
268         catch (Exception &exception) {
269                 OCIO_reportException(exception);
270         }
271
272         return NULL;
273 }
274
275 const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view)
276 {
277         try {
278                 return (*(ConstConfigRcPtr *) config)->getDisplayColorSpaceName(display, view);
279         }
280         catch (Exception &exception) {
281                 OCIO_reportException(exception);
282         }
283
284         return NULL;
285 }
286
287 int OCIOImpl::colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs_)
288 {
289         ConstColorSpaceRcPtr *cs = (ConstColorSpaceRcPtr *) cs_;
290         const char *family = (*cs)->getFamily();
291
292         if (!strcmp(family, "rrt") || !strcmp(family, "display")) {
293                 /* assume display and rrt transformations are not invertible
294                  * in fact some of them could be, but it doesn't make much sense to allow use them as invertible
295                  */
296                 return false;
297         }
298
299         if ((*cs)->isData()) {
300                 /* data color spaces don't have transformation at all */
301                 return true;
302         }
303
304         if ((*cs)->getTransform(COLORSPACE_DIR_TO_REFERENCE)) {
305                 /* if there's defined transform to reference space, color space could be converted to scene linear */
306                 return true;
307         }
308
309         return true;
310 }
311
312 int OCIOImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs)
313 {
314         return (*(ConstColorSpaceRcPtr *) cs)->isData();
315 }
316
317 void OCIOImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs)
318 {
319         MEM_DELETE((ConstColorSpaceRcPtr *) cs, ConstColorSpaceRcPtr);
320 }
321
322 OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName)
323 {
324         ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
325
326         try {
327                 *p = (*(ConstConfigRcPtr *) config)->getProcessor(srcName, dstName);
328
329                 if (*p)
330                         return (OCIO_ConstProcessorRcPtr *) p;
331         }
332         catch (Exception &exception) {
333                 OCIO_reportException(exception);
334         }
335
336         MEM_DELETE(p, ConstProcessorRcPtr);
337
338         return 0;
339 }
340
341 OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessor(OCIO_ConstConfigRcPtr *config, OCIO_ConstTransformRcPtr *transform)
342 {
343         ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
344
345         try {
346                 *p = (*(ConstConfigRcPtr *) config)->getProcessor(*(ConstTransformRcPtr *) transform);
347
348                 if (*p)
349                         return (OCIO_ConstProcessorRcPtr *) p;
350         }
351         catch (Exception &exception) {
352                 OCIO_reportException(exception);
353         }
354
355         MEM_DELETE(p, ConstProcessorRcPtr);
356
357         return NULL;
358 }
359
360 void OCIOImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img)
361 {
362         try {
363                 (*(ConstProcessorRcPtr *) processor)->apply(*(PackedImageDesc *) img);
364         }
365         catch (Exception &exception) {
366                 OCIO_reportException(exception);
367         }
368 }
369
370 void OCIOImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img_)
371 {
372         try {
373                 PackedImageDesc *img = (PackedImageDesc *) img_;
374                 int channels = img->getNumChannels();
375
376                 if (channels == 4) {
377                         float *pixels = img->getData();
378
379                         int width = img->getWidth();
380                         int height = img->getHeight();
381
382                         for (int y = 0; y < height; y++) {
383                                 for (int x = 0; x < width; x++) {
384                                         float *pixel = pixels + 4 * (y * width + x);
385
386                                         processorApplyRGBA_predivide(processor, pixel);
387                                 }
388                         }
389                 }
390                 else {
391                         (*(ConstProcessorRcPtr *) processor)->apply(*img);
392                 }
393         }
394         catch (Exception &exception) {
395                 OCIO_reportException(exception);
396         }
397 }
398
399 void OCIOImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel)
400 {
401         (*(ConstProcessorRcPtr *) processor)->applyRGB(pixel);
402 }
403
404 void OCIOImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel)
405 {
406         (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel);
407 }
408
409 void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel)
410 {
411         if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
412                 (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel);
413         }
414         else {
415                 float alpha, inv_alpha;
416
417                 alpha = pixel[3];
418                 inv_alpha = 1.0f / alpha;
419
420                 pixel[0] *= inv_alpha;
421                 pixel[1] *= inv_alpha;
422                 pixel[2] *= inv_alpha;
423
424                 (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel);
425
426                 pixel[0] *= alpha;
427                 pixel[1] *= alpha;
428                 pixel[2] *= alpha;
429         }
430 }
431
432 void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *p)
433 {
434         MEM_DELETE(p, ConstProcessorRcPtr);
435 }
436
437 const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
438 {
439         return (*(ConstColorSpaceRcPtr *) cs)->getName();
440 }
441
442 const char *OCIOImpl::colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs)
443 {
444         return (*(ConstColorSpaceRcPtr *) cs)->getDescription();
445 }
446
447 const char *OCIOImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs)
448 {
449         return (*(ConstColorSpaceRcPtr *)cs)->getFamily();
450 }
451
452 OCIO_DisplayTransformRcPtr *OCIOImpl::createDisplayTransform(void)
453 {
454         DisplayTransformRcPtr *dt = MEM_NEW(DisplayTransformRcPtr);
455
456         *dt = DisplayTransform::Create();
457
458         return (OCIO_DisplayTransformRcPtr *) dt;
459 }
460
461 void OCIOImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name)
462 {
463         (*(DisplayTransformRcPtr *) dt)->setInputColorSpaceName(name);
464 }
465
466 void OCIOImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name)
467 {
468         (*(DisplayTransformRcPtr *) dt)->setDisplay(name);
469 }
470
471 void OCIOImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name)
472 {
473         (*(DisplayTransformRcPtr *) dt)->setView(name);
474 }
475
476 void OCIOImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t)
477 {
478         (*(DisplayTransformRcPtr *) dt)->setDisplayCC(* (ConstTransformRcPtr *) t);
479 }
480
481 void OCIOImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t)
482 {
483         (*(DisplayTransformRcPtr *) dt)->setLinearCC(*(ConstTransformRcPtr *) t);
484 }
485
486 void OCIOImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *dt)
487 {
488         MEM_DELETE((DisplayTransformRcPtr *) dt, DisplayTransformRcPtr);
489 }
490
491 OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels,
492                                                            long chanStrideBytes, long xStrideBytes, long yStrideBytes)
493 {
494         try {
495                 void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__);
496                 PackedImageDesc *id = new(mem) PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes);
497
498                 return (OCIO_PackedImageDesc *) id;
499         }
500         catch (Exception &exception) {
501                 OCIO_reportException(exception);
502         }
503
504         return NULL;
505 }
506
507 void OCIOImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id)
508 {
509         MEM_DELETE((PackedImageDesc *) id, PackedImageDesc);
510 }
511
512 OCIO_ExponentTransformRcPtr *OCIOImpl::createExponentTransform(void)
513 {
514         ExponentTransformRcPtr *et = MEM_NEW(ExponentTransformRcPtr);
515
516         *et = ExponentTransform::Create();
517
518         return (OCIO_ExponentTransformRcPtr *) et;
519 }
520
521 void OCIOImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent)
522 {
523         (*(ExponentTransformRcPtr *) et)->setValue(exponent);
524 }
525
526 void OCIOImpl::exponentTransformRelease(OCIO_ExponentTransformRcPtr *et)
527 {
528         MEM_DELETE((ExponentTransformRcPtr *) et, ExponentTransformRcPtr);
529 }
530
531 OCIO_MatrixTransformRcPtr *OCIOImpl::createMatrixTransform(void)
532 {
533         MatrixTransformRcPtr *mt = MEM_NEW(MatrixTransformRcPtr);
534
535         *mt = MatrixTransform::Create();
536
537         return (OCIO_MatrixTransformRcPtr *) mt;
538 }
539
540 void OCIOImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, const float *m44, const float *offset4)
541 {
542         (*(MatrixTransformRcPtr *) mt)->setValue(m44, offset4);
543 }
544
545 void OCIOImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt)
546 {
547         MEM_DELETE((MatrixTransformRcPtr *) mt, MatrixTransformRcPtr);
548 }
549
550 void OCIOImpl::matrixTransformScale(float * m44, float * offset4, const float *scale4f)
551 {
552         MatrixTransform::Scale(m44, offset4, scale4f);
553 }