Implement GPU-side dither
[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 static void OCIO_reportError(const char *err)
59 {
60         std::cerr << "OpenColorIO Error: " << err << std::endl;
61
62         OCIO_abort();
63 }
64
65 static void OCIO_reportException(Exception &exception)
66 {
67         OCIO_reportError(exception.what());
68 }
69
70 OCIO_ConstConfigRcPtr *OCIOImpl::getCurrentConfig(void)
71 {
72         ConstConfigRcPtr *config = OBJECT_GUARDED_NEW(ConstConfigRcPtr);
73
74         try {
75                 *config = GetCurrentConfig();
76
77                 if (*config)
78                         return (OCIO_ConstConfigRcPtr *) config;
79         }
80         catch (Exception &exception) {
81                 OCIO_reportException(exception);
82         }
83
84         OBJECT_GUARDED_DELETE(config, ConstConfigRcPtr);
85
86         return NULL;
87 }
88
89 void OCIOImpl::setCurrentConfig(const OCIO_ConstConfigRcPtr *config)
90 {
91         try {
92                 SetCurrentConfig(*(ConstConfigRcPtr *) config);
93         }
94         catch (Exception &exception) {
95                 OCIO_reportException(exception);
96         }
97 }
98
99 OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromEnv(void)
100 {
101         ConstConfigRcPtr *config = OBJECT_GUARDED_NEW(ConstConfigRcPtr);
102
103         try {
104                 *config = Config::CreateFromEnv();
105
106                 if (*config)
107                         return (OCIO_ConstConfigRcPtr *) config;
108         }
109         catch (Exception &exception) {
110                 OCIO_reportException(exception);
111         }
112
113         OBJECT_GUARDED_DELETE(config, ConstConfigRcPtr);
114
115         return NULL;
116 }
117
118
119 OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromFile(const char *filename)
120 {
121         ConstConfigRcPtr *config = OBJECT_GUARDED_NEW(ConstConfigRcPtr);
122
123         try {
124                 *config = Config::CreateFromFile(filename);
125
126                 if (*config)
127                         return (OCIO_ConstConfigRcPtr *) config;
128         }
129         catch (Exception &exception) {
130                 OCIO_reportException(exception);
131         }
132
133         OBJECT_GUARDED_DELETE(config, ConstConfigRcPtr);
134
135         return NULL;
136 }
137
138 void OCIOImpl::configRelease(OCIO_ConstConfigRcPtr *config)
139 {
140         OBJECT_GUARDED_DELETE((ConstConfigRcPtr *) config, ConstConfigRcPtr);
141 }
142
143 int OCIOImpl::configGetNumColorSpaces(OCIO_ConstConfigRcPtr *config)
144 {
145         try {
146                 return (*(ConstConfigRcPtr *) config)->getNumColorSpaces();
147         }
148         catch (Exception &exception) {
149                 OCIO_reportException(exception);
150         }
151
152         return 0;
153 }
154
155 const char *OCIOImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *config, int index)
156 {
157         try {
158                 return (*(ConstConfigRcPtr *) config)->getColorSpaceNameByIndex(index);
159         }
160         catch (Exception &exception) {
161                 OCIO_reportException(exception);
162         }
163
164         return NULL;
165 }
166
167 OCIO_ConstColorSpaceRcPtr *OCIOImpl::configGetColorSpace(OCIO_ConstConfigRcPtr *config, const char *name)
168 {
169         ConstColorSpaceRcPtr *cs = OBJECT_GUARDED_NEW(ConstColorSpaceRcPtr);
170
171         try {
172                 *cs = (*(ConstConfigRcPtr *) config)->getColorSpace(name);
173
174                 if (*cs)
175                         return (OCIO_ConstColorSpaceRcPtr *) cs;
176         }
177         catch (Exception &exception) {
178                 OCIO_reportException(exception);
179         }
180
181         OBJECT_GUARDED_DELETE(cs, ConstColorSpaceRcPtr);
182
183         return NULL;
184 }
185
186 int OCIOImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name)
187 {
188         try {
189                 return (*(ConstConfigRcPtr *) config)->getIndexForColorSpace(name);
190         }
191         catch (Exception &exception) {
192                 OCIO_reportException(exception);
193         }
194
195         return -1;
196 }
197
198 const char *OCIOImpl::configGetDefaultDisplay(OCIO_ConstConfigRcPtr *config)
199 {
200         try {
201                 return (*(ConstConfigRcPtr *) config)->getDefaultDisplay();
202         }
203         catch (Exception &exception) {
204                 OCIO_reportException(exception);
205         }
206
207         return NULL;
208 }
209
210 int OCIOImpl::configGetNumDisplays(OCIO_ConstConfigRcPtr* config)
211 {
212         try {
213                 return (*(ConstConfigRcPtr *) config)->getNumDisplays();
214         }
215         catch (Exception &exception) {
216                 OCIO_reportException(exception);
217         }
218
219         return 0;
220 }
221
222 const char *OCIOImpl::configGetDisplay(OCIO_ConstConfigRcPtr *config, int index)
223 {
224         try {
225                 return (*(ConstConfigRcPtr *) config)->getDisplay(index);
226         }
227         catch (Exception &exception) {
228                 OCIO_reportException(exception);
229         }
230
231         return NULL;
232 }
233
234 const char *OCIOImpl::configGetDefaultView(OCIO_ConstConfigRcPtr *config, const char *display)
235 {
236         try {
237                 return (*(ConstConfigRcPtr *) config)->getDefaultView(display);
238         }
239         catch (Exception &exception) {
240                 OCIO_reportException(exception);
241         }
242
243         return NULL;
244 }
245
246 int OCIOImpl::configGetNumViews(OCIO_ConstConfigRcPtr *config, const char *display)
247 {
248         try {
249                 return (*(ConstConfigRcPtr *) config)->getNumViews(display);
250         }
251         catch (Exception &exception) {
252                 OCIO_reportException(exception);
253         }
254
255         return 0;
256 }
257
258 const char *OCIOImpl::configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index)
259 {
260         try {
261                 return (*(ConstConfigRcPtr *) config)->getView(display, index);
262         }
263         catch (Exception &exception) {
264                 OCIO_reportException(exception);
265         }
266
267         return NULL;
268 }
269
270 const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view)
271 {
272         try {
273                 return (*(ConstConfigRcPtr *) config)->getDisplayColorSpaceName(display, view);
274         }
275         catch (Exception &exception) {
276                 OCIO_reportException(exception);
277         }
278
279         return NULL;
280 }
281
282 int OCIOImpl::configGetNumLooks(OCIO_ConstConfigRcPtr *config)
283 {
284         try {
285                 return (*(ConstConfigRcPtr *) config)->getNumLooks();
286         }
287         catch (Exception &exception) {
288                 OCIO_reportException(exception);
289         }
290
291         return 0;
292 }
293
294 const char *OCIOImpl::configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index)
295 {
296         try {
297                 return (*(ConstConfigRcPtr *) config)->getLookNameByIndex(index);
298         }
299         catch (Exception &exception) {
300                 OCIO_reportException(exception);
301         }
302
303         return NULL;
304 }
305
306 OCIO_ConstLookRcPtr *OCIOImpl::configGetLook(OCIO_ConstConfigRcPtr *config, const char *name)
307 {
308         ConstLookRcPtr *look = OBJECT_GUARDED_NEW(ConstLookRcPtr);
309
310         try {
311                 *look = (*(ConstConfigRcPtr *) config)->getLook(name);
312
313                 if (*look)
314                         return (OCIO_ConstLookRcPtr *) look;
315         }
316         catch (Exception &exception) {
317                 OCIO_reportException(exception);
318         }
319
320         OBJECT_GUARDED_DELETE(look, ConstLookRcPtr);
321
322         return NULL;
323 }
324
325 const char *OCIOImpl::lookGetProcessSpace(OCIO_ConstLookRcPtr *look)
326 {
327         return (*(ConstLookRcPtr *) look)->getProcessSpace();
328 }
329
330 void OCIOImpl::lookRelease(OCIO_ConstLookRcPtr *look)
331 {
332         OBJECT_GUARDED_DELETE((ConstLookRcPtr *) look, ConstLookRcPtr);
333 }
334
335 int OCIOImpl::colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs_)
336 {
337         ConstColorSpaceRcPtr *cs = (ConstColorSpaceRcPtr *) cs_;
338         const char *family = (*cs)->getFamily();
339
340         if (!strcmp(family, "rrt") || !strcmp(family, "display")) {
341                 /* assume display and rrt transformations are not invertible
342                  * in fact some of them could be, but it doesn't make much sense to allow use them as invertible
343                  */
344                 return false;
345         }
346
347         if ((*cs)->isData()) {
348                 /* data color spaces don't have transformation at all */
349                 return true;
350         }
351
352         if ((*cs)->getTransform(COLORSPACE_DIR_TO_REFERENCE)) {
353                 /* if there's defined transform to reference space, color space could be converted to scene linear */
354                 return true;
355         }
356
357         return true;
358 }
359
360 int OCIOImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs)
361 {
362         return (*(ConstColorSpaceRcPtr *) cs)->isData();
363 }
364
365 void OCIOImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs)
366 {
367         OBJECT_GUARDED_DELETE((ConstColorSpaceRcPtr *) cs, ConstColorSpaceRcPtr);
368 }
369
370 OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName)
371 {
372         ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr);
373
374         try {
375                 *p = (*(ConstConfigRcPtr *) config)->getProcessor(srcName, dstName);
376
377                 if (*p)
378                         return (OCIO_ConstProcessorRcPtr *) p;
379         }
380         catch (Exception &exception) {
381                 OCIO_reportException(exception);
382         }
383
384         OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr);
385
386         return 0;
387 }
388
389 OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessor(OCIO_ConstConfigRcPtr *config, OCIO_ConstTransformRcPtr *transform)
390 {
391         ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr);
392
393         try {
394                 *p = (*(ConstConfigRcPtr *) config)->getProcessor(*(ConstTransformRcPtr *) transform);
395
396                 if (*p)
397                         return (OCIO_ConstProcessorRcPtr *) p;
398         }
399         catch (Exception &exception) {
400                 OCIO_reportException(exception);
401         }
402
403         OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr);
404
405         return NULL;
406 }
407
408 void OCIOImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img)
409 {
410         try {
411                 (*(ConstProcessorRcPtr *) processor)->apply(*(PackedImageDesc *) img);
412         }
413         catch (Exception &exception) {
414                 OCIO_reportException(exception);
415         }
416 }
417
418 void OCIOImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img_)
419 {
420         try {
421                 PackedImageDesc *img = (PackedImageDesc *) img_;
422                 int channels = img->getNumChannels();
423
424                 if (channels == 4) {
425                         float *pixels = img->getData();
426
427                         int width = img->getWidth();
428                         int height = img->getHeight();
429
430                         for (int y = 0; y < height; y++) {
431                                 for (int x = 0; x < width; x++) {
432                                         float *pixel = pixels + 4 * (y * width + x);
433
434                                         processorApplyRGBA_predivide(processor, pixel);
435                                 }
436                         }
437                 }
438                 else {
439                         (*(ConstProcessorRcPtr *) processor)->apply(*img);
440                 }
441         }
442         catch (Exception &exception) {
443                 OCIO_reportException(exception);
444         }
445 }
446
447 void OCIOImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel)
448 {
449         (*(ConstProcessorRcPtr *) processor)->applyRGB(pixel);
450 }
451
452 void OCIOImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel)
453 {
454         (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel);
455 }
456
457 void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel)
458 {
459         if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
460                 (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel);
461         }
462         else {
463                 float alpha, inv_alpha;
464
465                 alpha = pixel[3];
466                 inv_alpha = 1.0f / alpha;
467
468                 pixel[0] *= inv_alpha;
469                 pixel[1] *= inv_alpha;
470                 pixel[2] *= inv_alpha;
471
472                 (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel);
473
474                 pixel[0] *= alpha;
475                 pixel[1] *= alpha;
476                 pixel[2] *= alpha;
477         }
478 }
479
480 void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *p)
481 {
482         OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr);
483 }
484
485 const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
486 {
487         return (*(ConstColorSpaceRcPtr *) cs)->getName();
488 }
489
490 const char *OCIOImpl::colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs)
491 {
492         return (*(ConstColorSpaceRcPtr *) cs)->getDescription();
493 }
494
495 const char *OCIOImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs)
496 {
497         return (*(ConstColorSpaceRcPtr *)cs)->getFamily();
498 }
499
500 OCIO_DisplayTransformRcPtr *OCIOImpl::createDisplayTransform(void)
501 {
502         DisplayTransformRcPtr *dt = OBJECT_GUARDED_NEW(DisplayTransformRcPtr);
503
504         *dt = DisplayTransform::Create();
505
506         return (OCIO_DisplayTransformRcPtr *) dt;
507 }
508
509 void OCIOImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name)
510 {
511         (*(DisplayTransformRcPtr *) dt)->setInputColorSpaceName(name);
512 }
513
514 void OCIOImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name)
515 {
516         (*(DisplayTransformRcPtr *) dt)->setDisplay(name);
517 }
518
519 void OCIOImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name)
520 {
521         (*(DisplayTransformRcPtr *) dt)->setView(name);
522 }
523
524 void OCIOImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t)
525 {
526         (*(DisplayTransformRcPtr *) dt)->setDisplayCC(* (ConstTransformRcPtr *) t);
527 }
528
529 void OCIOImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t)
530 {
531         (*(DisplayTransformRcPtr *) dt)->setLinearCC(*(ConstTransformRcPtr *) t);
532 }
533
534 void OCIOImpl::displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks)
535 {
536         (*(DisplayTransformRcPtr *) dt)->setLooksOverride(looks);
537 }
538
539 void OCIOImpl::displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, bool enabled)
540 {
541         (*(DisplayTransformRcPtr *) dt)->setLooksOverrideEnabled(enabled);
542 }
543
544 void OCIOImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *dt)
545 {
546         OBJECT_GUARDED_DELETE((DisplayTransformRcPtr *) dt, DisplayTransformRcPtr);
547 }
548
549 OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels,
550                                                            long chanStrideBytes, long xStrideBytes, long yStrideBytes)
551 {
552         try {
553                 void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__);
554                 PackedImageDesc *id = new(mem) PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes);
555
556                 return (OCIO_PackedImageDesc *) id;
557         }
558         catch (Exception &exception) {
559                 OCIO_reportException(exception);
560         }
561
562         return NULL;
563 }
564
565 void OCIOImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id)
566 {
567         OBJECT_GUARDED_DELETE((PackedImageDesc *) id, PackedImageDesc);
568 }
569
570 OCIO_ExponentTransformRcPtr *OCIOImpl::createExponentTransform(void)
571 {
572         ExponentTransformRcPtr *et = OBJECT_GUARDED_NEW(ExponentTransformRcPtr);
573
574         *et = ExponentTransform::Create();
575
576         return (OCIO_ExponentTransformRcPtr *) et;
577 }
578
579 void OCIOImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent)
580 {
581         (*(ExponentTransformRcPtr *) et)->setValue(exponent);
582 }
583
584 void OCIOImpl::exponentTransformRelease(OCIO_ExponentTransformRcPtr *et)
585 {
586         OBJECT_GUARDED_DELETE((ExponentTransformRcPtr *) et, ExponentTransformRcPtr);
587 }
588
589 OCIO_MatrixTransformRcPtr *OCIOImpl::createMatrixTransform(void)
590 {
591         MatrixTransformRcPtr *mt = OBJECT_GUARDED_NEW(MatrixTransformRcPtr);
592
593         *mt = MatrixTransform::Create();
594
595         return (OCIO_MatrixTransformRcPtr *) mt;
596 }
597
598 void OCIOImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, const float *m44, const float *offset4)
599 {
600         (*(MatrixTransformRcPtr *) mt)->setValue(m44, offset4);
601 }
602
603 void OCIOImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt)
604 {
605         OBJECT_GUARDED_DELETE((MatrixTransformRcPtr *) mt, MatrixTransformRcPtr);
606 }
607
608 void OCIOImpl::matrixTransformScale(float *m44, float *offset4, const float *scale4f)
609 {
610         MatrixTransform::Scale(m44, offset4, scale4f);
611 }
612
613 const char *OCIOImpl::getVersionString(void)
614 {
615         return GetVersion();
616 }
617
618 int OCIOImpl::getVersionHex(void)
619 {
620         return GetVersionHex();
621 }