Implement GPU-side display transform for clip editor
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 29 Mar 2013 16:02:27 +0000 (16:02 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 29 Mar 2013 16:02:27 +0000 (16:02 +0000)
Implemented using GLSL API from OpenColorIO library and
some general functions were added to it's c-api:

- OCIO_setupGLSLDraw prepares OpenGL context for GPU-based
  transformation for a giver processor.

  This function compiles and links shader, sets  up it's
  argument. After this transformation would be applied
  on an image displaying as a 2D texture.

  So, glaDrawPixelsTex called after OCIO_setupGLSLDraw will
  do a proper color space transform.

- OCIO_finishGLSLDraw restores OpenGL context after all
  color-managed display is over.

- OCIO_freeOGLState frees allocated state structure used
  for cacheing some GLSL-related stuff.

There're some utility functions in IMB_colormanagent which
are basically proxies to lower level OCIO functions but
which could be used from any place in blender.

Chacheing of movie clip frame on GPU is also removed now,
and either glaDrawPixelsTex or glaDrawPixelsAuto are used
for display now. This is so no code duplication happens
now and no large textures are lurking around in GPU memory.

Known issues:
- Texture buffer and GLSL are no longer checking for
  video card capabilities, possibly could lead to some
  artifacts on crappy drivers/cards.

- Only float buffers are displaying using GLSL, byte
  buffers will still use fallback display method.

  This is to be addressed later.

- If RGB curves are used as a part of display transform,
  GLSL display will also be disabled. This is also thing
  to be solved later.

Additional changes:

- glaDrawPixelsTexScaled will now use RGBA16F as an
  internal format of storing textures when it's used
  to draw float buffer. This is needed so LUT are
  applied without precision loss.

17 files changed:
intern/opencolorio/CMakeLists.txt
intern/opencolorio/SConscript
intern/opencolorio/fallback_impl.cc
intern/opencolorio/ocio_capi.cc
intern/opencolorio/ocio_capi.h
intern/opencolorio/ocio_impl.cc
intern/opencolorio/ocio_impl.h
intern/opencolorio/ocio_impl_glsl.cc [new file with mode: 0644]
source/blender/blenloader/intern/readfile.c
source/blender/editors/include/ED_clip.h
source/blender/editors/screen/glutil.c
source/blender/editors/space_clip/clip_draw.c
source/blender/editors/space_clip/clip_editor.c
source/blender/editors/space_clip/space_clip.c
source/blender/imbuf/IMB_colormanagement.h
source/blender/imbuf/intern/colormanagement.c
source/blender/makesdna/DNA_space_types.h

index c281a6e7bbb30818a9a653b86fa4896632a10cb0..91bf6550f276b5ba7146fd2938de888885e069c5 100644 (file)
@@ -52,6 +52,7 @@ if(WITH_OPENCOLORIO)
 
        list(APPEND SRC
                ocio_impl.cc
+               ocio_impl_glsl.cc
        )
 
        if(WIN32 AND NOT MINGW)
index 6e7c467f64f8914225d99bbbc6b6fea63c67da4c..e4a0d3ebb7cc97690fe4b80ab78c4ace9e1eeb29 100644 (file)
@@ -40,5 +40,6 @@ if env['WITH_BF_OCIO']:
         incs += ' ' + env['BF_BOOST_INC']
 else:
     sources.remove('ocio_impl.cc')
+    sources.remove('ocio_impl_glsl.cc')
 
 env.BlenderLib( 'bf_intern_opencolorio', sources, Split(incs), defs, libtype=['extern','player'], priority=[10, 185])
index d01d8d4c8f4c46b9ef8a312899868f2ba3774f98..47c648e9cbab4e079533366ce39bef42ea18950f 100644 (file)
@@ -380,3 +380,15 @@ void FallbackImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr *)
 void FallbackImpl::matrixTransformScale(float * , float * , const float *)
 {
 }
+
+void FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor)
+{
+}
+
+void FallbackImpl::finishGLSLDraw(OCIO_GLSLDrawState *state)
+{
+}
+
+void FallbackImpl::freeGLState(struct OCIO_GLSLDrawState *state_r)
+{
+}
index 4f839a61fadd94c9692c12df777a4d87588bcd57..73d8af295f20053ac8753f2d086236c2d26fdf18 100644 (file)
@@ -282,3 +282,18 @@ void OCIO_matrixTransformScale(float * m44, float * offset4, const float *scale4
 {
        impl->matrixTransformScale(m44, offset4, scale4f);
 }
+
+void OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor)
+{
+       impl->setupGLSLDraw(state_r, processor);
+}
+
+void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state)
+{
+       impl->finishGLSLDraw(state);
+}
+
+void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state)
+{
+       impl->freeGLState(state);
+}
index 19fd8fe643becc83090e0517973d072d3501f80c..3c42e0a1a1e7524f60ae466d1f858880e3055a9f 100644 (file)
@@ -32,6 +32,8 @@
 extern "C" {
 #endif
 
+struct OCIO_GLSLDrawState;
+
 #define OCIO_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
 
 #define OCIO_ROLE_SCENE_LINEAR       "scene_linear"
@@ -119,6 +121,10 @@ void OCIO_matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt);
 
 void OCIO_matrixTransformScale(float * m44, float * offset4, const float * scale4);
 
+void OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor);
+void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state);
+void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state);
+
 #ifdef __cplusplus
 }
 #endif
index b073a038f0d4abb08f9d386946009bf094eb5a1e..8803814ce3f979c5853532df44d9c6fcb2176da0 100644 (file)
  */
 
 #include <iostream>
+#include <sstream>
 #include <string.h>
 
+#ifdef __APPLE__
+#include <OpenGL/gl.h>
+#include <OpenGL/glu.h>
+#else
+#include <GL/glew.h>
+#endif
+
 #include <OpenColorIO/OpenColorIO.h>
 
 using namespace OCIO_NAMESPACE;
@@ -50,6 +58,8 @@ using namespace OCIO_NAMESPACE;
 #define MEM_NEW(type) new(MEM_mallocN(sizeof(type), __func__)) type()
 #define MEM_DELETE(what, type) if(what) { ((type*)(what))->~type(); MEM_freeN(what); } (void)0
 
+static const int LUT3D_EDGE_SIZE = 32;
+
 static void OCIO_reportError(const char *err)
 {
        std::cerr << "OpenColorIO Error: " << err << std::endl;
@@ -541,3 +551,228 @@ void OCIOImpl::matrixTransformScale(float * m44, float * offset4, const float *s
 {
        MatrixTransform::Scale(m44, offset4, scale4f);
 }
+
+/* **** OpenGL drawing routines using GLSL for color space transform ***** */
+
+/* Some of the GLSL transform related functions below are adopted from
+ * ociodisplay utility of OpenColorIO project which are originally
+ *
+ * Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
+ */
+
+typedef struct OCIO_GLSLDrawState {
+       bool lut3d_texture_allocated;  /* boolean flag indicating whether
+                                                                       * lut texture is allocated
+                                                                       */
+
+       GLuint lut3d_texture;  /* OGL texture ID for 3D LUT */
+
+       float *lut3d;  /* 3D LUT table */
+
+       /* Cache */
+       std::string lut3dcacheid;
+       std::string shadercacheid;
+
+       /* GLSL stuff */
+       GLuint fragShader;
+       GLuint program;
+
+       /* Previous OpenGL state. */
+       GLint last_texture, last_texture_unit;
+} OCIO_GLSLDrawState;
+
+static const char * g_fragShaderText = ""
+"\n"
+"uniform sampler2D tex1;\n"
+"uniform sampler3D tex2;\n"
+"\n"
+"void main()\n"
+"{\n"
+"    vec4 col = texture2D(tex1, gl_TexCoord[0].st);\n"
+"    gl_FragColor = OCIODisplay(col, tex2);\n"
+"}\n";
+
+static GLuint compileShaderText(GLenum shaderType, const char *text)
+{
+       GLuint shader;
+       GLint stat;
+
+       shader = glCreateShader(shaderType);
+       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);
+               return 0;
+       }
+
+       return shader;
+}
+
+static GLuint linkShaders(GLuint fragShader)
+{
+       if (!fragShader)
+               return 0;
+
+       GLuint program = glCreateProgram();
+
+       if (fragShader)
+               glAttachShader(program, fragShader);
+
+       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 OCIO_GLSLDrawState *allocateOpenGLState(void)
+{
+       OCIO_GLSLDrawState *state;
+
+       /* Allocate memory for state. */
+       state = (OCIO_GLSLDrawState *) MEM_callocN(sizeof(OCIO_GLSLDrawState),
+                                                    "OCIO OpenGL State struct");
+
+       /* Call constructors on new memory. */
+       new (&state->lut3dcacheid) std::string("");
+       new (&state->shadercacheid) std::string("");
+
+       return state;
+}
+
+/* Ensure LUT texture and array are allocated */
+static void ensureLUT3DAllocated(OCIO_GLSLDrawState *state)
+{
+       int num_3d_entries = 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE;
+
+       if (state->lut3d_texture_allocated)
+               return;
+
+       glGenTextures(1, &state->lut3d_texture);
+
+       state->lut3d = (float *) MEM_callocN(sizeof(float) * num_3d_entries, "OCIO GPU 3D LUT");
+
+    glActiveTexture(GL_TEXTURE1);
+       glBindTexture(GL_TEXTURE_3D, state->lut3d_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_ARB,
+                    LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
+                    0, GL_RGB,GL_FLOAT, &state->lut3d);
+
+       state->lut3d_texture_allocated = 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.
+ */
+void OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor)
+{
+       ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *) processor;
+
+       /* Create state if needed. */
+       OCIO_GLSLDrawState *state;
+       if (!*state_r)
+               *state_r = allocateOpenGLState();
+       state = *state_r;
+
+       glGetIntegerv(GL_TEXTURE_2D, &state->last_texture);
+       glGetIntegerv(GL_ACTIVE_TEXTURE, &state->last_texture_unit);
+
+       ensureLUT3DAllocated(state);
+
+       /* Step 1: Create a GPU Shader Description */
+       GpuShaderDesc shaderDesc;
+       shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_0);
+       shaderDesc.setFunctionName("OCIODisplay");
+       shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
+
+       /* Step 2: Compute the 3D LUT */
+       std::string lut3dCacheID = ocio_processor->getGpuLut3DCacheID(shaderDesc);
+       if (lut3dCacheID != state->lut3dcacheid) {
+               state->lut3dcacheid = lut3dCacheID;
+               ocio_processor->getGpuLut3D(state->lut3d, shaderDesc);
+
+               glActiveTexture(GL_TEXTURE1);
+               glBindTexture(GL_TEXTURE_3D, state->lut3d_texture);
+               glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0,
+                               LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
+                               GL_RGB, GL_FLOAT, state->lut3d);
+       }
+
+       /* Step 3: Compute the Shader */
+       std::string shaderCacheID = ocio_processor->getGpuShaderTextCacheID(shaderDesc);
+       if (state->program == 0 || shaderCacheID != state->shadercacheid) {
+               state->shadercacheid = shaderCacheID;
+
+               std::ostringstream os;
+               os << ocio_processor->getGpuShaderText(shaderDesc) << "\n";
+               os << g_fragShaderText;
+
+               if (state->fragShader)
+                       glDeleteShader(state->fragShader);
+               state->fragShader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
+
+               if (state->program)
+                       glDeleteProgram(state->program);
+
+               state->program = linkShaders(state->fragShader);
+       }
+
+       glActiveTexture(GL_TEXTURE1);
+       glBindTexture(GL_TEXTURE_3D, state->lut3d_texture);
+
+       glActiveTexture(GL_TEXTURE0);
+
+    glUseProgram(state->program);
+    glUniform1i(glGetUniformLocation(state->program, "tex1"), 0);
+    glUniform1i(glGetUniformLocation(state->program, "tex2"), 1);
+}
+
+void OCIOImpl::finishGLSLDraw(OCIO_GLSLDrawState *state)
+{
+       glActiveTexture(state->last_texture_unit);
+       glBindTexture(GL_TEXTURE_2D, state->last_texture);
+       glUseProgram(0);
+}
+
+void OCIOImpl::freeGLState(struct OCIO_GLSLDrawState *state)
+{
+       using std::string;
+
+       if (state->lut3d_texture_allocated)
+               glDeleteTextures(1, &state->lut3d_texture);
+
+       if (state->lut3d)
+               MEM_freeN(state->lut3d);
+
+       state->lut3dcacheid.~string();
+       state->shadercacheid.~string();
+
+       MEM_freeN(state);
+}
index b6bbc912e5bd74747691367e8c75b6a35c80f4b0..2a1f88be5f4962eebc922dd917ac2b06566b500c 100644 (file)
@@ -95,6 +95,10 @@ public:
        virtual void matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt) = 0;
 
        virtual void matrixTransformScale(float * m44, float * offset4, const float * scale4) = 0;
+
+       virtual void setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor) = 0;
+       virtual void finishGLSLDraw(struct OCIO_GLSLDrawState *state) = 0;
+       virtual void freeGLState(struct OCIO_GLSLDrawState *state_r) = 0;
 };
 
 class FallbackImpl : public IOCIOImpl {
@@ -164,6 +168,10 @@ public:
        void matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt);
 
        void matrixTransformScale(float * m44, float * offset4, const float * scale4);
+
+       void setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor);
+       void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
+       void freeGLState(struct OCIO_GLSLDrawState *state_r);
 };
 
 #ifdef WITH_OCIO
@@ -234,6 +242,10 @@ public:
        void matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt);
 
        void matrixTransformScale(float * m44, float * offset4, const float * scale4);
+
+       void setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor);
+       void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
+       void freeGLState(struct OCIO_GLSLDrawState *state_r);
 };
 #endif
 
diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc
new file mode 100644 (file)
index 0000000..c795937
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * 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.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ */
+
+#include <sstream>
+#include <string.h>
+
+#ifdef __APPLE__
+#include <OpenGL/gl.h>
+#include <OpenGL/glu.h>
+#else
+#include <GL/glew.h>
+#endif
+
+#include <OpenColorIO/OpenColorIO.h>
+
+using namespace OCIO_NAMESPACE;
+
+#include "MEM_guardedalloc.h"
+
+#include "ocio_impl.h"
+
+static const int LUT3D_EDGE_SIZE = 32;
+
+
+/* **** OpenGL drawing routines using GLSL for color space transform ***** */
+
+typedef struct OCIO_GLSLDrawState {
+       bool lut3d_texture_allocated;  /* boolean flag indicating whether
+                                       * lut texture is allocated
+                                       */
+
+       GLuint lut3d_texture;  /* OGL texture ID for 3D LUT */
+
+       float *lut3d;  /* 3D LUT table */
+
+       /* Cache */
+       std::string lut3dcacheid;
+       std::string shadercacheid;
+
+       /* GLSL stuff */
+       GLuint fragShader;
+       GLuint program;
+
+       /* Previous OpenGL state. */
+       GLint last_texture, last_texture_unit;
+} OCIO_GLSLDrawState;
+
+static const char * g_fragShaderText = ""
+"\n"
+"uniform sampler2D tex1;\n"
+"uniform sampler3D tex2;\n"
+"\n"
+"void main()\n"
+"{\n"
+"    vec4 col = texture2D(tex1, gl_TexCoord[0].st);\n"
+"    gl_FragColor = OCIODisplay(col, tex2);\n"
+"}\n";
+
+static GLuint compileShaderText(GLenum shaderType, const char *text)
+{
+       GLuint shader;
+       GLint stat;
+
+       shader = glCreateShader(shaderType);
+       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);
+               return 0;
+       }
+
+       return shader;
+}
+
+static GLuint linkShaders(GLuint fragShader)
+{
+       if (!fragShader)
+               return 0;
+
+       GLuint program = glCreateProgram();
+
+       if (fragShader)
+               glAttachShader(program, fragShader);
+
+       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 OCIO_GLSLDrawState *allocateOpenGLState(void)
+{
+       OCIO_GLSLDrawState *state;
+
+       /* Allocate memory for state. */
+       state = (OCIO_GLSLDrawState *) MEM_callocN(sizeof(OCIO_GLSLDrawState),
+                                                  "OCIO OpenGL State struct");
+
+       /* Call constructors on new memory. */
+       new (&state->lut3dcacheid) std::string("");
+       new (&state->shadercacheid) std::string("");
+
+       return state;
+}
+
+/* Ensure LUT texture and array are allocated */
+static void ensureLUT3DAllocated(OCIO_GLSLDrawState *state)
+{
+       int num_3d_entries = 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE;
+
+       if (state->lut3d_texture_allocated)
+               return;
+
+       glGenTextures(1, &state->lut3d_texture);
+
+       state->lut3d = (float *) MEM_callocN(sizeof(float) * num_3d_entries, "OCIO GPU 3D LUT");
+
+       glActiveTexture(GL_TEXTURE1);
+       glBindTexture(GL_TEXTURE_3D, state->lut3d_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_ARB,
+                    LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
+                    0, GL_RGB,GL_FLOAT, &state->lut3d);
+
+       state->lut3d_texture_allocated = 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.
+ */
+void OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor)
+{
+       ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *) processor;
+
+       /* Create state if needed. */
+       OCIO_GLSLDrawState *state;
+       if (!*state_r)
+               *state_r = allocateOpenGLState();
+       state = *state_r;
+
+       glGetIntegerv(GL_TEXTURE_2D, &state->last_texture);
+       glGetIntegerv(GL_ACTIVE_TEXTURE, &state->last_texture_unit);
+
+       ensureLUT3DAllocated(state);
+
+       /* Step 1: Create a GPU Shader Description */
+       GpuShaderDesc shaderDesc;
+       shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_0);
+       shaderDesc.setFunctionName("OCIODisplay");
+       shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
+
+       /* Step 2: Compute the 3D LUT */
+       std::string lut3dCacheID = ocio_processor->getGpuLut3DCacheID(shaderDesc);
+       if (lut3dCacheID != state->lut3dcacheid) {
+               state->lut3dcacheid = lut3dCacheID;
+               ocio_processor->getGpuLut3D(state->lut3d, shaderDesc);
+
+               glActiveTexture(GL_TEXTURE1);
+               glBindTexture(GL_TEXTURE_3D, state->lut3d_texture);
+               glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0,
+                               LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
+                               GL_RGB, GL_FLOAT, state->lut3d);
+       }
+
+       /* Step 3: Compute the Shader */
+       std::string shaderCacheID = ocio_processor->getGpuShaderTextCacheID(shaderDesc);
+       if (state->program == 0 || shaderCacheID != state->shadercacheid) {
+               state->shadercacheid = shaderCacheID;
+
+               std::ostringstream os;
+               os << ocio_processor->getGpuShaderText(shaderDesc) << "\n";
+               os << g_fragShaderText;
+
+               if (state->fragShader)
+                       glDeleteShader(state->fragShader);
+               state->fragShader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
+
+               if (state->program)
+                       glDeleteProgram(state->program);
+
+               state->program = linkShaders(state->fragShader);
+       }
+
+       glActiveTexture(GL_TEXTURE1);
+       glBindTexture(GL_TEXTURE_3D, state->lut3d_texture);
+
+       glActiveTexture(GL_TEXTURE0);
+
+       glUseProgram(state->program);
+       glUniform1i(glGetUniformLocation(state->program, "tex1"), 0);
+       glUniform1i(glGetUniformLocation(state->program, "tex2"), 1);
+}
+
+void OCIOImpl::finishGLSLDraw(OCIO_GLSLDrawState *state)
+{
+       glActiveTexture(state->last_texture_unit);
+       glBindTexture(GL_TEXTURE_2D, state->last_texture);
+       glUseProgram(0);
+}
+
+void OCIOImpl::freeGLState(struct OCIO_GLSLDrawState *state)
+{
+       using std::string;
+
+       if (state->lut3d_texture_allocated)
+               glDeleteTextures(1, &state->lut3d_texture);
+
+       if (state->lut3d)
+               MEM_freeN(state->lut3d);
+
+       state->lut3dcacheid.~string();
+       state->shadercacheid.~string();
+
+       MEM_freeN(state);
+}
index 7399bfec2b519ee20ce22f9023c5d6adf50e316c..682680e53c55464e2d3d90dc9da91b7160234e2d 100644 (file)
@@ -6350,7 +6350,6 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                
                                sclip->scopes.track_search = NULL;
                                sclip->scopes.track_preview = NULL;
-                               sclip->draw_context = NULL;
                                sclip->scopes.ok = 0;
                        }
                }
index 28727c913cbf6986165bffed038906e46c798a75..541956136bded52fcf2f5ba86f18ec0ce630ab6b 100644 (file)
@@ -39,6 +39,7 @@ struct Main;
 struct Mask;
 struct MovieClip;
 struct SpaceClip;
+struct Scene;
 
 /*  ** clip_editor.c ** */
 
@@ -81,12 +82,6 @@ void ED_space_clip_set_clip(struct bContext *C, struct bScreen *screen, struct S
 struct Mask *ED_space_clip_get_mask(struct SpaceClip *sc);
 void ED_space_clip_set_mask(struct bContext *C, struct SpaceClip *sc, struct Mask *mask);
 
-/* textures buffer */
-int ED_space_clip_texture_buffer_supported(struct SpaceClip *sc);
-int ED_space_clip_load_movieclip_buffer(struct SpaceClip *sc, struct ImBuf *ibuf, const unsigned char *display_buffer);
-void ED_space_clip_unload_movieclip_buffer(struct SpaceClip *sc);
-void ED_space_clip_free_texture_buffer(struct SpaceClip *sc);
-
 /* ** clip_ops.c ** */
 void ED_operatormacros_clip(void);
 
index 8501b53afaed0279c65446278302891dcfa92aa2..89315e041de7e1ab858ab2b5f5c7b3c51ba6e31c 100644 (file)
@@ -519,6 +519,15 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
        nsubparts_x = (img_w + (offset_x - 1)) / (offset_x);
        nsubparts_y = (img_h + (offset_y - 1)) / (offset_y);
 
+       if (format == GL_FLOAT) {
+               /* need to set internal format to higher range float */
+               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, tex_w, tex_h, 0, GL_RGBA, GL_FLOAT, NULL);
+       }
+       else {
+               /* switch to 8bit RGBA for byte buffer  */
+               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+       }
+
        for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) {
                for (subpart_x = 0; subpart_x < nsubparts_x; subpart_x++) {
                        int remainder_x = img_w - subpart_x * offset_x;
index 2d3dc9127c3c359acbf99390a6b7d04b3a6a965d..cbca2f0c46ebb568267aa1433c9671f987763950 100644 (file)
@@ -248,6 +248,53 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
                ED_region_info_draw(ar, str, block, 0.6f);
 }
 
+static void draw_movieclip_buffer_glsl(SpaceClip *sc, ImBuf *ibuf, int x, int y,
+                                       float zoomx, float zoomy)
+{
+       MovieClip *clip = ED_space_clip_get_clip(sc);
+       int filter = GL_LINEAR;
+
+       glPushMatrix();
+       glTranslatef(x, y, 0.0f);
+       glScalef(zoomx, zoomy, 1.0f);
+
+       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+       glColor4f(1.0, 1.0, 1.0, 1.0);
+
+       /* non-scaled proxy shouldn;t use diltering */
+       if ((clip->flag & MCLIP_USE_PROXY) == 0 ||
+           ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100))
+       {
+               filter = GL_NEAREST;
+       }
+
+       glaDrawPixelsTex(0, 0, ibuf->x, ibuf->y, GL_FLOAT, filter, ibuf->rect_float);
+
+       glPopMatrix();
+}
+
+static void draw_movieclip_buffer_fallback(const bContext *C, ImBuf *ibuf, int x, int y,
+                                           int width, int height, float zoomx, float zoomy)
+{
+       unsigned char *display_buffer;
+       void *cache_handle;
+
+       display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+
+       if (display_buffer) {
+               /* set zoom */
+               glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
+
+               glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer);
+
+               /* reset zoom */
+               glPixelZoom(1.0f, 1.0f);
+       }
+
+       IMB_display_buffer_release(cache_handle);
+}
+
 static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
                                   int width, int height, float zoomx, float zoomy)
 {
@@ -261,62 +308,32 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
                glRectf(x, y, x + zoomx * width, y + zoomy * height);
        }
        else {
-               unsigned char *display_buffer;
-               void *cache_handle;
-
-               display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
-
-               if (display_buffer) {
-                       int need_fallback = 1;
-
-                       /* checkerboard for case alpha */
-                       if (ibuf->planes == 32) {
-                               glEnable(GL_BLEND);
-                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-                               fdrawcheckerboard(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
-                       }
+               bool need_fallback = true;
 
-                       if (ED_space_clip_texture_buffer_supported(sc)) {
-                               if (ED_space_clip_load_movieclip_buffer(sc, ibuf, display_buffer)) {
-                                       glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+               /* checkerboard for case alpha */
+               if (ibuf->planes == 32) {
+                       glEnable(GL_BLEND);
+                       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
-                                       glPushMatrix();
-                                       glTranslatef(x, y, 0.0f);
-                                       glScalef(zoomx, zoomy, 1.0f);
-
-                                       glBegin(GL_QUADS);
-                                       glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f,  0.0f);
-                                       glTexCoord2f(1.0f, 0.0f); glVertex2f(width, 0.0f);
-                                       glTexCoord2f(1.0f, 1.0f); glVertex2f(width, height);
-                                       glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f,  height);
-                                       glEnd();
-
-                                       glPopMatrix();
-
-                                       ED_space_clip_unload_movieclip_buffer(sc);
-
-                                       need_fallback = 0;
-                               }
-                       }
+                       fdrawcheckerboard(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
+               }
 
-                       /* if texture buffers aren't efficiently supported or texture is too large to
-                        * be binder fallback to simple draw pixels solution */
-                       if (need_fallback) {
-                               /* set zoom */
-                               glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
+               /* GLSL display transform for byte buffers is not supported yet */
+               if (ibuf->rect_float && IMB_coloemanagement_setup_glsl_draw_from_ctx(C)) {
+                       draw_movieclip_buffer_glsl(sc, ibuf, x, y, zoomx, zoomy);
 
-                               glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer);
+                       IMB_coloemanagement_finish_glsl_draw();
 
-                               /* reset zoom */
-                               glPixelZoom(1.0f, 1.0f);
-                       }
+                       need_fallback = false;
+               }
 
-                       if (ibuf->planes == 32)
-                               glDisable(GL_BLEND);
+               /* if GLSL display failed, fallback to regular glaDrawPixelsAuto method */
+               if (need_fallback) {
+                       draw_movieclip_buffer_fallback(C, ibuf, x, y, width, height, zoomx, zoomy);
                }
 
-               IMB_display_buffer_release(cache_handle);
+               if (ibuf->planes == 32)
+                       glDisable(GL_BLEND);
        }
 }
 
index b00cc564a99357513dc4fee3fb3da0f7caad2db3..d297d0485e38d685af32b0591d6d5b34d5dcac1c 100644 (file)
 
 #include "GPU_extensions.h"
 
+#include "IMB_colormanagement.h"
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
 
 #include "ED_screen.h"
 #include "ED_clip.h"
 
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
 #include "WM_api.h"
 #include "WM_types.h"
 
@@ -580,163 +578,6 @@ void ED_space_clip_set_mask(bContext *C, SpaceClip *sc, Mask *mask)
        }
 }
 
-/* OpenGL draw context */
-
-typedef struct SpaceClipDrawContext {
-       int support_checked, buffers_supported;
-
-       GLuint texture;                 /* OGL texture ID */
-       short texture_allocated;        /* flag if texture was allocated by glGenTextures */
-       struct ImBuf *texture_ibuf;     /* image buffer for which texture was created */
-       const unsigned char *display_buffer; /* display buffer for which texture was created */
-       int image_width, image_height;  /* image width and height for which texture was created */
-       unsigned last_texture;          /* ID of previously used texture, so it'll be restored after clip drawing */
-
-       /* fields to check if cache is still valid */
-       int framenr, start_frame, frame_offset;
-       short render_size, render_flag;
-
-       char colorspace[64];
-} SpaceClipDrawContext;
-
-int ED_space_clip_texture_buffer_supported(SpaceClip *sc)
-{
-       SpaceClipDrawContext *context = sc->draw_context;
-
-       if (!context) {
-               context = MEM_callocN(sizeof(SpaceClipDrawContext), "SpaceClipDrawContext");
-               sc->draw_context = context;
-       }
-
-       if (!context->support_checked) {
-               context->support_checked = TRUE;
-               if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
-                       context->buffers_supported = FALSE;
-               }
-               else {
-                       context->buffers_supported = GPU_non_power_of_two_support();
-               }
-       }
-
-       return context->buffers_supported;
-}
-
-int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf, const unsigned char *display_buffer)
-{
-       SpaceClipDrawContext *context = sc->draw_context;
-       MovieClip *clip = ED_space_clip_get_clip(sc);
-       int need_rebind = 0;
-
-       context->last_texture = glaGetOneInteger(GL_TEXTURE_2D);
-
-       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
-       /* image texture need to be rebinded if displaying another image buffer
-        * assuming displaying happens of footage frames only on which painting doesn't happen.
-        * so not changed image buffer pointer means unchanged image content */
-       need_rebind |= context->texture_ibuf != ibuf;
-       need_rebind |= context->display_buffer != display_buffer;
-       need_rebind |= context->framenr != sc->user.framenr;
-       need_rebind |= context->render_size != sc->user.render_size;
-       need_rebind |= context->render_flag != sc->user.render_flag;
-       need_rebind |= context->start_frame != clip->start_frame;
-       need_rebind |= context->frame_offset != clip->frame_offset;
-
-       if (!need_rebind) {
-               /* OCIO_TODO: not entirely nice, but currently it seems to be easiest way
-                *            to deal with changing input color space settings
-                *            pointer-based check could fail due to new buffers could be
-                *            be allocated on on old memory
-                */
-               need_rebind = strcmp(context->colorspace, clip->colorspace_settings.name) != 0;
-       }
-
-       if (need_rebind) {
-               int width = ibuf->x, height = ibuf->y;
-               int need_recreate = 0;
-
-               if (width > GL_MAX_TEXTURE_SIZE || height > GL_MAX_TEXTURE_SIZE)
-                       return 0;
-
-               /* if image resolution changed (e.g. switched to proxy display) texture need to be recreated */
-               need_recreate = context->image_width != ibuf->x || context->image_height != ibuf->y;
-
-               if (context->texture_ibuf && need_recreate) {
-                       glDeleteTextures(1, &context->texture);
-                       context->texture_allocated = 0;
-               }
-
-               if (need_recreate || !context->texture_allocated) {
-                       /* texture doesn't exist yet or need to be re-allocated because of changed dimensions */
-                       int filter = GL_LINEAR;
-
-                       /* non-scaled proxy shouldn;t use diltering */
-                       if ((clip->flag & MCLIP_USE_PROXY) == 0 ||
-                           ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100))
-                       {
-                               filter = GL_NEAREST;
-                       }
-
-                       glGenTextures(1, &context->texture);
-                       glBindTexture(GL_TEXTURE_2D, context->texture);
-                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
-                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
-                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
-                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
-               }
-               else {
-                       /* if texture doesn't need to be reallocated itself, just bind it so
-                        * loading of image will happen to a proper texture */
-                       glBindTexture(GL_TEXTURE_2D, context->texture);
-               }
-
-               if (display_buffer)
-                       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
-
-               /* store settings */
-               context->texture_allocated = 1;
-               context->display_buffer = display_buffer;
-               context->texture_ibuf = ibuf;
-               context->image_width = ibuf->x;
-               context->image_height = ibuf->y;
-               context->framenr = sc->user.framenr;
-               context->render_size = sc->user.render_size;
-               context->render_flag = sc->user.render_flag;
-               context->start_frame = clip->start_frame;
-               context->frame_offset = clip->frame_offset;
-
-               BLI_strncpy(context->colorspace, clip->colorspace_settings.name, sizeof(context->colorspace));
-       }
-       else {
-               /* displaying exactly the same image which was loaded t oa texture,
-                * just bint texture in this case */
-               glBindTexture(GL_TEXTURE_2D, context->texture);
-       }
-
-       glEnable(GL_TEXTURE_2D);
-
-       return TRUE;
-}
-
-void ED_space_clip_unload_movieclip_buffer(SpaceClip *sc)
-{
-       SpaceClipDrawContext *context = sc->draw_context;
-
-       glBindTexture(GL_TEXTURE_2D, context->last_texture);
-       glDisable(GL_TEXTURE_2D);
-}
-
-void ED_space_clip_free_texture_buffer(SpaceClip *sc)
-{
-       SpaceClipDrawContext *context = sc->draw_context;
-
-       if (context) {
-               glDeleteTextures(1, &context->texture);
-
-               MEM_freeN(context);
-       }
-}
-
 /* ******** pre-fetching functions ******** */
 
 typedef struct PrefetchJob {
index ced19020034ed4180853a415ebf0c60486347649..64b643f8a5853628254e21416a451928ba19fb7c 100644 (file)
@@ -327,8 +327,6 @@ static void clip_free(SpaceLink *sl)
 
        if (sc->scopes.track_search)
                IMB_freeImBuf(sc->scopes.track_search);
-
-       ED_space_clip_free_texture_buffer(sc);
 }
 
 /* spacetype; init callback */
@@ -348,7 +346,6 @@ static SpaceLink *clip_duplicate(SpaceLink *sl)
        scn->scopes.track_search = NULL;
        scn->scopes.track_preview = NULL;
        scn->scopes.ok = FALSE;
-       scn->draw_context = NULL;
 
        return (SpaceLink *)scn;
 }
index b981390582e010f6789b48340fa525e9f1943d98..473bd7d0c7ae3fdb07e9f860e063487967c80bc4 100644 (file)
@@ -148,6 +148,14 @@ void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_process
                                          int channels, int predivide);
 void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processor);
 
+/* ** OpenGL drawing routines using GLSL for color space transform ** */
+
+int IMB_coloemanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings,
+                                        const struct ColorManagedDisplaySettings *display_settings);
+
+int IMB_coloemanagement_setup_glsl_draw_from_ctx(const struct bContext *C);
+void IMB_coloemanagement_finish_glsl_draw(void);
+
 /* Roles */
 enum {
        COLOR_ROLE_SCENE_LINEAR = 0,
index 65a3db839a99900d668a21c3ffa0700f4aaed760..6c33f6e3e335081068ce106e8feda610e0dc2c4e 100644 (file)
@@ -102,6 +102,19 @@ typedef struct ColormanageProcessor {
        int is_data_result;
 } ColormanageProcessor;
 
+static struct global_glsl_state {
+       /* Actual processor used for GLSL baked LUTs. */
+       OCIO_ConstProcessorRcPtr *processor;
+
+       /* Settings of processor for comparison. */
+       char view[MAX_COLORSPACE_NAME];
+       char display[MAX_COLORSPACE_NAME];
+       float exposure, gamma;
+
+       /* Container for GLSL state needed for OCIO module. */
+       struct OCIO_GLSLDrawState *ocio_glsl_state;
+} global_glsl_state;
+
 /*********************** Color managed cache *************************/
 
 /* Cache Implementation Notes
@@ -607,6 +620,12 @@ void colormanagement_init(void)
 
 void colormanagement_exit(void)
 {
+       if (global_glsl_state.processor)
+               OCIO_processorRelease(global_glsl_state.processor);
+
+       if (global_glsl_state.ocio_glsl_state)
+               OCIO_freeOGLState(global_glsl_state.ocio_glsl_state);
+
        colormanage_free_config();
 }
 
@@ -2691,3 +2710,72 @@ void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor)
 
        MEM_freeN(cm_processor);
 }
+
+/* **** OpenGL drawing routines using GLSL for color space transform ***** */
+
+static bool check_glsl_display_processor_changed(const ColorManagedViewSettings *view_settings,
+                                                 const ColorManagedDisplaySettings *display_settings)
+{
+       return !(global_glsl_state.exposure == view_settings->exposure &&
+                global_glsl_state.gamma == view_settings->gamma &&
+                STREQ(global_glsl_state.view, view_settings->view_transform) &&
+                STREQ(global_glsl_state.display, display_settings->display_device));
+}
+
+static void update_glsl_display_processor(const ColorManagedViewSettings *view_settings,
+                                          const ColorManagedDisplaySettings *display_settings)
+{
+       /* Update state if there's no processor yet or
+        * processor settings has been changed.
+        */
+       if (global_glsl_state.processor == NULL ||
+           check_glsl_display_processor_changed(view_settings, display_settings))
+       {
+               /* Store settings of processor for further comparison. */
+               strcpy(global_glsl_state.view, view_settings->view_transform);
+               strcpy(global_glsl_state.display, display_settings->display_device);
+               global_glsl_state.exposure = view_settings->exposure;
+               global_glsl_state.gamma = view_settings->gamma;
+
+               /* Free old processor, if any. */
+               if (global_glsl_state.processor)
+                       OCIO_processorRelease(global_glsl_state.processor);
+
+               /* We're using display OCIO processor, no RGB curves yet. */
+               global_glsl_state.processor =
+                       create_display_buffer_processor(global_glsl_state.view,
+                                                       global_glsl_state.display,
+                                                       global_glsl_state.exposure,
+                                                       global_glsl_state.gamma);
+       }
+}
+
+int IMB_coloemanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings,
+                                        const ColorManagedDisplaySettings *display_settings)
+{
+       /* RGB curves mapping is not supported on GPU yet. */
+       if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)
+               return FALSE;
+
+       /* Make sure OCIO processor is up-to-date. */
+       update_glsl_display_processor(view_settings, display_settings);
+
+       OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor);
+
+       return TRUE;
+}
+
+int IMB_coloemanagement_setup_glsl_draw_from_ctx(const bContext *C)
+{
+       ColorManagedViewSettings *view_settings;
+       ColorManagedDisplaySettings *display_settings;
+
+       display_transform_get_from_ctx(C, &view_settings, &display_settings);
+
+       return IMB_coloemanagement_setup_glsl_draw(view_settings, display_settings);
+}
+
+void IMB_coloemanagement_finish_glsl_draw(void)
+{
+       OCIO_finishGLSLDraw(global_glsl_state.ocio_glsl_state);
+}
index e5e38d66de5b049d1126f6c8eb2e2910df52b582..8253bb570f6b944f88b28ba4d690745620a18c9e 100644 (file)
@@ -1072,8 +1072,6 @@ typedef struct SpaceClip {
        /* grease pencil */
        short gpencil_src, pad2;
 
-       void *draw_context;
-
        int around, pad4;             /* pivot point for transforms */
 
        MaskSpaceInfo mask_info;