Merge branch 'master' into blender2.8
[blender.git] / intern / opencolorio / ocio_impl_glsl.cc
1 /*
2  * Adapted from OpenColorIO with this license:
3  *
4  * Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
5  * All Rights Reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are
9  * met:
10  * * Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  * * Neither the name of Sony Pictures Imageworks nor the names of its
16  *   contributors may be used to endorse or promote products derived from
17  *   this software without specific prior written permission.
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * Modifications Copyright 2013, Blender Foundation.
31  *
32  * Contributor(s): Sergey Sharybin
33  *
34  */
35
36 #include <limits>
37 #include <sstream>
38 #include <string.h>
39
40 #include "glew-mx.h"
41
42 #ifdef _MSC_VER
43 #  pragma warning(push)
44 #  pragma warning(disable : 4251 4275)
45 #endif
46 #include <OpenColorIO/OpenColorIO.h>
47 #ifdef _MSC_VER
48 #  pragma warning(pop)
49 #endif
50
51 extern "C" {
52 #include "GPU_immediate.h"
53 }
54
55 using namespace OCIO_NAMESPACE;
56
57 #include "MEM_guardedalloc.h"
58
59 #include "ocio_impl.h"
60
61 static const int LUT3D_EDGE_SIZE = 64;
62 static const int SHADER_CACHE_SIZE = 4;
63
64 extern "C" char datatoc_gpu_shader_display_transform_glsl[];
65 extern "C" char datatoc_gpu_shader_display_transform_vertex_glsl[];
66
67 /* **** OpenGL drawing routines using GLSL for color space transform ***** */
68
69 typedef struct OCIO_GLSLShader {
70         /* Cache ID */
71         std::string lut3dCacheID;
72         std::string shaderCacheID;
73
74         /* LUT */
75         bool lut3d_texture_allocated;  /* boolean flag indicating whether
76                                         * lut texture is allocated
77                                         */
78         bool lut3d_texture_valid;
79
80         GLuint lut3d_texture;  /* OGL texture ID for 3D LUT */
81
82         float *lut3d;  /* 3D LUT table */
83
84         /* Dither */
85         bool use_dither;
86
87         /* Curve Mapping */
88         bool use_curve_mapping;
89         bool curve_mapping_texture_allocated;
90         bool curve_mapping_texture_valid;
91         GLuint curve_mapping_texture;
92         size_t curve_mapping_cache_id;
93
94         /* Alpha Predivide */
95         bool use_predivide;
96
97         /* GLSL stuff */
98         GLuint ocio_shader;
99         GLuint vert_shader;
100         GLuint program;
101         GPUShaderInterface *shader_interface;
102 } GLSLDrawState;
103
104 typedef struct OCIO_GLSLDrawState {
105         /* Shader Cache */
106         OCIO_GLSLShader *shader_cache[SHADER_CACHE_SIZE];
107
108         /* Previous OpenGL state. */
109         GLint last_texture, last_texture_unit;
110 } OCIO_GLSLDrawState;
111
112 static GLuint compileShaderText(GLenum shaderType, const char *text)
113 {
114         GLuint shader;
115         GLint stat;
116
117         shader = glCreateShader(shaderType);
118         glShaderSource(shader, 1, (const GLchar **) &text, NULL);
119         glCompileShader(shader);
120         glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
121
122         if (!stat) {
123                 GLchar log[1000];
124                 GLsizei len;
125                 glGetShaderInfoLog(shader, 1000, &len, log);
126                 fprintf(stderr, "Shader compile error:\n%s\n", log);
127                 return 0;
128         }
129
130         return shader;
131 }
132
133 static GLuint linkShaders(GLuint ocio_shader, GLuint vert_shader)
134 {
135         if (!ocio_shader || !vert_shader)
136                 return 0;
137
138         GLuint program = glCreateProgram();
139
140         glAttachShader(program, ocio_shader);
141         glAttachShader(program, vert_shader);
142
143         glLinkProgram(program);
144
145         /* check link */
146         {
147                 GLint stat;
148                 glGetProgramiv(program, GL_LINK_STATUS, &stat);
149                 if (!stat) {
150                         GLchar log[1000];
151                         GLsizei len;
152                         glGetProgramInfoLog(program, 1000, &len, log);
153                         fprintf(stderr, "Shader link error:\n%s\n", log);
154                         return 0;
155                 }
156         }
157
158         return program;
159 }
160
161 static OCIO_GLSLDrawState *allocateOpenGLState(void)
162 {
163         return (OCIO_GLSLDrawState *) MEM_callocN(sizeof(OCIO_GLSLDrawState),
164                                                   "OCIO OpenGL State struct");
165 }
166
167 /* Ensure LUT texture and array are allocated */
168 static bool ensureLUT3DAllocated(OCIO_GLSLShader *shader)
169 {
170         int num_3d_entries = 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE;
171
172         if (shader->lut3d_texture_allocated)
173                 return shader->lut3d_texture_valid;
174
175         glGenTextures(1, &shader->lut3d_texture);
176
177         shader->lut3d = (float *) MEM_callocN(sizeof(float) * num_3d_entries, "OCIO GPU 3D LUT");
178
179         glActiveTexture(GL_TEXTURE1);
180         glBindTexture(GL_TEXTURE_3D, shader->lut3d_texture);
181         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
182         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
183         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
184         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
185         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
186
187         /* clean glError buffer */
188         while (glGetError() != GL_NO_ERROR) {}
189
190         glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16F_ARB,
191                      LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
192                      0, GL_RGB, GL_FLOAT, shader->lut3d);
193
194         shader->lut3d_texture_allocated = true;
195
196         /* GL_RGB16F_ARB could be not supported at some drivers
197          * in this case we could not use GLSL display
198          */
199         shader->lut3d_texture_valid = glGetError() == GL_NO_ERROR;
200
201         return shader->lut3d_texture_valid;
202 }
203
204 static bool ensureCurveMappingAllocated(OCIO_GLSLShader *shader, OCIO_CurveMappingSettings *curve_mapping_settings)
205 {
206         if (shader->curve_mapping_texture_allocated)
207                 return shader->curve_mapping_texture_valid;
208
209         glGenTextures(1, &shader->curve_mapping_texture);
210
211         glActiveTexture(GL_TEXTURE2);
212         glBindTexture(GL_TEXTURE_1D, shader->curve_mapping_texture);
213         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
214         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
215         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
216         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
217         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
218
219         /* clean glError buffer */
220         while (glGetError() != GL_NO_ERROR) {}
221
222         glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16F, curve_mapping_settings->lut_size,
223                      0, GL_RGBA, GL_FLOAT, curve_mapping_settings->lut);
224
225         shader->curve_mapping_texture_allocated = true;
226
227         /* GL_RGB16F_ARB could be not supported at some drivers
228          * in this case we could not use GLSL display
229          */
230         shader->curve_mapping_texture_valid = glGetError() == GL_NO_ERROR;
231
232         return shader->curve_mapping_texture_valid;
233 }
234
235 static void freeGLSLShader(OCIO_GLSLShader *shader)
236 {
237         if (shader->curve_mapping_texture_allocated) {
238                 glDeleteTextures(1, &shader->curve_mapping_texture);
239         }
240
241         if (shader->lut3d_texture_allocated) {
242                 glDeleteTextures(1, &shader->lut3d_texture);
243         }
244
245         if (shader->lut3d) {
246                 MEM_freeN(shader->lut3d);
247         }
248
249         if (shader->program) {
250                 glDeleteProgram(shader->program);
251         }
252
253         if (shader->shader_interface) {
254                 GPU_shaderinterface_discard(shader->shader_interface);
255         }
256
257         if (shader->ocio_shader) {
258                 glDeleteShader(shader->ocio_shader);
259         }
260
261         using std::string;
262         shader->lut3dCacheID.~string();
263         shader->shaderCacheID.~string();
264
265         MEM_freeN(shader);
266 }
267
268
269
270 /* Detect if we can support GLSL drawing */
271 bool OCIOImpl::supportGLSLDraw()
272 {
273         /* uses GL_RGB16F_ARB */
274         return GLEW_VERSION_3_0 || GLEW_ARB_texture_float;
275 }
276
277 /**
278  * Setup OpenGL contexts for a transform defined by processor using GLSL
279  * All LUT allocating baking and shader compilation happens here.
280  *
281  * Once this function is called, callee could start drawing images
282  * using regular 2D texture.
283  *
284  * When all drawing is finished, finishGLSLDraw shall be called to
285  * restore OpenGL context to it's pre-GLSL draw state.
286  */
287 bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
288                              OCIO_CurveMappingSettings *curve_mapping_settings,
289                              float dither, bool use_predivide)
290 {
291         ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *) processor;
292         bool use_curve_mapping = curve_mapping_settings != NULL;
293         bool use_dither = dither > std::numeric_limits<float>::epsilon();
294
295         /* Create state if needed. */
296         OCIO_GLSLDrawState *state;
297         if (!*state_r)
298                 *state_r = allocateOpenGLState();
299         state = *state_r;
300
301         glGetIntegerv(GL_TEXTURE_BINDING_2D, &state->last_texture);
302         glGetIntegerv(GL_ACTIVE_TEXTURE, &state->last_texture_unit);
303
304         /* Compute cache IDs. */
305         GpuShaderDesc shaderDesc;
306         shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_3);
307         shaderDesc.setFunctionName("OCIODisplay");
308         shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
309
310         std::string lut3dCacheID = ocio_processor->getGpuLut3DCacheID(shaderDesc);
311         std::string shaderCacheID = ocio_processor->getGpuShaderTextCacheID(shaderDesc);
312
313         /* Find matching cached shader. */
314         OCIO_GLSLShader *shader = NULL;
315         for (int i = 0; i < SHADER_CACHE_SIZE; i++) {
316                 OCIO_GLSLShader *cached_shader = state->shader_cache[i];
317                 if (cached_shader == NULL) {
318                         continue;
319                 }
320
321                 if (cached_shader->lut3dCacheID == lut3dCacheID &&
322                     cached_shader->shaderCacheID == shaderCacheID &&
323                     cached_shader->use_predivide == use_predivide &&
324                     cached_shader->use_curve_mapping == use_curve_mapping &&
325                     cached_shader->use_dither == use_dither)
326                 {
327                         /* LRU cache, so move to front. */
328                         for (int j = i; j > 0; j--) {
329                                 state->shader_cache[j] = state->shader_cache[j - 1];
330                         }
331                         state->shader_cache[0] = cached_shader;
332
333                         shader = cached_shader;
334                         break;
335                 }
336         }
337
338         if (shader == NULL) {
339                 /* LRU cache, shift other items back so we can insert at the front. */
340                 OCIO_GLSLShader *last_shader = state->shader_cache[SHADER_CACHE_SIZE - 1];
341                 if (last_shader) {
342                         freeGLSLShader(last_shader);
343                 }
344                 for (int j = SHADER_CACHE_SIZE - 1; j > 0; j--) {
345                         state->shader_cache[j] = state->shader_cache[j - 1];
346                 }
347
348                 /* Allocate memory for shader. */
349                 shader = (OCIO_GLSLShader *) MEM_callocN(sizeof(OCIO_GLSLShader),
350                                                          "OCIO GLSL Shader");
351                 state->shader_cache[0] = shader;
352
353                 new (&shader->lut3dCacheID) std::string();
354                 new (&shader->shaderCacheID) std::string();
355
356         shader->lut3dCacheID = lut3dCacheID;
357         shader->shaderCacheID = shaderCacheID;
358                 shader->use_curve_mapping = use_curve_mapping;
359                 shader->use_dither = use_dither;
360                 shader->use_predivide = use_predivide;
361
362                 bool valid = true;
363
364                 /* Compute 3D LUT. */
365                 if (valid && ensureLUT3DAllocated(shader)) {
366                     ocio_processor->getGpuLut3D(shader->lut3d, shaderDesc);
367
368                     glActiveTexture(GL_TEXTURE1);
369                     glBindTexture(GL_TEXTURE_3D, shader->lut3d_texture);
370                     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0,
371                                     LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
372                                     GL_RGB, GL_FLOAT, shader->lut3d);
373                 }
374                 else {
375                         valid = false;
376                 }
377
378                 /* Allocate curve mapping texture. */
379                 if (valid && use_curve_mapping) {
380                         if (!ensureCurveMappingAllocated(shader, curve_mapping_settings)) {
381                                 valid = false;
382                         }
383                 }
384
385                 if (valid) {
386                         /* Vertex shader */
387                         std::ostringstream osv;
388
389                         osv << "#version 330\n";
390                         osv << datatoc_gpu_shader_display_transform_vertex_glsl;
391
392                         shader->vert_shader = compileShaderText(GL_VERTEX_SHADER, osv.str().c_str());
393
394                         /* Fragment shader */
395                         std::ostringstream os;
396
397                         os << "#version 330\n";
398
399                         /* Work around OpenColorIO not supporting latest GLSL yet. */
400                         os << "#define texture2D texture\n";
401                         os << "#define texture3D texture\n";
402
403                         if (use_predivide) {
404                                 os << "#define USE_PREDIVIDE\n";
405                         }
406
407                         if (use_dither) {
408                                 os << "#define USE_DITHER\n";
409                         }
410
411                         if (use_curve_mapping) {
412                                 os << "#define USE_CURVE_MAPPING\n";
413                         }
414
415                         os << ocio_processor->getGpuShaderText(shaderDesc) << "\n";
416                         os << datatoc_gpu_shader_display_transform_glsl;
417
418                         shader->ocio_shader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
419
420                         /* Program */
421                         if (shader->ocio_shader && shader->vert_shader) {
422                                 shader->program = linkShaders(shader->ocio_shader, shader->vert_shader);
423                         }
424
425                         if (shader->program) {
426                                 if (shader->shader_interface) {
427                                         GPU_shaderinterface_discard(shader->shader_interface);
428                                 }
429                                 shader->shader_interface = GPU_shaderinterface_create(shader->program);
430                         }
431                 }
432         }
433
434         /* Update curve mapping texture. */
435         if (use_curve_mapping && shader->curve_mapping_texture_allocated) {
436                 if (shader->curve_mapping_cache_id != curve_mapping_settings->cache_id) {
437                         glActiveTexture(GL_TEXTURE2);
438                         glBindTexture(GL_TEXTURE_1D, shader->curve_mapping_texture);
439                         glTexSubImage1D(GL_TEXTURE_1D, 0, 0, curve_mapping_settings->lut_size,
440                                         GL_RGBA, GL_FLOAT, curve_mapping_settings->lut);
441                 }
442         }
443
444         /* Bind Shader. */
445         if (shader->program) {
446                 glActiveTexture(GL_TEXTURE1);
447                 glBindTexture(GL_TEXTURE_3D, shader->lut3d_texture);
448
449                 if (use_curve_mapping) {
450                         glActiveTexture(GL_TEXTURE2);
451                         glBindTexture(GL_TEXTURE_1D, shader->curve_mapping_texture);
452                 }
453
454                 glActiveTexture(GL_TEXTURE0);
455
456                 /* IMM needs vertex format even if we don't draw with it.
457                  *
458                  * NOTE: The only reason why it's here is because of Cycles viewport.
459                  * All other areas are managing their own vertex formats.
460                  * Doing it here is probably harmless, but kind of stupid.
461                  *
462                  * TODO(sergey): Look into some nicer solution.
463                  */
464                 GPUVertFormat *format = immVertexFormat();
465                 GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
466                 GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
467                 immBindProgram(shader->program, shader->shader_interface);
468
469                 immUniform1i("image_texture", 0);
470                 immUniform1i("lut3d_texture", 1);
471
472                 if (use_dither) {
473                         immUniform1f("dither", dither);
474                 }
475
476                 if (use_curve_mapping) {
477                         immUniform1i("curve_mapping_texture", 2);
478                         immUniform1i("curve_mapping_lut_size", curve_mapping_settings->lut_size);
479                         immUniform4iv("use_curve_mapping_extend_extrapolate", curve_mapping_settings->use_extend_extrapolate);
480                         immUniform4fv("curve_mapping_mintable", curve_mapping_settings->mintable);
481                         immUniform4fv("curve_mapping_range", curve_mapping_settings->range);
482                         immUniform4fv("curve_mapping_ext_in_x", curve_mapping_settings->ext_in_x);
483                         immUniform4fv("curve_mapping_ext_in_y", curve_mapping_settings->ext_in_y);
484                         immUniform4fv("curve_mapping_ext_out_x", curve_mapping_settings->ext_out_x);
485                         immUniform4fv("curve_mapping_ext_out_y", curve_mapping_settings->ext_out_y);
486                         immUniform4fv("curve_mapping_first_x", curve_mapping_settings->first_x);
487                         immUniform4fv("curve_mapping_first_y", curve_mapping_settings->first_y);
488                         immUniform4fv("curve_mapping_last_x", curve_mapping_settings->last_x);
489                         immUniform4fv("curve_mapping_last_y", curve_mapping_settings->last_y);
490                         immUniform3fv("curve_mapping_black", curve_mapping_settings->black);
491                         immUniform3fv("curve_mapping_bwmul", curve_mapping_settings->bwmul);
492                 }
493
494                 return true;
495         }
496         else {
497                 glActiveTexture(state->last_texture_unit);
498                 glBindTexture(GL_TEXTURE_2D, state->last_texture);
499
500                 return false;
501         }
502 }
503
504 void OCIOImpl::finishGLSLDraw(OCIO_GLSLDrawState *state)
505 {
506         glActiveTexture(state->last_texture_unit);
507         glBindTexture(GL_TEXTURE_2D, state->last_texture);
508         immUnbindProgram();
509 }
510
511 void OCIOImpl::freeGLState(OCIO_GLSLDrawState *state)
512 {
513         for (int i = 0; i < SHADER_CACHE_SIZE; i++) {
514                 if (state->shader_cache[i]) {
515                         freeGLSLShader(state->shader_cache[i]);
516                 }
517         }
518
519         MEM_freeN(state);
520 }