From 60ff60dcdc9f43891fb8a19e10f9bb7964a539bf Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 30 Aug 2013 23:49:35 +0000 Subject: [PATCH] RenderEngine API: add viewport draw utility functions to bind a GLSL fragment shader for converting colors from linear to display space, based on the scene color management settings. if engine.support_display_space_shader(scene): # test graphics card support engine.bind_display_space_shader(scene) # draw pixels .. engine.unbind_display_space_shader() --- intern/opencolorio/fallback_impl.cc | 5 ++ intern/opencolorio/ocio_capi.cc | 5 ++ intern/opencolorio/ocio_capi.h | 1 + intern/opencolorio/ocio_impl.h | 3 ++ intern/opencolorio/ocio_impl_glsl.cc | 12 +++-- .../blender/editors/render/render_internal.c | 2 +- source/blender/editors/screen/glutil.c | 9 ++-- source/blender/imbuf/IMB_colormanagement.h | 9 +++- source/blender/imbuf/intern/colormanagement.c | 25 +++++++--- source/blender/makesrna/intern/rna_color.c | 1 + source/blender/makesrna/intern/rna_render.c | 47 ++++++++++++++++++- 11 files changed, 100 insertions(+), 19 deletions(-) diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc index 37f624e1f8b..9d6561fb4cb 100644 --- a/intern/opencolorio/fallback_impl.cc +++ b/intern/opencolorio/fallback_impl.cc @@ -381,6 +381,11 @@ void FallbackImpl::matrixTransformScale(float * , float * , const float *) { } +bool FallbackImpl::supportGLSLDraw(void) +{ + return false; +} + bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide) { return false; diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc index c8db2c2b531..49f8d2ca41e 100644 --- a/intern/opencolorio/ocio_capi.cc +++ b/intern/opencolorio/ocio_capi.cc @@ -283,6 +283,11 @@ void OCIO_matrixTransformScale(float * m44, float * offset4, const float *scale4 impl->matrixTransformScale(m44, offset4, scale4f); } +int OCIO_supportGLSLDraw(void) +{ + return (int) impl->supportGLSLDraw(); +} + int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide) { return (int) impl->setupGLSLDraw(state_r, processor, (bool) predivide); diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 3632a0da1c6..0b3102a290d 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -121,6 +121,7 @@ void OCIO_matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt); void OCIO_matrixTransformScale(float * m44, float * offset4, const float * scale4); +int OCIO_supportGLSLDraw(void); int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide); void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state); void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state); diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h index a328470ccb5..a1e743bf2f6 100644 --- a/intern/opencolorio/ocio_impl.h +++ b/intern/opencolorio/ocio_impl.h @@ -96,6 +96,7 @@ public: virtual void matrixTransformScale(float * m44, float * offset4, const float * scale4) = 0; + virtual bool supportGLSLDraw(void) = 0; virtual bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide) = 0; virtual void finishGLSLDraw(struct OCIO_GLSLDrawState *state) = 0; virtual void freeGLState(struct OCIO_GLSLDrawState *state_r) = 0; @@ -169,6 +170,7 @@ public: void matrixTransformScale(float * m44, float * offset4, const float * scale4); + bool supportGLSLDraw(void); bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide); void finishGLSLDraw(struct OCIO_GLSLDrawState *state); void freeGLState(struct OCIO_GLSLDrawState *state_r); @@ -243,6 +245,7 @@ public: void matrixTransformScale(float * m44, float * offset4, const float * scale4); + bool supportGLSLDraw(void); bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide); void finishGLSLDraw(struct OCIO_GLSLDrawState *state); void freeGLState(struct OCIO_GLSLDrawState *state_r); diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc index 54be1e0f339..1a3132fa4b3 100644 --- a/intern/opencolorio/ocio_impl_glsl.cc +++ b/intern/opencolorio/ocio_impl_glsl.cc @@ -36,12 +36,7 @@ #include #include -#ifdef __APPLE__ -#include -#include -#else #include -#endif #include @@ -202,6 +197,13 @@ static bool ensureLUT3DAllocated(OCIO_GLSLDrawState *state) return state->lut3d_texture_valid; } +/* Detect if we can support GLSL drawing */ +bool OCIOImpl::supportGLSLDraw() +{ + /* GLSL and GL_RGB16F_ARB */ + return GLEW_VERSION_2_0 && (GLEW_VERSION_3_0 || GLEW_ARB_texture_float); +} + /** * Setup OpenGL contexts for a transform defined by processor using GLSL * All LUT allocating baking and shader compilation happens here. diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index d3818e1cac7..b1978c001f3 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -1125,7 +1125,7 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C) /* Try using GLSL display transform. */ if (force_fallback == false) { - if (IMB_colormanagement_setup_glsl_draw(NULL, &scene->display_settings, TRUE)) { + if (IMB_colormanagement_setup_glsl_draw(NULL, &scene->display_settings, TRUE, FALSE)) { glEnable(GL_BLEND); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glaDrawPixelsTex(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_FLOAT, diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 723dce5e226..785c21481c5 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -1091,15 +1091,18 @@ void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter, if (ibuf->rect_float) { if (ibuf->float_colorspace) { ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, - ibuf->float_colorspace, TRUE); + ibuf->float_colorspace, + TRUE, FALSE); } else { - ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings, TRUE); + ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings, + TRUE, FALSE); } } else { ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, - ibuf->rect_colorspace, FALSE); + ibuf->rect_colorspace, + FALSE, FALSE); } if (ok) { diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 7399b8554aa..3d2eab56d14 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -159,15 +159,20 @@ void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processo /* ** OpenGL drawing routines using GLSL for color space transform ** */ +/* Test if GLSL drawing is supported for combination of graphics card and this configuration */ +int IMB_colormanagement_support_glsl_draw(const struct ColorManagedViewSettings *view_settings, + int skip_curves); /* Configures GLSL shader for conversion from scene linear to display space */ int IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, - int predivide); + int predivide, + int skip_curves); /* Same as above, but display space conversion happens from a specified space */ int IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, struct ColorSpace *colorspace, - int predivide); + int predivide, + int skip_curves); /* Same as setup_glsl_draw, but color management settings are guessing from a given context */ int IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, int predivide); /* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 0167eaccef0..2c4863c3598 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -2807,6 +2807,17 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s } } +int IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *view_settings, + int skip_curves) +{ + /* curves not supported yet */ + if (!skip_curves) + if (view_settings && (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)) + return 0; + + return OCIO_supportGLSLDraw(); +} + /** * Configures GLSL shader for conversion from specified to * display color space @@ -2822,7 +2833,8 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s */ int IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, - struct ColorSpace *from_colorspace, int predivide) + struct ColorSpace *from_colorspace, int predivide, + int skip_curves) { ColorManagedViewSettings default_view_settings; const ColorManagedViewSettings *applied_view_settings; @@ -2840,8 +2852,9 @@ int IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSetting } /* RGB curves mapping is not supported on GPU yet. */ - if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) - return FALSE; + if (!skip_curves) + if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) + return FALSE; /* Make sure OCIO processor is up-to-date. */ update_glsl_display_processor(applied_view_settings, display_settings, @@ -2853,10 +2866,10 @@ int IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSetting /* Configures GLSL shader for conversion from scene linear to display space */ int IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, - int predivide) + int predivide, int skip_curves) { return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, - NULL, predivide); + NULL, predivide, skip_curves); } /* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ @@ -2867,7 +2880,7 @@ int IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings); - return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide); + return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide, FALSE); } /* Same as setup_glsl_draw, but color management settings are guessing from a given context */ diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index ebd06475c79..933f06cec8c 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -584,6 +584,7 @@ static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene) return; if (GS(id->name) == ID_SCE) { + DAG_id_tag_update(id, 0); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); } } diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 82cdfcdd631..5b809a51705 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -49,6 +49,9 @@ #include "BKE_context.h" #include "BKE_report.h" +#include "IMB_colormanagement.h" +#include "GPU_extensions.h" + /* RenderEngine Callbacks */ static void engine_tag_redraw(RenderEngine *engine) @@ -61,6 +64,23 @@ static void engine_tag_update(RenderEngine *engine) engine->flag |= RE_ENGINE_DO_UPDATE; } +static int engine_support_display_space_shader(RenderEngine *UNUSED(engine), Scene *scene) +{ + return IMB_colormanagement_support_glsl_draw(&scene->view_settings, true); +} + +static void engine_bind_display_space_shader(RenderEngine *UNUSED(engine), Scene *scene) +{ + IMB_colormanagement_setup_glsl_draw(&scene->view_settings, + &scene->display_settings, + false, true); +} + +static void engine_unbind_display_space_shader(RenderEngine *UNUSED(engine)) +{ + IMB_colormanagement_finish_glsl_draw(); +} + static void engine_update(RenderEngine *engine, Main *bmain, Scene *scene) { extern FunctionRNA rna_RenderEngine_update_func; @@ -342,14 +362,15 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_RNAPTR); /* tag for redraw */ - RNA_def_function(srna, "tag_redraw", "engine_tag_redraw"); + func = RNA_def_function(srna, "tag_redraw", "engine_tag_redraw"); RNA_def_function_ui_description(func, "Request redraw for viewport rendering"); /* tag for update */ - RNA_def_function(srna, "tag_update", "engine_tag_update"); + func = RNA_def_function(srna, "tag_update", "engine_tag_update"); RNA_def_function_ui_description(func, "Request update call for viewport rendering"); func = RNA_def_function(srna, "begin_result", "RE_engine_begin_result"); + RNA_def_function_ui_description(func, "Create render result to write linear floating point render layers and passes"); prop = RNA_def_int(func, "x", 0, 0, INT_MAX, "X", "", 0, INT_MAX); RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_int(func, "y", 0, 0, INT_MAX, "Y", "", 0, INT_MAX); @@ -363,39 +384,61 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_function_return(func, prop); func = RNA_def_function(srna, "update_result", "RE_engine_update_result"); + RNA_def_function_ui_description(func, "Signal that pixels have been updated and can be redrawn in the user interface"); prop = RNA_def_pointer(func, "result", "RenderResult", "Result", ""); RNA_def_property_flag(prop, PROP_REQUIRED); func = RNA_def_function(srna, "end_result", "RE_engine_end_result"); + RNA_def_function_ui_description(func, "All pixels in the render result have been set and are final"); prop = RNA_def_pointer(func, "result", "RenderResult", "Result", ""); RNA_def_property_flag(prop, PROP_REQUIRED); RNA_def_boolean(func, "cancel", 0, "Cancel", "Don't merge back results"); func = RNA_def_function(srna, "test_break", "RE_engine_test_break"); + RNA_def_function_ui_description(func, "Test if the render operation should been cancelled, this is a fast call that should be used regularly for responsiveness"); prop = RNA_def_boolean(func, "do_break", 0, "Break", ""); RNA_def_function_return(func, prop); func = RNA_def_function(srna, "update_stats", "RE_engine_update_stats"); + RNA_def_function_ui_description(func, "Update and signal to redraw render status text"); prop = RNA_def_string(func, "stats", "", 0, "Stats", ""); RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_string(func, "info", "", 0, "Info", ""); RNA_def_property_flag(prop, PROP_REQUIRED); func = RNA_def_function(srna, "update_progress", "RE_engine_update_progress"); + RNA_def_function_ui_description(func, "Update progress percentage of render"); prop = RNA_def_float(func, "progress", 0, 0.0f, 1.0f, "", "Percentage of render that's done", 0.0f, 1.0f); RNA_def_property_flag(prop, PROP_REQUIRED); func = RNA_def_function(srna, "update_memory_stats", "RE_engine_update_memory_stats"); + RNA_def_function_ui_description(func, "Update memory usage statistics"); RNA_def_float(func, "memory_used", 0, 0.0f, FLT_MAX, "", "Current memory usage in megabytes", 0.0f, FLT_MAX); RNA_def_float(func, "memory_peak", 0, 0.0f, FLT_MAX, "", "Peak memory usage in megabytes", 0.0f, FLT_MAX); RNA_def_property_flag(prop, PROP_REQUIRED); func = RNA_def_function(srna, "report", "RE_engine_report"); + RNA_def_function_ui_description(func, "Report info, warning or error messages"); prop = RNA_def_enum_flag(func, "type", wm_report_items, 0, "Type", ""); RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_string(func, "message", "", 0, "Report Message", ""); RNA_def_property_flag(prop, PROP_REQUIRED); + func = RNA_def_function(srna, "bind_display_space_shader", "engine_bind_display_space_shader"); + RNA_def_function_ui_description(func, "Bind GLSL fragment shader that converts linear colors to display space colors using scene color management settings"); + prop = RNA_def_pointer(func, "scene", "Scene", "", ""); + RNA_def_property_flag(prop, PROP_REQUIRED); + + func = RNA_def_function(srna, "unbind_display_space_shader", "engine_unbind_display_space_shader"); + RNA_def_function_ui_description(func, "Unbind GLSL display space shader, must always be called after binding the shader"); + + func = RNA_def_function(srna, "support_display_space_shader", "engine_support_display_space_shader"); + RNA_def_function_ui_description(func, "Test if GLSL display space shader is supported for the combination of graphics card and scene settings"); + prop = RNA_def_pointer(func, "scene", "Scene", "", ""); + RNA_def_property_flag(prop, PROP_REQUIRED); + prop = RNA_def_boolean(func, "supported", 0, "Supported", ""); + RNA_def_function_return(func, prop); + RNA_define_verify_sdna(0); prop = RNA_def_property(srna, "is_animation", PROP_BOOLEAN, PROP_NONE);