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
33 #include <limits>
34 #include <sstream>
35 #include <string.h>
36
37 #ifdef _MSC_VER
38 # pragma warning(push)
39 # pragma warning(disable : 4251 4275)
40 #endif
41 #include <OpenColorIO/OpenColorIO.h>
42 #ifdef _MSC_VER
43 # pragma warning(pop)
44 #endif
45
46 #include "GPU_immediate.h"
47 #include "GPU_shader.h"
48 #include "GPU_uniform_buffer.h"
49
50 using namespace OCIO_NAMESPACE;
51
52 #include "MEM_guardedalloc.h"
53
54 #include "ocio_impl.h"
55
56 static const int LUT3D_EDGE_SIZE = 64;
57 static const int LUT3D_TEXTURE_SIZE = sizeof(float) * 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE *
58 LUT3D_EDGE_SIZE;
59 static const int SHADER_CACHE_SIZE = 4;
60
61 #define UBO_BIND_LOC 0
62
63 extern "C" char datatoc_gpu_shader_display_transform_glsl[];
64 extern "C" char datatoc_gpu_shader_display_transform_vertex_glsl[];
65
66 /* **** OpenGL drawing routines using GLSL for color space transform ***** */
67
68 /* Curve mapping parameters
69 *
70 * See documentation for OCIO_CurveMappingSettings to get fields descriptions.
71 * (this ones pretty much copies stuff from C structure.)
72 */
73 struct OCIO_GLSLCurveMappingParameters {
74 float curve_mapping_mintable[4];
75 float curve_mapping_range[4];
76 float curve_mapping_ext_in_x[4];
77 float curve_mapping_ext_in_y[4];
78 float curve_mapping_ext_out_x[4];
79 float curve_mapping_ext_out_y[4];
80 float curve_mapping_first_x[4];
81 float curve_mapping_first_y[4];
82 float curve_mapping_last_x[4];
83 float curve_mapping_last_y[4];
84 float curve_mapping_black[4];
85 float curve_mapping_bwmul[4];
86 int curve_mapping_lut_size;
87 int curve_mapping_use_extend_extrapolate;
88 int _pad[2];
89 /** WARNING: Needs to be 16byte aligned. Used as UBO data. */
90 };
91
92 struct OCIO_GLSLShader {
93 /** Cache IDs */
94 std::string cacheId;
95
96 struct GPUShader *shader;
97 /** Uniform locations. */
98 int dither_loc;
99 int overlay_loc;
100 int predivide_loc;
101 int curve_mapping_loc;
102 int ubo_bind;
103 /** Error checking. */
104 bool valid;
105 };
106
107 struct OCIO_GLSLLut3d {
108 /** Cache IDs */
109 std::string cacheId;
110 /** OpenGL Texture handles. NULL if not allocated. */
111 GPUTexture *texture;
112 GPUTexture *texture_display;
113 GPUTexture *texture_dummy;
114 /** Error checking. */
115 bool valid;
116 };
117
118 struct OCIO_GLSLCurveMappping {
119 /** Cache IDs */
120 size_t cacheId;
121 /** GPU Uniform Buffer handle. 0 if not allocated. */
122 GPUUniformBuf *buffer;
123 /** OpenGL Texture handles. 0 if not allocated. */
124 GPUTexture *texture;
125 /** Error checking. */
126 bool valid;
127 };
128
129 struct OCIO_GLSLCacheHandle {
130 size_t cache_id;
131 void *data;
132 };
133
134 struct OCIO_GLSLDrawState {
135 /* Shader Cache */
136 OCIO_GLSLCacheHandle shader_cache[SHADER_CACHE_SIZE];
137 OCIO_GLSLCacheHandle lut3d_cache[SHADER_CACHE_SIZE];
138 OCIO_GLSLCacheHandle curvemap_cache[SHADER_CACHE_SIZE];
139 };
140
allocateOpenGLState(void)141 static OCIO_GLSLDrawState *allocateOpenGLState(void)
142 {
143 return (OCIO_GLSLDrawState *)MEM_callocN(sizeof(OCIO_GLSLDrawState), "OCIO OpenGL State struct");
144 }
145
146 /* -------------------------------------------------------------------- */
147 /** \name Shader
148 * \{ */
149
updateGLSLShader(OCIO_GLSLShader * shader,ConstProcessorRcPtr * processor_scene_to_ui,ConstProcessorRcPtr * processpr_ui_to_display,GpuShaderDesc * shader_desc,const std::string & cache_id)150 static void updateGLSLShader(OCIO_GLSLShader *shader,
151 ConstProcessorRcPtr *processor_scene_to_ui,
152 ConstProcessorRcPtr *processpr_ui_to_display,
153 GpuShaderDesc *shader_desc,
154 const std::string &cache_id)
155 {
156 if (shader->cacheId == cache_id) {
157 return;
158 }
159
160 /* Delete any previous shader. */
161 if (shader->shader) {
162 GPU_shader_free(shader->shader);
163 }
164
165 std::ostringstream os;
166 {
167 /* Fragment shader */
168
169 /* Work around OpenColorIO not supporting latest GLSL yet. */
170 os << "#define texture2D texture\n";
171 os << "#define texture3D texture\n";
172
173 shader_desc->setFunctionName("OCIO_to_display_linear_with_look");
174 os << (*processor_scene_to_ui)->getGpuShaderText(*shader_desc) << "\n";
175
176 shader_desc->setFunctionName("OCIO_to_display_encoded");
177 os << (*processpr_ui_to_display)->getGpuShaderText(*shader_desc) << "\n";
178
179 os << datatoc_gpu_shader_display_transform_glsl;
180 }
181
182 shader->shader = GPU_shader_create(datatoc_gpu_shader_display_transform_vertex_glsl,
183 os.str().c_str(),
184 NULL,
185 NULL,
186 NULL,
187 "OCIOShader");
188
189 if (shader->shader) {
190 shader->dither_loc = GPU_shader_get_uniform(shader->shader, "dither");
191 shader->overlay_loc = GPU_shader_get_uniform(shader->shader, "overlay");
192 shader->predivide_loc = GPU_shader_get_uniform(shader->shader, "predivide");
193 shader->curve_mapping_loc = GPU_shader_get_uniform(shader->shader, "curve_mapping");
194 shader->ubo_bind = GPU_shader_get_uniform_block_binding(shader->shader,
195 "OCIO_GLSLCurveMappingParameters");
196
197 GPU_shader_bind(shader->shader);
198
199 /* Set texture bind point uniform once. This is saved by the shader. */
200 GPUShader *sh = shader->shader;
201 GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "image_texture"), 0);
202 GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "overlay_texture"), 1);
203 GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "lut3d_texture"), 2);
204 GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "lut3d_display_texture"), 3);
205 GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "curve_mapping_texture"), 4);
206 }
207
208 shader->cacheId = cache_id;
209 shader->valid = (shader->shader != NULL);
210 }
211
ensureGLSLShader(OCIO_GLSLShader ** shader_ptr,ConstProcessorRcPtr * processor_scene_to_ui,ConstProcessorRcPtr * processpr_ui_to_display,GpuShaderDesc * shader_desc,const std::string & cache_id)212 static void ensureGLSLShader(OCIO_GLSLShader **shader_ptr,
213 ConstProcessorRcPtr *processor_scene_to_ui,
214 ConstProcessorRcPtr *processpr_ui_to_display,
215 GpuShaderDesc *shader_desc,
216 const std::string &cache_id)
217 {
218 if (*shader_ptr != NULL) {
219 return;
220 }
221
222 OCIO_GLSLShader *shader = OBJECT_GUARDED_NEW(OCIO_GLSLShader);
223
224 updateGLSLShader(shader, processor_scene_to_ui, processpr_ui_to_display, shader_desc, cache_id);
225
226 *shader_ptr = shader;
227 }
228
freeGLSLShader(OCIO_GLSLShader * shader)229 static void freeGLSLShader(OCIO_GLSLShader *shader)
230 {
231 if (shader->shader) {
232 GPU_shader_free(shader->shader);
233 }
234
235 OBJECT_GUARDED_DELETE(shader, OCIO_GLSLShader);
236 }
237
238 /** \} */
239
240 /* -------------------------------------------------------------------- */
241 /** \name Lut3D
242 * \{ */
243
updateGLSLLut3d(OCIO_GLSLLut3d * lut3d,ConstProcessorRcPtr * processor_scene_to_ui,ConstProcessorRcPtr * processpr_ui_to_display,GpuShaderDesc * shader_desc,const std::string & cache_id)244 static void updateGLSLLut3d(OCIO_GLSLLut3d *lut3d,
245 ConstProcessorRcPtr *processor_scene_to_ui,
246 ConstProcessorRcPtr *processpr_ui_to_display,
247 GpuShaderDesc *shader_desc,
248 const std::string &cache_id)
249 {
250 if (lut3d->cacheId == cache_id)
251 return;
252
253 float *lut_data = (float *)MEM_mallocN(LUT3D_TEXTURE_SIZE, __func__);
254
255 ConstProcessorRcPtr *ocio_processors[2] = {processor_scene_to_ui, processpr_ui_to_display};
256
257 for (int i = 0; i < 2; i++) {
258 ConstProcessorRcPtr *processor = ocio_processors[i];
259 GPUTexture *texture = (&lut3d->texture)[i];
260
261 (*processor)->getGpuLut3D(lut_data, *shader_desc);
262
263 int offset[3] = {0, 0, 0};
264 int extent[3] = {LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE};
265 GPU_texture_update_sub(texture, GPU_DATA_FLOAT, lut_data, UNPACK3(offset), UNPACK3(extent));
266 }
267
268 MEM_freeN(lut_data);
269
270 lut3d->cacheId = cache_id;
271 }
272
ensureGLSLLut3d(OCIO_GLSLLut3d ** lut3d_ptr,ConstProcessorRcPtr * processor_scene_to_ui,ConstProcessorRcPtr * processpr_ui_to_display,GpuShaderDesc * shaderDesc,const std::string & cache_id)273 static void ensureGLSLLut3d(OCIO_GLSLLut3d **lut3d_ptr,
274 ConstProcessorRcPtr *processor_scene_to_ui,
275 ConstProcessorRcPtr *processpr_ui_to_display,
276 GpuShaderDesc *shaderDesc,
277 const std::string &cache_id)
278 {
279 if (*lut3d_ptr != NULL) {
280 return;
281 }
282
283 OCIO_GLSLLut3d *lut3d = OBJECT_GUARDED_NEW(OCIO_GLSLLut3d);
284
285 int extent[3] = {LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE};
286
287 lut3d->texture = GPU_texture_create_3d(
288 "OCIOLut", UNPACK3(extent), 1, GPU_RGB16F, GPU_DATA_FLOAT, NULL);
289 GPU_texture_filter_mode(lut3d->texture, true);
290 GPU_texture_wrap_mode(lut3d->texture, false, true);
291
292 lut3d->texture_display = GPU_texture_create_3d(
293 "OCIOLutDisplay", UNPACK3(extent), 1, GPU_RGB16F, GPU_DATA_FLOAT, NULL);
294 GPU_texture_filter_mode(lut3d->texture_display, true);
295 GPU_texture_wrap_mode(lut3d->texture_display, false, true);
296
297 lut3d->texture_dummy = GPU_texture_create_error(2, false);
298
299 updateGLSLLut3d(lut3d, processor_scene_to_ui, processpr_ui_to_display, shaderDesc, cache_id);
300
301 lut3d->valid = (lut3d->texture && lut3d->texture_display);
302
303 *lut3d_ptr = lut3d;
304 }
305
freeGLSLLut3d(OCIO_GLSLLut3d * lut3d)306 static void freeGLSLLut3d(OCIO_GLSLLut3d *lut3d)
307 {
308 GPU_texture_free(lut3d->texture);
309 GPU_texture_free(lut3d->texture_display);
310 GPU_texture_free(lut3d->texture_dummy);
311
312 OBJECT_GUARDED_DELETE(lut3d, OCIO_GLSLLut3d);
313 }
314
315 /** \} */
316
317 /* -------------------------------------------------------------------- */
318 /** \name Curve Mapping
319 * \{ */
allocateCurveMappingTexture(OCIO_GLSLCurveMappping * curvemap,OCIO_CurveMappingSettings * curve_mapping_settings)320 static void allocateCurveMappingTexture(OCIO_GLSLCurveMappping *curvemap,
321 OCIO_CurveMappingSettings *curve_mapping_settings)
322 {
323 int lut_size = curve_mapping_settings ? curve_mapping_settings->lut_size : 1;
324 /* Do not initialize. Only if used. */
325 curvemap->texture = GPU_texture_create_1d("OCIOCurveMap", lut_size, 1, GPU_RGBA16F, NULL);
326 GPU_texture_filter_mode(curvemap->texture, false);
327 GPU_texture_wrap_mode(curvemap->texture, false, true);
328 }
329
330 /* curve_mapping_settings can be null. In this case we alloc a dummy curvemap. */
ensureGLSLCurveMapping(OCIO_GLSLCurveMappping ** curvemap_ptr,OCIO_CurveMappingSettings * curve_mapping_settings)331 static void ensureGLSLCurveMapping(OCIO_GLSLCurveMappping **curvemap_ptr,
332 OCIO_CurveMappingSettings *curve_mapping_settings)
333 {
334 if (*curvemap_ptr != NULL) {
335 return;
336 }
337
338 OCIO_GLSLCurveMappping *curvemap = OBJECT_GUARDED_NEW(OCIO_GLSLCurveMappping);
339
340 /* Texture. */
341 allocateCurveMappingTexture(curvemap, curve_mapping_settings);
342
343 /* Uniform buffer object. */
344 curvemap->buffer = GPU_uniformbuf_create(sizeof(OCIO_GLSLCurveMappingParameters));
345
346 curvemap->valid = (curvemap->texture != 0);
347 curvemap->cacheId = 0;
348
349 *curvemap_ptr = curvemap;
350 }
351
freeGLSLCurveMapping(OCIO_GLSLCurveMappping * curvemap)352 static void freeGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap)
353 {
354 GPU_texture_free(curvemap->texture);
355 GPU_uniformbuf_free(curvemap->buffer);
356
357 OBJECT_GUARDED_DELETE(curvemap, OCIO_GLSLCurveMappping);
358 }
359
updateGLSLCurveMapping(OCIO_GLSLCurveMappping * curvemap,OCIO_CurveMappingSettings * curve_mapping_settings,size_t cacheId)360 static void updateGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap,
361 OCIO_CurveMappingSettings *curve_mapping_settings,
362 size_t cacheId)
363 {
364 /* No need to continue if curvemapping is not used. Just use whatever is in this cache. */
365 if (curve_mapping_settings == NULL)
366 return;
367
368 if (curvemap->cacheId == cacheId)
369 return;
370
371 if (curvemap->cacheId == 0) {
372 /* This cache was previously used as dummy. Recreate the texture. */
373 GPU_texture_free(curvemap->texture);
374 allocateCurveMappingTexture(curvemap, curve_mapping_settings);
375 }
376
377 /* Update texture. */
378 int offset[3] = {0, 0, 0};
379 int extent[3] = {curve_mapping_settings->lut_size, 0, 0};
380 const float *pixels = curve_mapping_settings->lut;
381 GPU_texture_update_sub(
382 curvemap->texture, GPU_DATA_FLOAT, pixels, UNPACK3(offset), UNPACK3(extent));
383
384 /* Update uniforms. */
385 OCIO_GLSLCurveMappingParameters data;
386 for (int i = 0; i < 4; i++) {
387 data.curve_mapping_range[i] = curve_mapping_settings->range[i];
388 data.curve_mapping_mintable[i] = curve_mapping_settings->mintable[i];
389 data.curve_mapping_ext_in_x[i] = curve_mapping_settings->ext_in_x[i];
390 data.curve_mapping_ext_in_y[i] = curve_mapping_settings->ext_in_y[i];
391 data.curve_mapping_ext_out_x[i] = curve_mapping_settings->ext_out_x[i];
392 data.curve_mapping_ext_out_y[i] = curve_mapping_settings->ext_out_y[i];
393 data.curve_mapping_first_x[i] = curve_mapping_settings->first_x[i];
394 data.curve_mapping_first_y[i] = curve_mapping_settings->first_y[i];
395 data.curve_mapping_last_x[i] = curve_mapping_settings->last_x[i];
396 data.curve_mapping_last_y[i] = curve_mapping_settings->last_y[i];
397 }
398 for (int i = 0; i < 3; i++) {
399 data.curve_mapping_black[i] = curve_mapping_settings->black[i];
400 data.curve_mapping_bwmul[i] = curve_mapping_settings->bwmul[i];
401 }
402 data.curve_mapping_lut_size = curve_mapping_settings->lut_size;
403 data.curve_mapping_use_extend_extrapolate = curve_mapping_settings->use_extend_extrapolate;
404
405 GPU_uniformbuf_update(curvemap->buffer, &data);
406
407 curvemap->cacheId = cacheId;
408 }
409
410 /** \} */
411
412 /* -------------------------------------------------------------------- */
413 /** \name LRU cache
414 * \{ */
415
hash_string(const char * str)416 static size_t hash_string(const char *str)
417 {
418 size_t i = 0, c;
419 while ((c = *str++)) {
420 i = i * 37 + c;
421 }
422 return i;
423 }
424
cacheSearch(OCIO_GLSLCacheHandle cache[SHADER_CACHE_SIZE],size_t cache_id)425 static OCIO_GLSLCacheHandle *cacheSearch(OCIO_GLSLCacheHandle cache[SHADER_CACHE_SIZE],
426 size_t cache_id)
427 {
428 OCIO_GLSLCacheHandle *cached_item = &cache[0];
429 for (int i = 0; i < SHADER_CACHE_SIZE; i++, cached_item++) {
430 if (cached_item->data == NULL) {
431 continue;
432 }
433 else if (cached_item->cache_id == cache_id) {
434 /* LRU cache, so move to front. */
435 OCIO_GLSLCacheHandle found_item = *cached_item;
436 for (int j = i; j > 0; j--) {
437 cache[j] = cache[j - 1];
438 }
439 cache[0] = found_item;
440 return &cache[0];
441 }
442 }
443 /* LRU cache, shift other items back so we can insert at the front. */
444 OCIO_GLSLCacheHandle last_item = cache[SHADER_CACHE_SIZE - 1];
445 for (int j = SHADER_CACHE_SIZE - 1; j > 0; j--) {
446 cache[j] = cache[j - 1];
447 }
448 /* Copy last to front and let the caller initialize it. */
449 cache[0] = last_item;
450 return &cache[0];
451 }
452
453 /** \} */
454
455 /* -------------------------------------------------------------------- */
456 /** \name OCIO GLSL Implementation
457 * \{ */
458
459 /* Detect if we can support GLSL drawing */
supportGLSLDraw()460 bool OCIOImpl::supportGLSLDraw()
461 {
462 /* Minimum supported version 3.3 does meet all requirements. */
463 return true;
464 }
465
466 /**
467 * Setup OpenGL contexts for a transform defined by processor using GLSL
468 * All LUT allocating baking and shader compilation happens here.
469 *
470 * Once this function is called, callee could start drawing images
471 * using regular 2D texture.
472 *
473 * When all drawing is finished, finishGLSLDraw shall be called to
474 * restore OpenGL context to its pre-GLSL draw state.
475 */
setupGLSLDraw(OCIO_GLSLDrawState ** state_r,OCIO_ConstProcessorRcPtr * ocio_processor_scene_to_ui,OCIO_ConstProcessorRcPtr * ocio_processor_ui_to_display,OCIO_CurveMappingSettings * curve_mapping_settings,float dither,bool use_predivide,bool use_overlay)476 bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r,
477 OCIO_ConstProcessorRcPtr *ocio_processor_scene_to_ui,
478 OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display,
479 OCIO_CurveMappingSettings *curve_mapping_settings,
480 float dither,
481 bool use_predivide,
482 bool use_overlay)
483 {
484 ConstProcessorRcPtr processor_scene_to_ui = *(ConstProcessorRcPtr *)ocio_processor_scene_to_ui;
485 ConstProcessorRcPtr processpr_ui_to_display = *(
486 ConstProcessorRcPtr *)ocio_processor_ui_to_display;
487 bool use_curve_mapping = curve_mapping_settings != NULL;
488
489 if (!processor_scene_to_ui || !processor_scene_to_ui) {
490 return false;
491 }
492
493 /* Create state if needed. */
494 OCIO_GLSLDrawState *state;
495 if (!*state_r)
496 *state_r = allocateOpenGLState();
497 state = *state_r;
498
499 /* Compute cache IDs. */
500 GpuShaderDesc shaderDesc;
501 shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_3);
502 shaderDesc.setFunctionName("OCIODisplay");
503 shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
504
505 const char *shader_cache_str = processor_scene_to_ui->getGpuShaderTextCacheID(shaderDesc);
506 const char *lut3d_cache_str = processor_scene_to_ui->getGpuLut3DCacheID(shaderDesc);
507 /* Used for comparison. */
508 std::string shaderCacheID = shader_cache_str;
509 std::string lut3dCacheID = lut3d_cache_str;
510
511 size_t shader_cache_id = hash_string(shader_cache_str);
512 size_t lut3d_cache_id = hash_string(lut3d_cache_str);
513 size_t curvemap_cache_id = curve_mapping_settings ? curve_mapping_settings->cache_id : 0;
514
515 OCIO_GLSLCacheHandle *shader_handle = cacheSearch(state->shader_cache, shader_cache_id);
516 OCIO_GLSLCacheHandle *lut3d_handle = cacheSearch(state->lut3d_cache, lut3d_cache_id);
517 /* We cannot keep more than one cache for curvemap because their cache id is a pointer.
518 * The pointer cannot be the same for one update but can be the same after a second update. */
519 OCIO_GLSLCacheHandle *curvemap_handle = &state->curvemap_cache[0];
520
521 OCIO_GLSLShader **shader_ptr = (OCIO_GLSLShader **)&shader_handle->data;
522 OCIO_GLSLLut3d **lut3d_ptr = (OCIO_GLSLLut3d **)&lut3d_handle->data;
523 OCIO_GLSLCurveMappping **curvemap_ptr = (OCIO_GLSLCurveMappping **)&curvemap_handle->data;
524
525 ensureGLSLShader(
526 shader_ptr, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, shaderCacheID);
527 ensureGLSLLut3d(
528 lut3d_ptr, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, shaderCacheID);
529 ensureGLSLCurveMapping(curvemap_ptr, curve_mapping_settings);
530
531 OCIO_GLSLShader *shader = (OCIO_GLSLShader *)shader_handle->data;
532 OCIO_GLSLLut3d *shader_lut = (OCIO_GLSLLut3d *)lut3d_handle->data;
533 OCIO_GLSLCurveMappping *shader_curvemap = (OCIO_GLSLCurveMappping *)curvemap_handle->data;
534
535 updateGLSLShader(
536 shader, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, shaderCacheID);
537 updateGLSLLut3d(
538 shader_lut, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, lut3dCacheID);
539 updateGLSLCurveMapping(shader_curvemap, curve_mapping_settings, curvemap_cache_id);
540
541 /* Update handles cache keys. */
542 shader_handle->cache_id = shader_cache_id;
543 lut3d_handle->cache_id = lut3d_cache_id;
544 curvemap_handle->cache_id = curvemap_cache_id;
545
546 if (shader->valid && shader_lut->valid && shader_curvemap->valid) {
547 /* Bind textures to sampler units. Texture 0 is set by caller.
548 * Uniforms have already been set for texture bind points.*/
549
550 if (!use_overlay) {
551 /* Avoid missing binds. */
552 GPU_texture_bind(shader_lut->texture_dummy, 1);
553 }
554 GPU_texture_bind(shader_lut->texture, 2);
555 GPU_texture_bind(shader_lut->texture_display, 3);
556 GPU_texture_bind(shader_curvemap->texture, 4);
557
558 /* Bind UBO. */
559 GPU_uniformbuf_bind(shader_curvemap->buffer, shader->ubo_bind);
560
561 /* TODO(fclem): remove remains of IMM. */
562 immBindShader(shader->shader);
563
564 /* Bind Shader and set uniforms. */
565 // GPU_shader_bind(shader->shader);
566 GPU_shader_uniform_float(shader->shader, shader->dither_loc, dither);
567 GPU_shader_uniform_int(shader->shader, shader->overlay_loc, use_overlay);
568 GPU_shader_uniform_int(shader->shader, shader->predivide_loc, use_predivide);
569 GPU_shader_uniform_int(shader->shader, shader->curve_mapping_loc, use_curve_mapping);
570
571 return true;
572 }
573
574 return false;
575 }
576
finishGLSLDraw(OCIO_GLSLDrawState *)577 void OCIOImpl::finishGLSLDraw(OCIO_GLSLDrawState * /*state*/)
578 {
579 immUnbindProgram();
580 }
581
freeGLState(OCIO_GLSLDrawState * state)582 void OCIOImpl::freeGLState(OCIO_GLSLDrawState *state)
583 {
584 for (int i = 0; i < SHADER_CACHE_SIZE; i++) {
585 if (state->shader_cache[i].data) {
586 freeGLSLShader((OCIO_GLSLShader *)state->shader_cache[i].data);
587 }
588 if (state->lut3d_cache[i].data) {
589 freeGLSLLut3d((OCIO_GLSLLut3d *)state->lut3d_cache[i].data);
590 }
591 if (state->curvemap_cache[i].data) {
592 freeGLSLCurveMapping((OCIO_GLSLCurveMappping *)state->curvemap_cache[i].data);
593 }
594 }
595
596 MEM_freeN(state);
597 }
598
599 /** \} */
600