/* * Adapted from OpenColorIO with this license: * * Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al. * All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Sony Pictures Imageworks nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Modifications Copyright 2013, Blender Foundation. */ #include #include #include #include "glew-mx.h" #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable : 4251 4275) #endif #include #ifdef _MSC_VER # pragma warning(pop) #endif extern "C" { #include "GPU_immediate.h" } using namespace OCIO_NAMESPACE; #include "MEM_guardedalloc.h" #include "ocio_impl.h" static const int LUT3D_EDGE_SIZE = 64; static const int LUT3D_TEXTURE_SIZE = sizeof(float) * 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE; static const int SHADER_CACHE_SIZE = 4; #define UBO_BIND_LOC 0 extern "C" char datatoc_gpu_shader_display_transform_glsl[]; extern "C" char datatoc_gpu_shader_display_transform_vertex_glsl[]; /* **** OpenGL drawing routines using GLSL for color space transform ***** */ /* Curve mapping parameters * * See documentation for OCIO_CurveMappingSettings to get fields descriptions. * (this ones pretty much copies stuff from C structure.) */ struct OCIO_GLSLCurveMappingParameters { float curve_mapping_mintable[4]; float curve_mapping_range[4]; float curve_mapping_ext_in_x[4]; float curve_mapping_ext_in_y[4]; float curve_mapping_ext_out_x[4]; float curve_mapping_ext_out_y[4]; float curve_mapping_first_x[4]; float curve_mapping_first_y[4]; float curve_mapping_last_x[4]; float curve_mapping_last_y[4]; float curve_mapping_black[4]; float curve_mapping_bwmul[4]; int curve_mapping_lut_size; int curve_mapping_use_extend_extrapolate; int _pad[2]; /** WARNING: Needs to be 16byte aligned. Used as UBO data. */ }; struct OCIO_GLSLShader { /** Cache IDs */ std::string cacheId; /** TODO(fclem): Remove. IMM shader interface. */ struct GPUShaderInterface *interface; /** OpenGL Shader objects handles. */ GLuint frag; GLuint vert; GLuint program; /** Uniform locations. */ GLint dither_loc; GLint overlay_loc; GLint overlay_tex_loc; GLint predivide_loc; GLint curve_mapping_loc; /** Error checking. */ bool valid; }; struct OCIO_GLSLLut3d { /** Cache IDs */ std::string cacheId; /** OpenGL Texture handles. 0 if not allocated. */ GLuint texture; GLuint texture_display; /** Error checking. */ bool valid; }; struct OCIO_GLSLCurveMappping { /** Cache IDs */ size_t cacheId; /** OpenGL Uniform Buffer handle. 0 if not allocated. */ GLuint buffer; /** OpenGL Texture handles. 0 if not allocated. */ GLuint texture; /** Error checking. */ bool valid; }; struct OCIO_GLSLCacheHandle { size_t cache_id; void *data; }; struct OCIO_GLSLDrawState { /* Shader Cache */ OCIO_GLSLCacheHandle shader_cache[SHADER_CACHE_SIZE]; OCIO_GLSLCacheHandle lut3d_cache[SHADER_CACHE_SIZE]; OCIO_GLSLCacheHandle curvemap_cache[SHADER_CACHE_SIZE]; }; static OCIO_GLSLDrawState *allocateOpenGLState(void) { return (OCIO_GLSLDrawState *)MEM_callocN(sizeof(OCIO_GLSLDrawState), "OCIO OpenGL State struct"); } /* -------------------------------------------------------------------- */ /** \name Shader * \{ */ static GLuint compileShaderText(GLenum shader_type, const char *text) { GLuint shader; GLint stat; shader = glCreateShader(shader_type); glShaderSource(shader, 1, (const GLchar **)&text, NULL); glCompileShader(shader); glGetShaderiv(shader, GL_COMPILE_STATUS, &stat); if (!stat) { GLchar log[1000]; GLsizei len; glGetShaderInfoLog(shader, 1000, &len, log); fprintf(stderr, "Shader compile error:\n%s\n", log); return 0; } return shader; } static GLuint linkShaders(GLuint frag, GLuint vert) { if (!frag || !vert) { return 0; } GLuint program = glCreateProgram(); glAttachShader(program, frag); glAttachShader(program, vert); glLinkProgram(program); /* check link */ { GLint stat; glGetProgramiv(program, GL_LINK_STATUS, &stat); if (!stat) { GLchar log[1000]; GLsizei len; glGetProgramInfoLog(program, 1000, &len, log); fprintf(stderr, "Shader link error:\n%s\n", log); return 0; } } return program; } static void updateGLSLShader(OCIO_GLSLShader *shader, ConstProcessorRcPtr *processor_scene_to_ui, ConstProcessorRcPtr *processpr_ui_to_display, GpuShaderDesc *shader_desc, const std::string &cache_id) { if (shader->cacheId == cache_id) { return; } /* Delete any previous shader. */ glDeleteProgram(shader->program); glDeleteShader(shader->frag); glDeleteShader(shader->vert); if (shader->interface) { GPU_shaderinterface_discard(shader->interface); } { /* Vertex shader */ std::ostringstream osv; osv << "#version 330\n"; osv << datatoc_gpu_shader_display_transform_vertex_glsl; shader->vert = compileShaderText(GL_VERTEX_SHADER, osv.str().c_str()); } { /* Fragment shader */ std::ostringstream os; os << "#version 330\n"; /* Work around OpenColorIO not supporting latest GLSL yet. */ os << "#define texture2D texture\n"; os << "#define texture3D texture\n"; shader_desc->setFunctionName("OCIO_to_display_linear_with_look"); os << (*processor_scene_to_ui)->getGpuShaderText(*shader_desc) << "\n"; shader_desc->setFunctionName("OCIO_to_display_encoded"); os << (*processpr_ui_to_display)->getGpuShaderText(*shader_desc) << "\n"; os << datatoc_gpu_shader_display_transform_glsl; shader->frag = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str()); } /* shader_Program */ if (shader->frag && shader->vert) { shader->program = linkShaders(shader->frag, shader->vert); } if (shader->program) { shader->dither_loc = glGetUniformLocation(shader->program, "dither"); shader->overlay_tex_loc = glGetUniformLocation(shader->program, "overlay_texture"); shader->overlay_loc = glGetUniformLocation(shader->program, "overlay"); shader->predivide_loc = glGetUniformLocation(shader->program, "predivide"); shader->curve_mapping_loc = glGetUniformLocation(shader->program, "curve_mapping"); glUseProgram(shader->program); /* Set texture bind point uniform once. This is saved by the shader. */ glUniform1i(glGetUniformLocation(shader->program, "image_texture"), 0); glUniform1i(glGetUniformLocation(shader->program, "lut3d_texture"), 2); glUniform1i(glGetUniformLocation(shader->program, "lut3d_display_texture"), 3); glUniform1i(glGetUniformLocation(shader->program, "curve_mapping_texture"), 4); /* Set UBO binding location. */ GLuint index = glGetUniformBlockIndex(shader->program, "OCIO_GLSLCurveMappingParameters"); glUniformBlockBinding(shader->program, index, UBO_BIND_LOC); /* TODO(fclem) Remove this. Make caller always assume viewport space and * specify texco via vertex attribs. */ shader->interface = GPU_shaderinterface_create(shader->program); } shader->cacheId = cache_id; shader->valid = (shader->program != 0); } static void ensureGLSLShader(OCIO_GLSLShader **shader_ptr, ConstProcessorRcPtr *processor_scene_to_ui, ConstProcessorRcPtr *processpr_ui_to_display, GpuShaderDesc *shader_desc, const std::string &cache_id) { if (*shader_ptr != NULL) { return; } OCIO_GLSLShader *shader = OBJECT_GUARDED_NEW(OCIO_GLSLShader); updateGLSLShader(shader, processor_scene_to_ui, processpr_ui_to_display, shader_desc, cache_id); *shader_ptr = shader; } static void freeGLSLShader(OCIO_GLSLShader *shader) { glDeleteProgram(shader->program); glDeleteShader(shader->frag); glDeleteShader(shader->vert); if (shader->interface) { GPU_shaderinterface_discard(shader->interface); } OBJECT_GUARDED_DELETE(shader, OCIO_GLSLShader); } /** \} */ /* -------------------------------------------------------------------- */ /** \name Lut3D * \{ */ static void updateGLSLLut3d(OCIO_GLSLLut3d *lut3d, ConstProcessorRcPtr *processor_scene_to_ui, ConstProcessorRcPtr *processpr_ui_to_display, GpuShaderDesc *shader_desc, const std::string &cache_id) { if (lut3d->cacheId == cache_id) return; float *lut_data = (float *)MEM_mallocN(LUT3D_TEXTURE_SIZE, __func__); ConstProcessorRcPtr *ocio_processors[2] = {processor_scene_to_ui, processpr_ui_to_display}; for (int i = 0; i < 2; i++) { ConstProcessorRcPtr *processor = ocio_processors[i]; GLuint texture = (&lut3d->texture)[i]; (*processor)->getGpuLut3D(lut_data, *shader_desc); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_3D, texture); glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, GL_RGB, GL_FLOAT, lut_data); } MEM_freeN(lut_data); lut3d->cacheId = cache_id; } static void ensureGLSLLut3d(OCIO_GLSLLut3d **lut3d_ptr, ConstProcessorRcPtr *processor_scene_to_ui, ConstProcessorRcPtr *processpr_ui_to_display, GpuShaderDesc *shaderDesc, const std::string &cache_id) { if (*lut3d_ptr != NULL) { return; } OCIO_GLSLLut3d *lut3d = OBJECT_GUARDED_NEW(OCIO_GLSLLut3d); glGenTextures(3, &lut3d->texture); for (int i = 0; i < 2; i++) { GLuint texture = (&lut3d->texture)[i]; glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_3D, texture); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16F, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, 0, GL_RGB, GL_FLOAT, NULL); } updateGLSLLut3d(lut3d, processor_scene_to_ui, processpr_ui_to_display, shaderDesc, cache_id); lut3d->valid = (lut3d->texture != 0); *lut3d_ptr = lut3d; } static void freeGLSLLut3d(OCIO_GLSLLut3d *lut3d) { glDeleteTextures(1, &lut3d->texture); OBJECT_GUARDED_DELETE(lut3d, OCIO_GLSLLut3d); } /** \} */ /* -------------------------------------------------------------------- */ /** \name Curve Mapping * \{ */ static void allocateCurveMappingTexture(OCIO_GLSLCurveMappping *curvemap, OCIO_CurveMappingSettings *curve_mapping_settings) { glGenTextures(1, &curvemap->texture); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_1D, curvemap->texture); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); /* Do not initialize. Only if used. */ int lut_size = curve_mapping_settings ? curve_mapping_settings->lut_size : 1; glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16F, lut_size, 0, GL_RGBA, GL_FLOAT, NULL); } /* curve_mapping_settings can be null. In this case we alloc a dummy curvemap. */ static void ensureGLSLCurveMapping(OCIO_GLSLCurveMappping **curvemap_ptr, OCIO_CurveMappingSettings *curve_mapping_settings) { if (*curvemap_ptr != NULL) { return; } OCIO_GLSLCurveMappping *curvemap = OBJECT_GUARDED_NEW(OCIO_GLSLCurveMappping); /* Texture. */ allocateCurveMappingTexture(curvemap, curve_mapping_settings); /* Uniform buffer object. */ glGenBuffers(1, &curvemap->buffer); glBindBuffer(GL_UNIFORM_BUFFER, curvemap->buffer); glBufferData(GL_UNIFORM_BUFFER, sizeof(OCIO_GLSLCurveMappingParameters), 0, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); curvemap->valid = (curvemap->texture != 0); curvemap->cacheId = 0; *curvemap_ptr = curvemap; } static void freeGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap) { glDeleteTextures(1, &curvemap->texture); glDeleteBuffers(1, &curvemap->buffer); OBJECT_GUARDED_DELETE(curvemap, OCIO_GLSLCurveMappping); } static void updateGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap, OCIO_CurveMappingSettings *curve_mapping_settings, size_t cacheId) { /* No need to continue if curvemapping is not used. Just use whatever is in this cache. */ if (curve_mapping_settings == NULL) return; if (curvemap->cacheId == cacheId) return; if (curvemap->cacheId == 0) { /* This cache was previously used as dummy. Recreate the texture. */ glDeleteTextures(1, &curvemap->texture); allocateCurveMappingTexture(curvemap, curve_mapping_settings); } /* Update texture. */ glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_1D, curvemap->texture); glTexSubImage1D(GL_TEXTURE_1D, 0, 0, curve_mapping_settings->lut_size, GL_RGBA, GL_FLOAT, curve_mapping_settings->lut); /* Update uniforms. */ OCIO_GLSLCurveMappingParameters data; for (int i = 0; i < 4; i++) { data.curve_mapping_range[i] = curve_mapping_settings->range[i]; data.curve_mapping_mintable[i] = curve_mapping_settings->mintable[i]; data.curve_mapping_ext_in_x[i] = curve_mapping_settings->ext_in_x[i]; data.curve_mapping_ext_in_y[i] = curve_mapping_settings->ext_in_y[i]; data.curve_mapping_ext_out_x[i] = curve_mapping_settings->ext_out_x[i]; data.curve_mapping_ext_out_y[i] = curve_mapping_settings->ext_out_y[i]; data.curve_mapping_first_x[i] = curve_mapping_settings->first_x[i]; data.curve_mapping_first_y[i] = curve_mapping_settings->first_y[i]; data.curve_mapping_last_x[i] = curve_mapping_settings->last_x[i]; data.curve_mapping_last_y[i] = curve_mapping_settings->last_y[i]; } for (int i = 0; i < 3; i++) { data.curve_mapping_black[i] = curve_mapping_settings->black[i]; data.curve_mapping_bwmul[i] = curve_mapping_settings->bwmul[i]; } data.curve_mapping_lut_size = curve_mapping_settings->lut_size; data.curve_mapping_use_extend_extrapolate = curve_mapping_settings->use_extend_extrapolate; glBindBuffer(GL_UNIFORM_BUFFER, curvemap->buffer); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(OCIO_GLSLCurveMappingParameters), &data); glBindBuffer(GL_UNIFORM_BUFFER, 0); curvemap->cacheId = cacheId; } /** \} */ /* -------------------------------------------------------------------- */ /** \name LRU cache * \{ */ static size_t hash_string(const char *str) { size_t i = 0, c; while ((c = *str++)) { i = i * 37 + c; } return i; } static OCIO_GLSLCacheHandle *cacheSearch(OCIO_GLSLCacheHandle cache[SHADER_CACHE_SIZE], size_t cache_id) { OCIO_GLSLCacheHandle *cached_item = &cache[0]; for (int i = 0; i < SHADER_CACHE_SIZE; i++, cached_item++) { if (cached_item->data == NULL) { continue; } else if (cached_item->cache_id == cache_id) { /* LRU cache, so move to front. */ OCIO_GLSLCacheHandle found_item = *cached_item; for (int j = i; j > 0; j--) { cache[j] = cache[j - 1]; } cache[0] = found_item; return &cache[0]; } } /* LRU cache, shift other items back so we can insert at the front. */ OCIO_GLSLCacheHandle last_item = cache[SHADER_CACHE_SIZE - 1]; for (int j = SHADER_CACHE_SIZE - 1; j > 0; j--) { cache[j] = cache[j - 1]; } /* Copy last to front and let the caller initialize it. */ cache[0] = last_item; return &cache[0]; } /** \} */ /* -------------------------------------------------------------------- */ /** \name OCIO GLSL Implementation * \{ */ /* Detect if we can support GLSL drawing */ bool OCIOImpl::supportGLSLDraw() { /* Minimum supported version 3.3 does meet all requirements. */ return true; } /** * Setup OpenGL contexts for a transform defined by processor using GLSL * All LUT allocating baking and shader compilation happens here. * * Once this function is called, callee could start drawing images * using regular 2D texture. * * When all drawing is finished, finishGLSLDraw shall be called to * restore OpenGL context to it's pre-GLSL draw state. */ bool OCIOImpl::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) { ConstProcessorRcPtr processor_scene_to_ui = *(ConstProcessorRcPtr *)ocio_processor_scene_to_ui; ConstProcessorRcPtr processpr_ui_to_display = *( ConstProcessorRcPtr *)ocio_processor_ui_to_display; bool use_curve_mapping = curve_mapping_settings != NULL; if (!processor_scene_to_ui || !processor_scene_to_ui) { return false; } /* Create state if needed. */ OCIO_GLSLDrawState *state; if (!*state_r) *state_r = allocateOpenGLState(); state = *state_r; /* Compute cache IDs. */ GpuShaderDesc shaderDesc; shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_3); shaderDesc.setFunctionName("OCIODisplay"); shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE); const char *shader_cache_str = processor_scene_to_ui->getGpuShaderTextCacheID(shaderDesc); const char *lut3d_cache_str = processor_scene_to_ui->getGpuLut3DCacheID(shaderDesc); /* Used for comparison. */ std::string shaderCacheID = shader_cache_str; std::string lut3dCacheID = lut3d_cache_str; size_t shader_cache_id = hash_string(shader_cache_str); size_t lut3d_cache_id = hash_string(lut3d_cache_str); size_t curvemap_cache_id = curve_mapping_settings ? curve_mapping_settings->cache_id : 0; OCIO_GLSLCacheHandle *shader_handle = cacheSearch(state->shader_cache, shader_cache_id); OCIO_GLSLCacheHandle *lut3d_handle = cacheSearch(state->lut3d_cache, lut3d_cache_id); /* We cannot keep more than one cache for curvemap because their cache id is a pointer. * The pointer cannot be the same for one update but can be the same after a second update. */ OCIO_GLSLCacheHandle *curvemap_handle = &state->curvemap_cache[0]; OCIO_GLSLShader **shader_ptr = (OCIO_GLSLShader **)&shader_handle->data; OCIO_GLSLLut3d **lut3d_ptr = (OCIO_GLSLLut3d **)&lut3d_handle->data; OCIO_GLSLCurveMappping **curvemap_ptr = (OCIO_GLSLCurveMappping **)&curvemap_handle->data; ensureGLSLShader( shader_ptr, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, shaderCacheID); ensureGLSLLut3d( lut3d_ptr, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, shaderCacheID); ensureGLSLCurveMapping(curvemap_ptr, curve_mapping_settings); OCIO_GLSLShader *shader = (OCIO_GLSLShader *)shader_handle->data; OCIO_GLSLLut3d *shader_lut = (OCIO_GLSLLut3d *)lut3d_handle->data; OCIO_GLSLCurveMappping *shader_curvemap = (OCIO_GLSLCurveMappping *)curvemap_handle->data; updateGLSLShader( shader, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, shaderCacheID); updateGLSLLut3d( shader_lut, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, lut3dCacheID); updateGLSLCurveMapping(shader_curvemap, curve_mapping_settings, curvemap_cache_id); /* Update handles cache keys. */ shader_handle->cache_id = shader_cache_id; lut3d_handle->cache_id = lut3d_cache_id; curvemap_handle->cache_id = curvemap_cache_id; if (shader->valid && shader_lut->valid && shader_curvemap->valid) { /* Bind textures to sampler units. Texture 0 is set by caller. * Uniforms have already been set for texture bind points.*/ glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_3D, shader_lut->texture); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_3D, shader_lut->texture_display); glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_1D, shader_curvemap->texture); glActiveTexture(GL_TEXTURE0); /* Bind UBO. */ glBindBufferBase(GL_UNIFORM_BUFFER, 0, shader_curvemap->buffer); /* TODO(fclem) remove remains of IMM. */ immBindProgram(shader->program, shader->interface); /* Bind Shader and set uniforms. */ // glUseProgram(shader->program); glUniform1f(shader->dither_loc, dither); glUniform1i(shader->overlay_tex_loc, use_overlay ? 1 : 0); glUniform1i(shader->overlay_loc, use_overlay); glUniform1i(shader->predivide_loc, use_predivide); glUniform1i(shader->curve_mapping_loc, use_curve_mapping); return true; } return false; } void OCIOImpl::finishGLSLDraw(OCIO_GLSLDrawState * /*state*/) { immUnbindProgram(); } void OCIOImpl::freeGLState(OCIO_GLSLDrawState *state) { for (int i = 0; i < SHADER_CACHE_SIZE; i++) { if (state->shader_cache[i].data) { freeGLSLShader((OCIO_GLSLShader *)state->shader_cache[i].data); } if (state->lut3d_cache[i].data) { freeGLSLLut3d((OCIO_GLSLLut3d *)state->lut3d_cache[i].data); } if (state->curvemap_cache[i].data) { freeGLSLCurveMapping((OCIO_GLSLCurveMappping *)state->curvemap_cache[i].data); } } MEM_freeN(state); } /** \} */