Fix T37810: GLSL dither shader not working on OS X.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 14 Dec 2013 14:24:20 +0000 (15:24 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 14 Dec 2013 15:01:48 +0000 (16:01 +0100)
The GLSL function textureSize() is not supported here, only when we start using
OpenGL core profile will this work. For now check the supported GLSL version and
use a somewhat slower replacement.

intern/opencolorio/gpu_shader_display_transform.glsl
intern/opencolorio/ocio_impl_glsl.cc

index 8a85d6cbffe8b22ab31b9803747535533f8050d4..5921d6d9c73ff45605304b6764efe1356a278d11 100644 (file)
@@ -1,11 +1,15 @@
 uniform sampler2D image_texture;
 uniform sampler3D lut3d_texture;
-uniform bool predivide;
 
 #ifdef USE_DITHER
 uniform float dither;
 #endif
 
+#ifdef USE_TEXTURE_SIZE
+uniform float image_texture_width;
+uniform float image_texture_height;
+#endif
+
 #ifdef USE_CURVE_MAPPING
 /* Curve mapping parameters
  *
@@ -115,7 +119,11 @@ float dither_random_value(vec2 co)
 vec2 round_to_pixel(vec2 st)
 {
        vec2 result;
+#ifdef USE_TEXTURE_SIZE
+       vec2 size = vec2(image_texture_width, image_texture_height);
+#else
        vec2 size = textureSize(image_texture, 0);
+#endif
        result.x = float(int(st.x * size.x)) / size.x;
        result.y = float(int(st.y * size.y)) / size.y;
        return result;
@@ -139,12 +147,15 @@ void main()
 #ifdef USE_CURVE_MAPPING
        col = curvemapping_evaluate_premulRGBF(col);
 #endif
-       if (predivide && col[3] > 0.0 && col[3] < 1.0) {
+
+#ifdef USE_PREDIVIDE
+       if (col[3] > 0.0 && col[3] < 1.0) {
                float inv_alpha = 1.0 / col[3];
                col[0] *= inv_alpha;
                col[1] *= inv_alpha;
                col[2] *= inv_alpha;
        }
+#endif
 
        /* NOTE: This is true we only do de-premul here and NO premul
         *       and the reason is simple -- opengl is always configured
index 3a23c26634533edaea119416ab2d4b23e399d24f..677be0bf9ed93e206c1a703a4626980690053936 100644 (file)
@@ -71,6 +71,10 @@ typedef struct OCIO_GLSLDrawState {
        GLuint curve_mapping_texture;
        size_t curve_mapping_cache_id;
 
+       bool predivide_used;
+
+       bool texture_size_used;
+
        /* Cache */
        std::string lut3dcacheid;
        std::string shadercacheid;
@@ -221,6 +225,17 @@ bool OCIOImpl::supportGLSLDraw()
        return GLEW_VERSION_2_0 && (GLEW_VERSION_3_0 || GLEW_ARB_texture_float);
 }
 
+static bool supportGLSL13()
+{
+       const char *version = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
+       int major = 1, minor = 0;
+
+       if (version && sscanf(version, "%d.%d", &major, &minor) == 2)
+               return (major > 1 || (major == 1 && minor >= 30));
+
+       return false;
+}
+
 /**
  * Setup OpenGL contexts for a transform defined by processor using GLSL
  * All LUT allocating baking and shader compilation happens here.
@@ -233,7 +248,7 @@ bool OCIOImpl::supportGLSLDraw()
  */
 bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
                              OCIO_CurveMappingSettings *curve_mapping_settings,
-                             float dither, bool predivide)
+                             float dither, bool use_predivide)
 {
        ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *) processor;
        bool use_curve_mapping = curve_mapping_settings != NULL;
@@ -302,6 +317,7 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
        std::string shaderCacheID = ocio_processor->getGpuShaderTextCacheID(shaderDesc);
        if (state->program == 0 ||
            shaderCacheID != state->shadercacheid ||
+           use_predivide != state->predivide_used ||
            use_curve_mapping != state->curve_mapping_used ||
            use_dither != state->dither_used)
        {
@@ -317,7 +333,17 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
 
                std::ostringstream os;
 
-               os << "#version 130\n";
+               if (supportGLSL13()) {
+                       os << "#version 130\n";
+               }
+               else {
+                       os << "#define USE_TEXTURE_SIZE\n";
+                       state->texture_size_used = use_dither;
+               }
+
+               if (use_predivide) {
+                       os << "#define USE_PREDIVIDE\n";
+               }
 
                if (use_dither) {
                        os << "#define USE_DITHER\n";
@@ -338,6 +364,7 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
 
                state->curve_mapping_used = use_curve_mapping;
                state->dither_used = use_dither;
+               state->predivide_used = use_predivide;
        }
 
        if (state->program) {
@@ -355,7 +382,18 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
 
                glUniform1i(glGetUniformLocation(state->program, "image_texture"), 0);
                glUniform1i(glGetUniformLocation(state->program, "lut3d_texture"), 1);
-               glUniform1i(glGetUniformLocation(state->program, "predivide"), predivide);
+
+               if (state->texture_size_used) {
+                       /* we use textureSize() if possible for best performance, if not
+                        * supported we query the size and pass it as uniform variables */
+                       GLint width, height;
+
+                       glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
+                       glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
+
+                       glUniform1f(glGetUniformLocation(state->program, "image_texture_width"), (float)width);
+                       glUniform1f(glGetUniformLocation(state->program, "image_texture_height"), (float)height);
+               }
 
                if (use_dither) {
                        glUniform1f(glGetUniformLocation(state->program, "dither"), dither);