Merge branch 'master' into blender2.8
authorBastien Montagne <montagne29@wanadoo.fr>
Thu, 12 Jan 2017 11:59:45 +0000 (12:59 +0100)
committerBastien Montagne <montagne29@wanadoo.fr>
Thu, 12 Jan 2017 11:59:45 +0000 (12:59 +0100)
237 files changed:
CMakeLists.txt
build_files/build_environment/install_deps.sh
intern/cycles/blender/addon/ui.py
intern/ghost/intern/GHOST_ContextCGL.h
intern/ghost/intern/GHOST_ContextCGL.mm
intern/ghost/intern/GHOST_ContextGLX.cpp
intern/ghost/intern/GHOST_ContextWGL.cpp
intern/ghost/intern/GHOST_ContextWGL.h
intern/ghost/intern/GHOST_WindowCocoa.mm
intern/ghost/intern/GHOST_WindowWin32.cpp
intern/ghost/intern/GHOST_WindowX11.cpp
release/darwin/blender.app/Contents/Info.plist
release/scripts/startup/bl_ui/properties_physics_cloth.py
release/scripts/startup/bl_ui/space_info.py
release/scripts/startup/bl_ui/space_view3d.py
source/blender/blenfont/BLF_api.h
source/blender/blenfont/intern/blf.c
source/blender/blenfont/intern/blf_font.c
source/blender/blenfont/intern/blf_glyph.c
source/blender/blenfont/intern/blf_internal.h
source/blender/blenfont/intern/blf_internal_types.h
source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/BKE_screen.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/dynamicpaint.c
source/blender/blenkernel/intern/icons.c
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/library_query.c
source/blender/blenkernel/intern/rigidbody.c
source/blender/blenkernel/intern/screen.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenlib/BLI_math_color.h
source/blender/blenlib/BLI_math_matrix.h
source/blender/blenlib/BLI_math_vector.h
source/blender/blenlib/intern/math_color_inline.c
source/blender/blenlib/intern/math_matrix.c
source/blender/blenlib/intern/math_vector.c
source/blender/blenlib/intern/scanfill_utils.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/versioning_270.c
source/blender/blenloader/intern/writefile.c
source/blender/bmesh/tools/bmesh_intersect.c
source/blender/depsgraph/intern/depsgraph_tag.cc
source/blender/draw/CMakeLists.txt [new file with mode: 0644]
source/blender/draw/DRW_defines.h [new file with mode: 0644]
source/blender/draw/DRW_engines.h [new file with mode: 0644]
source/blender/editors/animation/anim_channels_defines.c
source/blender/editors/animation/anim_draw.c
source/blender/editors/gpencil/drawgpencil.c
source/blender/editors/gpencil/gpencil_brush.c
source/blender/editors/gpencil/gpencil_paint.c
source/blender/editors/include/BIF_glutil.h
source/blender/editors/include/ED_screen.h
source/blender/editors/include/UI_interface.h
source/blender/editors/include/UI_resources.h
source/blender/editors/interface/interface_draw.c
source/blender/editors/interface/interface_eyedropper.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_icons.c
source/blender/editors/interface/interface_intern.h
source/blender/editors/interface/interface_panel.c
source/blender/editors/interface/interface_regions.c
source/blender/editors/interface/interface_style.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/interface/interface_widgets.c
source/blender/editors/interface/resources.c
source/blender/editors/interface/view2d.c
source/blender/editors/render/render_preview.c
source/blender/editors/screen/CMakeLists.txt
source/blender/editors/screen/area.c
source/blender/editors/screen/glutil.c
source/blender/editors/screen/screen_draw.c [new file with mode: 0644]
source/blender/editors/screen/screen_edit.c
source/blender/editors/screen/screen_intern.h
source/blender/editors/screen/screen_ops.c
source/blender/editors/screen/screendump.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/space_action/action_draw.c
source/blender/editors/space_api/spacetypes.c
source/blender/editors/space_console/console_draw.c
source/blender/editors/space_file/file_draw.c
source/blender/editors/space_graph/graph_draw.c
source/blender/editors/space_image/image_draw.c
source/blender/editors/space_info/textview.c
source/blender/editors/space_nla/nla_draw.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_draw.c
source/blender/editors/space_node/node_intern.h
source/blender/editors/space_outliner/outliner_draw.c
source/blender/editors/space_outliner/outliner_edit.c
source/blender/editors/space_outliner/outliner_intern.h
source/blender/editors/space_outliner/outliner_ops.c
source/blender/editors/space_outliner/outliner_select.c
source/blender/editors/space_outliner/outliner_tools.c
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/editors/space_text/text_draw.c
source/blender/editors/space_time/space_time.c
source/blender/editors/space_view3d/CMakeLists.txt
source/blender/editors/space_view3d/drawarmature.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/drawsimdebug.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_draw_legacy.c [new file with mode: 0644]
source/blender/editors/space_view3d/view3d_fly.c
source/blender/editors/space_view3d/view3d_header.c
source/blender/editors/space_view3d/view3d_intern.h
source/blender/editors/space_view3d/view3d_ruler.c
source/blender/editors/space_view3d/view3d_walk.c
source/blender/editors/transform/transform_manipulator.c
source/blender/editors/util/ed_util.c
source/blender/gpu/CMakeLists.txt
source/blender/gpu/GPU_basic_shader.h
source/blender/gpu/GPU_batch.h [new file with mode: 0644]
source/blender/gpu/GPU_debug.h
source/blender/gpu/GPU_draw.h
source/blender/gpu/GPU_framebuffer.h
source/blender/gpu/GPU_immediate.h [new file with mode: 0644]
source/blender/gpu/GPU_matrix.h [new file with mode: 0644]
source/blender/gpu/GPU_shader.h
source/blender/gpu/GPU_viewport.h [new file with mode: 0644]
source/blender/gpu/gawain/attrib_binding.c [new file with mode: 0644]
source/blender/gpu/gawain/attrib_binding.h [new file with mode: 0644]
source/blender/gpu/gawain/batch.c [new file with mode: 0644]
source/blender/gpu/gawain/batch.h [new file with mode: 0644]
source/blender/gpu/gawain/buffer_id.cpp [new file with mode: 0644]
source/blender/gpu/gawain/buffer_id.h [new file with mode: 0644]
source/blender/gpu/gawain/common.h [new file with mode: 0644]
source/blender/gpu/gawain/element.c [new file with mode: 0644]
source/blender/gpu/gawain/element.h [new file with mode: 0644]
source/blender/gpu/gawain/imm_util.c [new file with mode: 0644]
source/blender/gpu/gawain/imm_util.h [new file with mode: 0644]
source/blender/gpu/gawain/immediate.c [new file with mode: 0644]
source/blender/gpu/gawain/immediate.h [new file with mode: 0644]
source/blender/gpu/gawain/vertex_buffer.c [new file with mode: 0644]
source/blender/gpu/gawain/vertex_buffer.h [new file with mode: 0644]
source/blender/gpu/gawain/vertex_format.c [new file with mode: 0644]
source/blender/gpu/gawain/vertex_format.h [new file with mode: 0644]
source/blender/gpu/intern/gpu_basic_shader.c
source/blender/gpu/intern/gpu_batch.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_compositing.c
source/blender/gpu/intern/gpu_debug.c
source/blender/gpu/intern/gpu_draw.c
source/blender/gpu/intern/gpu_extensions.c
source/blender/gpu/intern/gpu_framebuffer.c
source/blender/gpu/intern/gpu_immediate.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_init_exit.c
source/blender/gpu/intern/gpu_material.c
source/blender/gpu/intern/gpu_matrix.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_shader.c
source/blender/gpu/intern/gpu_shader_private.h [new file with mode: 0644]
source/blender/gpu/intern/gpu_texture.c
source/blender/gpu/intern/gpu_viewport.c [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_smooth_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_2D_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_smooth_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_smooth_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
source/blender/gpu/shaders/gpu_shader_basic_geom.glsl
source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl [new file with mode: 0755]
source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl [new file with mode: 0755]
source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_image_color_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_image_mask_uniform_color_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_point_uniform_color_smooth_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_smooth_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_text_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_text_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl [new file with mode: 0644]
source/blender/makesdna/DNA_gpencil_types.h
source/blender/makesdna/DNA_outliner_types.h
source/blender/makesdna/DNA_screen_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesdna/DNA_view3d_types.h
source/blender/makesrna/intern/rna_image_api.c
source/blender/makesrna/intern/rna_main_api.c
source/blender/makesrna/intern/rna_space.c
source/blender/python/generic/bgl.c
source/blender/python/generic/blf_py_api.c
source/blender/render/intern/source/voxeldata.c
source/blender/windowmanager/CMakeLists.txt
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm_dragdrop.c
source/blender/windowmanager/intern/wm_draw.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_init_exit.c
source/blender/windowmanager/intern/wm_operators.c
source/blender/windowmanager/intern/wm_stereo.c
source/blender/windowmanager/intern/wm_window.c
source/blender/windowmanager/manipulators/WM_manipulator_api.h [new file with mode: 0644]
source/blender/windowmanager/manipulators/WM_manipulator_types.h [new file with mode: 0644]
source/blender/windowmanager/manipulators/intern/manipulator_library/manipulator_library_intern.h [new file with mode: 0644]
source/blender/windowmanager/manipulators/intern/manipulator_library/manipulator_library_utils.c [new file with mode: 0644]
source/blender/windowmanager/manipulators/intern/wm_manipulator.c [new file with mode: 0644]
source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h [new file with mode: 0644]
source/blender/windowmanager/manipulators/intern/wm_manipulatorgroup.c [new file with mode: 0644]
source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c [new file with mode: 0644]
source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h [new file with mode: 0644]
source/blender/windowmanager/wm.h
source/blender/windowmanager/wm_draw.h
source/blender/windowmanager/wm_event_system.h
source/blender/windowmanager/wm_event_types.h
source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
source/blenderplayer/bad_level_call_stubs/stubs.c
source/creator/creator_args.c

index 8b64f7b8afdfbc03fe21a354a8c63d599e2d936c..de01be1d29973acb42bbee884735b492fa3d4f48 100644 (file)
@@ -497,11 +497,10 @@ endif()
 # We default options to whatever default standard in the current compiler.
 if(CMAKE_COMPILER_IS_GNUCC AND (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "6.0") AND (NOT WITH_CXX11))
        set(_c11_init ON)
-       set(_cxx11_init ON)
 else()
        set(_c11_init OFF)
-       set(_cxx11_init OFF)
 endif()
+set(_cxx11_init ON)
 
 option(WITH_C11 "Build with C11 standard enabled, for development use only!" ${_c11_init})
 mark_as_advanced(WITH_C11)
index ecb1cf875113e33345ecfb145b8bfecd71b66a9f..be983ebff4a39720dbcaafe1a1f38642cb80de92 100755 (executable)
@@ -25,7 +25,7 @@
 ARGS=$( \
 getopt \
 -o s:i:t:h \
---long source:,install:,tmp:,info:,threads:,help,show-deps,no-sudo,no-build,no-confirm,use-cxx11,\
+--long source:,install:,tmp:,info:,threads:,help,show-deps,no-sudo,no-build,no-confirm,\
 with-all,with-opencollada,\
 ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,\
 force-all,force-python,force-numpy,force-boost,\
@@ -104,11 +104,6 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
     --no-confirm
         Disable any interaction with user (suitable for automated run).
 
-    --use-cxx11
-        Build all libraries in cpp11 'mode' (will be mandatory soon in blender2.8 branch).
-        NOTE: If your compiler is gcc-6.0 or above, you probably *want* to enable this option (since it's default
-              standard starting from this version).
-
     --with-all
         By default, a number of optional and not-so-often needed libraries are not installed.
         This option will try to install them, at the cost of potential conflicts (depending on
@@ -287,7 +282,7 @@ SUDO="sudo"
 
 NO_BUILD=false
 NO_CONFIRM=false
-USE_CXX11=false
+USE_CXX11=true  # Mandatory in blender2.8
 
 PYTHON_VERSION="3.5.2"
 PYTHON_VERSION_MIN="3.5"
@@ -499,9 +494,6 @@ while true; do
     --no-confirm)
       NO_CONFIRM=true; shift; continue
     ;;
-    --use-cxx11)
-      USE_CXX11=true; shift; continue
-    ;;
     --with-all)
       WITH_ALL=true; shift; continue
     ;;
@@ -793,7 +785,7 @@ FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
 
 CXXFLAGS_BACK=$CXXFLAGS
 if [ "$USE_CXX11" = true ]; then
-  WARNING "You are trying to use c++11, this *should* go smoothely with any very recent distribution
+  WARNING "C++11 is now mandatory for blender2.8, this *should* go smoothly with any very recent distribution.
 However, if you are experiencing linking errors (also when building Blender itself), please try the following:
     * Re-run this script with `--build-all --force-all` options.
     * Ensure your gcc version is at the very least 4.8, if possible you should really rather use gcc-5.1 or above.
index 925f923dd41ac9aa99c925917b3d50805294a211..a573fa1ce22db0668f36fb9291852c4fd0b8508c 100644 (file)
@@ -1577,6 +1577,7 @@ class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
         row.prop(rd, "simplify_subdivision", text="Viewport")
         row.prop(rd, "simplify_subdivision_render", text="Render")
 
+
         col = layout.column(align=True)
         col.label(text="Child Particles")
         row = col.row(align=True)
index dd49b81b561ee04acf910b8923e83d83ef716240..8186eaa759d54ea6fc667a85f4816e23b596bab5 100644 (file)
@@ -134,6 +134,8 @@ private:
        /** The OpenGL drawing context */
        NSOpenGLContext *m_openGLContext;
 
+       bool m_coreProfile;
+
        //static CGLEWContext *s_cglewContext;
 
        const bool m_debug;
index 03c45f9945bc8ff3f803ac10e073bb1b084af07e..64db70197bbe3686e45685bc93999ccf6e9a0c32 100644 (file)
@@ -63,6 +63,23 @@ GHOST_ContextCGL::GHOST_ContextCGL(
       m_debug(contextFlags)
 {
        assert(openGLView != nil);
+
+       // for now be very strict about OpenGL version requested
+       switch (contextMajorVersion) {
+               case 2:
+                       assert(contextMinorVersion == 1);
+                       assert(contextProfileMask == 0);
+                       m_coreProfile = false;
+                       break;
+               case 3:
+                       // Apple didn't implement 3.0 or 3.1
+                       assert(contextMinorVersion == 2);
+                       assert(contextProfileMask == GL_CONTEXT_CORE_PROFILE_BIT);
+                       m_coreProfile = true;
+                       break;
+               default:
+                       assert(false);
+       }
 }
 
 
@@ -170,6 +187,7 @@ GHOST_TSuccess GHOST_ContextCGL::updateDrawingContext()
 
 static void makeAttribList(
         std::vector<NSOpenGLPixelFormatAttribute>& attribs,
+        bool coreProfile, 
         bool stereoVisual,
         int numOfAASamples,
         bool needAlpha,
@@ -178,6 +196,9 @@ static void makeAttribList(
 {
        attribs.clear();
 
+       attribs.push_back(NSOpenGLPFAOpenGLProfile);
+       attribs.push_back(coreProfile ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy);
+       
        // Pixel Format Attributes for the windowed NSOpenGLContext
        attribs.push_back(NSOpenGLPFADoubleBuffer);
 
@@ -190,8 +211,7 @@ static void makeAttribList(
                attribs.push_back(NSOpenGLPFANoRecovery);
        }
 
-       /* Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway */
-       //attribs.push_back(NSOpenGLPFAAllowOfflineRenderers);
+       attribs.push_back(NSOpenGLPFAAllowOfflineRenderers); // for automatic GPU switching
 
        attribs.push_back(NSOpenGLPFADepthSize);
        attribs.push_back((NSOpenGLPixelFormatAttribute) 32);
@@ -263,7 +283,7 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
        NSOpenGLPixelFormat *pixelFormat;
        // TODO: keep pixel format for subsequent windows/contexts instead of recreating each time
 
-       makeAttribList(attribs, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, softwareGL);
+       makeAttribList(attribs, m_coreProfile, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, softwareGL);
 
        pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
 
@@ -274,7 +294,7 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
                // (Now that I think about it, does WGL really require the code that it has for finding a lesser match?)
 
                attribs.clear();
-               makeAttribList(attribs, m_stereoVisual, 0, needAlpha, needStencil, softwareGL);
+               makeAttribList(attribs, m_coreProfile, m_stereoVisual, 0, needAlpha, needStencil, softwareGL);
                pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
        }
 
@@ -316,7 +336,7 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
                [m_openGLContext release];
 
                // create software GL context
-               makeAttribList(attribs, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, softwareGL);
+               makeAttribList(attribs, m_coreProfile, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, softwareGL);
                pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
                m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:s_sharedOpenGLContext];
                [pixelFormat release];
index 9ac61db40412dde946ac8e5c691e38f08aa0436f..60cdce83602d910993f7c1aa22726ce4f898a6f7 100644 (file)
@@ -255,9 +255,6 @@ const bool GLXEW_ARB_create_context_robustness =
                if (m_contextMajorVersion != 0) {
                        attribs[i++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
                        attribs[i++] = m_contextMajorVersion;
-               }
-
-               if (m_contextMinorVersion != 0) {
                        attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB;
                        attribs[i++] = m_contextMinorVersion;
                }
@@ -300,8 +297,8 @@ const bool GLXEW_ARB_create_context_robustness =
                }
        }
        else {
-               /* Create legacy context */
-               m_context = glXCreateContext(m_display, m_visualInfo, s_sharedContext, True);
+               /* Don't create legacy context */
+               fprintf(stderr, "Warning! GLX_ARB_create_context not available.\n");
        }
 
        GHOST_TSuccess success;
@@ -328,8 +325,14 @@ const bool GLXEW_ARB_create_context_robustness =
 
                version = glGetString(GL_VERSION);
 
-               if (!version || version[0] < '2' || ((version[0] == '2') &&  (version[2] < '1'))) {
-                       fprintf(stderr, "Error! Blender requires OpenGL 2.1 to run. Try updating your drivers.\n");
+#if 0 // enable this when Blender switches to 3.3 core profile
+               if (!version || version[0] < '3' || ((version[0] == '3') && (version[2] < '3'))) {
+                       fprintf(stderr, "Error! Blender requires OpenGL 3.3 to run. Try updating your drivers.\n");
+#else
+               // with Mesa, the closest thing to 3.3 compatibility profile is 3.0
+               if (!version || version[0] < '3') {
+                       fprintf(stderr, "Error! Blender requires OpenGL 3.0 (soon 3.3) to run. Try updating your drivers.\n");
+#endif
                        fflush(stderr);
                        /* ugly, but we get crashes unless a whole bunch of systems are patched. */
                        exit(0);
index 64ee692797b5ee87c861a77bd3a5de837ffa3d5d..39ef63fa723054a030ec154717a0352843c94457 100644 (file)
@@ -962,7 +962,7 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
             strcmp(renderer, "GDI Generic") == 0) && version[0] == '1' && version[2] == '1')
        {
                MessageBox(m_hWnd, "Your system does not use 3D hardware acceleration.\n"
-                                  "Blender requires a graphics driver with OpenGL 2.1 support.\n\n"
+                                  "Blender requires a graphics driver with OpenGL 3.3 support.\n\n"
                                   "This may be caused by:\n"
                                   "* A missing or faulty graphics driver installation.\n"
                                   "  Blender needs a graphics card driver to work correctly.\n"
@@ -973,8 +973,8 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
                           MB_OK | MB_ICONERROR);
                exit(0);
        }
-       else if (version[0] < '2' || (version[0] == '2' && version[2] < '1')) {
-               MessageBox(m_hWnd, "Blender requires a graphics driver with OpenGL 2.1 support.\n\n"
+       else if (version[0] < '3' || (version[0] == '3' && version[2] < '3')) {
+               MessageBox(m_hWnd, "Blender requires a graphics driver with OpenGL 3.3 support.\n\n"
                                   "The program will now close.",
                           "Blender - Unsupported Graphics Driver!",
                           MB_OK | MB_ICONERROR);
index 580b4dcb82f1e29087b40206c0ba05dae7e1989e..99efcc5ebd7d5721d12e28b126fdc81a72be6169 100644 (file)
 extern "C" WGLEWContext *wglewContext;
 #endif
 
-#ifndef GHOST_OPENGL_WGL_CONTEXT_FLAGS
-#  ifdef WITH_GPU_DEBUG
-#    define GHOST_OPENGL_WGL_CONTEXT_FLAGS WGL_CONTEXT_DEBUG_BIT_ARB
-#  else
-#    define GHOST_OPENGL_WGL_CONTEXT_FLAGS 0
-#  endif
-#endif
-
 #ifndef GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY
 #define GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY 0
 #endif
index 97615dcea96b32af675c48154449572d95aba5c8..b0feb11a6afc079a1076cf40542043891d169d25 100644 (file)
@@ -1086,82 +1086,23 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
 GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType type)
 {
        if (type == GHOST_kDrawingContextTypeOpenGL) {
-#if !defined(WITH_GL_EGL)
 
-#if defined(WITH_GL_PROFILE_CORE)
-               GHOST_Context *context = new GHOST_ContextCGL(
-                       m_wantStereoVisual,
-                       m_wantNumOfAASamples,
-                       m_window,
-                       m_openGLView,
-                       GL_CONTEXT_CORE_PROFILE_BIT,
-                       3, 2,
-                       GHOST_OPENGL_CGL_CONTEXT_FLAGS,
-                       GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
-#elif defined(WITH_GL_PROFILE_ES20)
                GHOST_Context *context = new GHOST_ContextCGL(
                        m_wantStereoVisual,
                        m_wantNumOfAASamples,
                        m_window,
                        m_openGLView,
-                       CGL_CONTEXT_ES2_PROFILE_BIT_EXT,
-                       2, 0,
-                       GHOST_OPENGL_CGL_CONTEXT_FLAGS,
-                       GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
-#elif defined(WITH_GL_PROFILE_COMPAT)
-               GHOST_Context *context = new GHOST_ContextCGL(
-                       m_wantStereoVisual,
-                       m_wantNumOfAASamples,
-                       m_window,
-                       m_openGLView,
-                       0, // profile bit
-                       0, 0,
-                       m_debug_context,
-                       GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
-#else
-#  error
-#endif
-
-#else
 
 #if defined(WITH_GL_PROFILE_CORE)
-               GHOST_Context *context = new GHOST_ContextEGL(
-                       m_wantStereoVisual,
-                       m_wantNumOfAASamples,
-                       m_window,
-                       m_openGLView,
-                       EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+                       GL_CONTEXT_CORE_PROFILE_BIT,
                        3, 2,
-                       GHOST_OPENGL_EGL_CONTEXT_FLAGS,
-                       GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
-                       EGL_OPENGL_API);
-#elif defined(WITH_GL_PROFILE_ES20)
-               GHOST_Context *context = new GHOST_ContextEGL(
-                       m_wantStereoVisual,
-                       m_wantNumOfAASamples,
-                       m_window,
-                       m_openGLView,
-                       0, // profile bit
-                       2, 0,
-                       GHOST_OPENGL_EGL_CONTEXT_FLAGS,
-                       GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
-                       EGL_OPENGL_ES_API);
-#elif defined(WITH_GL_PROFILE_COMPAT)
-               GHOST_Context *context = new GHOST_ContextEGL(
-                       m_wantStereoVisual,
-                       m_wantNumOfAASamples,
-                       m_window,
-                       m_openGLView,
-                       0, // profile bit
-                       0, 0,
-                       GHOST_OPENGL_EGL_CONTEXT_FLAGS,
-                       GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
-                       EGL_OPENGL_API);
 #else
-#  error
+                       0, // no profile bit
+                       2, 1,
 #endif
+                       GHOST_OPENGL_CGL_CONTEXT_FLAGS,
+                       GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
 
-#endif
                if (context->initializeDrawingContext())
                        return context;
                else
index 7d80aa43a401fdf1038940a3b8d6a116c4280126..58aa0b87045a0fe9730ff5a7c10ae97abe86ff72 100644 (file)
@@ -610,97 +610,37 @@ GHOST_TSuccess GHOST_WindowWin32::invalidate()
 GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType type)
 {
        if (type == GHOST_kDrawingContextTypeOpenGL) {
-#if !defined(WITH_GL_EGL)
 
+               const int profile_mask =
 #if defined(WITH_GL_PROFILE_CORE)
-               GHOST_Context *context = new GHOST_ContextWGL(
-                       m_wantStereoVisual,
-                       m_wantAlphaBackground,
-                       m_wantNumOfAASamples,
-                       m_hWnd,
-                       m_hDC,
-                       WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
-                       3, 2,
-                       GHOST_OPENGL_WGL_CONTEXT_FLAGS,
-                       GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
-#elif defined(WITH_GL_PROFILE_ES20)
-               GHOST_Context *context = new GHOST_ContextWGL(
-                       m_wantStereoVisual,
-                       m_wantAlphaBackground,
-                       m_wantNumOfAASamples,
-                       m_hWnd,
-                       m_hDC,
-                       WGL_CONTEXT_ES2_PROFILE_BIT_EXT,
-                       2, 0,
-                       GHOST_OPENGL_WGL_CONTEXT_FLAGS,
-                       GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
+                       WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
 #elif defined(WITH_GL_PROFILE_COMPAT)
+                       WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+#else
+#  error // must specify either core or compat at build time
+#endif
+
                GHOST_Context *context = new GHOST_ContextWGL(
                        m_wantStereoVisual,
                        m_wantAlphaBackground,
                        m_wantNumOfAASamples,
                        m_hWnd,
                        m_hDC,
-#if 1
-                       0, // profile bit
-                       2, 1, // GL version requested
+                       profile_mask,
+#if 0
+                       3, 3, // specific GL version requested
+                             // AMD gives us exactly this version
+                             // NVIDIA gives at least this version <-- desired behavior
 #else
-                       // switch to this for Blender 2.8 development
-                       WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
-                       3, 2,
+                       2, 1, // any GL version >= 2.1 (hopefully the latest)
+                             // we check later to ensure it's >= 3.3 on Windows
+                             // TODO(merwin): fix properly!
+                             //               2.1 ignores the profile bit & is incompatible with core profile
+                             //               query version of initial dummy context, request that + profile + debug
 #endif
                        (m_debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
                        GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
-#else
-#  error
-#endif
-
-#else
 
-#if defined(WITH_GL_PROFILE_CORE)
-               GHOST_Context *context = new GHOST_ContextEGL(
-                       m_wantStereoVisual,
-                       m_wantNumOfAASamples,
-                       m_hWnd,
-                       m_hDC,
-                       EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
-                       3, 2,
-                       GHOST_OPENGL_EGL_CONTEXT_FLAGS,
-                       GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
-                       EGL_OPENGL_API);
-#elif defined(WITH_GL_PROFILE_ES20)
-               GHOST_Context *context = new GHOST_ContextEGL(
-                       m_wantStereoVisual,
-                       m_wantNumOfAASamples,
-                       m_hWnd,
-                       m_hDC,
-                       0, // profile bit
-                       2, 0,
-                       GHOST_OPENGL_EGL_CONTEXT_FLAGS,
-                       GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
-                       EGL_OPENGL_ES_API);
-#elif defined(WITH_GL_PROFILE_COMPAT)
-               GHOST_Context *context = new GHOST_ContextEGL(
-                       m_wantStereoVisual,
-                       m_wantNumOfAASamples,
-                       m_hWnd,
-                       m_hDC,
-#if 1
-                       0, // profile bit
-                       2, 1, // GL version requested
-#else
-                       // switch to this for Blender 2.8 development
-                       EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT,
-                       3, 2,
-#endif
-                       GHOST_OPENGL_EGL_CONTEXT_FLAGS,
-                       GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
-                       EGL_OPENGL_API);
-#else
-#  error
-#endif
-
-#endif
                if (context->initializeDrawingContext())
                        return context;
                else
index 47fbe1256b1d363a3e3c1ae07cd54476ccaeb936..992200a0b095a9b23966d884d4be88a65d64fab8 100644 (file)
@@ -1314,33 +1314,24 @@ GHOST_WindowX11::
 GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type)
 {
        if (type == GHOST_kDrawingContextTypeOpenGL) {
-#if !defined(WITH_GL_EGL)
 
+               // During development:
+               //   try 3.3 compatibility profile
+               //   fall back to 3.0 if needed
+               //
+               // Final Blender 2.8:
+               //   try 3.3 core profile
+               //   no fallbacks
+
+               const int profile_mask =
 #if defined(WITH_GL_PROFILE_CORE)
-               GHOST_Context *context = new GHOST_ContextGLX(
-                       m_wantStereoVisual,
-                       m_wantNumOfAASamples,
-                       m_window,
-                       m_display,
-                       m_visualInfo,
-                       (GLXFBConfig)m_fbconfig,
-                       GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
-                       3, 2,
-                       GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
-                       GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
-#elif defined(WITH_GL_PROFILE_ES20)
-               GHOST_Context *context = new GHOST_ContextGLX(
-                       m_wantStereoVisual,
-                       m_wantNumOfAASamples,
-                       m_window,
-                       m_display,
-                       m_visualInfo,
-                       (GLXFBConfig)m_fbconfig,
-                       GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
-                       2, 0,
-                       GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
-                       GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+                       GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
 #elif defined(WITH_GL_PROFILE_COMPAT)
+                       GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+#else
+#  error // must specify either core or compat at build time
+#endif
+
                GHOST_Context *context = new GHOST_ContextGLX(
                        m_wantStereoVisual,
                        m_wantNumOfAASamples,
@@ -1348,58 +1339,34 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
                        m_display,
                        m_visualInfo,
                        (GLXFBConfig)m_fbconfig,
-                       0, // profile bit
-                       0, 0,
+                       profile_mask,
+                       3, 3,
                        GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
                        GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
-#else
-#  error
-#endif
 
-#else
-
-#if defined(WITH_GL_PROFILE_CORE)
-               GHOST_Context *context = new GHOST_ContextEGL(
-                       m_wantStereoVisual,
-                       m_wantNumOfAASamples,
-                       m_window,
-                       m_display,
-                       EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
-                       3, 2,
-                       GHOST_OPENGL_EGL_CONTEXT_FLAGS,
-                       GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
-                       EGL_OPENGL_API);
-#elif defined(WITH_GL_PROFILE_ES20)
-               GHOST_Context *context = new GHOST_ContextEGL(
-                       m_wantStereoVisual,
-                       m_wantNumOfAASamples,
-                       m_window,
-                       m_display,
-                       0, // profile bit
-                       2, 0,
-                       GHOST_OPENGL_EGL_CONTEXT_FLAGS,
-                       GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
-                       EGL_OPENGL_ES_API);
-#elif defined(WITH_GL_PROFILE_COMPAT)
-               GHOST_Context *context = new GHOST_ContextEGL(
-                       m_wantStereoVisual,
-                       m_wantNumOfAASamples,
-                       m_window,
-                       m_display,
-                       0, // profile bit
-                       0, 0,
-                       GHOST_OPENGL_EGL_CONTEXT_FLAGS,
-                       GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
-                       EGL_OPENGL_API);
-#else
-#  error
-#endif
-
-#endif
                if (context->initializeDrawingContext())
                        return context;
-               else
+               else {
                        delete context;
+
+                       // since that failed try 3.0 (mostly for Mesa, which doesn't implement compatibility profile)
+                       context = new GHOST_ContextGLX(
+                               m_wantStereoVisual,
+                               m_wantNumOfAASamples,
+                               m_window,
+                               m_display,
+                               m_visualInfo,
+                               (GLXFBConfig)m_fbconfig,
+                               0, // no profile bit
+                               3, 0,
+                               GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+                               GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+
+                       if (context->initializeDrawingContext())
+                               return context;
+                       else
+                               delete context;
+               }
        }
 
        return NULL;
index 0649a2075cd5e328b126f75ed7690a73ab5e844e..36cb5d2ccafcc2f19b8da7af24d4e3432c84efde 100644 (file)
@@ -2,6 +2,8 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
+       <key>LSMinimumSystemVersion</key>
+       <string>10.7.0</string>
        <key>CFBundleDocumentTypes</key>
        <array>
                <dict>
@@ -47,5 +49,7 @@
        <string>NSApplication</string>
        <key>NSHighResolutionCapable</key>
        <true/>
+       <key>NSSupportsAutomaticGraphicsSwitching</key>
+       <true/>
 </dict>
 </plist>
index 3ebf2691b4c6c41935b37363d64ec8b8d795d185..54581c9276d83dbb32a8868aa1b48918b7ba2c4c 100644 (file)
@@ -64,6 +64,8 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
 
         split = layout.split(percentage=0.25)
 
+        col = split.column()
+
         split.label(text="Presets:")
         sub = split.row(align=True)
         sub.menu("CLOTH_MT_presets", text=bpy.types.CLOTH_MT_presets.bl_label)
index 780dc4cf98290e4e5a4da28b7f570a89b21f3fae..d77113ef7fce692a61dcb2b2cd83e45b9837bb00 100644 (file)
@@ -40,7 +40,7 @@ class INFO_HT_header(Header):
             layout.operator("screen.back_to_previous", icon='SCREEN_BACK', text="Back to Previous")
             layout.separator()
         else:
-            layout.template_ID(context.window, "screen", new="screen.new", unlink="screen.delete")
+            layout.template_ID_preview(context.window, "screen", new="screen.new", unlink="screen.delete", rows=2, cols=6)
             layout.template_ID(context.screen, "scene", new="scene.new", unlink="scene.delete")
 
         layout.separator()
index 5e936076d0e502f6b1ee850d969d95c0af894431..f8e4d1338f9402746378f543417b924af2af4319 100644 (file)
@@ -710,7 +710,6 @@ class VIEW3D_MT_select_particle(Menu):
         layout = self.layout
 
         layout.operator("view3d.select_border")
-        layout.operator("view3d.select_circle")
 
         layout.separator()
 
@@ -3127,6 +3126,47 @@ class VIEW3D_MT_edit_gpencil_interpolate(Menu):
 # ********** Panel **********
 
 
+class VIEW3D_PT_viewport_debug(Panel):
+    bl_space_type = 'VIEW_3D'
+    bl_region_type = 'UI'
+    bl_label = "Modern Viewport"
+    bl_options = {'DEFAULT_CLOSED'}
+
+    @classmethod
+    def poll(cls, context):
+        view = context.space_data
+        return (view)
+
+    def draw_header(self, context):
+        view = context.space_data
+        self.layout.prop(view, "use_modern_viewport", text="")
+
+    def draw(self, context):
+        layout = self.layout
+        view = context.space_data
+
+        layout.active = view.use_modern_viewport
+
+        col = layout.column()
+        col.label(text="Placeholder for debugging options")
+        col.separator()
+
+        row = col.row()
+        row.active = not view.show_combined_depth
+        row.prop(view, "show_scene_depth")
+        row = col.row()
+        row.active = not view.show_scene_depth
+        row.prop(view, "show_combined_depth")
+
+        row = col.row(align=True)
+        row.active = view.show_scene_depth or view.show_combined_depth
+        row.prop(view, "debug_near")
+        row.prop(view, "debug_far")
+
+        col.label(text="Background:")
+        col.row(align=True).prop(view, "debug_background", expand=True)
+
+
 class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
     bl_space_type = 'VIEW_3D'
     bl_region_type = 'UI'
@@ -3240,7 +3280,7 @@ class VIEW3D_PT_view3d_display(Panel):
     @classmethod
     def poll(cls, context):
         view = context.space_data
-        return (view)
+        return (view) and not view.use_modern_viewport
 
     def draw(self, context):
         layout = self.layout
@@ -3340,6 +3380,11 @@ class VIEW3D_PT_view3d_shading(Panel):
     bl_region_type = 'UI'
     bl_label = "Shading"
 
+    @classmethod
+    def poll(cls, context):
+        view = context.space_data
+        return (view) and not view.use_modern_viewport
+
     def draw(self, context):
         layout = self.layout
 
index 1f38d64924c88af54961c7141a70176506802993..3da0434687caceee658c505731725549718864ef 100644 (file)
@@ -34,6 +34,9 @@
 
 #include "BLI_compiler_attrs.h"
 
+/* enable this only if needed (unused circa 2016) */
+#define BLF_BLUR_ENABLE 0
+
 struct rctf;
 struct ColorManagedDisplay;
 struct ResultBLF;
@@ -144,7 +147,10 @@ void BLF_rotation(int fontid, float angle);
 void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax);
 void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax);
 void BLF_wordwrap(int fontid, int wrap_width);
+
+#if BLF_BLUR_ENABLE
 void BLF_blur(int fontid, int size);
+#endif
 
 void BLF_enable(int fontid, int option);
 void BLF_disable(int fontid, int option);
index 132a0ec38086178cecf6394dbb4ca260b1ec820b..1ce4753cc392b02a61ec7a826529641ae5dc5fee 100644 (file)
@@ -56,7 +56,9 @@
 #include "IMB_colormanagement.h"
 
 #ifndef BLF_STANDALONE
-#include "GPU_basic_shader.h"
+#include "GPU_shader.h"
+#include "GPU_matrix.h"
+#include "GPU_immediate.h"
 #endif
 
 #include "blf_internal_types.h"
@@ -453,6 +455,7 @@ void BLF_size(int fontid, int size, int dpi)
        }
 }
 
+#if BLF_BLUR_ENABLE
 void BLF_blur(int fontid, int size)
 {
        FontBLF *font = blf_get(fontid);
@@ -461,6 +464,7 @@ void BLF_blur(int fontid, int size)
                font->blur = size;
        }
 }
+#endif
 
 void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
 {
@@ -490,7 +494,7 @@ void BLF_rotation_default(float angle)
        }
 }
 
-static void blf_draw_gl__start(FontBLF *font, GLint *mode)
+static void blf_draw_gl__start(FontBLF *font)
 {
        /*
         * The pixmap alignment hack is handle
@@ -500,52 +504,48 @@ static void blf_draw_gl__start(FontBLF *font, GLint *mode)
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
-#ifndef BLF_STANDALONE
-       GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
-#endif
-
-       /* Save the current matrix mode. */
-       glGetIntegerv(GL_MATRIX_MODE, mode);
-
-       glMatrixMode(GL_TEXTURE);
-       glPushMatrix();
-       glLoadIdentity();
-
-       glMatrixMode(GL_MODELVIEW);
-       glPushMatrix();
+       gpuMatrixBegin3D_legacy();
 
        if (font->flags & BLF_MATRIX)
-               glMultMatrixf(font->m);
+               gpuMultMatrix3D((float (*)[4])font->m);
 
-       glTranslate3fv(font->pos);
+       gpuTranslate3fv(font->pos);
 
        if (font->flags & BLF_ASPECT)
-               glScalef(font->aspect[0], font->aspect[1], font->aspect[2]);
+               gpuScale3fv(font->aspect);
 
        if (font->flags & BLF_ROTATION)  /* radians -> degrees */
-               glRotatef(font->angle * (float)(180.0 / M_PI), 0.0f, 0.0f, 1.0f);
+               gpuRotateAxis(RAD2DEG(font->angle), 'Z');
+
+       float temp_color[4];
+       glGetFloatv(GL_CURRENT_COLOR, temp_color); /* TODO(merwin): new BLF_color function? */
+       rgba_float_to_uchar(font->color, temp_color);
+
+#ifndef BLF_STANDALONE
+       VertexFormat *format = immVertexFormat();
+       unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+       unsigned texCoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+       unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+       BLI_assert(pos == BLF_POS_ID);
+       BLI_assert(texCoord == BLF_COORD_ID);
+       BLI_assert(color == BLF_COLOR_ID);
 
-       if (font->shadow || font->blur)
-               glGetFloatv(GL_CURRENT_COLOR, font->orig_col);
+       immBindBuiltinProgram(GPU_SHADER_TEXT);
+#endif
 
        /* always bind the texture for the first glyph */
        font->tex_bind_state = -1;
 }
 
-static void blf_draw_gl__end(GLint mode)
+static void blf_draw_gl__end(void)
 {
-       glMatrixMode(GL_TEXTURE);
-       glPopMatrix();
-
-       glMatrixMode(GL_MODELVIEW);
-       glPopMatrix();
-
-       if (mode != GL_MODELVIEW)
-               glMatrixMode(mode);
+       gpuMatrixEnd();
 
 #ifndef BLF_STANDALONE
-       GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+       immUnbindProgram();
 #endif
+
        glDisable(GL_BLEND);
 }
 
@@ -554,23 +554,26 @@ void BLF_draw_ex(
         struct ResultBLF *r_info)
 {
        FontBLF *font = blf_get(fontid);
-       GLint mode;
 
        BLF_RESULT_CHECK_INIT(r_info);
 
        if (font && font->glyph_cache) {
-               blf_draw_gl__start(font, &mode);
+               blf_draw_gl__start(font);
                if (font->flags & BLF_WORD_WRAP) {
                        blf_font_draw__wrap(font, str, len, r_info);
                }
                else {
                        blf_font_draw(font, str, len, r_info);
                }
-               blf_draw_gl__end(mode);
+               blf_draw_gl__end();
        }
 }
 void BLF_draw(int fontid, const char *str, size_t len)
 {
+       if (len == 0 || str[0] == '\0') {
+               return;
+       }
+
        BLF_draw_ex(fontid, str, len, NULL);
 }
 
@@ -579,12 +582,11 @@ void BLF_draw_ascii_ex(
         struct ResultBLF *r_info)
 {
        FontBLF *font = blf_get(fontid);
-       GLint mode;
 
        BLF_RESULT_CHECK_INIT(r_info);
 
        if (font && font->glyph_cache) {
-               blf_draw_gl__start(font, &mode);
+               blf_draw_gl__start(font);
                if (font->flags & BLF_WORD_WRAP) {
                        /* use non-ascii draw function for word-wrap */
                        blf_font_draw__wrap(font, str, len, r_info);
@@ -592,24 +594,31 @@ void BLF_draw_ascii_ex(
                else {
                        blf_font_draw_ascii(font, str, len, r_info);
                }
-               blf_draw_gl__end(mode);
+               blf_draw_gl__end();
        }
 }
 void BLF_draw_ascii(int fontid, const char *str, size_t len)
 {
+       if (len == 0 || str[0] == '\0') {
+               return;
+       }
+
        BLF_draw_ascii_ex(fontid, str, len, NULL);
 }
 
 int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
 {
+       if (len == 0 || str[0] == '\0') {
+               return 0;
+       }
+
        FontBLF *font = blf_get(fontid);
-       GLint mode;
        int columns = 0;
 
        if (font && font->glyph_cache) {
-               blf_draw_gl__start(font, &mode);
+               blf_draw_gl__start(font);
                columns = blf_font_draw_mono(font, str, len, cwidth);
-               blf_draw_gl__end(mode);
+               blf_draw_gl__end();
        }
 
        return columns;
@@ -855,7 +864,7 @@ void BLF_shadow(int fontid, int level, const float rgba[4])
 
        if (font) {
                font->shadow = level;
-               copy_v4_v4(font->shadow_col, rgba);
+               rgba_float_to_uchar(font->shadow_color, rgba);
        }
 }
 
index 44a1d08f1fdb642334b33e545eac1ebde9ec4647..71350a0f8dcbe2f298a2a3b3d5e50f07072047ec 100644 (file)
@@ -58,6 +58,8 @@
 #include "BIF_gl.h"
 #include "BLF_api.h"
 
+#include "GPU_immediate.h"
+
 #include "blf_internal_types.h"
 #include "blf_internal.h"
 
@@ -172,6 +174,23 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
        }                                                                            \
 } (void)0
 
+static unsigned verts_needed(const FontBLF *font, const char *str, size_t len)
+{
+       unsigned length = (unsigned)((len == INT_MAX) ? strlen(str) : len);
+       unsigned quad_ct = 1;
+
+       if (font->flags & BLF_SHADOW) {
+               if (font->shadow == 0)
+                       quad_ct += 1;
+               if (font->shadow <= 4)
+                       quad_ct += 9; /* 3x3 kernel */
+               else
+                       quad_ct += 25; /* 5x5 kernel */
+       }
+
+       return length * quad_ct * 4;
+}
+
 static void blf_font_draw_ex(
         FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
         int pen_y)
@@ -187,6 +206,9 @@ static void blf_font_draw_ex(
 
        blf_font_ensure_ascii_table(font);
 
+       immBeginAtMost(GL_QUADS, verts_needed(font, str, len));
+       /* at most because some glyphs might be clipped & not drawn */
+
        while ((i < len) && str[i]) {
                BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
 
@@ -204,6 +226,8 @@ static void blf_font_draw_ex(
                g_prev = g;
        }
 
+       immEnd();
+
        if (r_info) {
                r_info->lines = 1;
                r_info->width = pen_x;
@@ -229,6 +253,8 @@ static void blf_font_draw_ascii_ex(
 
        blf_font_ensure_ascii_table(font);
 
+       immBeginAtMost(GL_QUADS, verts_needed(font, str, len));
+
        while ((c = *(str++)) && len--) {
                BLI_assert(c < 128);
                if ((g = glyph_ascii_table[c]) == NULL)
@@ -243,6 +269,8 @@ static void blf_font_draw_ascii_ex(
                g_prev = g;
        }
 
+       immEnd();
+
        if (r_info) {
                r_info->lines = 1;
                r_info->width = pen_x;
@@ -265,6 +293,8 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
 
        blf_font_ensure_ascii_table(font);
 
+       immBeginAtMost(GL_QUADS, verts_needed(font, str, len));
+
        while ((i < len) && str[i]) {
                BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
 
@@ -284,6 +314,8 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
                pen_x += cwidth * col;
        }
 
+       immEnd();
+
        return columns;
 }
 
@@ -922,7 +954,9 @@ static void blf_font_fill(FontBLF *font)
        font->size = 0;
        BLI_listbase_clear(&font->cache);
        font->glyph_cache = NULL;
+#if BLF_BLUR_ENABLE
        font->blur = 0;
+#endif
        font->max_tex_size = -1;
 
        font->buf_info.fbuf = NULL;
index aa7d539538b0249c71c1656c0280414e8efa2628..b1bab13f3ae23b66a61c8e611e2ac1556cb52219 100644 (file)
@@ -56,7 +56,7 @@
 #include "BLF_api.h"
 
 #ifndef BLF_STANDALONE
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
 #endif
 
 #include "blf_internal_types.h"
@@ -182,17 +182,6 @@ static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
-#ifndef BLF_STANDALONE
-       /* needed since basic shader doesn't support alpha-only textures,
-        * while we could add support this is only used in a few places
-        * (an alternative could be to have a simple shader for BLF). */
-       if (GLEW_ARB_texture_swizzle && GPU_basic_shader_use_glsl_get()) {
-               GLint swizzle_mask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
-               glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_mask);
-       }
-#endif
-
        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, gc->p2_width, gc->p2_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL);
 }
 
@@ -326,73 +315,73 @@ void blf_glyph_free(GlyphBLF *g)
        MEM_freeN(g);
 }
 
-static void blf_texture_draw(float uv[2][2], float dx, float y1, float dx1, float y2)
+static void blf_texture_draw(const unsigned char color[4], float uv[2][2], float dx, float y1, float dx1, float y2)
 {
-       glBegin(GL_QUADS);
-       glTexCoord2f(uv[0][0], uv[0][1]);
-       glVertex2f(dx, y1);
-       
-       glTexCoord2f(uv[0][0], uv[1][1]);
-       glVertex2f(dx, y2);
-       
-       glTexCoord2f(uv[1][0], uv[1][1]);
-       glVertex2f(dx1, y2);
-       
-       glTexCoord2f(uv[1][0], uv[0][1]);
-       glVertex2f(dx1, y1);
-       glEnd();
+       immAttrib2f(BLF_COORD_ID, uv[0][0], uv[0][1]);
+       immSkipAttrib(BLF_COLOR_ID); /* skip color of most vertices */
+       immVertex2f(BLF_POS_ID, dx, y1);
+
+       immAttrib2f(BLF_COORD_ID, uv[0][0], uv[1][1]);
+       immSkipAttrib(BLF_COLOR_ID);
+       immVertex2f(BLF_POS_ID, dx, y2);
+
+       immAttrib2f(BLF_COORD_ID, uv[1][0], uv[1][1]);
+       immSkipAttrib(BLF_COLOR_ID);
+       immVertex2f(BLF_POS_ID, dx1, y2);
+
+       immAttrib2f(BLF_COORD_ID, uv[1][0], uv[0][1]);
+       immAttrib4ubv(BLF_COLOR_ID, color); /* set color of provoking vertex */
+       immVertex2f(BLF_POS_ID, dx1, y1);
 }
 
-static void blf_texture5_draw(const float shadow_col[4], float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture5_draw(const unsigned char color_in[4], float uv[2][2], float x1, float y1, float x2, float y2)
 {
        const float soft[25] = {1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f,
                                1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
                                2 / 60.0f, 5 / 60.0f, 8 / 60.0f, 5 / 60.0f, 2 / 60.0f,
                                1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
                                1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f};
-       
+
        const float *fp = soft;
-       float color[4];
+       unsigned char color[4];
        float dx, dy;
 
-       color[0] = shadow_col[0];
-       color[1] = shadow_col[1];
-       color[2] = shadow_col[2];
-       
+       color[0] = color_in[0];
+       color[1] = color_in[1];
+       color[2] = color_in[2];
+
+       const float alpha_in = (1 / 255.0f) * color_in[3];
+
        for (dx = -2; dx < 3; dx++) {
                for (dy = -2; dy < 3; dy++, fp++) {
-                       color[3] = *(fp) * shadow_col[3];
-                       glColor4fv(color);
-                       blf_texture_draw(uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
+                       color[3] = FTOCHAR(*fp * alpha_in);
+                       blf_texture_draw(color, uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
                }
        }
-       
-       glColor4fv(color);
 }
 
-static void blf_texture3_draw(const float shadow_col[4], float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture3_draw(const unsigned char color_in[4], float uv[2][2], float x1, float y1, float x2, float y2)
 {
        const float soft[9] = {1 / 16.0f, 2 / 16.0f, 1 / 16.0f,
                               2 / 16.0f, 4 / 16.0f, 2 / 16.0f,
                               1 / 16.0f, 2 / 16.0f, 1 / 16.0f};
 
        const float *fp = soft;
-       float color[4];
+       unsigned char color[4];
        float dx, dy;
 
-       color[0] = shadow_col[0];
-       color[1] = shadow_col[1];
-       color[2] = shadow_col[2];
+       color[0] = color_in[0];
+       color[1] = color_in[1];
+       color[2] = color_in[2];
+
+       const float alpha_in = (1 / 255.0f) * color_in[3];
 
        for (dx = -1; dx < 2; dx++) {
                for (dy = -1; dy < 2; dy++, fp++) {
-                       color[3] = *(fp) * shadow_col[3];
-                       glColor4fv(color);
-                       blf_texture_draw(uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
+                       color[3] = FTOCHAR(*fp * alpha_in);
+                       blf_texture_draw(color, uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
                }
        }
-       
-       glColor4fv(color);
 }
 
 static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
@@ -486,39 +475,37 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
                glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = g->tex));
        }
 
+       /* TODO: blur & shadow in shader, single quad per glyph */
+
        if (font->flags & BLF_SHADOW) {
                rctf rect_ofs;
                blf_glyph_calc_rect(&rect_ofs, g,
                                    x + (float)font->shadow_x,
                                    y + (float)font->shadow_y);
 
-               switch (font->shadow) {
-                       case 3:
-                               blf_texture3_draw(font->shadow_col, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
-                               break;
-                       case 5:
-                               blf_texture5_draw(font->shadow_col, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
-                               break;
-                       default:
-                               glColor4fv(font->shadow_col);
-                               blf_texture_draw(g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
-                               break;
+               if (font->shadow == 0) {
+                       blf_texture_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+               }
+               else if (font->shadow <= 4) {
+                       blf_texture3_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+               }
+               else {
+                       blf_texture5_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
                }
-
-               glColor4fv(font->orig_col);
        }
 
+#if BLF_BLUR_ENABLE
        switch (font->blur) {
                case 3:
-                       blf_texture3_draw(font->orig_col, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+                       blf_texture3_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
                        break;
                case 5:
-                       blf_texture5_draw(font->orig_col, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+                       blf_texture5_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
                        break;
                default:
-                       blf_texture_draw(g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
-                       break;
+                       blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
        }
-
-       return;
+#else
+       blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+#endif
 }
index d9d758ce548b84c7b04183dca01bd1fd83400269..ba17e0503997a63b80aa2ceb54467bb1a851f9b6 100644 (file)
@@ -37,6 +37,11 @@ struct GlyphBLF;
 struct GlyphCacheBLF;
 struct rctf;
 
+/* vertex attribute IDs (fixed IDs so we don't have to pass them around) */
+#define BLF_POS_ID 0
+#define BLF_COORD_ID 1
+#define BLF_COLOR_ID 2
+
 unsigned int blf_next_p2(unsigned int x);
 unsigned int blf_hash(unsigned int val);
 
index 0fac576a8ccb399cb00050100bf26d6a9cfb2ad0..9164a02b2ccf5684cb3be4a73e7ba2528bcc09d0 100644 (file)
@@ -175,8 +175,10 @@ typedef struct FontBLF {
        /* angle in radians. */
        float angle;
        
+#if 0 /* BLF_BLUR_ENABLE */
        /* blur: 3 or 5 large kernel */
        int blur;
+#endif
 
        /* shadow level. */
        int shadow;
@@ -186,10 +188,10 @@ typedef struct FontBLF {
        int shadow_y;
 
        /* shadow color. */
-       float shadow_col[4];
+       unsigned char shadow_color[4];
 
-       /* store color here when drawing shadow or blur. */
-       float orig_col[4];
+       /* main text color. */
+       unsigned char color[4];
 
        /* Multiplied this matrix with the current one before
         * draw the text! see blf_draw__start.
index 789bc8df7e50a303a83605eacfa0e99437f88efe..059f7309cf588b740921edaa2b615da8db739597 100644 (file)
@@ -145,6 +145,10 @@ typedef DMDrawOption (*DMSetDrawOptions)(void *userData, int index);
 typedef DMDrawOption (*DMSetDrawOptionsMappedTex)(void *userData, int origindex, int mat_nr);
 typedef DMDrawOption (*DMSetDrawOptionsTex)(struct MTexPoly *mtexpoly, const bool has_vcol, int matnr);
 
+/* Cleanup callback type */
+typedef void (*DMCleanupBatchCache)(void *batchCache);
+void DM_set_batch_cleanup_callback(DMCleanupBatchCache);
+
 typedef enum DMDrawFlag {
        DM_DRAW_USE_COLORS          = (1 << 0),
        DM_DRAW_ALWAYS_SMOOTH       = (1 << 1),
@@ -183,6 +187,7 @@ struct DerivedMesh {
        int deformedOnly; /* set by modifier stack if only deformed from original */
        BVHCache *bvhCache;
        struct GPUDrawObject *drawObject;
+       void *batchCache;
        DerivedMeshType type;
        float auto_bump_scale;
        DMDirtyFlag dirty;
index 14e978b23f239c4446c88a193b246237aa2283bf..010810ad0cc7abc517abc6e4e548846d4abd60d4 100644 (file)
@@ -49,6 +49,7 @@ struct bScreen;
 struct uiLayout;
 struct uiList;
 struct wmKeyConfig;
+struct wmManipulatorMap;
 struct wmNotifier;
 struct wmWindow;
 struct wmWindowManager;
@@ -96,6 +97,9 @@ typedef struct SpaceType {
        /* on startup, define dropboxes for spacetype+regions */
        void (*dropboxes)(void);
 
+       /* initialize manipulator-map-types and manipulator-group-types with the region */
+       void (*manipulators)(void);
+
        /* return context data */
        int (*context)(const struct bContext *, const char *, struct bContextDataResult *);
 
@@ -284,6 +288,8 @@ void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID
 struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar);
 void            BKE_area_region_free(struct SpaceType *st, struct ARegion *ar);
 void            BKE_screen_area_free(struct ScrArea *sa);
+/* Manipulator-maps of a region need to be freed with the region. Uses callback to avoid low-level call. */
+void BKE_region_callback_free_manipulatormap_set(void (*callback)(struct wmManipulatorMap *));
 
 struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type);
 struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa);
index 1f937d837b41ca6a87d679faa769b1e6aea1414f..fb0087aefac1e1aa32ad08b9094b86da2862a3f5 100644 (file)
@@ -260,6 +260,12 @@ static CustomData *dm_getPolyCData(DerivedMesh *dm)
        return &dm->polyData;
 }
 
+static DMCleanupBatchCache cleanupBatchCache = NULL;
+void DM_set_batch_cleanup_callback(DMCleanupBatchCache func)
+{
+       cleanupBatchCache = func;
+}
+
 /**
  * Utility function to initialize a DerivedMesh's function pointers to
  * the default implementation (for those functions which have a default)
@@ -317,7 +323,9 @@ void DM_init(
        dm->numPolyData = numPolys;
 
        DM_init_funcs(dm);
-       
+
+       dm->batchCache = NULL; /* necessary? dm->drawObject is not set to NULL yet it works fine */
+
        dm->needsFree = 1;
        dm->auto_bump_scale = -1.0f;
        dm->dirty = 0;
@@ -377,6 +385,10 @@ int DM_release(DerivedMesh *dm)
        if (dm->needsFree) {
                bvhcache_free(&dm->bvhCache);
                GPU_drawobject_free(dm);
+               if (dm->batchCache && cleanupBatchCache) {
+                       cleanupBatchCache(dm->batchCache);
+                       dm->batchCache = NULL;
+               }
                CustomData_free(&dm->vertData, dm->numVertData);
                CustomData_free(&dm->edgeData, dm->numEdgeData);
                CustomData_free(&dm->faceData, dm->numTessFaceData);
index 28ef3f6f24819d7e8db4da59606d96c6398f49ac..162525c7cd527e606526ccd85c6a5c53c5ddd726 100644 (file)
@@ -478,7 +478,6 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
                return;
        }
 
-       if (!can_simulate)
                return;
 
        /* if on second frame, write cache for first frame */
index 1d198e36e058d9d2439bcb34272d4bc48a178818..1e8d0f0d767a56b3b17aa1cec8047e68f77f436b 100644 (file)
@@ -5562,8 +5562,6 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
                                                dynamicPaint_updateBrushMaterials(brushObj, brush->mat, scene, &bMats);
 
                                        /* Apply brush on the surface depending on it's collision type */
-                                       /* Particle brush: */
-                                       if (brush->collision == MOD_DPAINT_COL_PSYS) {
                                                if (brush->psys && brush->psys->part &&
                                                    ELEM(brush->psys->part->type, PART_EMITTER, PART_FLUID) &&
                                                    psys_check_enabled(brushObj, brush->psys, G.is_rendering))
@@ -5573,9 +5571,8 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
                                                                                      BKE_scene_frame_get(scene), ADT_RECALC_ANIM);
                                                        dynamicPaint_paintParticles(surface, brush->psys, brush, timescale);
                                                }
-                                       }
                                        /* Object center distance: */
-                                       else if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) {
+                                       if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) {
                                                dynamicPaint_paintSinglePoint(surface, brushObj->loc, brush, brushObj, &bMats, scene, timescale);
                                        }
                                        /* Mesh volume/proximity: */
index 7669c4ba112b747aa46f67e6537a3414c80cb8b6..70cf0d5a4456b95c05302588d6a7e3abd56f0fd5 100644 (file)
@@ -42,6 +42,7 @@
 #include "DNA_material_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
 #include "DNA_texture_types.h"
 #include "DNA_world_types.h"
 #include "DNA_brush_types.h"
@@ -252,6 +253,7 @@ PreviewImage **BKE_previewimg_id_get_p(ID *id)
                ID_PRV_CASE(ID_OB, Object);
                ID_PRV_CASE(ID_GR, Group);
                ID_PRV_CASE(ID_SCE, Scene);
+               ID_PRV_CASE(ID_SCR, bScreen);
 #undef ID_PRV_CASE
        }
 
index 64535f229a918ef03f418b9aee4319caccfabc9f..056e302eee28d6f4078ea370007c23b204f04c45 100644 (file)
@@ -1208,41 +1208,41 @@ void BKE_main_free(Main *mainvar)
                        /* errors freeing ID's can be hard to track down,
                         * enable this so valgrind will give the line number in its error log */
                        switch (a) {
-                               case   0: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case   1: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case   2: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case   3: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case   4: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case   5: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case   6: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case   7: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case   8: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case   9: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  10: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  11: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  12: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  13: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  14: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  15: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  16: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  17: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  18: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  19: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  20: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  21: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  22: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  23: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  24: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  25: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  26: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  27: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  28: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  29: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  30: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  31: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  32: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  33: BKE_libblock_free_ex(mainvar, id, false, false); break;
-                               case  34: BKE_libblock_free_ex(mainvar, id, false, false); break;
+                               case   0: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case   1: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case   2: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case   3: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case   4: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case   5: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case   6: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case   7: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case   8: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case   9: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  10: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  11: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  12: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  13: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  14: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  15: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  16: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  17: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  18: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  19: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  20: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  21: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  22: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  23: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  24: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  25: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  26: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  27: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  28: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  29: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  30: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  31: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  32: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  33: BKE_libblock_free_ex(mainvar, id, false); break;
+                               case  34: BKE_libblock_free_ex(mainvar, id, false); break;
                                default:
                                        BLI_assert(0);
                                        break;
index fa75c906fb19edf33cebdf08af6d31ad7ed50ca1..bfc26fcac0f54afc08ce769109d53d863deb3244 100644 (file)
@@ -63,7 +63,6 @@
 #include "DNA_world_types.h"
 
 #include "BLI_utildefines.h"
-#include "BLI_listbase.h"
 #include "BLI_ghash.h"
 #include "BLI_linklist_stack.h"
 
@@ -405,7 +404,6 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
                                        CALLBACK_INVOKE(toolsett->particle.scene, IDWALK_NOP);
                                        CALLBACK_INVOKE(toolsett->particle.object, IDWALK_NOP);
                                        CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_NOP);
-
                                        library_foreach_paint(&data, &toolsett->imapaint.paint);
                                        CALLBACK_INVOKE(toolsett->imapaint.stencil, IDWALK_USER);
                                        CALLBACK_INVOKE(toolsett->imapaint.clone, IDWALK_USER);
@@ -945,7 +943,7 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id
                        /* Could be the following, but simpler to just always say 'yes' here. */
 #if 0
                        return ELEM(id_type_used, ID_ME, ID_CU, ID_MB, ID_LT, ID_SPK, ID_AR, ID_LA, ID_CA,  /* obdata */
-                                                 ID_OB, ID_MA, ID_GD, ID_GR, ID_TE, ID_PA, ID_TXT, ID_SO, ID_MC, ID_IM, ID_AC
+                                                 ID_OB, ID_MA, ID_GD, ID_GR, ID_TE, ID_TXT, ID_SO, ID_MC, ID_IM, ID_AC
                                                  /* + constraints, modifiers and game logic ID types... */);
 #else
                        return true;
index b5f34a29ebbc4bfe62c88aa5b17151d3aa1ef9ab..6f86c68dc072f18e150a2ee2052701e492d78551 100644 (file)
@@ -1589,7 +1589,7 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
        }
 
        /* advance simulation, we can only step one frame forward */
-       if (can_simulate) {
+       if (ctime == rbw->ltime + 1) {
                /* write cache for first frame when on second frame */
                if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) {
                        BKE_ptcache_write(&pid, startframe);
index 857bd5447c8546afe3aeab182bcc6016316bc079..c5d00d63b6dedc673a6239029c0fc9a38f4b47eb 100644 (file)
@@ -50,6 +50,7 @@
 #include "BLI_utildefines.h"
 #include "BLI_rect.h"
 
+#include "BKE_icons.h"
 #include "BKE_idprop.h"
 #include "BKE_screen.h"
 
@@ -180,6 +181,7 @@ ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar)
        BLI_listbase_clear(&newar->panels_category_active);
        BLI_listbase_clear(&newar->ui_lists);
        newar->swinid = 0;
+       newar->manipulator_map = NULL;
        newar->regiontimer = NULL;
        
        /* use optional regiondata callback */
@@ -288,6 +290,17 @@ void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID
        }
 }
 
+
+/**
+ * Avoid bad-level calls to #WM_manipulatormap_delete.
+ */
+static void (*region_free_manipulatormap_callback)(struct wmManipulatorMap *) = NULL;
+
+void BKE_region_callback_free_manipulatormap_set(void (*callback)(struct wmManipulatorMap *))
+{
+       region_free_manipulatormap_callback = callback;
+}
+
 /* not region itself */
 void BKE_area_region_free(SpaceType *st, ARegion *ar)
 {
@@ -337,6 +350,8 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
                        MEM_freeN(uilst->properties);
                }
        }
+
+       region_free_manipulatormap_callback(ar->manipulator_map);
        BLI_freelistN(&ar->ui_lists);
        BLI_freelistN(&ar->ui_previews);
        BLI_freelistN(&ar->panels_category);
@@ -380,6 +395,8 @@ void BKE_screen_free(bScreen *sc)
        BLI_freelistN(&sc->vertbase);
        BLI_freelistN(&sc->edgebase);
        BLI_freelistN(&sc->areabase);
+
+       BKE_previewimg_free(&sc->preview);
 }
 
 /* for depsgraph */
index 03cf33083dacd13ae4ddd8083933e78c79a57e89..660107eb2e65e2515219249db52ad34e9033d2c9 100644 (file)
@@ -3650,7 +3650,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
        float dtime, timescale;
        int framedelta, framenr, startframe, endframe;
        int cache_result;
-
        cache= sb->pointcache;
 
        framenr= (int)cfra;
@@ -3719,7 +3718,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
        }
 
        /* try to read from cache */
-       bool can_simulate = (framenr == sb->last_frame+1) && !(cache->flag & PTCACHE_BAKED);
+       bool can_simulate = (framenr == sb->last_frame + 1) && !(cache->flag & PTCACHE_BAKED);
 
        cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate);
 
index 5e6b1256d309dcbd529d3e4c56d38b411de80c0e..c7abe6192f77730ef1f5f96058214b993f7bd3d8 100644 (file)
@@ -142,6 +142,7 @@ MINLINE void float_to_byte_dither_v3(unsigned char b[3], const float f[3], float
        rgba_char_args_set(col, (r) * 255, (g) * 255, (b) * 255, (a) * 255)
 
 MINLINE void rgba_char_args_set(char col[4], const char r, const char g, const char b, const char a);
+MINLINE void rgba_float_args_set(float col[4], const float r, const float g, const float b, const float a);
 MINLINE void rgba_char_args_test_set(char col[4], const char r, const char g, const char b, const char a);
 MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack);
 
index d0dfad2a02ffd4e32dae5ff3a4d35e5e424198a6..029f6872b048ef3cb96aa526297c0fd8c4dde3b6 100644 (file)
@@ -46,31 +46,43 @@ void unit_m2(float R[2][2]);
 void unit_m3(float R[3][3]);
 void unit_m4(float R[4][4]);
 
-void copy_m2_m2(float R[2][2], float A[2][2]);
-void copy_m3_m3(float R[3][3], float A[3][3]);
-void copy_m4_m4(float R[4][4], float A[4][4]);
-void copy_m3_m4(float R[3][3], float A[4][4]);
-void copy_m4_m3(float R[4][4], float A[3][3]);
+void copy_m2_m2(float R[2][2], const float A[2][2]);
+void copy_m3_m3(float R[3][3], const float A[3][3]);
+void copy_m4_m4(float R[4][4], const float A[4][4]);
+void copy_m3_m4(float R[3][3], const float A[4][4]);
+void copy_m4_m3(float R[4][4], const float A[3][3]);
 
 /* double->float */
-void copy_m3_m3d(float R[3][3], double A[3][3]);
+void copy_m3_m3d(float R[3][3], const double A[3][3]);
 
 void swap_m3m3(float A[3][3], float B[3][3]);
 void swap_m4m4(float A[4][4], float B[4][4]);
 
 /******************************** Arithmetic *********************************/
 
-void add_m3_m3m3(float R[3][3], float A[3][3], float B[3][3]);
-void add_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
+void add_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]);
+void add_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4]);
 
-void sub_m3_m3m3(float R[3][3], float A[3][3], float B[3][3]);
-void sub_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
+void sub_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]);
+void sub_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4]);
 
-void mul_m3_m3m3(float R[3][3], float A[3][3], float B[3][3]);
-void mul_m4_m3m4(float R[4][4], float A[3][3], float B[4][4]);
-void mul_m4_m4m3(float R[4][4], float A[4][4], float B[3][3]);
-void mul_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
-void mul_m3_m3m4(float R[3][3], float A[4][4], float B[3][3]);
+void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]);
+void mul_m4_m3m4(float R[4][4], const float A[3][3], const float B[4][4]);
+void mul_m4_m4m3(float R[4][4], const float A[4][4], const float B[3][3]);
+void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4]);
+void mul_m3_m3m4(float R[3][3], const float A[4][4], const float B[3][3]);
+
+/* special matrix multiplies
+ * uniq: R <-- AB, R is neither A nor B
+ * pre:  R <-- AR
+ * post: R <-- RB
+ */
+void mul_m3_m3m3_uniq(float R[3][3], const float A[3][3], const float B[3][3]);
+void mul_m3_m3_pre(float R[3][3], const float A[3][3]);
+void mul_m3_m3_post(float R[3][3], const float B[3][3]);
+void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4]);
+void mul_m4_m4_pre(float R[4][4], const float A[4][4]);
+void mul_m4_m4_post(float R[4][4], const float B[4][4]);
 
 /* mul_m3_series */
 void _va_mul_m3_series_3(float R[3][3], float M1[3][3], float M2[3][3]) ATTR_NONNULL();
@@ -100,27 +112,28 @@ void _va_mul_m4_series_9(float R[4][4], float M1[4][4], float M2[4][4], float M3
 #define mul_m3_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m3_series_, __VA_ARGS__)
 #define mul_m4_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m4_series_, __VA_ARGS__)
 
-void mul_m4_v3(float M[4][4], float r[3]);
-void mul_v3_m4v3(float r[3], float M[4][4], const float v[3]);
-void mul_v2_m4v3(float r[2], float M[4][4], const float v[3]);
-void mul_v2_m2v2(float r[2], float M[2][2], const float v[2]);
-void mul_m2v2(float M[2][2], float v[2]);
-void mul_mat3_m4_v3(float M[4][4], float r[3]);
-void mul_v3_mat3_m4v3(float r[3], float M[4][4], const float v[3]);
-void mul_m4_v4(float M[4][4], float r[4]);
-void mul_v4_m4v4(float r[4], float M[4][4], const float v[4]);
-void mul_project_m4_v3(float M[4][4], float vec[3]);
-void mul_v3_project_m4_v3(float r[3], float mat[4][4], const float vec[3]);
-void mul_v2_project_m4_v3(float r[2], float M[4][4], const float vec[3]);
-
-void mul_m3_v2(float m[3][3], float r[2]);
-void mul_v2_m3v2(float r[2], float m[3][3], float v[2]);
-void mul_m3_v3(float M[3][3], float r[3]);
-void mul_v3_m3v3(float r[3], float M[3][3], const float a[3]);
-void mul_v2_m3v3(float r[2], float M[3][3], const float a[3]);
-void mul_transposed_m3_v3(float M[3][3], float r[3]);
-void mul_transposed_mat3_m4_v3(float M[4][4], float r[3]);
-void mul_m3_v3_double(float M[3][3], double r[3]);
+void mul_m4_v3(const float M[4][4], float r[3]);
+void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3]);
+void mul_v2_m4v3(float r[2], const float M[4][4], const float v[3]);
+void mul_v2_m2v2(float r[2], const float M[2][2], const float v[2]);
+void mul_m2v2(const float M[2][2], float v[2]);
+void mul_mat3_m4_v3(const float M[4][4], float r[3]);
+void mul_v3_mat3_m4v3(float r[3], const float M[4][4], const float v[3]);
+void mul_m4_v4(const float M[4][4], float r[4]);
+void mul_v4_m4v4(float r[4], const float M[4][4], const float v[4]);
+void mul_v4_m4v3(float r[4], const float M[4][4], const float v[3]); /* v has implicit w = 1.0f */
+void mul_project_m4_v3(const float M[4][4], float vec[3]);
+void mul_v3_project_m4_v3(float r[3], const float mat[4][4], const float vec[3]);
+void mul_v2_project_m4_v3(float r[2], const float M[4][4], const float vec[3]);
+
+void mul_m3_v2(const float m[3][3], float r[2]);
+void mul_v2_m3v2(float r[2], const float m[3][3], const float v[2]);
+void mul_m3_v3(const float M[3][3], float r[3]);
+void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3]);
+void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3]);
+void mul_transposed_m3_v3(const float M[3][3], float r[3]);
+void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3]);
+void mul_m3_v3_double(const float M[3][3], double r[3]);
 
 void mul_m3_fl(float R[3][3], float f);
 void mul_m4_fl(float R[4][4], float f);
@@ -131,102 +144,102 @@ void negate_mat3_m4(float R[4][4]);
 void negate_m4(float R[4][4]);
 
 bool invert_m3_ex(float m[3][3], const float epsilon);
-bool invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon);
+bool invert_m3_m3_ex(float m1[3][3], const float m2[3][3], const float epsilon);
 
 bool invert_m3(float R[3][3]);
-bool invert_m3_m3(float R[3][3], float A[3][3]);
+bool invert_m3_m3(float R[3][3], const float A[3][3]);
 bool invert_m4(float R[4][4]);
-bool invert_m4_m4(float R[4][4], float A[4][4]);
+bool invert_m4_m4(float R[4][4], const float A[4][4]);
 
 /* double arithmetic (mixed float/double) */
-void mul_m4_v4d(float M[4][4], double r[4]);
-void mul_v4d_m4v4d(double r[4], float M[4][4], double v[4]);
+void mul_m4_v4d(const float M[4][4], double r[4]);
+void mul_v4d_m4v4d(double r[4], const float M[4][4], const double v[4]);
 
 /* double matrix functions (no mixing types) */
-void mul_v3_m3v3_db(double r[3], double M[3][3], const double a[3]);
-void mul_m3_v3_db(double M[3][3], double r[3]);
+void mul_v3_m3v3_db(double r[3], const double M[3][3], const double a[3]);
+void mul_m3_v3_db(const double M[3][3], double r[3]);
 
 
 /****************************** Linear Algebra *******************************/
 
 void transpose_m3(float R[3][3]);
-void transpose_m3_m3(float R[3][3], float A[3][3]);
-void transpose_m3_m4(float R[3][3], float A[4][4]);
+void transpose_m3_m3(float R[3][3], const float A[3][3]);
+void transpose_m3_m4(float R[3][3], const float A[4][4]);
 void transpose_m4(float R[4][4]);
-void transpose_m4_m4(float R[4][4], float A[4][4]);
+void transpose_m4_m4(float R[4][4], const float A[4][4]);
 
-int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit);
+int compare_m4m4(const float mat1[4][4], const float mat2[4][4], float limit);
 
 void normalize_m3_ex(float R[3][3], float r_scale[3]) ATTR_NONNULL();
 void normalize_m3(float R[3][3]) ATTR_NONNULL();
-void normalize_m3_m3_ex(float R[3][3], float A[3][3], float r_scale[3]) ATTR_NONNULL();
-void normalize_m3_m3(float R[3][3], float A[3][3]) ATTR_NONNULL();
+void normalize_m3_m3_ex(float R[3][3], const float A[3][3], float r_scale[3]) ATTR_NONNULL();
+void normalize_m3_m3(float R[3][3], const float A[3][3]) ATTR_NONNULL();
 void normalize_m4_ex(float R[4][4], float r_scale[3]) ATTR_NONNULL();
 void normalize_m4(float R[4][4]) ATTR_NONNULL();
-void normalize_m4_m4_ex(float R[4][4], float A[4][4], float r_scale[3]) ATTR_NONNULL();
-void normalize_m4_m4(float R[4][4], float A[4][4]) ATTR_NONNULL();
+void normalize_m4_m4_ex(float R[4][4], const float A[4][4], float r_scale[3]) ATTR_NONNULL();
+void normalize_m4_m4(float R[4][4],const float A[4][4]) ATTR_NONNULL();
 
 void orthogonalize_m3(float R[3][3], int axis);
 void orthogonalize_m4(float R[4][4], int axis);
 
-bool is_orthogonal_m3(float mat[3][3]);
-bool is_orthogonal_m4(float mat[4][4]);
-bool is_orthonormal_m3(float mat[3][3]);
-bool is_orthonormal_m4(float mat[4][4]);
+bool is_orthogonal_m3(const float mat[3][3]);
+bool is_orthogonal_m4(const float mat[4][4]);
+bool is_orthonormal_m3(const float mat[3][3]);
+bool is_orthonormal_m4(const float mat[4][4]);
 
-bool is_uniform_scaled_m3(float mat[3][3]);
-bool is_uniform_scaled_m4(float m[4][4]);
+bool is_uniform_scaled_m3(const float mat[3][3]);
+bool is_uniform_scaled_m4(const float m[4][4]);
 
 /* Note: 'adjoint' here means the adjugate (adjunct, "classical adjoint") matrix!
  * Nowadays 'adjoint' usually refers to the conjugate transpose,
  * which for real-valued matrices is simply the transpose.
  */
-void adjoint_m2_m2(float R[2][2], float A[2][2]);
-void adjoint_m3_m3(float R[3][3], float A[3][3]);
-void adjoint_m4_m4(float R[4][4], float A[4][4]);
+void adjoint_m2_m2(float R[2][2], const float A[2][2]);
+void adjoint_m3_m3(float R[3][3], const float A[3][3]);
+void adjoint_m4_m4(float R[4][4], const float A[4][4]);
 
 float determinant_m2(float a, float b,
                      float c, float d);
 float determinant_m3(float a, float b, float c,
                      float d, float e, float f,
                      float g, float h, float i);
-float determinant_m3_array(float m[3][3]);
-float determinant_m4(float A[4][4]);
+float determinant_m3_array(const float m[3][3]);
+float determinant_m4(const float A[4][4]);
 
 #define PSEUDOINVERSE_EPSILON 1e-8f
 
 void svd_m4(float U[4][4], float s[4], float V[4][4], float A[4][4]);
-void pseudoinverse_m4_m4(float Ainv[4][4], float A[4][4], float epsilon);
-void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon);
+void pseudoinverse_m4_m4(float Ainv[4][4], const float A[4][4], float epsilon);
+void pseudoinverse_m3_m3(float Ainv[3][3], const float A[3][3], float epsilon);
 
-bool has_zero_axis_m4(float matrix[4][4]);
+bool has_zero_axis_m4(const float matrix[4][4]);
 
-void invert_m4_m4_safe(float Ainv[4][4], float A[4][4]);
+void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4]);
 
 /****************************** Transformations ******************************/
 
 void scale_m3_fl(float R[3][3], float scale);
 void scale_m4_fl(float R[4][4], float scale);
 
-float mat3_to_scale(float M[3][3]);
-float mat4_to_scale(float M[4][4]);
+float mat3_to_scale(const float M[3][3]);
+float mat4_to_scale(const float M[4][4]);
 
 void size_to_mat3(float R[3][3], const float size[3]);
 void size_to_mat4(float R[4][4], const float size[3]);
 
-void mat3_to_size(float r[3], float M[3][3]);
-void mat4_to_size(float r[3], float M[4][4]);
+void mat3_to_size(float r[3], const float M[3][3]);
+void mat4_to_size(float r[3], const float M[4][4]);
 
 void translate_m4(float mat[4][4], float tx, float ty, float tz);
 void rotate_m4(float mat[4][4], const char axis, const float angle);
 void transform_pivot_set_m4(float mat[4][4], const float pivot[3]);
 
-void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3]);
-void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4]);
-void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4]);
-void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4]);
+void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3]);
+void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4]);
+void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4]);
+void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat[4][4]);
 
-void mat3_polar_decompose(float mat3[3][3], float r_U[3][3], float r_P[3][3]);
+void mat3_polar_decompose(const float mat3[3][3], float r_U[3][3], float r_P[3][3]);
 
 void loc_eul_size_to_mat4(float R[4][4],
                           const float loc[3], const float eul[3], const float size[3]);
@@ -237,20 +250,20 @@ void loc_quat_size_to_mat4(float R[4][4],
 void loc_axisangle_size_to_mat4(float R[4][4],
                                 const float loc[3], const float axis[4], const float angle, const float size[3]);
 
-void blend_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t);
-void blend_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t);
+void blend_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], const float t);
+void blend_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], const float t);
 
-void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t);
-void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t);
+void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], const float t);
+void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], const float t);
 
-bool is_negative_m3(float mat[3][3]);
-bool is_negative_m4(float mat[4][4]);
+bool is_negative_m3(const float mat[3][3]);
+bool is_negative_m4(const float mat[4][4]);
 
-bool is_zero_m3(float mat[3][3]);
-bool is_zero_m4(float mat[4][4]);
+bool is_zero_m3(const float mat[3][3]);
+bool is_zero_m4(const float mat[4][4]);
 
-bool equals_m3m3(float mat1[3][3], float mat2[3][3]);
-bool equals_m4m4(float mat1[4][4], float mat2[4][4]);
+bool equals_m3m3(const float mat1[3][3], const float mat2[3][3]);
+bool equals_m4m4(const float mat1[4][4], const float mat2[4][4]);
 
 /* SpaceTransform helper */
 typedef struct SpaceTransform {
@@ -259,8 +272,8 @@ typedef struct SpaceTransform {
 
 } SpaceTransform;
 
-void BLI_space_transform_from_matrices(struct SpaceTransform *data, float local[4][4], float target[4][4]);
-void BLI_space_transform_global_from_matrices(struct SpaceTransform *data, float local[4][4], float target[4][4]);
+void BLI_space_transform_from_matrices(struct SpaceTransform *data, const float local[4][4], const float target[4][4]);
+void BLI_space_transform_global_from_matrices(struct SpaceTransform *data, const float local[4][4], const float target[4][4]);
 void BLI_space_transform_apply(const struct SpaceTransform *data, float co[3]);
 void BLI_space_transform_invert(const struct SpaceTransform *data, float co[3]);
 void BLI_space_transform_apply_normal(const struct SpaceTransform *data, float no[3]);
@@ -271,8 +284,8 @@ void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float
 
 /*********************************** Other ***********************************/
 
-void print_m3(const char *str, float M[3][3]);
-void print_m4(const char *str, float M[4][4]);
+void print_m3(const char *str, const float M[3][3]);
+void print_m4(const char *str, const float M[4][4]);
 
 #define print_m3_id(M) print_m3(STRINGIFY(M), M)
 #define print_m4_id(M) print_m4(STRINGIFY(M), M)
index 8e0884ba34794c469327342c1a2067e38a3f84c4..2bf3747c41d167e2980861d756f83ea2555208d4 100644 (file)
@@ -305,6 +305,7 @@ void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3]);
 void ortho_v3_v3(float out[3], const float v[3]);
 void ortho_v2_v2(float out[2], const float v[2]);
 void bisect_v3_v3v3v3(float r[3], const float a[3], const float b[3], const float c[3]);
+void rotate_v2_v2fl(float r[2], const float p[2], const float angle);
 void rotate_v3_v3v3fl(float v[3], const float p[3], const float axis[3], const float angle);
 void rotate_normalized_v3_v3v3fl(float out[3], const float p[3], const float axis[3], const float angle);
 
index 01a805a09b6b3c7b5693c873fee1ea8fd074675a..bc3a1ee3e9085898027b4c62adb1eb17b33db5ba 100644 (file)
@@ -239,6 +239,14 @@ MINLINE void rgba_char_args_set(char col[4], const char r, const char g, const c
        col[3] = a;
 }
 
+MINLINE void rgba_float_args_set(float col[4], const float r, const float g, const float b, const float a)
+{
+       col[0] = r;
+       col[1] = g;
+       col[2] = b;
+       col[3] = a;
+}
+
 MINLINE void rgba_char_args_test_set(char col[4], const char r, const char g, const char b, const char a)
 {
        if (col[3] == 0) {
index 9a60c670ec7a4e0909fde47dbdeb58d2720e109a..50b92f5a383af274feaa6aa1f129a2c4515d65b9 100644 (file)
@@ -74,23 +74,23 @@ void unit_m4(float m[4][4])
        m[3][0] = m[3][1] = m[3][2] = 0.0f;
 }
 
-void copy_m2_m2(float m1[2][2], float m2[2][2])
+void copy_m2_m2(float m1[2][2], const float m2[2][2])
 {
        memcpy(m1, m2, sizeof(float[2][2]));
 }
 
-void copy_m3_m3(float m1[3][3], float m2[3][3])
+void copy_m3_m3(float m1[3][3], const float m2[3][3])
 {
        /* destination comes first: */
        memcpy(m1, m2, sizeof(float[3][3]));
 }
 
-void copy_m4_m4(float m1[4][4], float m2[4][4])
+void copy_m4_m4(float m1[4][4], const float m2[4][4])
 {
        memcpy(m1, m2, sizeof(float[4][4]));
 }
 
-void copy_m3_m4(float m1[3][3], float m2[4][4])
+void copy_m3_m4(float m1[3][3], const float m2[4][4])
 {
        m1[0][0] = m2[0][0];
        m1[0][1] = m2[0][1];
@@ -105,7 +105,7 @@ void copy_m3_m4(float m1[3][3], float m2[4][4])
        m1[2][2] = m2[2][2];
 }
 
-void copy_m4_m3(float m1[4][4], float m2[3][3]) /* no clear */
+void copy_m4_m3(float m1[4][4], const float m2[3][3]) /* no clear */
 {
        m1[0][0] = m2[0][0];
        m1[0][1] = m2[0][1];
@@ -131,7 +131,7 @@ void copy_m4_m3(float m1[4][4], float m2[3][3]) /* no clear */
 
 }
 
-void copy_m3_m3d(float R[3][3], double A[3][3])
+void copy_m3_m3d(float R[3][3], const double A[3][3])
 {
        /* Keep it stupid simple for better data flow in CPU. */
        R[0][0] = (float)A[0][0];
@@ -177,64 +177,107 @@ void swap_m4m4(float m1[4][4], float m2[4][4])
 
 /******************************** Arithmetic *********************************/
 
-void mul_m4_m4m4(float m1[4][4], float m3_[4][4], float m2_[4][4])
+void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
 {
-       float m2[4][4], m3[4][4];
+       if (A == R)
+               mul_m4_m4_post(R, B);
+       else if (B == R)
+               mul_m4_m4_pre(R, A);
+       else
+               mul_m4_m4m4_uniq(R, A, B);
+}
 
-       /* copy so it works when m1 is the same pointer as m2 or m3 */
-       copy_m4_m4(m2, m2_);
-       copy_m4_m4(m3, m3_);
+void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4])
+{
+       BLI_assert(R != A && R != B);
 
-       /* matrix product: m1[j][k] = m2[j][i].m3[i][k] */
-       m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0] + m2[0][3] * m3[3][0];
-       m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1] + m2[0][3] * m3[3][1];
-       m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2] + m2[0][3] * m3[3][2];
-       m1[0][3] = m2[0][0] * m3[0][3] + m2[0][1] * m3[1][3] + m2[0][2] * m3[2][3] + m2[0][3] * m3[3][3];
+       /* matrix product: R[j][k] = A[j][i] . B[i][k] */
+       R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0] + B[0][3] * A[3][0];
+       R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1] + B[0][3] * A[3][1];
+       R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2] + B[0][3] * A[3][2];
+       R[0][3] = B[0][0] * A[0][3] + B[0][1] * A[1][3] + B[0][2] * A[2][3] + B[0][3] * A[3][3];
 
-       m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0] + m2[1][3] * m3[3][0];
-       m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1] + m2[1][3] * m3[3][1];
-       m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2] + m2[1][3] * m3[3][2];
-       m1[1][3] = m2[1][0] * m3[0][3] + m2[1][1] * m3[1][3] + m2[1][2] * m3[2][3] + m2[1][3] * m3[3][3];
+       R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0] + B[1][3] * A[3][0];
+       R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1] + B[1][3] * A[3][1];
+       R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2] + B[1][3] * A[3][2];
+       R[1][3] = B[1][0] * A[0][3] + B[1][1] * A[1][3] + B[1][2] * A[2][3] + B[1][3] * A[3][3];
 
-       m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0] + m2[2][3] * m3[3][0];
-       m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1] + m2[2][3] * m3[3][1];
-       m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2] + m2[2][3] * m3[3][2];
-       m1[2][3] = m2[2][0] * m3[0][3] + m2[2][1] * m3[1][3] + m2[2][2] * m3[2][3] + m2[2][3] * m3[3][3];
+       R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0] + B[2][3] * A[3][0];
+       R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1] + B[2][3] * A[3][1];
+       R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2] + B[2][3] * A[3][2];
+       R[2][3] = B[2][0] * A[0][3] + B[2][1] * A[1][3] + B[2][2] * A[2][3] + B[2][3] * A[3][3];
 
-       m1[3][0] = m2[3][0] * m3[0][0] + m2[3][1] * m3[1][0] + m2[3][2] * m3[2][0] + m2[3][3] * m3[3][0];
-       m1[3][1] = m2[3][0] * m3[0][1] + m2[3][1] * m3[1][1] + m2[3][2] * m3[2][1] + m2[3][3] * m3[3][1];
-       m1[3][2] = m2[3][0] * m3[0][2] + m2[3][1] * m3[1][2] + m2[3][2] * m3[2][2] + m2[3][3] * m3[3][2];
-       m1[3][3] = m2[3][0] * m3[0][3] + m2[3][1] * m3[1][3] + m2[3][2] * m3[2][3] + m2[3][3] * m3[3][3];
+       R[3][0] = B[3][0] * A[0][0] + B[3][1] * A[1][0] + B[3][2] * A[2][0] + B[3][3] * A[3][0];
+       R[3][1] = B[3][0] * A[0][1] + B[3][1] * A[1][1] + B[3][2] * A[2][1] + B[3][3] * A[3][1];
+       R[3][2] = B[3][0] * A[0][2] + B[3][1] * A[1][2] + B[3][2] * A[2][2] + B[3][3] * A[3][2];
+       R[3][3] = B[3][0] * A[0][3] + B[3][1] * A[1][3] + B[3][2] * A[2][3] + B[3][3] * A[3][3];
+}
 
+void mul_m4_m4_pre(float R[4][4], const float A[4][4])
+{
+       BLI_assert(A != R);
+       float B[4][4];
+       copy_m4_m4(B, R);
+       mul_m4_m4m4_uniq(R, A, B);
 }
 
-void mul_m3_m3m3(float m1[3][3], float m3_[3][3], float m2_[3][3])
+void mul_m4_m4_post(float R[4][4], const float B[4][4])
 {
-       float m2[3][3], m3[3][3];
+       BLI_assert(B != R);
+       float A[4][4];
+       copy_m4_m4(A, R);
+       mul_m4_m4m4_uniq(R, A, B);
+}
 
-       /* copy so it works when m1 is the same pointer as m2 or m3 */
-       copy_m3_m3(m2, m2_);
-       copy_m3_m3(m3, m3_);
+void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
+{
+       if (A == R)
+               mul_m3_m3_post(R, B);
+       else if (B == R)
+               mul_m3_m3_pre(R, A);
+       else
+               mul_m3_m3m3_uniq(R, A, B);
+}
 
-       /* m1[i][j] = m2[i][k] * m3[k][j], args are flipped!  */
-       m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0];
-       m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1];
-       m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2];
+void mul_m3_m3_pre(float R[3][3], const float A[3][3])
+{
+       BLI_assert(A != R);
+       float B[3][3];
+       copy_m3_m3(B, R);
+       mul_m3_m3m3_uniq(R, A, B);
+}
 
-       m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0];
-       m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1];
-       m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2];
+void mul_m3_m3_post(float R[3][3], const float B[3][3])
+{
+       BLI_assert(B != R);
+       float A[3][3];
+       copy_m3_m3(A, R);
+       mul_m3_m3m3_uniq(R, A, B);
+}
 
-       m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0];
-       m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1];
-       m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2];
+void mul_m3_m3m3_uniq(float R[3][3], const float A[3][3], const float B[3][3])
+{
+       BLI_assert(R != A && R != B);
+
+       R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0];
+       R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1];
+       R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2];
+
+       R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0];
+       R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1];
+       R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2];
+
+       R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0];
+       R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1];
+       R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2];
 }
 
-void mul_m4_m4m3(float m1[4][4], float m3_[4][4], float m2_[3][3])
+void mul_m4_m4m3(float m1[4][4], const float m3_[4][4], const float m2_[3][3])
 {
        float m2[3][3], m3[4][4];
 
        /* copy so it works when m1 is the same pointer as m2 or m3 */
+       /* TODO: avoid copying when matrices are different */
        copy_m3_m3(m2, m2_);
        copy_m4_m4(m3, m3_);
 
@@ -250,11 +293,12 @@ void mul_m4_m4m3(float m1[4][4], float m3_[4][4], float m2_[3][3])
 }
 
 /* m1 = m2 * m3, ignore the elements on the 4th row/column of m3 */
-void mul_m3_m3m4(float m1[3][3], float m3_[4][4], float m2_[3][3])
+void mul_m3_m3m4(float m1[3][3], const float m3_[4][4], const float m2_[3][3])
 {
        float m2[3][3], m3[4][4];
 
        /* copy so it works when m1 is the same pointer as m2 or m3 */
+       /* TODO: avoid copying when matrices are different */
        copy_m3_m3(m2, m2_);
        copy_m4_m4(m3, m3_);
 
@@ -272,11 +316,12 @@ void mul_m3_m3m4(float m1[3][3], float m3_[4][4], float m2_[3][3])
        m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2];
 }
 
-void mul_m4_m3m4(float m1[4][4], float m3_[3][3], float m2_[4][4])
+void mul_m4_m3m4(float m1[4][4], const float m3_[3][3], const float m2_[4][4])
 {
        float m2[4][4], m3[3][3];
 
        /* copy so it works when m1 is the same pointer as m2 or m3 */
+       /* TODO: avoid copying when matrices are different */
        copy_m4_m4(m2, m2_);
        copy_m3_m3(m3, m3_);
 
@@ -434,7 +479,7 @@ void _va_mul_m4_series_9(
 }
 /** \} */
 
-void mul_v2_m3v2(float r[2], float m[3][3], float v[2])
+void mul_v2_m3v2(float r[2], const float m[3][3], const float v[2])
 {
        float temp[3], warped[3];
 
@@ -447,12 +492,12 @@ void mul_v2_m3v2(float r[2], float m[3][3], float v[2])
        r[1] = warped[1] / warped[2];
 }
 
-void mul_m3_v2(float m[3][3], float r[2])
+void mul_m3_v2(const float m[3][3], float r[2])
 {
        mul_v2_m3v2(r, m, r);
 }
 
-void mul_m4_v3(float mat[4][4], float vec[3])
+void mul_m4_v3(const float mat[4][4], float vec[3])
 {
        const float x = vec[0];
        const float y = vec[1];
@@ -462,7 +507,7 @@ void mul_m4_v3(float mat[4][4], float vec[3])
        vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
 }
 
-void mul_v3_m4v3(float r[3], float mat[4][4], const float vec[3])
+void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
 {
        const float x = vec[0];
        const float y = vec[1];
@@ -472,7 +517,7 @@ void mul_v3_m4v3(float r[3], float mat[4][4], const float vec[3])
        r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
 }
 
-void mul_v2_m4v3(float r[2], float mat[4][4], const float vec[3])
+void mul_v2_m4v3(float r[2], const float mat[4][4], const float vec[3])
 {
        const float x = vec[0];
 
@@ -480,7 +525,7 @@ void mul_v2_m4v3(float r[2], float mat[4][4], const float vec[3])
        r[1] = x * mat[0][1] + vec[1] * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
 }
 
-void mul_v2_m2v2(float r[2], float mat[2][2], const float vec[2])
+void mul_v2_m2v2(float r[2], const float mat[2][2], const float vec[2])
 {
        const float x = vec[0];
 
@@ -488,13 +533,13 @@ void mul_v2_m2v2(float r[2], float mat[2][2], const float vec[2])
        r[1] = mat[0][1] * x + mat[1][1] * vec[1];
 }
 
-void mul_m2v2(float mat[2][2], float vec[2])
+void mul_m2v2(const float mat[2][2], float vec[2])
 {
        mul_v2_m2v2(vec, mat, vec);
 }
 
 /* same as mul_m4_v3() but doesnt apply translation component */
-void mul_mat3_m4_v3(float mat[4][4], float vec[3])
+void mul_mat3_m4_v3(const float mat[4][4], float vec[3])
 {
        const float x = vec[0];
        const float y = vec[1];
@@ -504,7 +549,7 @@ void mul_mat3_m4_v3(float mat[4][4], float vec[3])
        vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
 }
 
-void mul_v3_mat3_m4v3(float r[3], float mat[4][4], const float vec[3])
+void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3])
 {
        const float x = vec[0];
        const float y = vec[1];
@@ -514,7 +559,7 @@ void mul_v3_mat3_m4v3(float r[3], float mat[4][4], const float vec[3])
        r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
 }
 
-void mul_project_m4_v3(float mat[4][4], float vec[3])
+void mul_project_m4_v3(const float mat[4][4], float vec[3])
 {
        /* absolute value to not flip the frustum upside down behind the camera */
        const float w = fabsf(mul_project_m4_v3_zfac(mat, vec));
@@ -525,7 +570,7 @@ void mul_project_m4_v3(float mat[4][4], float vec[3])
        vec[2] /= w;
 }
 
-void mul_v3_project_m4_v3(float r[3], float mat[4][4], const float vec[3])
+void mul_v3_project_m4_v3(float r[3], const float mat[4][4], const float vec[3])
 {
        const float w = fabsf(mul_project_m4_v3_zfac(mat, vec));
        mul_v3_m4v3(r, mat, vec);
@@ -535,7 +580,7 @@ void mul_v3_project_m4_v3(float r[3], float mat[4][4], const float vec[3])
        r[2] /= w;
 }
 
-void mul_v2_project_m4_v3(float r[2], float mat[4][4], const float vec[3])
+void mul_v2_project_m4_v3(float r[2], const float mat[4][4], const float vec[3])
 {
        const float w = fabsf(mul_project_m4_v3_zfac(mat, vec));
        mul_v2_m4v3(r, mat, vec);
@@ -544,7 +589,7 @@ void mul_v2_project_m4_v3(float r[2], float mat[4][4], const float vec[3])
        r[1] /= w;
 }
 
-void mul_v4_m4v4(float r[4], float mat[4][4], const float v[4])
+void mul_v4_m4v4(float r[4], const float mat[4][4], const float v[4])
 {
        const float x = v[0];
        const float y = v[1];
@@ -556,12 +601,12 @@ void mul_v4_m4v4(float r[4], float mat[4][4], const float v[4])
        r[3] = x * mat[0][3] + y * mat[1][3] + z * mat[2][3] + mat[3][3] * v[3];
 }
 
-void mul_m4_v4(float mat[4][4], float r[4])
+void mul_m4_v4(const float mat[4][4], float r[4])
 {
        mul_v4_m4v4(r, mat, r);
 }
 
-void mul_v4d_m4v4d(double r[4], float mat[4][4], double v[4])
+void mul_v4d_m4v4d(double r[4], const float mat[4][4], const double v[4])
 {
        const double x = v[0];
        const double y = v[1];
@@ -573,12 +618,21 @@ void mul_v4d_m4v4d(double r[4], float mat[4][4], double v[4])
        r[3] = x * (double)mat[0][3] + y * (double)mat[1][3] + z * (double)mat[2][3] + (double)mat[3][3] * v[3];
 }
 
-void mul_m4_v4d(float mat[4][4], double r[4])
+void mul_m4_v4d(const float mat[4][4], double r[4])
 {
        mul_v4d_m4v4d(r, mat, r);
 }
 
-void mul_v3_m3v3(float r[3], float M[3][3], const float a[3])
+void mul_v4_m4v3(float r[4], const float M[4][4], const float v[3])
+{
+       /* v has implicit w = 1.0f */
+       r[0] = v[0] * M[0][0] + v[1] * M[1][0] + M[2][0] * v[2] + M[3][0];
+       r[1] = v[0] * M[0][1] + v[1] * M[1][1] + M[2][1] * v[2] + M[3][1];
+       r[2] = v[0] * M[0][2] + v[1] * M[1][2] + M[2][2] * v[2] + M[3][2];
+       r[3] = v[0] * M[0][3] + v[1] * M[1][3] + M[2][3] * v[2] + M[3][3];
+}
+
+void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
 {
        BLI_assert(r != a);
 
@@ -587,7 +641,7 @@ void mul_v3_m3v3(float r[3], float M[3][3], const float a[3])
        r[2] = M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
 }
 
-void mul_v3_m3v3_db(double r[3], double M[3][3], const double a[3])
+void mul_v3_m3v3_db(double r[3], const double M[3][3], const double a[3])
 {
        BLI_assert(r != a);
 
@@ -596,7 +650,7 @@ void mul_v3_m3v3_db(double r[3], double M[3][3], const double a[3])
        r[2] = M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
 }
 
-void mul_v2_m3v3(float r[2], float M[3][3], const float a[3])
+void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
 {
        BLI_assert(r != a);
 
@@ -604,17 +658,17 @@ void mul_v2_m3v3(float r[2], float M[3][3], const float a[3])
        r[1] = M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2];
 }
 
-void mul_m3_v3(float M[3][3], float r[3])
+void mul_m3_v3(const float M[3][3], float r[3])
 {
        mul_v3_m3v3(r, M, (const float[3]){UNPACK3(r)});
 }
 
-void mul_m3_v3_db(double M[3][3], double r[3])
+void mul_m3_v3_db(const double M[3][3], double r[3])
 {
        mul_v3_m3v3_db(r, M, (const double[3]){UNPACK3(r)});
 }
 
-void mul_transposed_m3_v3(float mat[3][3], float vec[3])
+void mul_transposed_m3_v3(const float mat[3][3], float vec[3])
 {
        const float x = vec[0];
        const float y = vec[1];
@@ -624,7 +678,7 @@ void mul_transposed_m3_v3(float mat[3][3], float vec[3])
        vec[2] = x * mat[2][0] + y * mat[2][1] + mat[2][2] * vec[2];
 }
 
-void mul_transposed_mat3_m4_v3(float mat[4][4], float vec[3])
+void mul_transposed_mat3_m4_v3(const float mat[4][4], float vec[3])
 {
        const float x = vec[0];
        const float y = vec[1];
@@ -688,7 +742,7 @@ void negate_m4(float m[4][4])
                        m[i][j] *= -1.0f;
 }
 
-void mul_m3_v3_double(float mat[3][3], double vec[3])
+void mul_m3_v3_double(const float mat[3][3], double vec[3])
 {
        const double x = vec[0];
        const double y = vec[1];
@@ -698,7 +752,7 @@ void mul_m3_v3_double(float mat[3][3], double vec[3])
        vec[2] = x * (double)mat[0][2] + y * (double)mat[1][2] + (double)mat[2][2] * vec[2];
 }
 
-void add_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
+void add_m3_m3m3(float m1[3][3], const float m2[3][3], const float m3[3][3])
 {
        int i, j;
 
@@ -707,7 +761,7 @@ void add_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
                        m1[i][j] = m2[i][j] + m3[i][j];
 }
 
-void add_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
+void add_m4_m4m4(float m1[4][4], const float m2[4][4], const float m3[4][4])
 {
        int i, j;
 
@@ -716,7 +770,7 @@ void add_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
                        m1[i][j] = m2[i][j] + m3[i][j];
 }
 
-void sub_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
+void sub_m3_m3m3(float m1[3][3], const float m2[3][3], const float m3[3][3])
 {
        int i, j;
 
@@ -725,7 +779,7 @@ void sub_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
                        m1[i][j] = m2[i][j] - m3[i][j];
 }
 
-void sub_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
+void sub_m4_m4m4(float m1[4][4], const float m2[4][4], const float m3[4][4])
 {
        int i, j;
 
@@ -734,7 +788,7 @@ void sub_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
                        m1[i][j] = m2[i][j] - m3[i][j];
 }
 
-float determinant_m3_array(float m[3][3])
+float determinant_m3_array(const float m[3][3])
 {
        return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
                m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) +
@@ -750,7 +804,7 @@ bool invert_m3_ex(float m[3][3], const float epsilon)
        return success;
 }
 
-bool invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon)
+bool invert_m3_m3_ex(float m1[3][3], const float m2[3][3], const float epsilon)
 {
        float det;
        int a, b;
@@ -786,7 +840,7 @@ bool invert_m3(float m[3][3])
        return success;
 }
 
-bool invert_m3_m3(float m1[3][3], float m2[3][3])
+bool invert_m3_m3(float m1[3][3], const float m2[3][3])
 {
        float det;
        int a, b;
@@ -830,7 +884,7 @@ bool invert_m4(float m[4][4])
  *                                     Mark Segal - 1992
  */
 
-bool invert_m4_m4(float inverse[4][4], float mat[4][4])
+bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
 {
        int i, j, k;
        double temp;
@@ -908,7 +962,7 @@ void transpose_m3(float mat[3][3])
        mat[2][1] = t;
 }
 
-void transpose_m3_m3(float rmat[3][3], float mat[3][3])
+void transpose_m3_m3(float rmat[3][3], const float mat[3][3])
 {
        BLI_assert(rmat != mat);
 
@@ -924,7 +978,7 @@ void transpose_m3_m3(float rmat[3][3], float mat[3][3])
 }
 
 /* seems obscure but in-fact a common operation */
-void transpose_m3_m4(float rmat[3][3], float mat[4][4])
+void transpose_m3_m4(float rmat[3][3], const float mat[4][4])
 {
        BLI_assert(&rmat[0][0] != &mat[0][0]);
 
@@ -965,7 +1019,7 @@ void transpose_m4(float mat[4][4])
        mat[3][2] = t;
 }
 
-void transpose_m4_m4(float rmat[4][4], float mat[4][4])
+void transpose_m4_m4(float rmat[4][4], const float mat[4][4])
 {
        BLI_assert(rmat != mat);
 
@@ -987,7 +1041,8 @@ void transpose_m4_m4(float rmat[4][4], float mat[4][4])
        rmat[3][3] = mat[3][3];
 }
 
-int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit)
+/* TODO: return bool */
+int compare_m4m4(const float mat1[4][4], const float mat2[4][4], float limit)
 {
        if (compare_v4v4(mat1[0], mat2[0], limit))
                if (compare_v4v4(mat1[1], mat2[1], limit))
@@ -1165,7 +1220,7 @@ void orthogonalize_m4(float mat[4][4], int axis)
        mul_v3_fl(mat[2], size[2]);
 }
 
-bool is_orthogonal_m3(float m[3][3])
+bool is_orthogonal_m3(const float m[3][3])
 {
        int i, j;
 
@@ -1179,7 +1234,7 @@ bool is_orthogonal_m3(float m[3][3])
        return true;
 }
 
-bool is_orthogonal_m4(float m[4][4])
+bool is_orthogonal_m4(const float m[4][4])
 {
        int i, j;
 
@@ -1194,7 +1249,7 @@ bool is_orthogonal_m4(float m[4][4])
        return true;
 }
 
-bool is_orthonormal_m3(float m[3][3])
+bool is_orthonormal_m3(const float m[3][3])
 {
        if (is_orthogonal_m3(m)) {
                int i;
@@ -1209,7 +1264,7 @@ bool is_orthonormal_m3(float m[3][3])
        return false;
 }
 
-bool is_orthonormal_m4(float m[4][4])
+bool is_orthonormal_m4(const float m[4][4])
 {
        if (is_orthogonal_m4(m)) {
                int i;
@@ -1224,7 +1279,7 @@ bool is_orthonormal_m4(float m[4][4])
        return false;
 }
 
-bool is_uniform_scaled_m3(float m[3][3])
+bool is_uniform_scaled_m3(const float m[3][3])
 {
        const float eps = 1e-7f;
        float t[3][3];
@@ -1252,7 +1307,7 @@ bool is_uniform_scaled_m3(float m[3][3])
        return false;
 }
 
-bool is_uniform_scaled_m4(float m[4][4])
+bool is_uniform_scaled_m4(const float m[4][4])
 {
        float t[3][3];
        copy_m3_m4(t, m);
@@ -1274,14 +1329,14 @@ void normalize_m3(float mat[3][3])
        }
 }
 
-void normalize_m3_m3_ex(float rmat[3][3], float mat[3][3], float r_scale[3])
+void normalize_m3_m3_ex(float rmat[3][3], const float mat[3][3], float r_scale[3])
 {
        int i;
        for (i = 0; i < 3; i++) {
                r_scale[i] = normalize_v3_v3(rmat[i], mat[i]);
        }
 }
-void normalize_m3_m3(float rmat[3][3], float mat[3][3])
+void normalize_m3_m3(float rmat[3][3], const float mat[3][3])
 {
        int i;
        for (i = 0; i < 3; i++) {
@@ -1310,7 +1365,7 @@ void normalize_m4(float mat[4][4])
        }
 }
 
-void normalize_m4_m4_ex(float rmat[4][4], float mat[4][4], float r_scale[3])
+void normalize_m4_m4_ex(float rmat[4][4], const float mat[4][4], float r_scale[3])
 {
        int i;
        for (i = 0; i < 3; i++) {
@@ -1319,7 +1374,7 @@ void normalize_m4_m4_ex(float rmat[4][4], float mat[4][4], float r_scale[3])
        }
        copy_v4_v4(rmat[3], mat[3]);
 }
-void normalize_m4_m4(float rmat[4][4], float mat[4][4])
+void normalize_m4_m4(float rmat[4][4], const float mat[4][4])
 {
        int i;
        for (i = 0; i < 3; i++) {
@@ -1329,7 +1384,7 @@ void normalize_m4_m4(float rmat[4][4], float mat[4][4])
        copy_v4_v4(rmat[3], mat[3]);
 }
 
-void adjoint_m2_m2(float m1[2][2], float m[2][2])
+void adjoint_m2_m2(float m1[2][2], const float m[2][2])
 {
        BLI_assert(m1 != m);
        m1[0][0] =  m[1][1];
@@ -1338,7 +1393,7 @@ void adjoint_m2_m2(float m1[2][2], float m[2][2])
        m1[1][1] =  m[0][0];
 }
 
-void adjoint_m3_m3(float m1[3][3], float m[3][3])
+void adjoint_m3_m3(float m1[3][3], const float m[3][3])
 {
        BLI_assert(m1 != m);
        m1[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];
@@ -1354,7 +1409,7 @@ void adjoint_m3_m3(float m1[3][3], float m[3][3])
        m1[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0];
 }
 
-void adjoint_m4_m4(float out[4][4], float in[4][4]) /* out = ADJ(in) */
+void adjoint_m4_m4(float out[4][4], const float in[4][4]) /* out = ADJ(in) */
 {
        float a1, a2, a3, a4, b1, b2, b3, b4;
        float c1, c2, c3, c4, d1, d2, d3, d4;
@@ -1420,7 +1475,7 @@ float determinant_m3(float a1, float a2, float a3,
        return ans;
 }
 
-float determinant_m4(float m[4][4])
+float determinant_m4(const float m[4][4])
 {
        float ans;
        float a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;
@@ -1488,14 +1543,14 @@ void size_to_mat4(float mat[4][4], const float size[3])
        mat[3][3] = 1.0f;
 }
 
-void mat3_to_size(float size[3], float mat[3][3])
+void mat3_to_size(float size[3], const float mat[3][3])
 {
        size[0] = len_v3(mat[0]);
        size[1] = len_v3(mat[1]);
        size[2] = len_v3(mat[2]);
 }
 
-void mat4_to_size(float size[3], float mat[4][4])
+void mat4_to_size(float size[3], const float mat[4][4])
 {
        size[0] = len_v3(mat[0]);
        size[1] = len_v3(mat[1]);
@@ -1505,7 +1560,7 @@ void mat4_to_size(float size[3], float mat[4][4])
 /* this gets the average scale of a matrix, only use when your scaling
  * data that has no idea of scale axis, examples are bone-envelope-radius
  * and curve radius */
-float mat3_to_scale(float mat[3][3])
+float mat3_to_scale(const float mat[3][3])
 {
        /* unit length vector */
        float unit_vec[3];
@@ -1514,7 +1569,7 @@ float mat3_to_scale(float mat[3][3])
        return len_v3(unit_vec);
 }
 
-float mat4_to_scale(float mat[4][4])
+float mat4_to_scale(const float mat[4][4])
 {
        /* unit length vector */
        float unit_vec[3];
@@ -1523,7 +1578,7 @@ float mat4_to_scale(float mat[4][4])
        return len_v3(unit_vec);
 }
 
-void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3])
+void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3])
 {
        /* keep rot as a 3x3 matrix, the caller can convert into a quat or euler */
        size[0] = normalize_v3_v3(rot[0], mat3[0]);
@@ -1535,7 +1590,7 @@ void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3])
        }
 }
 
-void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4])
+void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4])
 {
        float mat3[3][3]; /* wmat -> 3x3 */
 
@@ -1546,7 +1601,7 @@ void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wm
        copy_v3_v3(loc, wmat[3]);
 }
 
-void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4])
+void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4])
 {
        float mat3[3][3];
        float mat3_n[3][3]; /* normalized mat3 */
@@ -1564,7 +1619,7 @@ void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4])
        copy_v3_v3(loc, wmat[3]);
 }
 
-void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4])
+void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat[4][4])
 {
        float rot[3][3];
        mat4_to_loc_rot_size(loc, rot, size, wmat);
@@ -1581,7 +1636,7 @@ void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4]
  * See https://en.wikipedia.org/wiki/Polar_decomposition for more.
  */
 #ifndef MATH_STANDALONE
-void mat3_polar_decompose(float mat3[3][3], float r_U[3][3], float r_P[3][3])
+void mat3_polar_decompose(const float mat3[3][3], float r_U[3][3], float r_P[3][3])
 {
        /* From svd decomposition (M = WSV*), we have:
         *     U = WV*
@@ -1625,6 +1680,7 @@ void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
        mat[3][2] += (Tx * mat[0][2] + Ty * mat[1][2] + Tz * mat[2][2]);
 }
 
+/* TODO: enum for axis? */
 /**
  * Rotate a matrix in-place.
  *
@@ -1688,7 +1744,7 @@ void transform_pivot_set_m4(float mat[4][4], const float pivot[3])
        mul_m4_m4m4(mat, mat, tmat);
 }
 
-void blend_m3_m3m3(float out[3][3], float dst[3][3], float src[3][3], const float srcweight)
+void blend_m3_m3m3(float out[3][3], const float dst[3][3], const float src[3][3], const float srcweight)
 {
        float srot[3][3], drot[3][3];
        float squat[4], dquat[4], fquat[4];
@@ -1711,7 +1767,7 @@ void blend_m3_m3m3(float out[3][3], float dst[3][3], float src[3][3], const floa
        mul_m3_m3m3(out, rmat, smat);
 }
 
-void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const float srcweight)
+void blend_m4_m4m4(float out[4][4], const float dst[4][4], const float src[4][4], const float srcweight)
 {
        float sloc[3], dloc[3], floc[3];
        float srot[3][3], drot[3][3];
@@ -1749,7 +1805,7 @@ void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const floa
  * @param B the intput matrix which is totally effective with \a t = 1.0.
  * @param t the interpolation factor.
  */
-void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t)
+void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], const float t)
 {
        /* 'Rotation' component ('U' part of polar decomposition, the closest orthogonal matrix to M3 rot/scale
         * transformation matrix), spherically interpolated. */
@@ -1784,7 +1840,7 @@ void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t)
  * @param B the intput matrix which is totally effective with \a t = 1.0.
  * @param t the interpolation factor.
  */
-void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t)
+void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], const float t)
 {
        float A3[3][3], B3[3][3], R3[3][3];
 
@@ -1805,27 +1861,27 @@ void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t)
 }
 #endif  /* MATH_STANDALONE */
 
-bool is_negative_m3(float mat[3][3])
+bool is_negative_m3(const float mat[3][3])
 {
        float vec[3];
        cross_v3_v3v3(vec, mat[0], mat[1]);
        return (dot_v3v3(vec, mat[2]) < 0.0f);
 }
 
-bool is_negative_m4(float mat[4][4])
+bool is_negative_m4(const float mat[4][4])
 {
        float vec[3];
        cross_v3_v3v3(vec, mat[0], mat[1]);
        return (dot_v3v3(vec, mat[2]) < 0.0f);
 }
 
-bool is_zero_m3(float mat[3][3])
+bool is_zero_m3(const float mat[3][3])
 {
        return (is_zero_v3(mat[0]) &&
                is_zero_v3(mat[1]) &&
                is_zero_v3(mat[2]));
 }
-bool is_zero_m4(float mat[4][4])
+bool is_zero_m4(const float mat[4][4])
 {
        return (is_zero_v4(mat[0]) &&
                is_zero_v4(mat[1]) &&
@@ -1833,14 +1889,14 @@ bool is_zero_m4(float mat[4][4])
                is_zero_v4(mat[3]));
 }
 
-bool equals_m3m3(float mat1[3][3], float mat2[3][3])
+bool equals_m3m3(const float mat1[3][3], const float mat2[3][3])
 {
        return (equals_v3v3(mat1[0], mat2[0]) &&
                equals_v3v3(mat1[1], mat2[1]) &&
                equals_v3v3(mat1[2], mat2[2]));
 }
 
-bool equals_m4m4(float mat1[4][4], float mat2[4][4])
+bool equals_m4m4(const float mat1[4][4], const float mat2[4][4])
 {
        return (equals_v4v4(mat1[0], mat2[0]) &&
                equals_v4v4(mat1[1], mat2[1]) &&
@@ -1931,7 +1987,7 @@ void loc_axisangle_size_to_mat4(float mat[4][4], const float loc[3], const float
 
 /*********************************** Other ***********************************/
 
-void print_m3(const char *str, float m[3][3])
+void print_m3(const char *str, const float m[3][3])
 {
        printf("%s\n", str);
        printf("%f %f %f\n", m[0][0], m[1][0], m[2][0]);
@@ -1940,7 +1996,7 @@ void print_m3(const char *str, float m[3][3])
        printf("\n");
 }
 
-void print_m4(const char *str, float m[4][4])
+void print_m4(const char *str, const float m[4][4])
 {
        printf("%s\n", str);
        printf("%f %f %f %f\n", m[0][0], m[1][0], m[2][0], m[3][0]);
@@ -2394,7 +2450,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4])
        }
 }
 
-void pseudoinverse_m4_m4(float Ainv[4][4], float A_[4][4], float epsilon)
+void pseudoinverse_m4_m4(float Ainv[4][4], const float A_[4][4], float epsilon)
 {
        /* compute Moore-Penrose pseudo inverse of matrix, singular values
         * below epsilon are ignored for stability (truncated SVD) */
@@ -2415,7 +2471,7 @@ void pseudoinverse_m4_m4(float Ainv[4][4], float A_[4][4], float epsilon)
        mul_m4_series(Ainv, U, Wm, V);
 }
 
-void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon)
+void pseudoinverse_m3_m3(float Ainv[3][3], const float A[3][3], float epsilon)
 {
        /* try regular inverse when possible, otherwise fall back to slow svd */
        if (!invert_m3_m3(Ainv, A)) {
@@ -2427,14 +2483,14 @@ void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon)
        }
 }
 
-bool has_zero_axis_m4(float matrix[4][4])
+bool has_zero_axis_m4(const float matrix[4][4])
 {
        return len_squared_v3(matrix[0]) < FLT_EPSILON ||
               len_squared_v3(matrix[1]) < FLT_EPSILON ||
               len_squared_v3(matrix[2]) < FLT_EPSILON;
 }
 
-void invert_m4_m4_safe(float Ainv[4][4], float A[4][4])
+void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4])
 {
        if (!invert_m4_m4(Ainv, A)) {
                float Atemp[4][4];
@@ -2482,7 +2538,7 @@ void invert_m4_m4_safe(float Ainv[4][4], float A[4][4])
  * this defines a transform matrix TM such that (x', y', z') = TM * (x, y, z)
  * where (x', y', z') are the coordinates of P' in target space such that it keeps (X, Y, Z) coordinates in global space.
  */
-void BLI_space_transform_from_matrices(SpaceTransform *data, float local[4][4], float target[4][4])
+void BLI_space_transform_from_matrices(SpaceTransform *data, const float local[4][4], const float target[4][4])
 {
        float itarget[4][4];
        invert_m4_m4(itarget, target);
@@ -2500,7 +2556,7 @@ void BLI_space_transform_from_matrices(SpaceTransform *data, float local[4][4],
  * this defines a transform matrix TM such that (X', Y', Z') = TM * (X, Y, Z)
  * where (X', Y', Z') are the coordinates of p' in global space such that it keeps (x, y, z) coordinates in target space.
  */
-void BLI_space_transform_global_from_matrices(SpaceTransform *data, float local[4][4], float target[4][4])
+void BLI_space_transform_global_from_matrices(SpaceTransform *data, const float local[4][4], const float target[4][4])
 {
        float ilocal[4][4];
        invert_m4_m4(ilocal, local);
index dfecc3b556a8bfaa0d341bc18264ca1040d0870f..500c6e57923f203757ddae8f462f7f75c9642c34 100644 (file)
@@ -781,6 +781,20 @@ void ortho_v2_v2(float out[2], const float v[2])
        out[1] =  v[0];
 }
 
+/**
+ * Rotate a point \a p by \a angle around origin (0, 0)
+ */
+void rotate_v2_v2fl(float r[2], const float p[2], const float angle)
+{
+       const float co = cosf(angle);
+       const float si = sinf(angle);
+
+       BLI_assert(r != p);
+
+       r[0] = co * p[0] - si * p[1];
+       r[1] = si * p[0] + co * p[1];
+}
+
 /**
  * Rotate a point \a p by \a angle around an arbitrary unit length \a axis.
  * http://local.wasp.uwa.edu.au/~pbourke/geometry/
index 3b6ab99ae8695172da9340ae134689c13c83a4f7..ef1df479f13c95d5b67c9c99d49cbcf3c9bafa56 100644 (file)
@@ -95,20 +95,6 @@ void BLI_scanfill_obj_dump(ScanFillContext *sf_ctx)
 }
 #endif
 
-#if 0
-void BLI_scanfill_view3d_dump(ScanFillContext *sf_ctx)
-{
-       ScanFillEdge *eed;
-
-       bl_debug_draw_quad_clear();
-       bl_debug_color_set(0x0000ff);
-
-       for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
-               bl_debug_draw_edge_add(eed->v1->co, eed->v2->co);
-       }
-}
-#endif
-
 static ListBase *edge_isect_ls_ensure(GHash *isect_hash, ScanFillEdge *eed)
 {
        ListBase *e_ls;
index a63b9ed7d1909532266b405eacf533a36960680b..0e1861abcf147f41b182e19f9fb0bb820a761a56 100644 (file)
@@ -6910,6 +6910,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
                                rv3d->sms = NULL;
                                rv3d->smooth_timer = NULL;
                                rv3d->compositor = NULL;
+                               rv3d->viewport = NULL;
                        }
                }
        }
@@ -6926,6 +6927,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
        ar->type = NULL;
        ar->swap = 0;
        ar->do_draw = 0;
+       ar->manipulator_map = NULL;
        ar->regiontimer = NULL;
        memset(&ar->drawrct, 0, sizeof(ar->drawrct));
 }
@@ -6972,6 +6974,8 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
        sc->mainwin = sc->subwinactive= 0;      /* indices */
        sc->swap = 0;
 
+       sc->preview = direct_link_preview_image(fd, sc->preview);
+
        /* edges */
        for (se = sc->edgebase.first; se; se = se->next) {
                se->v1 = newdataadr(fd, se->v1);
@@ -9358,7 +9362,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
                expand_doit(fd, mainvar, ob->proxy);
        if (ob->proxy_group)
                expand_doit(fd, mainvar, ob->proxy_group);
-       
+
        for (psys = ob->particlesystem.first; psys; psys = psys->next)
                expand_doit(fd, mainvar, psys->part);
 
index 88c583b827e19bf1dba05ef4cedc00a4b32ba42d..ea654ad69061c0e74a71c856157ed7f90b9578c9 100644 (file)
@@ -1492,4 +1492,27 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
                        }
                }
        }
+
+       {
+               if (!DNA_struct_elem_find(fd->filesdna, "View3DDebug", "char", "background")) {
+                       bScreen *screen;
+
+                       for (screen = main->screen.first; screen; screen = screen->id.next) {
+                               ScrArea *sa;
+                               for (sa = screen->areabase.first; sa; sa = sa->next) {
+                                       SpaceLink *sl;
+
+                                       for (sl = sa->spacedata.first; sl; sl = sl->next) {
+                                               switch (sl->spacetype) {
+                                                       case SPACE_VIEW3D:
+                                                       {
+                                                               View3D *v3d = (View3D *)sl;
+                                                               v3d->debug.background = V3D_DEBUG_BACKGROUND_NONE;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
 }
index ad1999c0bc7927dc6edbf22e56e58d3d74d5eb78..27db83055bb87e69688b513662a28d1d18ef4716 100644 (file)
@@ -1721,6 +1721,8 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
                        SmokeModifierData *smd = (SmokeModifierData *)md;
 
                        if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
+                               writestruct(wd, DATA, SmokeDomainSettings, 1, smd->domain);
+
                                if (smd->domain) {
                                        write_pointcaches(wd, &(smd->domain->ptcaches[0]));
 
@@ -1734,11 +1736,8 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
                                        if (smd->domain->coba) {
                                                writestruct(wd, DATA, ColorBand, 1, smd->domain->coba);
                                        }
-                               }
 
-                               writestruct(wd, DATA, SmokeDomainSettings, 1, smd->domain);
 
-                               if (smd->domain) {
                                        /* cleanup the fake pointcache */
                                        BKE_ptcache_free_list(&smd->domain->ptcaches[1]);
                                        smd->domain->point_cache[1] = NULL;
@@ -3007,6 +3006,8 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
                writestruct(wd, ID_SCRN, bScreen, 1, sc);
                write_iddata(wd, &sc->id);
 
+               write_previews(wd, sc->preview);
+
                /* direct data */
                for (sv = sc->vertbase.first; sv; sv = sv->next) {
                        writestruct(wd, DATA, ScrVert, 1, sv);
index 58234ddf3bd4268aaddc5253c797e415134f266a..2b38af80fc9ad6ebf4caa61b0c5c0001046a7948 100644 (file)
 /* use accelerated overlap check */
 #define USE_BVH
 
-// #define USE_BOOLEAN_RAYCAST_DRAW
-
-#ifdef USE_BOOLEAN_RAYCAST_DRAW
-/* insert bl_debug_draw_quad_clear... here */
-#endif
-
 // #define USE_DUMP
 
 static void tri_v3_scale(
@@ -1006,10 +1000,6 @@ bool BM_mesh_intersect(
        int i_a, i_b;
 #endif
 
-#ifdef USE_BOOLEAN_RAYCAST_DRAW
-       bl_debug_draw_quad_clear();
-#endif
-
        s.bm = bm;
 
        s.edgetri_cache = BLI_ghash_new(BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, __func__);
@@ -1607,17 +1597,6 @@ bool BM_mesh_intersect(
                                                do_flip = (side == 0);
                                                break;
                                }
-
-#ifdef USE_BOOLEAN_RAYCAST_DRAW
-                               {
-                                       unsigned int colors[4] = {0x00000000, 0xffffffff, 0xff000000, 0x0000ff};
-                                       float co_other[3] = {UNPACK3(co)};
-                                       co_other[0] += 1000.0f;
-                                       bl_debug_color_set(colors[(hits & 1) == 1]);
-                                       bl_debug_draw_edge_add(co, co_other);
-                               }
-#endif
-
                        }
 
                        if (do_remove) {
index e8ed03666a65c6ffbefe814581c548a4204de02b..a9df68beb36fd07cd946bd05cd613563a4f43e72 100644 (file)
@@ -74,7 +74,9 @@ extern "C" {
  * design of those areas is more clear we'll do the same legacy code here.
  *                                                                  - sergey -
  */
+#if 0
 #define DEPSGRAPH_USE_LEGACY_TAGGING
+#endif
 
 namespace {
 
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
new file mode 100644 (file)
index 0000000..60449eb
--- /dev/null
@@ -0,0 +1,62 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2016, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Blender Institute
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+       .
+       intern
+       nodes
+       operations
+       ../blenkernel
+       ../blenlib
+       ../blentranslation
+       ../imbuf
+       ../makesdna
+       ../makesrna
+       ../windowmanager
+       ../nodes
+       ../nodes/composite
+       ../nodes/intern
+       ../render/extern/include
+       ../render/intern/include
+       ../../../extern/clew/include
+       ../../../intern/guardedalloc
+       ../../../intern/atomic
+)
+
+set(INC_SYS
+
+)
+
+set(SRC
+       DRW_defines.h
+
+)
+
+list(APPEND INC
+)
+
+endif()
+
+blender_add_lib(bf_draw "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/draw/DRW_defines.h b/source/blender/draw/DRW_defines.h
new file mode 100644 (file)
index 0000000..212c39e
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+#ifndef __DRW_DEFINES_H__
+#define __DRW_DEFINES_H__
+
+#endif  /* __DRW_DEFINES_H__ */
diff --git a/source/blender/draw/DRW_engines.h b/source/blender/draw/DRW_engines.h
new file mode 100644 (file)
index 0000000..e69de29
index 57302c18a8887b5e64ef30fd0b84043565649c5e..f05932db1b225b9b40de59285824e87b53f7b469 100644 (file)
@@ -119,11 +119,10 @@ static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, floa
        
        /* set backdrop drawing color */
        acf->get_backdrop_color(ac, ale, color);
-       glColor3fv(color);
        
        /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
        UI_draw_roundbox_corner_set((expanded) ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
-       UI_draw_roundbox_gl_mode(GL_POLYGON, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
+       UI_draw_roundbox_gl_mode_3fvAlpha(GL_POLYGON, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
 }
 
 
@@ -421,14 +420,13 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi
        
        /* set backdrop drawing color */
        acf->get_backdrop_color(ac, ale, color);
-       glColor3fv(color);
        
        /* rounded corners on LHS only 
         *      - top and bottom 
         *      - special hack: make the top a bit higher, since we are first... 
         */
        UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
-       UI_draw_roundbox_gl_mode(GL_POLYGON, 0,  yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
+       UI_draw_roundbox_gl_mode_3fvAlpha(GL_POLYGON, 0,  yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
 }
 
 /* name for summary entries */
@@ -814,11 +812,10 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc
        
        /* set backdrop drawing color */
        acf->get_backdrop_color(ac, ale, color);
-       glColor3fv(color);
        
        /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
        UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
-       UI_draw_roundbox_gl_mode(GL_POLYGON, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
+       UI_draw_roundbox_gl_mode_3fvAlpha(GL_POLYGON, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
 }
 
 /* name for group entries */
@@ -1071,11 +1068,10 @@ static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, floa
        
        /* set backdrop drawing color */
        acf->get_backdrop_color(ac, ale, color);
-       glColor3fv(color);
        
-       /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
+       /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */       
        UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
-       UI_draw_roundbox_gl_mode(GL_POLYGON, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5);
+       UI_draw_roundbox_gl_mode_3fvAlpha(GL_POLYGON, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f);
 }
 
 /* name for nla controls expander entries */
@@ -2002,83 +1998,6 @@ static bAnimChannelType ACF_DSWOR =
        acf_dswor_setting_ptr                   /* pointer for setting */
 };
 
-/* Particle Expander  ------------------------------------------- */
-
-// TODO: just get this from RNA?
-static int acf_dspart_icon(bAnimListElem *UNUSED(ale))
-{
-       return ICON_PARTICLE_DATA;
-}
-
-/* get the appropriate flag(s) for the setting when it is valid  */
-static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
-{
-       /* clear extra return data first */
-       *neg = false;
-       
-       switch (setting) {
-               case ACHANNEL_SETTING_EXPAND: /* expanded */
-                       return PART_DS_EXPAND;
-                       
-               case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
-                       return ADT_NLA_EVAL_OFF;
-                       
-               case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
-                       *neg = true;
-                       return ADT_CURVES_NOT_VISIBLE;
-                       
-               case ACHANNEL_SETTING_SELECT: /* selected */
-                       return ADT_UI_SELECTED;
-               
-               default: /* unsupported */
-                       return 0;
-       }
-}
-
-/* get pointer to the setting */
-static void *acf_dspart_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
-{
-       ParticleSettings *part = (ParticleSettings *)ale->data;
-       
-       /* clear extra return data first */
-       *type = 0;
-       
-       switch (setting) {
-               case ACHANNEL_SETTING_EXPAND: /* expanded */
-                       return GET_ACF_FLAG_PTR(part->flag, type);
-                       
-               case ACHANNEL_SETTING_SELECT: /* selected */
-               case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
-               case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
-                       if (part->adt)
-                               return GET_ACF_FLAG_PTR(part->adt->flag, type);
-                       return NULL;
-               
-               default: /* unsupported */
-                       return NULL;
-       }
-}
-
-/* particle expander type define */
-static bAnimChannelType ACF_DSPART =
-{
-       "Particle Data Expander",       /* type name */
-       ACHANNEL_ROLE_EXPANDER,         /* role */
-       
-       acf_generic_dataexpand_color,   /* backdrop color */
-       acf_generic_dataexpand_backdrop, /* backdrop */
-       acf_generic_indention_1,        /* indent level */
-       acf_generic_basic_offset,       /* offset */
-
-       acf_generic_idblock_name,       /* name */
-       acf_generic_idblock_name_prop,   /* name prop */
-       acf_dspart_icon,                /* icon */
-
-       acf_generic_dataexpand_setting_valid,   /* has setting */
-       acf_dspart_setting_flag,                /* flag for setting */
-       acf_dspart_setting_ptr                  /* pointer for setting */
-};
-
 /* MetaBall Expander  ------------------------------------------- */
 
 // TODO: just get this from RNA?
@@ -3420,24 +3339,20 @@ static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float y
         */
        nla_action_get_color(adt, (bAction *)ale->data, color);
        
-       if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
-               /* Yes, the color vector has 4 components, BUT we only want to be using 3 of them! */
-               glColor3fv(color);
-       }
-       else {
-               float alpha = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f;
-               glColor4f(color[0], color[1], color[2], alpha);
-       }
-       
-       /* only on top left corner, to show that this channel sits on top of the preceding ones 
+       if (adt && (adt->flag & ADT_NLA_EDIT_ON))
+               color[3] = 1.0f;
+       else
+               color[3] = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f;
+
+       /* only on top left corner, to show that this channel sits on top of the preceding ones
         * while still linking into the action line strip to the right
         */
        UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT);
-       
+
        /* draw slightly shifted up vertically to look like it has more separation from other channels,
         * but we then need to slightly shorten it so that it doesn't look like it overlaps
         */
-       UI_draw_roundbox_gl_mode(GL_POLYGON, offset,  yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8);
+       UI_draw_roundbox_gl_mode(GL_POLYGON, offset,  yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8, color);
 }
 
 /* name for nla action entries */
@@ -3580,7 +3495,6 @@ static void ANIM_init_channel_typeinfo_data(void)
                animchannelTypeInfo[type++] = &ACF_DSSKEY;       /* ShapeKey Channel */
                animchannelTypeInfo[type++] = &ACF_DSWOR;        /* World Channel */
                animchannelTypeInfo[type++] = &ACF_DSNTREE;      /* NodeTree Channel */
-               animchannelTypeInfo[type++] = &ACF_DSPART;       /* Particle Channel */
                animchannelTypeInfo[type++] = &ACF_DSMBALL;      /* MetaBall Channel */
                animchannelTypeInfo[type++] = &ACF_DSARM;        /* Armature Channel */
                animchannelTypeInfo[type++] = &ACF_DSMESH;       /* Mesh Channel */
index 33e44d738945bfe9036828c180b08e337c535c4c..58b9b8eba91bd6af962e9f3ef06df473933d80e0 100644 (file)
@@ -62,6 +62,8 @@
 #include "UI_resources.h"
 #include "UI_view2d.h"
 
+#include "GPU_immediate.h"
+
 /* *************************************************** */
 /* CURRENT FRAME DRAWING */
 
@@ -95,9 +97,16 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const
        x = cfra * xscale;
        y = 0.9f * U.widget_unit;
        
+       VertexFormat *format = immVertexFormat();
+       unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+       immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
        /* draw green box around/behind text */
-       UI_ThemeColorShade(TH_CFRAME, 0);
-       glRectf(x, y,  x + slen,  y + 0.75f * U.widget_unit);
+       immUniformThemeColorShade(TH_CFRAME, 0);
+
+       immRectf(pos, x, y,  x + slen,  y + 0.75f * U.widget_unit);
+       immUnbindProgram();
        
        /* draw current frame number - black text */
        UI_ThemeColor(TH_TEXT);
@@ -112,17 +121,23 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
 {
        Scene *scene = CTX_data_scene(C);
 
-       /* Draw a light green line to indicate current frame */
-       UI_ThemeColor(TH_CFRAME);
-
        const float x = (float)(scene->r.cfra * scene->r.framelen);
 
        glLineWidth((flag & DRAWCFRA_WIDE) ? 3.0 : 2.0);
 
-       glBegin(GL_LINES);
-       glVertex2f(x, v2d->cur.ymin - 500.0f); /* XXX arbitrary... want it go to bottom */
-       glVertex2f(x, v2d->cur.ymax);
-       glEnd();
+       VertexFormat *format = immVertexFormat();
+       unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+       immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+       /* Draw a light green line to indicate current frame */
+       immUniformThemeColor(TH_CFRAME);
+
+       immBegin(GL_LINES, 2);
+       immVertex2f(pos, x, v2d->cur.ymin - 500.0f); /* XXX arbitrary... want it go to bottom */
+       immVertex2f(pos, x, v2d->cur.ymax);
+       immEnd();
+       immUnbindProgram();
 
        /* Draw current frame number in a little box */
        if (flag & DRAWCFRA_SHOW_NUMBOX) {
@@ -144,17 +159,24 @@ void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width)
        if (PRVRANGEON) {
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                glEnable(GL_BLEND);
-               glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
-               
+
+               VertexFormat *format = immVertexFormat();
+               unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+               immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+               immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+
                /* only draw two separate 'curtains' if there's no overlap between them */
                if (PSFRA < PEFRA + end_frame_width) {
-                       glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
-                       glRectf((float)(PEFRA + end_frame_width), v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+                       immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
+                       immRectf(pos, (float)(PEFRA + end_frame_width), v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
                }
                else {
-                       glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+                       immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
                }
-               
+
+               immUnbindProgram();
+
                glDisable(GL_BLEND);
        }
 }
index 2fd574d6523961728240162784bc7c7d1ac484ba..8a4ba6687cd0f5bbeac6f59ec7b28c5fec089601 100644 (file)
 
 #include "WM_api.h"
 
-#include "BIF_gl.h"
 #include "BIF_glutil.h"
 
+#include "GPU_immediate.h"
+#include "GPU_draw.h"
+
 #include "ED_gpencil.h"
 #include "ED_screen.h"
 #include "ED_view3d.h"
@@ -94,97 +96,194 @@ typedef enum eDrawStrokeFlags {
 /* thickness above which we should use special drawing */
 #define GP_DRAWTHICKNESS_SPECIAL    3
 
+/* conversion utility (float --> normalized unsigned byte) */
+#define F2UB(x) (unsigned char)(255.0f * x)
+
 /* ----- Tool Buffer Drawing ------ */
-/* helper function to set color of buffer point */
-static void gp_set_tpoint_color(tGPspoint *pt, float ink[4])
+/* helper functions to set color of buffer point */
+
+static void gp_set_tpoint_varying_color(const tGPspoint *pt, const float ink[4], unsigned attrib_id)
 {
        float alpha = ink[3] * pt->strength;
        CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
-       glColor4f(ink[0], ink[1], ink[2], alpha);
+       immAttrib4ub(attrib_id, F2UB(ink[0]), F2UB(ink[1]), F2UB(ink[2]), F2UB(alpha));
 }
 
-/* helper function to set color of point */
-static void gp_set_point_color(bGPDspoint *pt, float ink[4])
+static void gp_set_point_uniform_color(const bGPDspoint *pt, const float ink[4])
 {
        float alpha = ink[3] * pt->strength;
        CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
-       glColor4f(ink[0], ink[1], ink[2], alpha);
+       immUniform4f("color", ink[0], ink[1], ink[2], alpha);
 }
 
-/* helper function to set color and point */
-static void gp_set_color_and_tpoint(tGPspoint *pt, float ink[4])
+static void gp_set_point_varying_color(const bGPDspoint *pt, const float ink[4], unsigned attrib_id)
 {
-       gp_set_tpoint_color(pt, ink);
-       glVertex2iv(&pt->x);
+       float alpha = ink[3] * pt->strength;
+       CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
+       immAttrib4ub(attrib_id, F2UB(ink[0]), F2UB(ink[1]), F2UB(ink[2]), F2UB(alpha));
+}
+
+/* draw fills for buffer stroke */
+static void gp_draw_stroke_buffer_fill(const tGPspoint *points, int totpoints, float ink[4])
+{
+       if (totpoints < 3) {
+               return;
+       }
+       int tot_triangles = totpoints - 2;
+       /* allocate memory for temporary areas */
+       unsigned int(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * tot_triangles, "GP Stroke buffer temp triangulation");
+       float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * totpoints, "GP Stroke buffer temp 2d points");
+
+       /* Convert points to array and triangulate
+       * Here a cache is not used because while drawing the information changes all the time, so the cache
+       * would be recalculated constantly, so it is better to do direct calculation for each function call
+       */
+       for (int i = 0; i < totpoints; i++) {
+               const tGPspoint *pt = &points[i];
+               points2d[i][0] = pt->x;
+               points2d[i][1] = pt->y;
+       }
+       BLI_polyfill_calc((const float(*)[2])points2d, (unsigned int)totpoints, 0, (unsigned int(*)[3])tmp_triangles);
+
+       /* draw triangulation data */
+       if (tot_triangles > 0) {
+               VertexFormat *format = immVertexFormat();
+               unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+               unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+               immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+               /* Draw all triangles for filling the polygon */
+               immBegin(GL_TRIANGLES, tot_triangles * 3);
+               /* TODO: use batch instead of immediate mode, to share vertices */
+
+               const tGPspoint *pt;
+               for (int i = 0; i < tot_triangles; i++) {
+                       /* vertex 1 */
+                       pt = &points[tmp_triangles[i][0]];
+                       gp_set_tpoint_varying_color(pt, ink, color);
+                       immVertex2iv(pos, &pt->x);
+                       /* vertex 2 */
+                       pt = &points[tmp_triangles[i][1]];
+                       gp_set_tpoint_varying_color(pt, ink, color);
+                       immVertex2iv(pos, &pt->x);
+                       /* vertex 3 */
+                       pt = &points[tmp_triangles[i][2]];
+                       gp_set_tpoint_varying_color(pt, ink, color);
+                       immVertex2iv(pos, &pt->x);
+               }
+
+               immEnd();
+               immUnbindProgram();
+       }
+
+       /* clear memory */
+       if (tmp_triangles) {
+               MEM_freeN(tmp_triangles);
+       }
+       if (points2d) {
+               MEM_freeN(points2d);
+       }
 }
 
 /* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */
-static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickness,
-                                  short dflag, short sflag, float ink[4])
+static void gp_draw_stroke_buffer(const tGPspoint *points, int totpoints, short thickness,
+                                  short dflag, short sflag, float ink[4], float fill_ink[4])
 {
-       tGPspoint *pt;
-       int i;
-       
+       int draw_points = 0;
+
        /* error checking */
        if ((points == NULL) || (totpoints <= 0))
                return;
-       
+
        /* check if buffer can be drawn */
        if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D))
                return;
-       
+
+       if (sflag & GP_STROKE_ERASER) {
+               /* don't draw stroke at all! */
+               return;
+       }
+
+       VertexFormat *format = immVertexFormat();
+       unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+       unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+       const tGPspoint *pt = points;
+
        if (totpoints == 1) {
                /* if drawing a single point, draw it larger */
                glPointSize((float)(thickness + 2) * points->pressure);
-               glBegin(GL_POINTS);
-
-               gp_set_color_and_tpoint(points, ink);
-               glEnd();
-       }
-       else if (sflag & GP_STROKE_ERASER) {
-               /* don't draw stroke at all! */
+               immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
+               immBegin(GL_POINTS, 1);
+               gp_set_tpoint_varying_color(pt, ink, color);
+               immVertex2iv(pos, &pt->x);
        }
        else {
                float oldpressure = points[0].pressure;
-               
+
                /* draw stroke curve */
                if (G.debug & G_DEBUG) setlinestyle(2);
-               
+
                glLineWidth(max_ff(oldpressure * thickness, 1.0));
-               glBegin(GL_LINE_STRIP);
-               
-               for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
+               immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+               immBeginAtMost(GL_LINE_STRIP, totpoints);
+
+               /* TODO: implement this with a geometry shader to draw one continuous tapered stroke */
+
+               for (int i = 0; i < totpoints; i++, pt++) {
                        /* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
                         * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
                         */
                        if (fabsf(pt->pressure - oldpressure) > 0.2f) {
-                               glEnd();
+                               /* need to have 2 points to avoid immEnd assert error */
+                               if (draw_points < 2) {
+                                       gp_set_tpoint_varying_color(pt - 1, ink, color);
+                                       immVertex2iv(pos, &(pt - 1)->x);
+                               }
+
+                               immEnd();
+                               draw_points = 0;
+
                                glLineWidth(max_ff(pt->pressure * thickness, 1.0f));
-                               glBegin(GL_LINE_STRIP);
-                               
+                               immBeginAtMost(GL_LINE_STRIP, totpoints - i + 1);
+
                                /* need to roll-back one point to ensure that there are no gaps in the stroke */
                                if (i != 0) { 
-                                       gp_set_color_and_tpoint((pt - 1), ink);
+                                       gp_set_tpoint_varying_color(pt - 1, ink, color);
+                                       immVertex2iv(pos, &(pt - 1)->x);
+                                       ++draw_points;
                                }
-                               
-                               /* now the point we want... */
-                               gp_set_color_and_tpoint(pt, ink);
-                               
-                               oldpressure = pt->pressure;
-                       }
-                       else {
-                               gp_set_color_and_tpoint(pt, ink);
+
+                               oldpressure = pt->pressure; /* reset our threshold */
                        }
+
+                       /* now the point we want */
+                       gp_set_tpoint_varying_color(pt, ink, color);
+                       immVertex2iv(pos, &pt->x);
+                       ++draw_points;
+               }
+               /* need to have 2 points to avoid immEnd assert error */
+               if (draw_points < 2) {
+                       gp_set_tpoint_varying_color(pt - 1, ink, color);
+                       immVertex2iv(pos, &(pt - 1)->x);
                }
-               glEnd();
 
                if (G.debug & G_DEBUG) setlinestyle(0);
        }
+
+       immEnd();
+       immUnbindProgram();
+
+       // draw fill
+       if (fill_ink[3] > GPENCIL_ALPHA_OPACITY_THRESH) {
+               gp_draw_stroke_buffer_fill(points, totpoints, fill_ink);
+       }
 }
 
 /* --------- 2D Stroke Drawing Helpers --------- */
 /* change in parameter list */
-static void gp_calc_2d_stroke_fxy(float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2])
+static void gp_calc_2d_stroke_fxy(const float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2])
 {
        if (sflag & GP_STROKE_2DSPACE) {
                r_co[0] = pt[0];
@@ -210,203 +309,141 @@ static void gp_calc_2d_stroke_fxy(float pt[3], short sflag, int offsx, int offsy
 /* draw a 2D buffer stroke in "volumetric" style
  * NOTE: the stroke buffer doesn't have any coordinate offsets/transforms
  */
-static void gp_draw_stroke_volumetric_buffer(tGPspoint *points, int totpoints, short thickness,
-                                             short dflag, short UNUSED(sflag), float ink[4])
+static void gp_draw_stroke_volumetric_buffer(const tGPspoint *points, int totpoints, short thickness,
+                                             short dflag, const float ink[4])
 {
-       GLUquadricObj *qobj = gluNewQuadric();
-       float modelview[4][4];
-       
-       tGPspoint *pt;
-       int i;
-       
        /* error checking */
        if ((points == NULL) || (totpoints <= 0))
                return;
-       
+
        /* check if buffer can be drawn */
        if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D))
                return;
-       
-       /* get basic matrix - should be camera space (i.e "identity") */
-       glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview);
-       
-       /* draw points */
-       glPushMatrix();
-       
-       for (i = 0, pt = points; i < totpoints; i++, pt++) {
-               /* set the transformed position */
-               // TODO: scale should change based on zoom level, which requires proper translation mult too!
-               modelview[3][0] = pt->x;
-               modelview[3][1] = pt->y;
-               
-               glLoadMatrixf((float *)modelview);
-               
-               /* draw the disk using the current state... */
-               gp_set_tpoint_color(pt, ink);
-               gluDisk(qobj, 0.0,  pt->pressure * thickness, 32, 1);
-               
-               
-               modelview[3][0] = modelview[3][1] = 0.0f;
+
+       VertexFormat *format = immVertexFormat();
+       unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+       unsigned size = add_attrib(format, "size", GL_FLOAT, 1, KEEP_FLOAT);
+       unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+       immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
+       GPU_enable_program_point_size();
+       immBegin(GL_POINTS, totpoints);
+
+       const tGPspoint *pt = points;
+       for (int i = 0; i < totpoints; i++, pt++) {
+               gp_set_tpoint_varying_color(pt, ink, color);
+               immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform (zoom level) */
+               immVertex2f(pos, pt->x, pt->y);
        }
 
-       glPopMatrix();
-       gluDeleteQuadric(qobj);
+       immEnd();
+       immUnbindProgram();
+       GPU_disable_program_point_size();
 }
 
 /* draw a 2D strokes in "volumetric" style */
-static void gp_draw_stroke_volumetric_2d(bGPDspoint *points, int totpoints, short thickness,
-                                         short dflag, short sflag,
+static void gp_draw_stroke_volumetric_2d(const bGPDspoint *points, int totpoints, short thickness,
+                                         short UNUSED(dflag), short sflag,
                                          int offsx, int offsy, int winx, int winy,
-                                         float diff_mat[4][4], float ink[4])
+                                         const float diff_mat[4][4], const float ink[4])
 {
-       GLUquadricObj *qobj = gluNewQuadric();
-       float modelview[4][4];
-       float baseloc[3];
-       float scalefac = 1.0f;
-       
-       bGPDspoint *pt;
-       int i;
-       float fpt[3];
-       
-       /* HACK: We need a scale factor for the drawing in the image editor,
-        * which seems to use 1 unit as it's maximum size, whereas everything
-        * else assumes 1 unit = 1 pixel. Otherwise, we only get a massive blob.
-        */
-       if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
-               scalefac = 0.001f;
-       }
-       
-       /* get basic matrix */
-       glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview);
-       copy_v3_v3(baseloc, modelview[3]);
-       
-       /* draw points */
-       glPushMatrix();
-       
-       for (i = 0, pt = points; i < totpoints; i++, pt++) {
-               /* color of point */
-               gp_set_point_color(pt, ink);
-
-               /* set the transformed position */
+       VertexFormat *format = immVertexFormat();
+       unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+       unsigned size = add_attrib(format, "size", GL_FLOAT, 1, KEEP_FLOAT);
+       unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+       immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
+       GPU_enable_program_point_size();
+       immBegin(GL_POINTS, totpoints);
+
+       const bGPDspoint *pt = points;
+       for (int i = 0; i < totpoints; i++, pt++) {
+               /* transform position to 2D */
                float co[2];
-               
+               float fpt[3];
+
                mul_v3_m4v3(fpt, diff_mat, &pt->x);
                gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
-               translate_m4(modelview, co[0], co[1], 0.0f);
-               
-               glLoadMatrixf((float *)modelview);
-               
-               /* draw the disk using the current state... */
-               gluDisk(qobj, 0.0,  pt->pressure * thickness * scalefac, 32, 1);
-               
-               /* restore matrix */
-               copy_v3_v3(modelview[3], baseloc);
+
+               gp_set_point_varying_color(pt, ink, color);
+               immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */
+               immVertex2f(pos, co[0], co[1]);
        }
-       
-       glPopMatrix();
-       gluDeleteQuadric(qobj);
+
+       immEnd();
+       immUnbindProgram();
+       GPU_disable_program_point_size();
 }
 
 /* draw a 3D stroke in "volumetric" style */
 static void gp_draw_stroke_volumetric_3d(
-        bGPDspoint *points, int totpoints, short thickness,
-        short UNUSED(dflag), short UNUSED(sflag), float diff_mat[4][4], float ink[4])
+        const bGPDspoint *points, int totpoints, short thickness,
+        const float ink[4])
 {
-       GLUquadricObj *qobj = gluNewQuadric();
-       
-       float base_modelview[4][4], modelview[4][4];
-       float base_loc[3];
-       
-       bGPDspoint *pt;
-       int i;
-       float fpt[3];
-       
-       /* Get the basic modelview matrix we use for performing calculations */
-       glGetFloatv(GL_MODELVIEW_MATRIX, (float *)base_modelview);
-       copy_v3_v3(base_loc, base_modelview[3]);
-       
-       /* Create the basic view-aligned billboard matrix we're going to actually draw qobj with:
-        * - We need to knock out the rotation so that we are
-        *   simply left with a camera-facing billboard
-        * - The scale factors here are chosen so that the thickness
-        *   is relatively reasonable. Otherwise, it gets far too
-        *   large!
-        */
-       scale_m4_fl(modelview, 0.1f);
-       
-       /* draw each point as a disk... */
-       glPushMatrix();
-       
-       for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
-               /* color of point */
-               gp_set_point_color(pt, ink);
-
-               mul_v3_m4v3(fpt, diff_mat, &pt->x);
-
-               /* apply translation to base_modelview, so that the translated point is put in the right place */
-               translate_m4(base_modelview, fpt[0], fpt[1], fpt[2]);
-               
-               /* copy the translation component to the billboard matrix we're going to use,
-                * then reset the base matrix to the original values so that we can do the same
-                * for the next point without accumulation/pollution effects
-                */
-               copy_v3_v3(modelview[3], base_modelview[3]); /* copy offset value */
-               copy_v3_v3(base_modelview[3], base_loc);     /* restore */
-               
-               /* apply our billboard matrix for drawing... */
-               glLoadMatrixf((float *)modelview);
-               
-               /* draw the disk using the current state... */
-               gluDisk(qobj, 0.0,  pt->pressure * thickness, 32, 1);
+       VertexFormat *format = immVertexFormat();
+       unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+       unsigned size = add_attrib(format, "size", GL_FLOAT, 1, KEEP_FLOAT);
+       unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+       immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
+       GPU_enable_program_point_size();
+       immBegin(GL_POINTS, totpoints);
+
+       const bGPDspoint *pt = points;
+       for (int i = 0; i < totpoints && pt; i++, pt++) {
+               gp_set_point_varying_color(pt, ink, color);             
+               immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */
+               immVertex3fv(pos, &pt->x);                   /* we can adjust size in vertex shader based on view/projection! */
        }
-       
-       glPopMatrix();
-       gluDeleteQuadric(qobj);
+
+       immEnd();
+       immUnbindProgram();
+       GPU_disable_program_point_size();
 }
 
 
 /* --------------- Stroke Fills ----------------- */
 
 /* Get points of stroke always flat to view not affected by camera view or view position */
-static void gp_stroke_2d_flat(bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction)
+static void gp_stroke_2d_flat(const bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction)
 {
-       bGPDspoint *pt0 = &points[0];
-       bGPDspoint *pt1 = &points[1];
-       bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
-       
+       const bGPDspoint *pt0 = &points[0];
+       const bGPDspoint *pt1 = &points[1];
+       const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
+
        float locx[3];
        float locy[3];
        float loc3[3];
        float normal[3];
-       
+
        /* local X axis (p0 -> p1) */
        sub_v3_v3v3(locx, &pt1->x, &pt0->x);
-       
+
        /* point vector at 3/4 */
        sub_v3_v3v3(loc3, &pt3->x, &pt0->x);
-       
+
        /* vector orthogonal to polygon plane */
        cross_v3_v3v3(normal, locx, loc3);
-       
+
        /* local Y axis (cross to normal/x axis) */
        cross_v3_v3v3(locy, normal, locx);
-       
+
        /* Normalize vectors */
        normalize_v3(locx);
        normalize_v3(locy);
-       
+
        /* Get all points in local space */
        for (int i = 0; i < totpoints; i++) {
-               bGPDspoint *pt = &points[i];
+               const bGPDspoint *pt = &points[i];
                float loc[3];
-               
+
                /* Get local space using first point as origin */
                sub_v3_v3v3(loc, &pt->x, &pt0->x);
-               
+
                points2d[i][0] = dot_v3v3(loc, locx);
                points2d[i][1] = dot_v3v3(loc, locy);
        }
-       
+
        /* Concave (-1), Convex (1), or Autodetect (0)? */
        *r_direction = (int)locy[2];
 }
@@ -416,14 +453,14 @@ static void gp_stroke_2d_flat(bGPDspoint *points, int totpoints, float(*points2d
 static void gp_triangulate_stroke_fill(bGPDstroke *gps)
 {
        BLI_assert(gps->totpoints >= 3);
-       
+
        /* allocate memory for temporary areas */
        gps->tot_triangles = gps->totpoints - 2;
        unsigned int (*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation");
        float (*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points");
-       
+
        int direction = 0;
-       
+
        /* convert to 2d and triangulate */
        gp_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction);
        BLI_polyfill_calc((const float(*)[2])points2d, (unsigned int)gps->totpoints, direction, (unsigned int(*)[3])tmp_triangles);
@@ -438,7 +475,7 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps)
                else {
                        gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
                }
-               
+
                for (int i = 0; i < gps->tot_triangles; i++) {
                        bGPDtriangle *stroke_triangle = &gps->triangles[i];
                        stroke_triangle->v1 = tmp_triangles[i][0];
@@ -450,15 +487,15 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps)
                /* No triangles needed - Free anything allocated previously */
                if (gps->triangles)
                        MEM_freeN(gps->triangles);
-                       
+
                gps->triangles = NULL;
        }
-       
+
        /* disable recalculation flag */
        if (gps->flag & GP_STROKE_RECALC_CACHES) {
                gps->flag &= ~GP_STROKE_RECALC_CACHES;
        }
-       
+
        /* clear memory */
        if (tmp_triangles) MEM_freeN(tmp_triangles);
        if (points2d) MEM_freeN(points2d);
@@ -468,42 +505,55 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps)
 /* draw fills for shapes */
 static void gp_draw_stroke_fill(
         bGPdata *gpd, bGPDstroke *gps,
-        int offsx, int offsy, int winx, int winy, float diff_mat[4][4])
+        int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float color[4])
 {
-       bGPDpalettecolor *palcolor;
-       int i;
        float fpt[3];
 
        BLI_assert(gps->totpoints >= 3);
 
-       palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
+       bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
 
        /* Triangulation fill if high quality flag is enabled */
        if (palcolor->flag & PC_COLOR_HQ_FILL) {
-               bGPDtriangle *stroke_triangle;
-               bGPDspoint *pt;
-
                /* Calculate triangles cache for filling area (must be done only after changes) */
                if ((gps->flag & GP_STROKE_RECALC_CACHES) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) {
                        gp_triangulate_stroke_fill(gps);
                }
-               /* Draw all triangles for filling the polygon (cache must be calculated before) */
                BLI_assert(gps->tot_triangles >= 1);
-               glBegin(GL_TRIANGLES);
-               for (i = 0, stroke_triangle = gps->triangles; i < gps->tot_triangles; i++, stroke_triangle++) {
+
+               unsigned pos;
+               if (gps->flag & GP_STROKE_3DSPACE) {
+                       pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+                       immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+               }
+               else {
+                       pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+                       immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+               }
+
+               immUniformColor4fv(color);
+
+               /* Draw all triangles for filling the polygon (cache must be calculated before) */
+               immBegin(GL_TRIANGLES, gps->tot_triangles * 3);
+               /* TODO: use batch instead of immediate mode, to share vertices */
+
+               bGPDtriangle *stroke_triangle = gps->triangles;
+               bGPDspoint *pt;
+
+               for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
                        if (gps->flag & GP_STROKE_3DSPACE) {
                                /* vertex 1 */
                                pt = &gps->points[stroke_triangle->v1];
                                mul_v3_m4v3(fpt, diff_mat, &pt->x);
-                               glVertex3fv(fpt);
+                               immVertex3fv(pos, fpt);
                                /* vertex 2 */
                                pt = &gps->points[stroke_triangle->v2];
                                mul_v3_m4v3(fpt, diff_mat, &pt->x);
-                               glVertex3fv(fpt);
+                               immVertex3fv(pos, fpt);
                                /* vertex 3 */
                                pt = &gps->points[stroke_triangle->v3];
                                mul_v3_m4v3(fpt, diff_mat, &pt->x);
-                               glVertex3fv(fpt);
+                               immVertex3fv(pos, fpt);
                        }
                        else {
                                float co[2];
@@ -511,21 +561,25 @@ static void gp_draw_stroke_fill(
                                pt = &gps->points[stroke_triangle->v1];
                                mul_v3_m4v3(fpt, diff_mat, &pt->x);
                                gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
-                               glVertex2fv(co);
+                               immVertex2fv(pos, co);
                                /* vertex 2 */
                                pt = &gps->points[stroke_triangle->v2];
                                mul_v3_m4v3(fpt, diff_mat, &pt->x);
                                gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
-                               glVertex2fv(co);
+                               immVertex2fv(pos, co);
                                /* vertex 3 */
                                pt = &gps->points[stroke_triangle->v3];
                                mul_v3_m4v3(fpt, diff_mat, &pt->x);
                                gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
-                               glVertex2fv(co);
+                               immVertex2fv(pos, co);
                        }
                }
-               glEnd();
+
+               immEnd();
+               immUnbindProgram();
        }
+
+#if 0 /* convert to modern GL only if needed */
        else {
                /* As an initial implementation, we use the OpenGL filled polygon drawing
                * here since it's the easiest option to implement for this case. It does
@@ -537,10 +591,10 @@ static void gp_draw_stroke_fill(
                * created using old versions of Blender which may have depended on the artifacts
                * the old fills created.
                */
-               bGPDspoint *pt;
+               bGPDspoint *pt = gps->points;
 
                glBegin(GL_POLYGON);
-               for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+               for (int i = 0; i < gps->totpoints; i++, pt++) {
                        if (gps->flag & GP_STROKE_3DSPACE) {
                                mul_v3_m4v3(fpt, diff_mat, &pt->x);
                                glVertex3fv(fpt);
@@ -555,159 +609,186 @@ static void gp_draw_stroke_fill(
 
                glEnd();
        }
+#endif
 }
 
 /* ----- Existing Strokes Drawing (3D and Point) ------ */
 
 /* draw a given stroke - just a single dot (only one point) */
 static void gp_draw_stroke_point(
-        bGPDspoint *points, short thickness, short dflag, short sflag,
-        int offsx, int offsy, int winx, int winy, float diff_mat[4][4], float ink[4])
+        const bGPDspoint *points, short thickness, short UNUSED(dflag), short sflag,
+        int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float ink[4])
 {
-       float fpt[3];
-       bGPDspoint *pt = &points[0];
-
-       /* color of point */
-       gp_set_point_color(pt, ink);
+       const bGPDspoint *pt = points;
 
-       /* set point thickness (since there's only one of these) */
-       glPointSize((float)(thickness + 2) * points->pressure);
-       
        /* get final position using parent matrix */
+       float fpt[3];
        mul_v3_m4v3(fpt, diff_mat, &pt->x);
 
-       /* draw point */
+       VertexFormat *format = immVertexFormat();
+       unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
        if (sflag & GP_STROKE_3DSPACE) {
-               glBegin(GL_POINTS);
-               glVertex3fv(fpt);
-               glEnd();
+               immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
        }
        else {
-               float co[2];
-               
-               /* get coordinates of point */
+               immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
+
+               /* get 2D coordinates of point */
+               float co[3] = { 0.0f };
                gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
-               
-               /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple dot looks ok
-                *  - also mandatory in if Image Editor 'image-based' dot
-                */
-               if ((thickness < GP_DRAWTHICKNESS_SPECIAL) ||
-                   ((dflag & GP_DRAWDATA_IEDITHACK) && (sflag & GP_STROKE_2DSPACE)))
-               {
-                       glBegin(GL_POINTS);
-                       glVertex2fv(co);
-                       glEnd();
-               }
-               else {
-                       /* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */
-                       GLUquadricObj *qobj = gluNewQuadric();
-                       
-                       gluQuadricDrawStyle(qobj, GLU_FILL);
-                       
-                       /* need to translate drawing position, but must reset after too! */
-                       glTranslate2fv(co);
-                       gluDisk(qobj, 0.0,  thickness, 32, 1);
-                       glTranslatef(-co[0], -co[1], 0.0);
-                       
-                       gluDeleteQuadric(qobj);
-               }
+               copy_v3_v3(fpt, co);
        }
+
+       gp_set_point_uniform_color(pt, ink);
+       /* set point thickness (since there's only one of these) */
+       immUniform1f("size", (float)(thickness + 2) * pt->pressure);
+
+       immBegin(GL_POINTS, 1);
+       immVertex3fv(pos, fpt);
+       immEnd();
+
+       immUnbindProgram();
 }
 
 /* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
-static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness, bool debug,
-                              short UNUSED(sflag), float diff_mat[4][4], float ink[4], bool cyclic)
+static void gp_draw_stroke_3d(const bGPDspoint *points, int totpoints, short thickness, bool UNUSED(debug),
+                              short UNUSED(sflag), const float diff_mat[4][4], const float ink[4], bool cyclic)
 {
-       bGPDspoint *pt, *pt2;
        float curpressure = points[0].pressure;
-       int i;
        float fpt[3];
        float cyclic_fpt[3];
+       int draw_points = 0;
+
+       /* if cyclic needs one vertex more */
+       int cyclic_add = 0;
+       if (cyclic) {
+               ++cyclic_add;
+       }
+
+
+       VertexFormat *format = immVertexFormat();
+       unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+       unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+       immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
+
+       /* TODO: implement this with a geometry shader to draw one continuous tapered stroke */
 
        /* draw stroke curve */
        glLineWidth(max_ff(curpressure * thickness, 1.0f));
-       glBegin(GL_LINE_STRIP);
-       for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
-               gp_set_point_color(pt, ink);
+       immBeginAtMost(GL_LINE_STRIP, totpoints + cyclic_add);
+       const bGPDspoint *pt = points;
+       for (int i = 0; i < totpoints; i++, pt++) {
+               gp_set_point_varying_color(pt, ink, color);
 
                /* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
                 * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
                 * Note: we want more visible levels of pressures when thickness is bigger.
                 */
                if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) {
-                       glEnd();
+                       /* if the pressure changes before get at least 2 vertices, need to repeat last point to avoid assert in immEnd() */
+                       if (draw_points < 2) {
+                               const bGPDspoint *pt2 = pt - 1;
+                               mul_v3_m4v3(fpt, diff_mat, &pt2->x);
+                               immVertex3fv(pos, fpt);
+                       }
+                       immEnd();
+                       draw_points = 0;
+
                        curpressure = pt->pressure;
                        glLineWidth(max_ff(curpressure * thickness, 1.0f));
-                       glBegin(GL_LINE_STRIP);
-                       
+                       immBeginAtMost(GL_LINE_STRIP, totpoints - i + 1 + cyclic_add);
+
                        /* need to roll-back one point to ensure that there are no gaps in the stroke */
                        if (i != 0) { 
-                               pt2 = pt - 1;
+                               const bGPDspoint *pt2 = pt - 1;
                                mul_v3_m4v3(fpt, diff_mat, &pt2->x);
-                               glVertex3fv(fpt);
+                               gp_set_point_varying_color(pt2, ink, color);
+                               immVertex3fv(pos, fpt);
+                               ++draw_points;
                        }
-                       
-                       /* now the point we want... */
-                       mul_v3_m4v3(fpt, diff_mat, &pt->x);
-                       glVertex3fv(fpt);
                }
-               else {
-                       mul_v3_m4v3(fpt, diff_mat, &pt->x);
-                       glVertex3fv(fpt);
-               }
-               /* saves first point to use in cyclic */
-               if (i == 0) {
+
+               /* now the point we want */
+               mul_v3_m4v3(fpt, diff_mat, &pt->x);
+               immVertex3fv(pos, fpt);
+               ++draw_points;
+
+               if (cyclic && i == 0) {
+                       /* save first point to use in cyclic */
                        copy_v3_v3(cyclic_fpt, fpt);
                }
        }
-       /* if cyclic draw line to first point */
+
        if (cyclic) {
-               glVertex3fv(cyclic_fpt);
+               /* draw line to first point to complete the cycle */
+               immVertex3fv(pos, cyclic_fpt);
+               ++draw_points;
+       }
+
+       /* if less of two points, need to repeat last point to avoid assert in immEnd() */
+       if (draw_points < 2) {
+               const bGPDspoint *pt2 = pt - 1;
+               mul_v3_m4v3(fpt, diff_mat, &pt2->x);
+               gp_set_point_varying_color(pt2, ink, color);
+               immVertex3fv(pos, fpt);
        }
-       glEnd();
 
+       immEnd();
+       immUnbindProgram();
+
+#if 0 /* convert to modern GL only if needed */
        /* draw debug points of curve on top? */
        /* XXX: for now, we represent "selected" strokes in the same way as debug, which isn't used anymore */
        if (debug) {
                glPointSize((float)(thickness + 2));
-               
+
                glBegin(GL_POINTS);
-               for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
+               const bGPDspoint *pt = points;
+               for (int i = 0; i < totpoints; i++, pt++) {
                        mul_v3_m4v3(fpt, diff_mat, &pt->x);
                        glVertex3fv(fpt);
                }
                glEnd();
-
        }
+#endif
 }
 
 /* ----- Fancy 2D-Stroke Drawing ------ */
 
 /* draw a given stroke in 2d */
-static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
-                              bool debug, int offsx, int offsy, int winx, int winy, float diff_mat[4][4], float ink[4])
+static void gp_draw_stroke_2d(const bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
+                              bool debug, int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float ink[4])
 {
        /* otherwise thickness is twice that of the 3D view */
        float thickness = (float)thickness_s * 0.5f;
-       
+
        /* strokes in Image Editor need a scale factor, since units there are not pixels! */
        float scalefac  = 1.0f;
        if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
                scalefac = 0.001f;
        }
-       
+
+       /* TODO: fancy++ with the magic of shaders */
+
        /* tessellation code - draw stroke as series of connected quads with connection
         * edges rotated to minimize shrinking artifacts, and rounded endcaps
         */
        {
-               bGPDspoint *pt1, *pt2;
+               const bGPDspoint *pt1, *pt2;
                float pm[2];
                int i;
                float fpt[3];
-               
-               glShadeModel(GL_FLAT);
-               glBegin(GL_QUADS);
-               
+
+               VertexFormat *format = immVertexFormat();
+               unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+               unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+               /* this code previously used glShadeModel(GL_FLAT) */
+               immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+               immBegin(GL_QUADS, (totpoints - 2) * 4 + 12);
+
                for (i = 0, pt1 = points, pt2 = points + 1; i < (totpoints - 1); i++, pt1++, pt2++) {
                        float s0[2], s1[2];     /* segment 'center' points */
                        float t0[2], t1[2];     /* tessellated coordinates */
@@ -721,19 +802,19 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
 
                        mul_v3_m4v3(fpt, diff_mat, &pt2->x);
                        gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s1);
-                       
+
                        /* calculate gradient and normal - 'angle'=(ny/nx) */
                        m1[1] = s1[1] - s0[1];
                        m1[0] = s1[0] - s0[0];
                        normalize_v2(m1);
                        m2[1] = -m1[0];
                        m2[0] = m1[1];
-                       
+
                        /* always use pressure from first point here */
                        pthick = (pt1->pressure * thickness * scalefac);
-                       
+
                        /* color of point */
-                       gp_set_point_color(pt1, ink);
+                       gp_set_point_varying_color(pt1, ink, color);
 
                        /* if the first segment, start of segment is segment's normal */
                        if (i == 0) {
@@ -744,40 +825,40 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
                                mt[1] = m2[1] * pthick * 0.5f;
                                sc[0] = s0[0] - (m1[0] * pthick * 0.75f);
                                sc[1] = s0[1] - (m1[1] * pthick * 0.75f);
-                               
+
                                t0[0] = sc[0] - mt[0];
                                t0[1] = sc[1] - mt[1];
                                t1[0] = sc[0] + mt[0];
                                t1[1] = sc[1] + mt[1];
-                               
-                               glVertex2fv(t0);
-                               glVertex2fv(t1);
-                               
+
+                               immVertex2fv(pos, t0);
+                               immVertex2fv(pos, t1);
+
                                /* calculate points for start of segment */
                                mt[0] = m2[0] * pthick;
                                mt[1] = m2[1] * pthick;
-                               
+
                                t0[0] = s0[0] - mt[0];
                                t0[1] = s0[1] - mt[1];
                                t1[0] = s0[0] + mt[0];
                                t1[1] = s0[1] + mt[1];
-                               
+
                                /* draw this line twice (first to finish off start cap, then for stroke) */
-                               glVertex2fv(t1);
-                               glVertex2fv(t0);
-                               glVertex2fv(t0);
-                               glVertex2fv(t1);
+                               immVertex2fv(pos, t1);
+                               immVertex2fv(pos, t0);
+                               immVertex2fv(pos, t0);
+                               immVertex2fv(pos, t1);
                        }
                        /* if not the first segment, use bisector of angle between segments */
                        else {
                                float mb[2];         /* bisector normal */
                                float athick, dfac;  /* actual thickness, difference between thicknesses */
-                               
+
                                /* calculate gradient of bisector (as average of normals) */
                                mb[0] = (pm[0] + m2[0]) / 2;
                                mb[1] = (pm[1] + m2[1]) / 2;
                                normalize_v2(mb);
-                               
+
                                /* calculate gradient to apply
                                 *  - as basis, use just pthick * bisector gradient
                                 *      - if cross-section not as thick as it should be, add extra padding to fix it
@@ -786,49 +867,48 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
                                mt[1] = mb[1] * pthick;
                                athick = len_v2(mt);
                                dfac = pthick - (athick * 2);
-                               
+
                                if (((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick) == 0)) {
                                        mt[0] += (mb[0] * dfac);
                                        mt[1] += (mb[1] * dfac);
                                }
-                               
+
                                /* calculate points for start of segment */
                                t0[0] = s0[0] - mt[0];
                                t0[1] = s0[1] - mt[1];
                                t1[0] = s0[0] + mt[0];
                                t1[1] = s0[1] + mt[1];
-                               
+
                                /* draw this line twice (once for end of current segment, and once for start of next) */
-                               glVertex2fv(t1);
-                               glVertex2fv(t0);
-                               glVertex2fv(t0);
-                               glVertex2fv(t1);
+                               immVertex2fv(pos, t1);
+                               immVertex2fv(pos, t0);
+                               immVertex2fv(pos, t0);
+                               immVertex2fv(pos, t1);
                        }
-                       
+
                        /* if last segment, also draw end of segment (defined as segment's normal) */
                        if (i == totpoints - 2) {
                                /* for once, we use second point's pressure (otherwise it won't be drawn) */
                                pthick = (pt2->pressure * thickness * scalefac);
-                               
+
                                /* color of point */
-                               gp_set_point_color(pt2, ink);
+                               gp_set_point_varying_color(pt2, ink, color);
 
                                /* calculate points for end of segment */
                                mt[0] = m2[0] * pthick;
                                mt[1] = m2[1] * pthick;
-                               
+
                                t0[0] = s1[0] - mt[0];
                                t0[1] = s1[1] - mt[1];
                                t1[0] = s1[0] + mt[0];
                                t1[1] = s1[1] + mt[1];
-                               
+
                                /* draw this line twice (once for end of stroke, and once for endcap)*/
-                               glVertex2fv(t1);
-                               glVertex2fv(t0);
-                               glVertex2fv(t0);
-                               glVertex2fv(t1);
-                               
-                               
+                               immVertex2fv(pos, t1);
+                               immVertex2fv(pos, t0);
+                               immVertex2fv(pos, t0);
+                               immVertex2fv(pos, t1);
+
                                /* draw end cap as last step
                                 *      - make points slightly closer to center (about halfway across)
                                 */
@@ -836,34 +916,33 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
                                mt[1] = m2[1] * pthick * 0.5f;
                                sc[0] = s1[0] + (m1[0] * pthick * 0.75f);
                                sc[1] = s1[1] + (m1[1] * pthick * 0.75f);
-                               
+
                                t0[0] = sc[0] - mt[0];
                                t0[1] = sc[1] - mt[1];
                                t1[0] = sc[0] + mt[0];
                                t1[1] = sc[1] + mt[1];
-                               
-                               glVertex2fv(t1);
-                               glVertex2fv(t0);
+
+                               immVertex2fv(pos, t1);
+                               immVertex2fv(pos, t0);
                        }
-                       
+
                        /* store stroke's 'natural' normal for next stroke to use */
                        copy_v2_v2(pm, m2);
                }
-               
-               glEnd();
-               glShadeModel(GL_SMOOTH);
+
+               immEnd();
+               immUnbindProgram();
        }
-       
+
+#if 0 /* convert to modern GL only if needed */
        /* draw debug points of curve on top? (original stroke points) */
        if (debug) {
-               bGPDspoint *pt;
-               int i;
-               float fpt[3];
-
                glPointSize((float)(thickness_s + 2));
-               
+
                glBegin(GL_POINTS);
-               for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
+               const bGPDspoint *pt = points;
+               for (int i = 0; i < totpoints && pt; i++, pt++) {
+                       float fpt[3];
                        float co[2];
                        mul_v3_m4v3(fpt, diff_mat, &pt->x);
                        gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
@@ -871,6 +950,9 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
                }
                glEnd();
        }
+#else
+       UNUSED_VARS(debug);
+#endif
 }
 
 /* ----- Strokes Drawing ------ */
@@ -884,41 +966,41 @@ static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag)
                return false;
        if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
                return false;
-       
+
        /* 2) Screen Space 2D Strokes */
        if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
                return false;
        if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
                return false;
-       
+
        /* 3) Image Space (2D) */
        if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
                return false;
        if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
                return false;
-       
-       
+
        /* skip stroke if it doesn't have any valid data */
        if ((gps->points == NULL) || (gps->totpoints < 1))
                return false;
-       
+
        /* stroke can be drawn */
        return true;
 }
 
 /* draw a set of strokes */
 static void gp_draw_strokes(
-        bGPdata *gpd, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag,
+        bGPdata *gpd, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag,
         bool debug, short lthick, const float opacity, const float tintcolor[4],
-        const bool onion, const bool custonion, float diff_mat[4][4])
+        const bool onion, const bool custonion, const float diff_mat[4][4])
 {
-       bGPDstroke *gps;
        float tcolor[4];
        float tfill[4];
        short sthickness;
        float ink[4];
 
-       for (gps = gpf->strokes.first; gps; gps = gps->next) {
+       GPU_enable_program_point_size();
+
+       for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
                /* check if stroke can be drawn */
                if (gp_can_draw_stroke(gps, dflag) == false) {
                        continue;
@@ -936,6 +1018,10 @@ static void gp_draw_strokes(
                /* calculate thickness */
                sthickness = gps->thickness + lthick;
 
+               if (sthickness <= 0) {
+                       continue;
+               }
+
                /* check which stroke-drawer to use */
                if (dflag & GP_DRAWDATA_ONLY3D) {
                        const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY);
@@ -962,19 +1048,20 @@ static void gp_draw_strokes(
                                interp_v3_v3v3(tfill, palcolor->fill, tintcolor, tintcolor[3]);
                                tfill[3] = palcolor->fill[3] * opacity;
                                if (tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) {
+                                       const float *color;
                                        if (!onion) {
-                                               glColor4fv(tfill);
+                                               color = tfill;
                                        }
                                        else {
                                                if (custonion) {
-                                                       glColor4fv(tintcolor);
+                                                       color = tintcolor;
                                                }
                                                else {
                                                        ARRAY_SET_ITEMS(tfill, UNPACK3(palcolor->fill), tintcolor[3]);
-                                                       glColor4fv(tfill);
+                                                       color = tfill;
                                                }
                                        }
-                                       gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat);
+                                       gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat, color);
                                }
                        }
 
@@ -996,7 +1083,7 @@ static void gp_draw_strokes(
                        }
                        if (palcolor->flag & PC_COLOR_VOLUMETRIC) {
                                /* volumetric stroke drawing */
-                               gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, dflag, gps->flag, diff_mat, ink);
+                               gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, ink);
                        }
                        else {
                                /* 3D Lines - OpenGL primitives-based */
@@ -1027,20 +1114,21 @@ static void gp_draw_strokes(
                                interp_v3_v3v3(tfill, palcolor->fill, tintcolor, tintcolor[3]);
                                tfill[3] = palcolor->fill[3] * opacity;
                                if (tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) {
+                                       const float *color;
                                        if (!onion) {
-                                               glColor4fv(tfill);
+                                               color = tfill;
                                        }
                                        else {
                                                if (custonion) {
-                                                       glColor4fv(tintcolor);
+                                                       color = tintcolor;
                                                }
                                                else {
                                                        ARRAY_SET_ITEMS(tfill, palcolor->fill[0], palcolor->fill[1], palcolor->fill[2],
                                                                        tintcolor[3]);
-                                                       glColor4fv(tfill);
+                                                       color = tfill;
                                                }
                                        }
-                                       gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat);
+                                       gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat, color);
                                }
                        }
 
@@ -1078,15 +1166,15 @@ static void gp_draw_strokes(
                        }
                }
        }
+
+       GPU_disable_program_point_size();
 }
 
 /* Draw selected verts for strokes being edited */
 static void gp_draw_strokes_edit(
-        bGPdata *gpd, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, short dflag,
-        short lflag, float diff_mat[4][4], float alpha)
+        bGPdata *gpd, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy, short dflag,
+        short lflag, const float diff_mat[4][4], float alpha)
 {
-       bGPDstroke *gps;
-       
        /* if alpha 0 do not draw */
        if (alpha == 0.0f)
                return;
@@ -1100,36 +1188,32 @@ static void gp_draw_strokes_edit(
                        glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
                        glDepthMask(0);
                        glEnable(GL_DEPTH_TEST);
-                       
+
                        /* first arg is normally rv3d->dist, but this isn't
                         * available here and seems to work quite well without */
                        bglPolygonOffset(1.0f, 1.0f);
 #if 0
-                       glEnable(GL_POLYGON_OFFSET_LINE);
+                       glEnable(GL_POLYGON_OFFSET_LINE); /* do we want LINE or POINT here? (merwin) */
                        glPolygonOffset(-1.0f, -1.0f);
 #endif
                }
        }
-       
-       
-       /* draw stroke verts */
-       for (gps = gpf->strokes.first; gps; gps = gps->next) {
-               bGPDspoint *pt;
-               float vsize, bsize;
-               int i;
-               float fpt[3];
 
+       GPU_enable_program_point_size();
+
+       /* draw stroke verts */
+       for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
                /* check if stroke can be drawn */
                if (gp_can_draw_stroke(gps, dflag) == false)
                        continue;
-               
+
                /* Optimisation: only draw points for selected strokes
                 * We assume that selected points can only occur in
                 * strokes that are selected too.
                 */
                if ((gps->flag & GP_STROKE_SELECT) == 0)
                        continue;
-               
+
                /* verify palette color lock */
                {
                        bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
@@ -1148,7 +1232,8 @@ static void gp_draw_strokes_edit(
                 *   they stand out more.
                 * - We use the theme setting for size of the unselected verts
                 */
-               bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
+               float bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
+               float vsize;
                if ((int)bsize > 8) {
                        vsize = 10.0f;
                        bsize = 8.0f;
@@ -1156,89 +1241,83 @@ static void gp_draw_strokes_edit(
                else {
                        vsize = bsize + 2;
                }
-               
-               /* First Pass: Draw all the verts (i.e. these become the unselected state) */
+
                /* for now, we assume that the base color of the points is not too close to the real color */
                /* set color using palette */
                bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
-               glColor3fv(palcolor->color);
 
-               glPointSize(bsize);
-               
-               glBegin(GL_POINTS);
-               for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
+               float selectColor[4];
+               UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor);
+               selectColor[3] = alpha;
+
+               VertexFormat *format = immVertexFormat();
+               unsigned pos; /* specified later */
+               unsigned size = add_attrib(format, "size", GL_FLOAT, 1, KEEP_FLOAT);
+               unsigned color = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT);
+
+               if (gps->flag & GP_STROKE_3DSPACE) {
+                       pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+                       immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
+               }
+               else {
+                       pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+                       immBindBuiltinProgram(GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR);
+               }
+
+               immBegin(GL_POINTS, gps->totpoints);
+
+               /* Draw start and end point differently if enabled stroke direction hint */
+               bool show_direction_hint = (gpd->flag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1);
+
+               /* Draw all the stroke points (selected or not) */
+               bGPDspoint *pt = gps->points;
+               float fpt[3];
+               for (int i = 0; i < gps->totpoints; i++, pt++) {
+                       /* size and color first */
+                       if (show_direction_hint && i == 0) {
+                               /* start point in green bigger */
+                               immAttrib3f(color, 0.0f, 1.0f, 0.0f);
+                               immAttrib1f(size, vsize + 4);
+                       }
+                       else if (show_direction_hint && (i == gps->totpoints - 1)) {
+                               /* end point in red smaller */
+                               immAttrib3f(color, 1.0f, 0.0f, 0.0f);
+                               immAttrib1f(size, vsize + 1);
+                       }
+                       else if (pt->flag & GP_SPOINT_SELECT) {
+                               immAttrib3fv(color, selectColor);
+                               immAttrib1f(size, vsize);
+                       }
+                       else {
+                               immAttrib3fv(color, palcolor->color);
+                               immAttrib1f(size, bsize);
+                       }
+
+                       /* then position */
                        if (gps->flag & GP_STROKE_3DSPACE) {
                                mul_v3_m4v3(fpt, diff_mat, &pt->x);
-                               glVertex3fv(fpt);
+                               immVertex3fv(pos, fpt);
                        }
                        else {
                                float co[2];
                                mul_v3_m4v3(fpt, diff_mat, &pt->x);
                                gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
-                               glVertex2fv(co);
+                               immVertex2fv(pos, co);
                        }
                }
-               glEnd();
-               
-               
-               /* Second Pass: Draw only verts which are selected */
-               float curColor[4];
-               UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, curColor);
-               glColor4f(curColor[0], curColor[1], curColor[2], alpha);
 
-               glPointSize(vsize);
-               
-               glBegin(GL_POINTS);
-               for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
-                       if (pt->flag & GP_SPOINT_SELECT) {
-                               if (gps->flag & GP_STROKE_3DSPACE) {
-                                       mul_v3_m4v3(fpt, diff_mat, &pt->x);
-                                       glVertex3fv(fpt);
-                               }
-                               else {
-                                       float co[2];
-                                       
-                                       mul_v3_m4v3(fpt, diff_mat, &pt->x);
-                                       gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
-                                       glVertex2fv(co);
-                               }
-                       }
-               }
-               glEnd();
-
-               /* Draw start and end point if enabled stroke direction hint */
-               if ((gpd->flag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1)) {
-                       bGPDspoint *p;
-                       
-                       glPointSize(vsize + 4);
-                       glBegin(GL_POINTS);
-
-                       /* start point in green bigger */
-                       glColor3f(0.0f, 1.0f, 0.0f);
-                       p = &gps->points[0];
-                       mul_v3_m4v3(fpt, diff_mat, &p->x);
-                       glVertex3fv(fpt);
-                       glEnd();
+               immEnd();
+               immUnbindProgram();
+       }
 
-                       /* end point in red smaller */
-                       glPointSize(vsize + 1);
-                       glBegin(GL_POINTS);
+       GPU_disable_program_point_size();
 
-                       glColor3f(1.0f, 0.0f, 0.0f);
-                       p = &gps->points[gps->totpoints - 1];
-                       mul_v3_m4v3(fpt, diff_mat, &p->x);
-                       glVertex3fv(fpt);
-                       glEnd();
-               }
-       }
-       
-       
        /* clear depth mask */
        if (dflag & GP_DRAWDATA_ONLY3D) {
                if (no_xray) {
                        glDepthMask(mask_orig);
                        glDisable(GL_DEPTH_TEST);
-                       
+
                        bglPolygonOffset(0.0, 0.0);
 #if 0
                        glDisable(GL_POLYGON_OFFSET_LINE);
@@ -1252,8 +1331,8 @@ static void gp_draw_strokes_edit(
 
 /* draw onion-skinning for a layer */
 static void gp_draw_onionskins(
-        bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy,
-        int UNUSED(cfra), int dflag, bool debug, float diff_mat[4][4])
+        bGPdata *gpd, const bGPDlayer *gpl, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy,
+        int UNUSED(cfra), int dflag, bool debug, const float diff_mat[4][4])
 {
        const float default_color[3] = {UNPACK3(U.gpencil_new_layer_col)};
        const float alpha = 1.0f;
@@ -1266,17 +1345,14 @@ static void gp_draw_onionskins(
        else {
                copy_v3_v3(color, default_color);
        }
-       
+
        if (gpl->gstep > 0) {
-               bGPDframe *gf;
-               float fac;
-               
                /* draw previous frames first */
-               for (gf = gpf->prev; gf; gf = gf->prev) {
+               for (bGPDframe *gf = gpf->prev; gf; gf = gf->prev) {
                        /* check if frame is drawable */
                        if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
                                /* alpha decreases with distance from curframe index */
-                               fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
+                               float fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
                                color[3] = alpha * fac * 0.66f;
                                gp_draw_strokes(gpd, gf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, 1.0f, color,
                                                true, gpl->flag & GP_LAYER_GHOST_PREVCOL, diff_mat);
@@ -1296,8 +1372,7 @@ static void gp_draw_onionskins(
        else {
                /* don't draw - disabled */
        }
-       
-       
+
        /* 2) Now draw next frames */
        if (gpl->flag & GP_LAYER_GHOST_NEXTCOL) {
                copy_v3_v3(color, gpl->gcolor_next);
@@ -1305,17 +1380,14 @@ static void gp_draw_onionskins(
        else {
                copy_v3_v3(color, default_color);
        }
-       
+
        if (gpl->gstep_next > 0) {
-               bGPDframe *gf;
-               float fac;
-               
                /* now draw next frames */
-               for (gf = gpf->next; gf; gf = gf->next) {
+               for (bGPDframe *gf = gpf->next; gf; gf = gf->next) {
                        /* check if frame is drawable */
                        if ((gf->framenum - gpf->framenum) <= gpl->gstep_next) {
                                /* alpha decreases with distance from curframe index */
-                               fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1));
+                               float fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1));
                                color[3] = alpha * fac * 0.66f;
                                gp_draw_strokes(gpd, gf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, 1.0f, color,
                                                true, gpl->flag & GP_LAYER_GHOST_NEXTCOL, diff_mat);
@@ -1335,7 +1407,6 @@ static void gp_draw_onionskins(
        else {
                /* don't draw - disabled */
        }
-       
 }
 
 /* draw interpolate strokes (used only while operator is running) */
@@ -1373,29 +1444,27 @@ void ED_gp_draw_interpolation(tGPDinterpolate *tgpi, const int type)
 
 /* loop over gpencil data layers, drawing them */
 static void gp_draw_data_layers(
-        bGPDbrush *brush, float alpha, bGPdata *gpd,
+        const bGPDbrush *brush, float alpha, bGPdata *gpd,
         int offsx, int offsy, int winx, int winy, int cfra, int dflag)
 {
-       bGPDlayer *gpl;
        float diff_mat[4][4];
 
-       for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
-               bGPDframe *gpf;
+       for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
                /* calculate parent position */
                ED_gpencil_parent_location(gpl, diff_mat);
 
-               bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? true : false;
+               bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG);
                short lthick = brush->thickness + gpl->thickness;
-               
+
                /* don't draw layer if hidden */
                if (gpl->flag & GP_LAYER_HIDE)
                        continue;
-               
+
                /* get frame to draw */
-               gpf = BKE_gpencil_layer_getframe(gpl, cfra, 0);
+               bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra, 0);
                if (gpf == NULL)
                        continue;
-               
+
                /* set basic stroke thickness */
                glLineWidth(lthick);
                
@@ -1407,10 +1476,10 @@ static void gp_draw_data_layers(
                        if (condition) dflag |= (draw_flag_value);      \
                        else           dflag &= ~(draw_flag_value);     \
                } (void)0
-               
+
                /* xray... */
                GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_NO_XRAY), GP_DRAWDATA_NO_XRAY);
-               
+
                /* volumetric strokes... */
                GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_VOLUMETRIC), GP_DRAWDATA_VOLUMETRIC);
 
@@ -1434,11 +1503,11 @@ static void gp_draw_data_layers(
                         */
                        gp_draw_onionskins(gpd, gpl, gpf, offsx, offsy, winx, winy, cfra, dflag, debug, diff_mat);
                }
-               
+
                /* draw the strokes already in active frame */
                gp_draw_strokes(gpd, gpf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness,
                                gpl->opacity, gpl->tintcolor, false, false, diff_mat);
-               
+
                /* Draw verts of selected strokes
                 *  - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering
                 *      - locked layers can't be edited, so there's no point showing these verts
@@ -1453,16 +1522,13 @@ static void gp_draw_data_layers(
                {
                        gp_draw_strokes_edit(gpd, gpf, offsx, offsy, winx, winy, dflag, gpl->flag, diff_mat, alpha);
                }
-               
+
                /* Check if may need to draw the active stroke cache, only if this layer is the active layer
                 * that is being edited. (Stroke buffer is currently stored in gp-data)
                 */
                if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
                    (gpf->flag & GP_FRAME_PAINT))
                {
-                       /* Set color for drawing buffer stroke - since this may not be set yet */
-                       // glColor4fv(gpl->color);
-                       
                        /* Buffer stroke needs to be drawn with a different linestyle
                         * to help differentiate them from normal strokes.
                         * 
@@ -1471,38 +1537,37 @@ static void gp_draw_data_layers(
                         */
                        if (gpd->sflag & PC_COLOR_VOLUMETRIC) {
                                gp_draw_stroke_volumetric_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick,
-                                                                dflag, gpd->sbuffer_sflag, gpd->scolor);
+                                                                dflag, gpd->scolor);
                        }
                        else {
-                               gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag, gpd->scolor);
+                               gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag, gpd->scolor, gpd->sfill);
                        }
                }
        }
 }
 
 /* draw a short status message in the top-right corner */
-static void gp_draw_status_text(bGPdata *gpd, ARegion *ar)
+static void gp_draw_status_text(const bGPdata *gpd, ARegion *ar)
 {
        rcti rect;
-       
+
        /* Cannot draw any status text when drawing OpenGL Renders */
        if (G.f & G_RENDER_OGL)
                return;
-       
+
        /* Get bounds of region - Necessary to avoid problems with region overlap */
        ED_region_visible_rect(ar, &rect);
-       
+
        /* for now, this should only be used to indicate when we are in stroke editmode */
        if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
                const char *printable = IFACE_("GPencil Stroke Editing");
                float       printable_size[2];
-               int xco, yco;
-               
+
                BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
                
-               xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
-               yco = (rect.ymax - U.widget_unit);
-               
+               int xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
+               int yco = (rect.ymax - U.widget_unit);
+
                /* text label */
                UI_ThemeColor(TH_TEXT_HI);
 #ifdef WITH_INTERNATIONAL
@@ -1510,50 +1575,54 @@ static void gp_draw_status_text(bGPdata *gpd, ARegion *ar)
 #else
                BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
 #endif
-               
+
                /* grease pencil icon... */
                // XXX: is this too intrusive?
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                glEnable(GL_BLEND);
-               
+
                xco -= U.widget_unit;
                yco -= (int)printable_size[1] / 2;
 
                UI_icon_draw(xco, yco, ICON_GREASEPENCIL);
-               
+
                glDisable(GL_BLEND);
        }
 }
 
 /* draw grease-pencil datablock */
 static void gp_draw_data(
-        bGPDbrush *brush, float alpha, bGPdata *gpd,
+        const bGPDbrush *brush, float alpha, bGPdata *gpd,
         int offsx, int offsy, int winx, int winy, int cfra, int dflag)
 {
+#if 0 /* disable to see if really needed. re-enable or delete by Dec 2016 */
        /* reset line drawing style (in case previous user didn't reset) */
        setlinestyle(0);
-       
+#endif
+
        /* turn on smooth lines (i.e. anti-aliasing) */
        glEnable(GL_LINE_SMOOTH);
-       
+
        /* XXX: turn on some way of ensuring that the polygon edges get smoothed 
         *      GL_POLYGON_SMOOTH is nasty and shouldn't be used, as it ends up
         *      creating internal white rays due to the ways it accumulates stuff
         */
-       
+
        /* turn on alpha-blending */
        glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);
-       
+
        /* draw! */
        gp_draw_data_layers(brush, alpha, gpd, offsx, offsy, winx, winy, cfra, dflag);
-       
+
        /* turn off alpha blending, then smooth lines */
        glDisable(GL_BLEND); // alpha blending
        glDisable(GL_LINE_SMOOTH); // smooth lines
-       
+
+#if 0 /* disable to see if really needed. re-enable or delete by Dec 2016 */
        /* restore initial gl conditions */
        glColor4f(0, 0, 0, 1);
+#endif
 }
 
 /* if we have strokes for scenes (3d view)/clips (movie clip editor)
@@ -1581,16 +1650,15 @@ static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, i
                        /* currently drawing only gpencil data from either clip or track, but not both - XXX fix logic behind */
                        gpd_source = (scene->clip->gpd ? scene->clip->gpd : NULL);
                }
-               
+
                if (gpd_source) {
                        if (brush != NULL) {
                                gp_draw_data(brush, ts->gp_sculpt.alpha, gpd_source,
                                             offsx, offsy, winx, winy, cfra, dflag);
                        }
-                       
                }
        }
-       
+
        /* scene/clip data has already been drawn, only object/track data is drawn here
         * if gpd_source == gpd, we don't have any object/track data and we can skip */
        if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) {
@@ -1616,28 +1684,27 @@ void ED_gpencil_draw_2dimage(const bContext *C)
        ScrArea *sa = CTX_wm_area(C);
        ARegio