Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Fri, 29 Jun 2018 06:05:38 +0000 (08:05 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 29 Jun 2018 06:05:38 +0000 (08:05 +0200)
147 files changed:
1  2 
intern/ghost/GHOST_IContext.h
intern/ghost/GHOST_ISystem.h
intern/ghost/intern/GHOST_SystemCocoa.h
intern/ghost/intern/GHOST_SystemX11.h
release/scripts/modules/keyingsets_utils.py
source/blender/blenlib/BLI_math_geom.h
source/blender/blenlib/BLI_math_matrix.h
source/blender/collada/GeometryExporter.cpp
source/blender/collada/SceneExporter.cpp
source/blender/collada/collada_internal.cpp
source/blender/draw/engines/eevee/shaders/ltc_lib.glsl
source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl
source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
source/blender/draw/engines/workbench/solid_mode.c
source/blender/draw/engines/workbench/transparent_mode.c
source/blender/draw/engines/workbench/workbench_effect_fxaa.c
source/blender/draw/intern/draw_anim_viz.c
source/blender/draw/modes/overlay_mode.c
source/blender/draw/modes/shaders/common_fxaa_lib.glsl
source/blender/editors/animation/keyframes_draw.c
source/blender/editors/armature/armature_intern.h
source/blender/editors/armature/armature_naming.c
source/blender/editors/armature/armature_ops.c
source/blender/editors/armature/armature_relations.c
source/blender/editors/armature/meshlaplacian.h
source/blender/editors/armature/pose_select.c
source/blender/editors/include/BIF_gl.h
source/blender/editors/include/ED_anim_api.h
source/blender/editors/include/ED_fileselect.h
source/blender/editors/include/ED_image.h
source/blender/editors/include/ED_node.h
source/blender/editors/include/ED_particle.h
source/blender/editors/include/ED_undo.h
source/blender/editors/include/ED_util.h
source/blender/editors/include/ED_uvedit.h
source/blender/editors/interface/interface_eyedropper.c
source/blender/editors/interface/interface_style.c
source/blender/editors/interface/view2d.c
source/blender/editors/interface/view2d_ops.c
source/blender/editors/manipulator_library/manipulator_library_intern.h
source/blender/editors/manipulator_library/manipulator_library_presets.c
source/blender/editors/mesh/mesh_ops.c
source/blender/editors/object/object_constraint.c
source/blender/editors/object/object_hook.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_shapekey.c
source/blender/editors/physics/particle_boids.c
source/blender/editors/physics/particle_edit.c
source/blender/editors/physics/physics_fluid.c
source/blender/editors/physics/physics_ops.c
source/blender/editors/physics/physics_pointcache.c
source/blender/editors/render/render_intern.h
source/blender/editors/render/render_ops.c
source/blender/editors/render/render_preview.c
source/blender/editors/render/render_shading.c
source/blender/editors/render/render_update.c
source/blender/editors/render/render_view.c
source/blender/editors/screen/screen_context.c
source/blender/editors/screen/screendump.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_image_proj.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/space_action/action_intern.h
source/blender/editors/space_buttons/buttons_intern.h
source/blender/editors/space_buttons/space_buttons.c
source/blender/editors/space_clip/tracking_ops_stabilize.c
source/blender/editors/space_file/file_panels.c
source/blender/editors/space_file/space_file.c
source/blender/editors/space_image/image_buttons.c
source/blender/editors/space_image/image_edit.c
source/blender/editors/space_image/image_intern.h
source/blender/editors/space_node/node_add.c
source/blender/editors/space_node/node_templates.c
source/blender/editors/space_outliner/outliner_ops.c
source/blender/editors/space_outliner/space_outliner.c
source/blender/editors/space_script/space_script.c
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/editors/space_sequencer/sequencer_intern.h
source/blender/editors/space_sequencer/sequencer_select.c
source/blender/editors/space_text/space_text.c
source/blender/editors/space_text/text_header.c
source/blender/editors/space_userpref/space_userpref.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_manipulator_forcefield.c
source/blender/editors/space_view3d/view3d_ops.c
source/blender/editors/transform/transform_generics.c
source/blender/editors/transform/transform_ops.c
source/blender/editors/uvedit/uvedit_buttons.c
source/blender/editors/uvedit/uvedit_draw.c
source/blender/gpu/CMakeLists.txt
source/blender/gpu/GPU_basic_shader.h
source/blender/gpu/GPU_draw.h
source/blender/gpu/intern/gpu_codegen.h
source/blender/gpu/intern/gpu_extensions.c
source/blender/gpu/intern/gpu_shader_private.h
source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
source/blender/ikplugin/intern/ikplugin_api.c
source/blender/ikplugin/intern/iksolver_plugin.c
source/blender/ikplugin/intern/itasc_plugin.cpp
source/blender/makesrna/RNA_define.h
source/blender/makesrna/intern/rna_context.c
source/blender/makesrna/intern/rna_image_api.c
source/blender/makesrna/intern/rna_lightprobe.c
source/blender/makesrna/intern/rna_screen.c
source/blender/makesrna/intern/rna_speaker.c
source/blender/makesrna/intern/rna_ui.c
source/blender/nodes/NOD_shader.h
source/blender/nodes/shader/node_shader_util.c
source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
source/blender/nodes/shader/nodes/node_shader_attribute.c
source/blender/nodes/shader/nodes/node_shader_light_falloff.c
source/blender/nodes/shader/nodes/node_shader_object_info.c
source/blender/nodes/shader/nodes/node_shader_particle_info.c
source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
source/blender/nodes/shader/nodes/node_shader_volume_principled.c
source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
source/blender/python/bmesh/bmesh_py_types_meshdata.c
source/blender/python/intern/bpy_manipulator_wrap.c
source/blender/python/intern/bpy_manipulator_wrap.h
source/blender/python/intern/bpy_msgbus.c
source/blender/python/intern/gpu.c
source/blender/python/simple_enum_gen.py
source/blender/render/extern/include/RE_engine.h
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/include/initrender.h
source/blender/render/intern/include/render_result.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/include/renderpipeline.h
source/blender/render/intern/include/texture.h
source/blender/render/intern/include/zbuf.h
source/blender/render/intern/source/initrender.c
source/blender/render/intern/source/pointdensity.c
source/blender/render/intern/source/render_texture.c
source/blender/windowmanager/WM_keymap.h
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm.c
source/blender/windowmanager/intern/wm_draw.c
source/blender/windowmanager/manipulators/intern/wm_manipulator_group_type.c
source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h
source/blender/windowmanager/wm_draw.h
source/blender/windowmanager/wm_event_types.h
source/blender/windowmanager/wm_files.h
source/blender/windowmanager/wm_window.h
tests/python/modules/render_report.py

index 5b027a614aba1f2d9b354a70c69e258c25637617,0000000000000000000000000000000000000000..22b63486398ff364df854f73ef59cbf18da41408
mode 100644,000000..100644
--- /dev/null
@@@ -1,78 -1,0 +1,77 @@@
 +/*
 + * ***** 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) 2001-2002 by NaN Holding BV.
 + * All rights reserved.
 + *
 + * The Original Code is: all of this file.
 + *
 + * Contributor(s): none yet.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +/** \file ghost/GHOST_IContext.h
 + *  \ingroup GHOST
 + * Declaration of GHOST_IContext interface class.
 + */
 +
 +#ifndef __GHOST_IContext_H__
 +#define __GHOST_IContext_H__
 +
 +#include "STR_String.h"
 +#include "GHOST_Types.h"
 +
 +
 +/**
 + * Interface for GHOST context.
 + *
 + * You can create a offscreen context (windowless) with the system's
 + * GHOST_ISystem::createOffscreenContext method.
 + * \see GHOST_ISystem#createOffscreenContext
 + *
 + * \author  Clément Foucault
 + * \date    Feb 9, 2018
 + */
 +class GHOST_IContext
 +{
 +public:
 +      /**
 +       * Destructor.
 +       */
 +      virtual ~GHOST_IContext()
 +      {
 +      }
 +
 +      /**
 +       * Activates the drawing context.
 +       * \return  A boolean success indicator.
 +       */
 +      virtual GHOST_TSuccess activateDrawingContext() = 0;
 +
 +      /**
 +       * Release the drawing context of the calling thread.
 +       * \return  A boolean success indicator.
 +       */
 +      virtual GHOST_TSuccess releaseDrawingContext() = 0;
 +
 +#ifdef WITH_CXX_GUARDEDALLOC
 +      MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IContext")
 +#endif
 +};
 +
 +#endif // __GHOST_IContext_H__
Simple merge
Simple merge
index 5c62cb19152bc523087841d24389bb1d1291af20,0000000000000000000000000000000000000000..11c223a45d6c072c8be3ead82a9bcecd18066b8e
mode 100644,000000..100644
--- /dev/null
@@@ -1,322 -1,0 +1,321 @@@
 +/**
 + * Adapted from :
 + * Real-Time Polygonal-Light Shading with Linearly Transformed Cosines.
 + * Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt.
 + * ACM Transactions on Graphics (Proceedings of ACM SIGGRAPH 2016) 35(4), 2016.
 + * Project page: https://eheitzresearch.wordpress.com/415-2/
 + **/
 +
 +#define USE_LTC
 +
 +#ifndef UTIL_TEX
 +#define UTIL_TEX
 +uniform sampler2DArray utilTex;
 +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
 +#endif /* UTIL_TEX */
 +
 +/* Diffuse *clipped* sphere integral. */
 +float diffuse_sphere_integral_lut(float avg_dir_z, float form_factor)
 +{
 +      vec2 uv = vec2(avg_dir_z * 0.5 + 0.5, form_factor);
 +      uv = uv * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE;
 +
 +      return texture(utilTex, vec3(uv, 1.0)).w;
 +}
 +
 +float diffuse_sphere_integral_cheap(float avg_dir_z, float form_factor)
 +{
 +      return max((form_factor * form_factor + avg_dir_z) / (form_factor + 1.0), 0.0);
 +}
 +
 +/**
 + * An extended version of the implementation from
 + * "How to solve a cubic equation, revisited"
 + * http://momentsingraphics.de/?p=105
 + **/
 +vec3 solve_cubic(vec4 coefs)
 +{
 +      /* Normalize the polynomial */
 +      coefs.xyz /= coefs.w;
 +      /* Divide middle coefficients by three */
 +      coefs.yz /= 3.0;
 +
 +      float A = coefs.w;
 +      float B = coefs.z;
 +      float C = coefs.y;
 +      float D = coefs.x;
 +
 +      /* Compute the Hessian and the discriminant */
 +      vec3 delta = vec3(
 +              -coefs.z*coefs.z + coefs.y,
 +              -coefs.y*coefs.z + coefs.x,
 +              dot(vec2(coefs.z, -coefs.y), coefs.xy)
 +      );
 +
 +      /* Discriminant */
 +      float discr = dot(vec2(4.0 * delta.x, -delta.y), delta.zy);
 +
 +      vec2 xlc, xsc;
 +
 +      /* Algorithm A */
 +      {
 +              float A_a = 1.0;
 +              float C_a = delta.x;
 +              float D_a = -2.0 * B * delta.x + delta.y;
 +
 +              /* Take the cubic root of a normalized complex number */
 +              float theta = atan(sqrt(discr), -D_a) / 3.0;
 +
 +              float x_1a = 2.0 * sqrt(-C_a) * cos(theta);
 +              float x_3a = 2.0 * sqrt(-C_a) * cos(theta + (2.0 / 3.0) * M_PI);
 +
 +              float xl;
 +              if ((x_1a + x_3a) > 2.0 * B) {
 +                      xl = x_1a;
 +              }
 +              else {
 +                      xl = x_3a;
 +              }
 +
 +              xlc = vec2(xl - B, A);
 +      }
 +
 +      /* Algorithm D */
 +      {
 +              float A_d = D;
 +              float C_d = delta.z;
 +              float D_d = -D * delta.y + 2.0 * C * delta.z;
 +
 +              /* Take the cubic root of a normalized complex number */
 +              float theta = atan(D * sqrt(discr), -D_d) / 3.0;
 +
 +              float x_1d = 2.0 * sqrt(-C_d) * cos(theta);
 +              float x_3d = 2.0 * sqrt(-C_d) * cos(theta + (2.0 / 3.0) * M_PI);
 +
 +              float xs;
 +              if (x_1d + x_3d < 2.0 * C)
 +                      xs = x_1d;
 +              else
 +                      xs = x_3d;
 +
 +              xsc = vec2(-D, xs + C);
 +      }
 +
 +      float E =  xlc.y * xsc.y;
 +      float F = -xlc.x * xsc.y - xlc.y * xsc.x;
 +      float G =  xlc.x * xsc.x;
 +
 +      vec2 xmc = vec2(C * F - B * G, -B * F + C * E);
 +
 +      vec3 root = vec3(xsc.x / xsc.y,
 +                       xmc.x / xmc.y,
 +                       xlc.x / xlc.y);
 +
 +      if (root.x < root.y && root.x < root.z) {
 +              root.xyz = root.yxz;
 +      }
 +      else if (root.z < root.x && root.z < root.y) {
 +              root.xyz = root.xzy;
 +      }
 +
 +      return root;
 +}
 +
 +/* from Real-Time Area Lighting: a Journey from Research to Production
 + * Stephen Hill and Eric Heitz */
 +vec3 edge_integral_vec(vec3 v1, vec3 v2)
 +{
 +      float x = dot(v1, v2);
 +      float y = abs(x);
 +
 +      float a = 0.8543985 + (0.4965155 + 0.0145206 * y) * y;
 +      float b = 3.4175940 + (4.1616724 + y) * y;
 +      float v = a / b;
 +
 +      float theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt(max(1.0 - x * x, 1e-7)) - v;
 +
 +      return cross(v1, v2) * theta_sintheta;
 +}
 +
 +mat3 ltc_matrix(vec4 lut)
 +{
 +      /* load inverse matrix */
 +      mat3 Minv = mat3(
 +              vec3(  1,   0, lut.y),
 +              vec3(  0, lut.z,   0),
 +              vec3(lut.w,   0, lut.x)
 +      );
 +
 +      return Minv;
 +}
 +
 +void ltc_transform_quad(vec3 N, vec3 V, mat3 Minv, inout vec3 corners[4])
 +{
 +      /* Avoid dot(N, V) == 1 in ortho mode, leading T1 normalize to fail. */
 +      V = normalize(V + 1e-8);
 +
 +      /* construct orthonormal basis around N */
 +      vec3 T1, T2;
 +      T1 = normalize(V - N * dot(N, V));
 +      T2 = cross(N, T1);
 +
 +      /* rotate area light in (T1, T2, R) basis */
 +      Minv = Minv * transpose(mat3(T1, T2, N));
 +
 +      /* Apply LTC inverse matrix. */
 +      corners[0] = normalize(Minv * corners[0]);
 +      corners[1] = normalize(Minv * corners[1]);
 +      corners[2] = normalize(Minv * corners[2]);
 +      corners[3] = normalize(Minv * corners[3]);
 +}
 +
 +/* If corners have already pass through ltc_transform_quad(), then N **MUST** be vec3(0.0, 0.0, 1.0),
 + * corresponding to the Up axis of the shading basis. */
 +float ltc_evaluate_quad(vec3 corners[4], vec3 N)
 +{
 +      /* Approximation using a sphere of the same solid angle than the quad.
 +       * Finding the clipped sphere diffuse integral is easier than clipping the quad. */
 +      vec3 avg_dir;
 +      avg_dir  = edge_integral_vec(corners[0], corners[1]);
 +      avg_dir += edge_integral_vec(corners[1], corners[2]);
 +      avg_dir += edge_integral_vec(corners[2], corners[3]);
 +      avg_dir += edge_integral_vec(corners[3], corners[0]);
 +
 +      float form_factor = length(avg_dir);
 +      float avg_dir_z = dot(N, avg_dir / form_factor);
 +
 +#if 1 /* use tabulated horizon-clipped sphere */
 +      return form_factor * diffuse_sphere_integral_lut(avg_dir_z, form_factor);
 +#else /* Less accurate version, a bit cheaper. */
 +      return form_factor * diffuse_sphere_integral_cheap(avg_dir_z, form_factor);
 +#endif
 +}
 +
 +/* If disk does not need to be transformed and is already front facing. */
 +float ltc_evaluate_disk_simple(float disk_radius, float NL)
 +{
 +      float r_sqr = disk_radius * disk_radius;
 +      float one_r_sqr = 1.0 + r_sqr;
 +      float form_factor = r_sqr * inversesqrt(one_r_sqr * one_r_sqr);
 +
 +#if 1 /* use tabulated horizon-clipped sphere */
 +      return form_factor * diffuse_sphere_integral_lut(NL, form_factor);
 +#else /* Less accurate version, a bit cheaper. */
 +      return form_factor * diffuse_sphere_integral_cheap(NL, form_factor);
 +#endif
 +}
 +
 +/* disk_points are WS vectors from the shading point to the disk "bounding domain" */
 +float ltc_evaluate_disk(vec3 N, vec3 V, mat3 Minv, vec3 disk_points[3])
 +{
 +      /* Avoid dot(N, V) == 1 in ortho mode, leading T1 normalize to fail. */
 +      V = normalize(V + 1e-8);
 +
 +      /* construct orthonormal basis around N */
 +      vec3 T1, T2;
 +      T1 = normalize(V - N * dot(V, N));
 +      T2 = cross(N, T1);
 +
 +      /* rotate area light in (T1, T2, R) basis */
 +      mat3 R = transpose(mat3(T1, T2, N));
 +
 +      /* Intermediate step: init ellipse. */
 +      vec3 L_[3];
 +      L_[0] = mul(R, disk_points[0]);
 +      L_[1] = mul(R, disk_points[1]);
 +      L_[2] = mul(R, disk_points[2]);
 +
 +      vec3 C  = 0.5 * (L_[0] + L_[2]);
 +      vec3 V1 = 0.5 * (L_[1] - L_[2]);
 +      vec3 V2 = 0.5 * (L_[1] - L_[0]);
 +
 +      /* Transform ellipse by Minv. */
 +      C  = Minv * C;
 +      V1 = Minv * V1;
 +      V2 = Minv * V2;
 +
 +      /* Compute eigenvectors of new ellipse. */
 +
 +      float d11 = dot(V1, V1);
 +      float d22 = dot(V2, V2);
 +      float d12 = dot(V1, V2);
 +      float a, b; /* Eigenvalues */
 +      const float threshold = 0.0007; /* Can be adjusted. Fix artifacts. */
 +      if (abs(d12) / sqrt(d11 * d22) > threshold) {
 +              float tr = d11 + d22;
 +              float det = -d12 * d12 + d11 * d22;
 +
 +              /* use sqrt matrix to solve for eigenvalues */
 +              det = sqrt(det);
 +              float u = 0.5 * sqrt(tr - 2.0 * det);
 +              float v = 0.5 * sqrt(tr + 2.0 * det);
 +              float e_max = (u + v);
 +              float e_min = (u - v);
 +              e_max *= e_max;
 +              e_min *= e_min;
 +
 +              vec3 V1_, V2_;
 +              if (d11 > d22) {
 +                      V1_ = d12 * V1 + (e_max - d11) * V2;
 +                      V2_ = d12 * V1 + (e_min - d11) * V2;
 +              }
 +              else {
 +                      V1_ = d12 * V2 + (e_max - d22) * V1;
 +                      V2_ = d12 * V2 + (e_min - d22) * V1;
 +              }
 +
 +              a = 1.0 / e_max;
 +              b = 1.0 / e_min;
 +              V1 = normalize(V1_);
 +              V2 = normalize(V2_);
 +      }
 +      else {
 +              a = 1.0 / d11;
 +              b = 1.0 / d22;
 +              V1 *= sqrt(a);
 +              V2 *= sqrt(b);
 +      }
 +
 +      /* Now find front facing ellipse with same solid angle. */
 +
 +      vec3 V3 = normalize(cross(V1, V2));
 +      if (dot(C, V3) < 0.0)
 +              V3 *= -1.0;
 +
 +      float L  = dot(V3, C);
 +      float x0 = dot(V1, C) / L;
 +      float y0 = dot(V2, C) / L;
 +
 +      a *= L*L;
 +      b *= L*L;
 +
 +      float c0 = a * b;
 +      float c1 = a * b * (1.0 + x0 * x0 + y0 * y0) - a - b;
 +      float c2 = 1.0 - a * (1.0 + x0 * x0) - b * (1.0 + y0 * y0);
 +      float c3 = 1.0;
 +
 +      vec3 roots = solve_cubic(vec4(c0, c1, c2, c3));
 +      float e1 = roots.x;
 +      float e2 = roots.y;
 +      float e3 = roots.z;
 +
 +      vec3 avg_dir = vec3(a * x0 / (a - e2), b * y0 / (b - e2), 1.0);
 +
 +      mat3 rotate = mat3(V1, V2, V3);
 +
 +      avg_dir = rotate * avg_dir;
 +      avg_dir = normalize(avg_dir);
 +
 +      /* L1, L2 are the extends of the front facing ellipse. */
 +      float L1 = sqrt(-e2/e3);
 +      float L2 = sqrt(-e2/e1);
 +
 +      /* Find the sphere and compute lighting. */
 +      float form_factor = max(0.0, L1 * L2 * inversesqrt((1.0 + L1 * L1) * (1.0 + L2 * L2)));
 +
 +#if 1 /* use tabulated horizon-clipped sphere */
 +      return form_factor * diffuse_sphere_integral_lut(avg_dir.z, form_factor);
 +#else /* Less accurate version, a bit cheaper. */
 +      return form_factor * diffuse_sphere_integral_cheap(avg_dir.z, form_factor);
 +#endif
 +}
index 450cb3e680bec6e387aefcb39fb0108343aeb575,0000000000000000000000000000000000000000..41726a774eb91fd0ba942de46034fc15c0e4fd06
mode 100644,000000..100644
--- /dev/null
@@@ -1,8 -1,0 +1,7 @@@
 +uniform int object_id = 0;
 +layout(location=0) out uint objectId;
 +
 +void main()
 +{
 +      objectId = uint(object_id);
 +}
index 1b3737193b06bc670a09b89f888d5164e5491b12,0000000000000000000000000000000000000000..c21dd2af68454b927de59ae5e36abfac00513533
mode 100644,000000..100644
--- /dev/null
@@@ -1,83 -1,0 +1,82 @@@
 +#ifdef V3D_SHADING_TEXTURE_COLOR
 +uniform sampler2D image;
 +#endif
 +uniform mat4 ProjectionMatrix;
 +uniform mat3 normalWorldMatrix;
 +uniform float alpha = 0.5;
 +uniform vec2 invertedViewportSize;
 +uniform vec4 viewvecs[3];
 +
 +#ifdef NORMAL_VIEWPORT_PASS_ENABLED
 +in vec3 normal_viewport;
 +#endif /* NORMAL_VIEWPORT_PASS_ENABLED */
 +#ifdef V3D_SHADING_TEXTURE_COLOR
 +in vec2 uv_interp;
 +#endif
 +#ifdef STUDIOLIGHT_ORIENTATION_VIEWNORMAL
 +uniform sampler2D matcapImage;
 +#endif
 +
 +layout(std140) uniform world_block {
 +      WorldData world_data;
 +};
 +
 +layout(std140) uniform material_block {
 +      MaterialData material_data;
 +};
 +
 +layout(location=0) out vec4 transparentAccum;
 +layout(location=1) out float revealageAccum; /* revealage actually stored in transparentAccum.a */
 +
 +void main()
 +{
 +      vec4 diffuse_color;
 +      vec3 diffuse_light = vec3(1.0);
 +
 +#ifdef V3D_SHADING_TEXTURE_COLOR
 +      diffuse_color = texture(image, uv_interp);
 +#else
 +      diffuse_color = material_data.diffuse_color;
 +#endif /* V3D_SHADING_TEXTURE_COLOR */
 +
 +      vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize;
 +      vec3 I_vs = view_vector_from_screen_uv(uv_viewport, viewvecs, ProjectionMatrix);
 +
 +#ifdef NORMAL_VIEWPORT_PASS_ENABLED
 +      vec3 nor = normalize(normal_viewport);
 +#endif
 +
 +#ifdef V3D_LIGHTING_MATCAP
 +      bool flipped = world_data.matcap_orientation != 0;
 +      vec2 matcap_uv = matcap_uv_compute(I_vs, nor, flipped);
 +      diffuse_light = texture(matcapImage, matcap_uv).rgb;
 +#endif
 +
 +#ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
 +      vec3 specular_color = get_world_specular_lights(world_data, vec4(material_data.specular_color.rgb, material_data.roughness), nor, I_vs);
 +#else
 +      vec3 specular_color = vec3(0.0);
 +#endif
 +
 +#ifdef V3D_LIGHTING_STUDIO
 +#  ifdef STUDIOLIGHT_ORIENTATION_CAMERA
 +      diffuse_light = get_camera_diffuse_light(world_data, nor);
 +#  endif
 +#  ifdef STUDIOLIGHT_ORIENTATION_WORLD
 +      vec3 normal_world = normalWorldMatrix * nor;
 +      diffuse_light = get_world_diffuse_light(world_data, normal_world);
 +#  endif
 +#endif
 +
 +      vec3 shaded_color = diffuse_light * diffuse_color.rgb + specular_color;
 +
 +      /* Based on :
 +       * McGuire and Bavoil, Weighted Blended Order-Independent Transparency, Journal of
 +       * Computer Graphics Techniques (JCGT), vol. 2, no. 2, 122–141, 2013
 +       */
 +      /* Listing 4 */
 +      float z = linear_zdepth(gl_FragCoord.z, viewvecs, ProjectionMatrix);
 +      float weight = calculate_transparent_weight(z, alpha);
 +      transparentAccum = vec4(shaded_color * weight, alpha);
 +      revealageAccum = weight;
 +}
index a3a42e10c8e913ca09d18d6b484a3d678ef1ef93,0000000000000000000000000000000000000000..b28263d48cf3bbf84b8ea92b31c910b383c0c958
mode 100644,000000..100644
--- /dev/null
@@@ -1,102 -1,0 +1,101 @@@
 +/*
 + * 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
 + *
 + */
 +
 +/** \file solid_mode.c
 + *  \ingroup draw_engine
 + *
 + * Simple engine for drawing color and/or depth.
 + * When we only need simple studio shaders.
 + */
 +
 +#include "DRW_render.h"
 +
 +#include "GPU_shader.h"
 +
 +#include "workbench_private.h"
 +
 +/* Functions */
 +
 +static void workbench_solid_engine_init(void *vedata)
 +{
 +      WORKBENCH_Data *data = vedata;
 +      workbench_deferred_engine_init(data);
 +}
 +
 +static void workbench_solid_cache_init(void *vedata)
 +{
 +
 +      WORKBENCH_Data *data = vedata;
 +      workbench_deferred_cache_init(data);
 +}
 +
 +static void workbench_solid_cache_populate(void *vedata, Object *ob)
 +{
 +      WORKBENCH_Data *data = vedata;
 +      workbench_deferred_solid_cache_populate(data, ob);
 +}
 +
 +static void workbench_solid_cache_finish(void *vedata)
 +{
 +      WORKBENCH_Data *data = vedata;
 +      workbench_deferred_cache_finish(data);
 +}
 +
 +static void workbench_solid_draw_background(void *vedata)
 +{
 +      WORKBENCH_Data *data = vedata;
 +      workbench_deferred_draw_background(data);
 +}
 +
 +static void workbench_solid_draw_scene(void *vedata)
 +{
 +      WORKBENCH_Data *data = vedata;
 +      workbench_deferred_draw_scene(data);
 +}
 +
 +static void workbench_solid_engine_free(void)
 +{
 +      workbench_deferred_engine_free();
 +}
 +
 +static void workbench_solid_view_update(void *vedata)
 +{
 +      WORKBENCH_Data *data = vedata;
 +      workbench_taa_view_updated(data);
 +}
 +
 +static const DrawEngineDataSize workbench_data_size = DRW_VIEWPORT_DATA_SIZE(WORKBENCH_Data);
 +
 +DrawEngineType draw_engine_workbench_solid = {
 +      NULL, NULL,
 +      N_("Workbench"),
 +      &workbench_data_size,
 +      &workbench_solid_engine_init,
 +      &workbench_solid_engine_free,
 +      &workbench_solid_cache_init,
 +      &workbench_solid_cache_populate,
 +      &workbench_solid_cache_finish,
 +      &workbench_solid_draw_background,
 +      &workbench_solid_draw_scene,
 +      &workbench_solid_view_update,
 +      NULL,
 +      NULL,
 +};
index c5d3db4b3903707fc2cb6906c2db093efc4adcea,0000000000000000000000000000000000000000..3c4f7796c2b32d8add20dccab1c8a68b0083efa8
mode 100644,000000..100644
--- /dev/null
@@@ -1,96 -1,0 +1,95 @@@
 +/*
 + * 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
 + *
 + */
 +
 +/** \file transparent_mode.c
 + *  \ingroup draw_engine
 + *
 + * Simple engine for drawing color and/or depth.
 + * When we only need simple studio shaders.
 + */
 +
 +#include "DRW_render.h"
 +
 +#include "GPU_shader.h"
 +
 +#include "workbench_private.h"
 +
 +/* Functions */
 +
 +static void workbench_transparent_engine_init(void *vedata)
 +{
 +      WORKBENCH_Data *data = vedata;
 +      workbench_forward_engine_init(data);
 +}
 +
 +static void workbench_transparent_cache_init(void *vedata)
 +{
 +
 +      WORKBENCH_Data *data = vedata;
 +      workbench_forward_cache_init(data);
 +}
 +
 +static void workbench_transparent_cache_populate(void *vedata, Object *ob)
 +{
 +      WORKBENCH_Data *data = vedata;
 +      workbench_forward_cache_populate(data, ob);
 +}
 +
 +static void workbench_transparent_cache_finish(void *vedata)
 +{
 +      WORKBENCH_Data *data = vedata;
 +      workbench_forward_cache_finish(data);
 +}
 +
 +static void workbench_transparent_draw_background(void *vedata)
 +{
 +      WORKBENCH_Data *data = vedata;
 +      workbench_forward_draw_background(data);
 +}
 +
 +static void workbench_transparent_draw_scene(void *vedata)
 +{
 +      WORKBENCH_Data *data = vedata;
 +      workbench_forward_draw_scene(data);
 +}
 +
 +static void workbench_transparent_engine_free(void)
 +{
 +      workbench_forward_engine_free();
 +}
 +
 +static const DrawEngineDataSize workbench_data_size = DRW_VIEWPORT_DATA_SIZE(WORKBENCH_Data);
 +
 +DrawEngineType draw_engine_workbench_transparent = {
 +      NULL, NULL,
 +      N_("Workbench"),
 +      &workbench_data_size,
 +      &workbench_transparent_engine_init,
 +      &workbench_transparent_engine_free,
 +      &workbench_transparent_cache_init,
 +      &workbench_transparent_cache_populate,
 +      &workbench_transparent_cache_finish,
 +      &workbench_transparent_draw_background,
 +      &workbench_transparent_draw_scene,
 +      NULL,
 +      NULL,
 +      NULL,
 +};
index aeccb7646c760d1b699234be45ab2393e9b9299f,0000000000000000000000000000000000000000..1beb35e6440065d0f20a8133e5b96423efaa24f2
mode 100644,000000..100644
--- /dev/null
@@@ -1,63 -1,0 +1,62 @@@
 +/*
 + * 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
 + *
 + */
 +
 +/** \file workbench_effect_fxaa.c
 + *  \ingroup draw_engine
 + */
 +#include "workbench_private.h"
 +
 +/* *********** STATIC *********** */
 +static struct {
 +      struct GPUShader *effect_fxaa_sh;
 +} e_data = {NULL};
 +
 +/* Shaders */
 +extern char datatoc_common_fxaa_lib_glsl[];
 +extern char datatoc_common_fullscreen_vert_glsl[];
 +extern char datatoc_workbench_effect_fxaa_frag_glsl[];
 +
 +/* *********** Functions *********** */
 +void workbench_fxaa_engine_init(void)
 +{
 +      if (e_data.effect_fxaa_sh == NULL) {
 +              e_data.effect_fxaa_sh = DRW_shader_create_with_lib(
 +                      datatoc_common_fullscreen_vert_glsl, NULL,
 +                      datatoc_workbench_effect_fxaa_frag_glsl,
 +                      datatoc_common_fxaa_lib_glsl,
 +                      NULL);
 +      }
 +}
 +
 +DRWPass *workbench_fxaa_create_pass(GPUTexture **color_buffer_tx)
 +{
 +      DRWPass *pass = DRW_pass_create("Effect FXAA", DRW_STATE_WRITE_COLOR);
 +      DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_fxaa_sh, pass);
 +      DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", color_buffer_tx);
 +      DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
 +      DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
 +      return pass;
 +}
 +
 +void workbench_fxaa_engine_free(void)
 +{
 +      DRW_SHADER_FREE_SAFE(e_data.effect_fxaa_sh);
 +}
index 717b23775dc524af8ea7e6a30fc5afa17e5eb102,0000000000000000000000000000000000000000..42c36ab366252a21854f53d4017ec711010841eb
mode 100644,000000..100644
--- /dev/null
@@@ -1,351 -1,0 +1,350 @@@
 +/*
 + * ***** 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) 2009/2018 by the Blender Foundation.
 + *
 + * Contributor(s): Joshua Leung
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +/** \file blender/draw/intern/draw_anim_viz.c
 + *  \ingroup draw
 + */
 +
 +
 +#include <stdlib.h>
 +#include <string.h>
 +#include <math.h>
 +
 +#include "BLI_sys_types.h"
 +
 +#include "DNA_anim_types.h"
 +#include "DNA_armature_types.h"
 +#include "DNA_scene_types.h"
 +#include "DNA_screen_types.h"
 +#include "DNA_view3d_types.h"
 +#include "DNA_object_types.h"
 +
 +#include "BLI_math.h"
 +#include "BLI_dlrbTree.h"
 +
 +#include "BKE_animsys.h"
 +#include "BKE_action.h"
 +
 +#include "ED_keyframes_draw.h"
 +
 +#include "UI_resources.h"
 +
 +#include "DEG_depsgraph_query.h"
 +
 +#include "DRW_engine.h"
 +#include "DRW_render.h"
 +
 +#include "GPU_shader.h"
 +#include "GPU_immediate.h"
 +#include "GPU_matrix.h"
 +
 +#include "draw_common.h"
 +#include "draw_manager_text.h"
 +
 +#include "draw_mode_engines.h"
 +
 +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
 +
 +/* ********************************* Lists ************************************** */
 +/* All lists are per viewport specific datas.
 + * They are all free when viewport changes engines
 + * or is free itself.
 + */
 +
 +/* XXX: How to show frame numbers, etc.?  Currently only doing the dots and lines */
 +typedef struct MPATH_PassList {
 +      struct DRWPass *lines;
 +      struct DRWPass *points;
 +} MPATH_PassList;
 +
 +typedef struct MPATH_StorageList {
 +      struct MPATH_PrivateData *g_data;
 +} MPATH_StorageList;
 +
 +typedef struct MPATH_Data {
 +      void *engine_type;
 +      DRWViewportEmptyList *fbl;
 +      DRWViewportEmptyList *txl;
 +      MPATH_PassList *psl;
 +      MPATH_StorageList *stl;
 +} MPATH_Data;
 +
 +struct {
 +      GPUShader *mpath_line_sh;
 +      GPUShader *mpath_points_sh;
 +} e_data = {0};
 +
 +/* *************************** Path Cache *********************************** */
 +
 +/* Just convert the CPU cache to GPU cache. */
 +static Gwn_VertBuf *mpath_vbo_get(bMotionPath *mpath)
 +{
 +      if (!mpath->points_vbo) {
 +              Gwn_VertFormat format = {0};
 +              /* Match structure of bMotionPathVert. */
 +              uint pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
 +              GWN_vertformat_attr_add(&format, "flag", GWN_COMP_I32, 1, GWN_FETCH_INT);
 +              mpath->points_vbo = GWN_vertbuf_create_with_format(&format);
 +              GWN_vertbuf_data_alloc(mpath->points_vbo, mpath->length);
 +
 +              /* meh... a useless memcpy. */
 +              Gwn_VertBufRaw raw_data;
 +              GWN_vertbuf_attr_get_raw_data(mpath->points_vbo, pos, &raw_data);
 +              memcpy(GWN_vertbuf_raw_step(&raw_data), mpath->points, sizeof(bMotionPathVert) * mpath->length);
 +      }
 +      return mpath->points_vbo;
 +}
 +
 +static Gwn_Batch *mpath_batch_line_get(bMotionPath *mpath)
 +{
 +      if (!mpath->batch_line) {
 +              mpath->batch_line = GWN_batch_create(GWN_PRIM_LINE_STRIP, mpath_vbo_get(mpath), NULL);
 +      }
 +      return mpath->batch_line;
 +}
 +
 +static Gwn_Batch *mpath_batch_points_get(bMotionPath *mpath)
 +{
 +      if (!mpath->batch_points) {
 +              mpath->batch_points = GWN_batch_create(GWN_PRIM_POINTS, mpath_vbo_get(mpath), NULL);
 +      }
 +      return mpath->batch_points;
 +}
 +
 +/* *************************** Draw Engine Entrypoints ************************** */
 +
 +static void MPATH_engine_init(void *UNUSED(vedata))
 +{
 +}
 +
 +static void MPATH_engine_free(void)
 +{
 +}
 +
 +/* Here init all passes and shading groups
 + * Assume that all Passes are NULL */
 +static void MPATH_cache_init(void *vedata)
 +{
 +      MPATH_PassList *psl = ((MPATH_Data *)vedata)->psl;
 +
 +      {
 +              DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
 +              psl->lines = DRW_pass_create("Motionpath Line Pass", state);
 +      }
 +
 +      {
 +              DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_POINT;
 +              psl->points = DRW_pass_create("Motionpath Point Pass", state);
 +      }
 +}
 +
 +static void MPATH_cache_motion_path(MPATH_PassList *psl,
 +                                    Object *ob, bPoseChannel *pchan,
 +                                    bAnimVizSettings *avs, bMotionPath *mpath)
 +{
 +      const DRWContextState *draw_ctx = DRW_context_state_get();
 +      struct DRWTextStore *dt = DRW_text_cache_ensure();
 +      int txt_flag = DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_ASCII;
 +      int stepsize = avs->path_step;
 +      int sfra, efra, sind, len;
 +      int cfra = (int)DEG_get_ctime(draw_ctx->depsgraph);
 +      bool sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT);
 +      bool show_keyframes = (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) != 0;
 +      bMotionPathVert *mpv, *mpv_start;
 +
 +      /* get frame ranges */
 +      if (avs->path_type == MOTIONPATH_TYPE_ACFRA) {
 +              /* With "Around Current", we only choose frames from around
 +               * the current frame to draw.
 +               */
 +              sfra = cfra - avs->path_bc;
 +              efra = cfra + avs->path_ac + 1;
 +      }
 +      else {
 +              /* Use the current display range */
 +              sfra = avs->path_sf;
 +              efra = avs->path_ef;
 +      }
 +
 +      /* no matter what, we can only show what is in the cache and no more
 +       * - abort if whole range is past ends of path
 +       * - otherwise clamp endpoints to extents of path
 +       */
 +      if (sfra < mpath->start_frame) {
 +              /* start clamp */
 +              sfra = mpath->start_frame;
 +      }
 +      if (efra > mpath->end_frame) {
 +              /* end clamp */
 +              efra = mpath->end_frame;
 +      }
 +
 +      if ((sfra > mpath->end_frame) || (efra < mpath->start_frame)) {
 +              /* whole path is out of bounds */
 +              return;
 +      }
 +
 +      len = efra - sfra;
 +
 +      if ((len <= 0) || (mpath->points == NULL)) {
 +              return;
 +      }
 +
 +      sind = sfra - mpath->start_frame;
 +      mpv_start = (mpath->points + sind);
 +
 +      bool use_custom_col = (mpath->flag & MOTIONPATH_FLAG_CUSTOM) != 0;
 +
 +      /* draw curve-line of path */
 +      /* Draw lines only if line drawing option is enabled */
 +      if (mpath->flag & MOTIONPATH_FLAG_LINES) {
 +              DRWShadingGroup *shgrp = DRW_shgroup_create(mpath_line_shader_get(), psl->lines);
 +              DRW_shgroup_uniform_int_copy(shgrp, "frameCurrent", cfra);
 +              DRW_shgroup_uniform_int_copy(shgrp, "frameStart", sfra);
 +              DRW_shgroup_uniform_int_copy(shgrp, "frameEnd", efra);
 +              DRW_shgroup_uniform_int_copy(shgrp, "cacheStart", mpath->start_frame);
 +              DRW_shgroup_uniform_int_copy(shgrp, "lineThickness", mpath->line_thickness);
 +              DRW_shgroup_uniform_bool_copy(shgrp, "selected", sel);
 +              DRW_shgroup_uniform_bool_copy(shgrp, "useCustomColor", use_custom_col);
 +              DRW_shgroup_uniform_vec2(shgrp, "viewportSize", DRW_viewport_size_get(), 1);
 +              DRW_shgroup_uniform_block(shgrp, "globalsBlock", globals_ubo);
 +              if (use_custom_col) {
 +                      DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1);
 +              }
 +              /* Only draw the required range. */
 +              DRW_shgroup_call_range_add(shgrp, mpath_batch_line_get(mpath), NULL, sind, len);
 +      }
 +
 +      /* Draw points. */
 +      DRWShadingGroup *shgrp = DRW_shgroup_create(mpath_points_shader_get(), psl->points);
 +      DRW_shgroup_uniform_int_copy(shgrp, "frameCurrent", cfra);
 +      DRW_shgroup_uniform_int_copy(shgrp, "cacheStart", mpath->start_frame);
 +      DRW_shgroup_uniform_int_copy(shgrp, "pointSize", mpath->line_thickness);
 +      DRW_shgroup_uniform_int_copy(shgrp, "stepSize", stepsize);
 +      DRW_shgroup_uniform_bool_copy(shgrp, "selected", sel);
 +      DRW_shgroup_uniform_bool_copy(shgrp, "showKeyFrames", show_keyframes);
 +      DRW_shgroup_uniform_bool_copy(shgrp, "useCustomColor", use_custom_col);
 +      DRW_shgroup_uniform_block(shgrp, "globalsBlock", globals_ubo);
 +      if (use_custom_col) {
 +              DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1);
 +      }
 +      /* Only draw the required range. */
 +      DRW_shgroup_call_range_add(shgrp, mpath_batch_points_get(mpath), NULL, sind, len);
 +
 +      /* Draw frame numbers at each framestep value */
 +      bool show_kf_no = (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) != 0;
 +      if ((avs->path_viewflag & (MOTIONPATH_VIEW_FNUMS)) || (show_kf_no && show_keyframes)) {
 +              int i;
 +              unsigned char col[4], col_kf[4];
 +              UI_GetThemeColor3ubv(TH_TEXT_HI, col);
 +              UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col_kf);
 +              col[3] = col_kf[3] = 255;
 +
 +              for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) {
 +                      int frame = sfra + i;
 +                      char numstr[32];
 +                      size_t numstr_len;
 +                      float co[3];
 +                      bool is_keyframe = (mpv->flag & MOTIONPATH_VERT_KEY) != 0;
 +
 +                      if ((show_keyframes && show_kf_no && is_keyframe) ||
 +                          ((avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) && (i == 0)))
 +                      {
 +                              numstr_len = sprintf(numstr, " %d", frame);
 +                              mul_v3_m4v3(co, ob->imat, mpv->co);
 +                              DRW_text_cache_add(dt, co, numstr, numstr_len, 0, txt_flag, (is_keyframe) ? col_kf : col);
 +                      }
 +                      else if (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) {
 +                              bMotionPathVert *mpvP = (mpv - stepsize);
 +                              bMotionPathVert *mpvN = (mpv + stepsize);
 +                              /* only draw framenum if several consecutive highlighted points don't occur on same point */
 +                              if ((equals_v3v3(mpv->co, mpvP->co) == 0) || (equals_v3v3(mpv->co, mpvN->co) == 0)) {
 +                                      numstr_len = sprintf(numstr, " %d", frame);
 +                                      mul_v3_m4v3(co, ob->imat, mpv->co);
 +                                      DRW_text_cache_add(dt, co, numstr, numstr_len, 0, txt_flag, col);
 +                              }
 +                      }
 +              }
 +      }
 +}
 +
 +/* Add geometry to shading groups. Execute for each objects */
 +static void MPATH_cache_populate(void *vedata, Object *ob)
 +{
 +      MPATH_PassList *psl = ((MPATH_Data *)vedata)->psl;
 +      const DRWContextState *draw_ctx = DRW_context_state_get();
 +
 +      if (draw_ctx->v3d->overlay.flag & V3D_OVERLAY_HIDE_MOTION_PATHS) {
 +              return;
 +      }
 +
 +      if (ob->type == OB_ARMATURE) {
 +              if (DRW_pose_mode_armature(ob, draw_ctx->obact)) {
 +                      for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
 +                              if (pchan->mpath) {
 +                                      MPATH_cache_motion_path(psl, ob, pchan, &ob->pose->avs, pchan->mpath);
 +                              }
 +                      }
 +              }
 +      }
 +      else {
 +              if (ob->mpath) {
 +                      MPATH_cache_motion_path(psl, ob, NULL, &ob->avs, ob->mpath);
 +              }
 +      }
 +}
 +
 +/* Draw time! Control rendering pipeline from here */
 +static void MPATH_draw_scene(void *vedata)
 +{
 +      MPATH_PassList *psl = ((MPATH_Data *)vedata)->psl;
 +      DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
 +      DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
 +
 +      MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl)
 +
 +      DRW_draw_pass(psl->lines);
 +      DRW_draw_pass(psl->points);
 +
 +      MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl)
 +}
 +
 +/* *************************** Draw Engine Defines ****************************** */
 +
 +static const DrawEngineDataSize MPATH_data_size = DRW_VIEWPORT_DATA_SIZE(MPATH_Data);
 +
 +DrawEngineType draw_engine_motion_path_type = {
 +      NULL, NULL,
 +      N_("MotionPath"),
 +      &MPATH_data_size,
 +      &MPATH_engine_init,
 +      &MPATH_engine_free,
 +      &MPATH_cache_init,
 +      &MPATH_cache_populate,
 +      NULL,
 +      NULL,
 +      &MPATH_draw_scene,
 +      NULL,
 +      NULL,
 +};
index 97403b14ac5bdfeae998ce6b1c5aed4eabde3eb9,0000000000000000000000000000000000000000..a67c7ffb131dbd8f9671d88b049aa53f445c8227
mode 100644,000000..100644
--- /dev/null
@@@ -1,249 -1,0 +1,248 @@@
 +/*
 + * 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
 + *
 + */
 +
 +/** \file overlay_mode.c
 + *  \ingroup draw_engine
 + */
 +
 +#include "DNA_view3d_types.h"
 +
 +#include "BKE_object.h"
 +
 +#include "GPU_shader.h"
 +#include "GPU_extensions.h"
 +#include "DRW_render.h"
 +
 +#include "draw_mode_engines.h"
 +
 +/* Structures */
 +typedef struct OVERLAY_StorageList {
 +      struct OVERLAY_PrivateData *g_data;
 +} OVERLAY_StorageList;
 +
 +typedef struct OVERLAY_PassList {
 +      struct DRWPass *face_orientation_pass;
 +      struct DRWPass *face_wireframe_pass;
 +} OVERLAY_PassList;
 +
 +typedef struct OVERLAY_Data {
 +      void *engine_type;
 +      DRWViewportEmptyList *fbl;
 +      DRWViewportEmptyList *txl;
 +      OVERLAY_PassList *psl;
 +      OVERLAY_StorageList *stl;
 +} OVERLAY_Data;
 +
 +typedef struct OVERLAY_PrivateData {
 +      GPUShader *wire_sh; /* reference */
 +      DRWShadingGroup *face_orientation_shgrp;
 +      View3DOverlay overlay;
 +      float wire_step_param[2];
 +} OVERLAY_PrivateData; /* Transient data */
 +
 +/* *********** STATIC *********** */
 +static struct {
 +      /* Face orientation shader */
 +      struct GPUShader *face_orientation_sh;
 +      /* Wireframe shader */
 +      struct GPUShader *face_wireframe_sh;
 +      struct GPUShader *face_wireframe_pretty_sh;
 +} e_data = {NULL};
 +
 +/* Shaders */
 +extern char datatoc_overlay_face_orientation_frag_glsl[];
 +extern char datatoc_overlay_face_orientation_vert_glsl[];
 +
 +extern char datatoc_overlay_face_wireframe_vert_glsl[];
 +extern char datatoc_overlay_face_wireframe_geom_glsl[];
 +extern char datatoc_overlay_face_wireframe_frag_glsl[];
 +
 +extern struct GlobalsUboStorage ts; /* draw_common.c */
 +
 +/* Functions */
 +static void overlay_engine_init(void *vedata)
 +{
 +      OVERLAY_Data * data = (OVERLAY_Data *)vedata;
 +      OVERLAY_StorageList *stl = data->stl;
 +
 +      if (!stl->g_data) {
 +              /* Alloc transient pointers */
 +              stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
 +      }
 +
 +      if (!e_data.face_orientation_sh) {
 +              /* Face orientation */
 +              e_data.face_orientation_sh = DRW_shader_create(
 +                      datatoc_overlay_face_orientation_vert_glsl, NULL,
 +                      datatoc_overlay_face_orientation_frag_glsl, NULL);
 +      }
 +
 +      if (!e_data.face_wireframe_sh) {
 +              bool use_geom = GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY);
 +
 +              e_data.face_wireframe_sh = DRW_shader_create(
 +                      datatoc_overlay_face_wireframe_vert_glsl,
 +                      use_geom ? datatoc_overlay_face_wireframe_geom_glsl : NULL,
 +                      datatoc_overlay_face_wireframe_frag_glsl,
 +                      use_geom ? "#define USE_GEOM_SHADER\n"
 +                               : NULL);
 +
 +              e_data.face_wireframe_pretty_sh = DRW_shader_create(
 +                      datatoc_overlay_face_wireframe_vert_glsl,
 +                      use_geom ? datatoc_overlay_face_wireframe_geom_glsl : NULL,
 +                      datatoc_overlay_face_wireframe_frag_glsl,
 +                      use_geom ? "#define USE_GEOM_SHADER\n"
 +                                 "#define LIGHT_EDGES\n"
 +                               : "#define LIGHT_EDGES\n");
 +      }
 +}
 +
 +static void overlay_cache_init(void *vedata)
 +{
 +      OVERLAY_Data * data = (OVERLAY_Data *)vedata;
 +      OVERLAY_PassList *psl = data->psl;
 +      OVERLAY_StorageList *stl = data->stl;
 +
 +      const DRWContextState *DCS = DRW_context_state_get();
 +
 +      View3D *v3d = DCS->v3d;
 +      if (v3d) {
 +              stl->g_data->overlay = v3d->overlay;
 +      }
 +      else {
 +              memset(&stl->g_data->overlay, 0, sizeof(stl->g_data->overlay));
 +      }
 +
 +      /* Face Orientation Pass */
 +      if (stl->g_data->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) {
 +              DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND;
 +              psl->face_orientation_pass = DRW_pass_create("Face Orientation", state);
 +              stl->g_data->face_orientation_shgrp = DRW_shgroup_create(
 +                      e_data.face_orientation_sh, psl->face_orientation_pass);
 +      }
 +      if (stl->g_data->overlay.flag & V3D_OVERLAY_WIREFRAMES) {
 +              DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND;
 +              psl->face_wireframe_pass = DRW_pass_create("Face Wires", state);
 +              /* Sticky uniforms (don't need to respecify each time since shader does not change). */
 +              stl->g_data->wire_sh = (stl->g_data->overlay.wireframe_threshold == 1.0f) ? e_data.face_wireframe_sh
 +                                                                                        : e_data.face_wireframe_pretty_sh;
 +              DRWShadingGroup *shgrp = DRW_shgroup_create(stl->g_data->wire_sh, psl->face_wireframe_pass);
 +              DRW_shgroup_uniform_vec2(shgrp, "viewportSize", DRW_viewport_size_get(), 1);
 +              DRW_shgroup_uniform_vec2(shgrp, "wireStepParam", stl->g_data->wire_step_param, 1);
 +
 +              /**
 +               * The wireframe threshold ranges from 0.0 to 1.0
 +               * When 1.0 we show all the edges, when 0.5 we show as many as 2.7.
 +               *
 +               * If we wanted 0.0 to match 2.7, factor would need to be 0.003f.
 +               * The range controls the falloff effect. If range was 0.0f we would get a hard cut (as in 2.7).
 +               * That said we are using a different algorithm so the results will always differ.
 +               */
 +              const float factor = 0.0045f;
 +              const float range = 0.00125f;
 +              stl->g_data->wire_step_param[1] = (1.0f - factor) + stl->g_data->overlay.wireframe_threshold * factor;
 +              stl->g_data->wire_step_param[0] = stl->g_data->wire_step_param[1] + range;
 +      }
 +}
 +
 +static void overlay_cache_populate(void *vedata, Object *ob)
 +{
 +      OVERLAY_Data * data = (OVERLAY_Data *)vedata;
 +      OVERLAY_StorageList *stl = data->stl;
 +      OVERLAY_PrivateData *pd = stl->g_data;
 +      OVERLAY_PassList *psl = data->psl;
 +      const DRWContextState *draw_ctx = DRW_context_state_get();
 +
 +      if (!DRW_object_is_renderable(ob))
 +              return;
 +
 +      if (stl->g_data->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) {
 +              struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
 +              if (geom) {
 +                      DRW_shgroup_call_add(pd->face_orientation_shgrp, geom, ob->obmat);
 +              }
 +      }
 +
 +      if (stl->g_data->overlay.flag & V3D_OVERLAY_WIREFRAMES) {
 +              /* Don't do that in edit mode. */
 +              if ((ob != draw_ctx->object_edit) && !BKE_object_is_in_editmode(ob)) {
 +                      int tri_count;
 +                      GPUTexture *verts = NULL, *faceids;
 +                      DRW_cache_object_face_wireframe_get(ob, &verts, &faceids, &tri_count);
 +                      if (verts) {
 +                              float *rim_col = ts.colorWire;
 +                              if ((ob->base_flag & BASE_SELECTED) != 0) {
 +                                      rim_col = (ob == draw_ctx->obact) ? ts.colorActive : ts.colorSelect;
 +                              }
 +                              DRWShadingGroup *shgrp = DRW_shgroup_create(stl->g_data->wire_sh, psl->face_wireframe_pass);
 +                              DRW_shgroup_uniform_texture(shgrp, "vertData", verts);
 +                              DRW_shgroup_uniform_texture(shgrp, "faceIds", faceids);
 +                              DRW_shgroup_uniform_vec3(shgrp, "wireColor", ts.colorWire, 1);
 +                              DRW_shgroup_uniform_vec3(shgrp, "rimColor", rim_col, 1);
 +                              DRW_shgroup_call_object_procedural_triangles_culled_add(shgrp, tri_count, ob);
 +                      }
 +              }
 +      }
 +}
 +
 +static void overlay_cache_finish(void *UNUSED(vedata))
 +{
 +}
 +
 +static void overlay_draw_scene(void *vedata)
 +{
 +      OVERLAY_Data * data = (OVERLAY_Data *)vedata;
 +      OVERLAY_PassList *psl = data->psl;
 +      OVERLAY_StorageList *stl = data->stl;
 +      OVERLAY_PrivateData *pd = stl->g_data;
 +
 +      if (pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) {
 +              DRW_draw_pass(psl->face_orientation_pass);
 +      }
 +      if (pd->overlay.flag & V3D_OVERLAY_WIREFRAMES) {
 +              DRW_draw_pass(psl->face_wireframe_pass);
 +      }
 +}
 +
 +static void overlay_engine_free(void)
 +{
 +      DRW_SHADER_FREE_SAFE(e_data.face_orientation_sh);
 +      DRW_SHADER_FREE_SAFE(e_data.face_wireframe_sh);
 +      DRW_SHADER_FREE_SAFE(e_data.face_wireframe_pretty_sh);
 +}
 +
 +static const DrawEngineDataSize overlay_data_size = DRW_VIEWPORT_DATA_SIZE(OVERLAY_Data);
 +
 +DrawEngineType draw_engine_overlay_type = {
 +      NULL, NULL,
 +      N_("OverlayEngine"),
 +      &overlay_data_size,
 +      &overlay_engine_init,
 +      &overlay_engine_free,
 +      &overlay_cache_init,
 +      &overlay_cache_populate,
 +      &overlay_cache_finish,
 +      NULL,
 +      &overlay_draw_scene,
 +      NULL,
 +      NULL,
 +      NULL,
 +};
index 8158437b9437237b959a2859e6065de71b317e3e,0000000000000000000000000000000000000000..236ac5c67f003992a503d3754c65d2d789582460
mode 100644,000000..100644
--- /dev/null
@@@ -1,678 -1,0 +1,677 @@@
 +//----------------------------------------------------------------------------------
 +// File:        es3-kepler\FXAA/FXAA3_11.h
 +// SDK Version: v3.00
 +// Email:       gameworks@nvidia.com
 +// Site:        http://developer.nvidia.com/
 +//
 +// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
 +//
 +// Redistribution and use in source and binary forms, with or without
 +// modification, are permitted provided that the following conditions
 +// are met:
 +//  * Redistributions of source code must retain the above copyright
 +//    notice, this list of conditions and the following disclaimer.
 +//  * Redistributions in binary form must reproduce the above copyright
 +//    notice, this list of conditions and the following disclaimer in the
 +//    documentation and/or other materials provided with the distribution.
 +//  * Neither the name of NVIDIA CORPORATION nor the names of its
 +//    contributors may be used to endorse or promote products derived
 +//    from this software without specific prior written permission.
 +//
 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 +// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 +//
 +//----------------------------------------------------------------------------------
 +
 +/* BLENDER MODIFICATIONS:
 + *
 + * - (#B1#) Compute luma on the fly using BT. 709 luma function
 + * - (#B2#) main function instead of #include, due to lack of
 + *          ARB_shading_language_include in 3.3
 + * - (#B3#) version and extension directives
 + * - removed "FXAA Console" algorithm support and shader parameters
 + * - removed  HLSL support shims
 + * - (#B4#) change luma sampling to compute, not use A channel
 + *          (this also removes GATHER4_ALPHA support)
 + * - removed all the console shaders (only remaining algorithm is "FXAA PC
 + * Quality")
 + *
 + * Note that this file doesn't follow the coding style guidelines.
 + */
 +
 +/*============================================================================
 +                        FXAA QUALITY - TUNING KNOBS
 +------------------------------------------------------------------------------
 +NOTE the other tuning knobs are now in the shader function inputs!
 +============================================================================*/
 +#ifndef FXAA_QUALITY__PRESET
 +    //
 +    // Choose the quality preset.
 +    // This needs to be compiled into the shader as it effects code.
 +    // Best option to include multiple presets is to
 +    // in each shader define the preset, then include this file.
 +    //
 +    // OPTIONS
 +    // -----------------------------------------------------------------------
 +    // 10 to 15 - default medium dither (10=fastest, 15=highest quality)
 +    // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality)
 +    // 39       - no dither, very expensive
 +    //
 +    // NOTES
 +    // -----------------------------------------------------------------------
 +    // 12 = slightly faster then FXAA 3.9 and higher edge quality (default)
 +    // 13 = about same speed as FXAA 3.9 and better than 12
 +    // 23 = closest to FXAA 3.9 visually and performance wise
 +    //  _ = the lowest digit is directly related to performance
 +    // _  = the highest digit is directly related to style
 +    //
 +    #define FXAA_QUALITY__PRESET 12
 +#endif
 +
 +/*============================================================================
 +
 +                           FXAA QUALITY - PRESETS
 +
 +============================================================================*/
 +
 +/*============================================================================
 +                     FXAA QUALITY - MEDIUM DITHER PRESETS
 +============================================================================*/
 +#if (FXAA_QUALITY__PRESET == 10)
 +    #define FXAA_QUALITY__PS 3
 +    #define FXAA_QUALITY__P0 1.5
 +    #define FXAA_QUALITY__P1 3.0
 +    #define FXAA_QUALITY__P2 12.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 11)
 +    #define FXAA_QUALITY__PS 4
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 3.0
 +    #define FXAA_QUALITY__P3 12.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 12)
 +    #define FXAA_QUALITY__PS 5
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 2.0
 +    #define FXAA_QUALITY__P3 4.0
 +    #define FXAA_QUALITY__P4 12.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 13)
 +    #define FXAA_QUALITY__PS 6
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 2.0
 +    #define FXAA_QUALITY__P3 2.0
 +    #define FXAA_QUALITY__P4 4.0
 +    #define FXAA_QUALITY__P5 12.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 14)
 +    #define FXAA_QUALITY__PS 7
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 2.0
 +    #define FXAA_QUALITY__P3 2.0
 +    #define FXAA_QUALITY__P4 2.0
 +    #define FXAA_QUALITY__P5 4.0
 +    #define FXAA_QUALITY__P6 12.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 15)
 +    #define FXAA_QUALITY__PS 8
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 2.0
 +    #define FXAA_QUALITY__P3 2.0
 +    #define FXAA_QUALITY__P4 2.0
 +    #define FXAA_QUALITY__P5 2.0
 +    #define FXAA_QUALITY__P6 4.0
 +    #define FXAA_QUALITY__P7 12.0
 +#endif
 +
 +/*============================================================================
 +                     FXAA QUALITY - LOW DITHER PRESETS
 +============================================================================*/
 +#if (FXAA_QUALITY__PRESET == 20)
 +    #define FXAA_QUALITY__PS 3
 +    #define FXAA_QUALITY__P0 1.5
 +    #define FXAA_QUALITY__P1 2.0
 +    #define FXAA_QUALITY__P2 8.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 21)
 +    #define FXAA_QUALITY__PS 4
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 2.0
 +    #define FXAA_QUALITY__P3 8.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 22)
 +    #define FXAA_QUALITY__PS 5
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 2.0
 +    #define FXAA_QUALITY__P3 2.0
 +    #define FXAA_QUALITY__P4 8.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 23)
 +    #define FXAA_QUALITY__PS 6
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 2.0
 +    #define FXAA_QUALITY__P3 2.0
 +    #define FXAA_QUALITY__P4 2.0
 +    #define FXAA_QUALITY__P5 8.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 24)
 +    #define FXAA_QUALITY__PS 7
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 2.0
 +    #define FXAA_QUALITY__P3 2.0
 +    #define FXAA_QUALITY__P4 2.0
 +    #define FXAA_QUALITY__P5 3.0
 +    #define FXAA_QUALITY__P6 8.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 25)
 +    #define FXAA_QUALITY__PS 8
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 2.0
 +    #define FXAA_QUALITY__P3 2.0
 +    #define FXAA_QUALITY__P4 2.0
 +    #define FXAA_QUALITY__P5 2.0
 +    #define FXAA_QUALITY__P6 4.0
 +    #define FXAA_QUALITY__P7 8.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 26)
 +    #define FXAA_QUALITY__PS 9
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 2.0
 +    #define FXAA_QUALITY__P3 2.0
 +    #define FXAA_QUALITY__P4 2.0
 +    #define FXAA_QUALITY__P5 2.0
 +    #define FXAA_QUALITY__P6 2.0
 +    #define FXAA_QUALITY__P7 4.0
 +    #define FXAA_QUALITY__P8 8.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 27)
 +    #define FXAA_QUALITY__PS 10
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 2.0
 +    #define FXAA_QUALITY__P3 2.0
 +    #define FXAA_QUALITY__P4 2.0
 +    #define FXAA_QUALITY__P5 2.0
 +    #define FXAA_QUALITY__P6 2.0
 +    #define FXAA_QUALITY__P7 2.0
 +    #define FXAA_QUALITY__P8 4.0
 +    #define FXAA_QUALITY__P9 8.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 28)
 +    #define FXAA_QUALITY__PS 11
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 2.0
 +    #define FXAA_QUALITY__P3 2.0
 +    #define FXAA_QUALITY__P4 2.0
 +    #define FXAA_QUALITY__P5 2.0
 +    #define FXAA_QUALITY__P6 2.0
 +    #define FXAA_QUALITY__P7 2.0
 +    #define FXAA_QUALITY__P8 2.0
 +    #define FXAA_QUALITY__P9 4.0
 +    #define FXAA_QUALITY__P10 8.0
 +#endif
 +/*--------------------------------------------------------------------------*/
 +#if (FXAA_QUALITY__PRESET == 29)
 +    #define FXAA_QUALITY__PS 12
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.5
 +    #define FXAA_QUALITY__P2 2.0
 +    #define FXAA_QUALITY__P3 2.0
 +    #define FXAA_QUALITY__P4 2.0
 +    #define FXAA_QUALITY__P5 2.0
 +    #define FXAA_QUALITY__P6 2.0
 +    #define FXAA_QUALITY__P7 2.0
 +    #define FXAA_QUALITY__P8 2.0
 +    #define FXAA_QUALITY__P9 2.0
 +    #define FXAA_QUALITY__P10 4.0
 +    #define FXAA_QUALITY__P11 8.0
 +#endif
 +
 +/*============================================================================
 +                     FXAA QUALITY - EXTREME QUALITY
 +============================================================================*/
 +#if (FXAA_QUALITY__PRESET == 39)
 +    #define FXAA_QUALITY__PS 12
 +    #define FXAA_QUALITY__P0 1.0
 +    #define FXAA_QUALITY__P1 1.0
 +    #define FXAA_QUALITY__P2 1.0
 +    #define FXAA_QUALITY__P3 1.0
 +    #define FXAA_QUALITY__P4 1.0
 +    #define FXAA_QUALITY__P5 1.5
 +    #define FXAA_QUALITY__P6 2.0
 +    #define FXAA_QUALITY__P7 2.0
 +    #define FXAA_QUALITY__P8 2.0
 +    #define FXAA_QUALITY__P9 2.0
 +    #define FXAA_QUALITY__P10 4.0
 +    #define FXAA_QUALITY__P11 8.0
 +#endif
 +
 +#define FxaaSat(x) clamp(x, 0.0, 1.0)
 +
 +#ifdef FXAA_ALPHA
 +
 +#define FxaaTexTop(t, p) textureLod(t, p, 0.0).aaaa
 +#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o).aaaa
 +#define FxaaLuma(rgba) rgba.a
 +
 +#else
 +
 +#define FxaaTexTop(t, p) textureLod(t, p, 0.0)
 +#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
 +
 +/* (#B1#) */
 +float FxaaLuma(vec4 rgba) {
 +    // note: sqrt because the sampled colors are in a linear colorspace!
 +    // this approximates a perceptual conversion, which is good enough for the
 +    // algorithm
 +    return sqrt(dot(rgba.rgb, vec3(0.2126, 0.7152, 0.0722)));
 +}
 +
 +#endif
 +
 +/*============================================================================
 +
 +                             FXAA3 QUALITY - PC
 +
 +============================================================================*/
 +/*--------------------------------------------------------------------------*/
 +vec4 FxaaPixelShader(
 +    //
 +    // Use noperspective interpolation here (turn off perspective interpolation).
 +    // {xy} = center of pixel
 +    vec2 pos,
 +    //
 +    // Input color texture.
 +    // {rgb_} = color in linear or perceptual color space
 +    sampler2D tex,
 +    //
 +    // Only used on FXAA Quality.
 +    // This must be from a constant/uniform.
 +    // {x_} = 1.0/screenWidthInPixels
 +    // {_y} = 1.0/screenHeightInPixels
 +    vec2 fxaaQualityRcpFrame,
 +    //
 +    // Only used on FXAA Quality.
 +    // This used to be the FXAA_QUALITY__SUBPIX define.
 +    // It is here now to allow easier tuning.
 +    // Choose the amount of sub-pixel aliasing removal.
 +    // This can effect sharpness.
 +    //   1.00 - upper limit (softer)
 +    //   0.75 - default amount of filtering
 +    //   0.50 - lower limit (sharper, less sub-pixel aliasing removal)
 +    //   0.25 - almost off
 +    //   0.00 - completely off
 +    float fxaaQualitySubpix,
 +    //
 +    // Only used on FXAA Quality.
 +    // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define.
 +    // It is here now to allow easier tuning.
 +    // The minimum amount of local contrast required to apply algorithm.
 +    //   0.333 - too little (faster)
 +    //   0.250 - low quality
 +    //   0.166 - default
 +    //   0.125 - high quality
 +    //   0.063 - overkill (slower)
 +    float fxaaQualityEdgeThreshold,
 +    //
 +    // Only used on FXAA Quality.
 +    // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define.
 +    // It is here now to allow easier tuning.
 +    // Trims the algorithm from processing darks.
 +    //   0.0833 - upper limit (default, the start of visible unfiltered edges)
 +    //   0.0625 - high quality (faster)
 +    //   0.0312 - visible limit (slower)
 +    float fxaaQualityEdgeThresholdMin
 +) {
 +/*--------------------------------------------------------------------------*/
 +    vec2 posM;
 +    posM.x = pos.x;
 +    posM.y = pos.y;
 +    vec4 rgbyM = FxaaTexTop(tex, posM);
 +    float lumaM = FxaaLuma(rgbyM); // (#B4#)
 +    float lumaS = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 0, 1), fxaaQualityRcpFrame.xy));
 +    float lumaE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1, 0), fxaaQualityRcpFrame.xy));
 +    float lumaN = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 0,-1), fxaaQualityRcpFrame.xy));
 +    float lumaW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1, 0), fxaaQualityRcpFrame.xy));
 +/*--------------------------------------------------------------------------*/
 +    float maxSM = max(lumaS, lumaM);
 +    float minSM = min(lumaS, lumaM);
 +    float maxESM = max(lumaE, maxSM);
 +    float minESM = min(lumaE, minSM);
 +    float maxWN = max(lumaN, lumaW);
 +    float minWN = min(lumaN, lumaW);
 +    float rangeMax = max(maxWN, maxESM);
 +    float rangeMin = min(minWN, minESM);
 +    float rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;
 +    float range = rangeMax - rangeMin;
 +    float rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);
 +    bool earlyExit = range < rangeMaxClamped;
 +/*--------------------------------------------------------------------------*/
 +    if(earlyExit) {
 +        return rgbyM;
 +    }
 +/*--------------------------------------------------------------------------*/
 +    float lumaNW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1,-1), fxaaQualityRcpFrame.xy));
 +    float lumaSE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1, 1), fxaaQualityRcpFrame.xy));
 +    float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1,-1), fxaaQualityRcpFrame.xy));
 +    float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1, 1), fxaaQualityRcpFrame.xy));
 +/*--------------------------------------------------------------------------*/
 +    float lumaNS = lumaN + lumaS;
 +    float lumaWE = lumaW + lumaE;
 +    float subpixRcpRange = 1.0/range;
 +    float subpixNSWE = lumaNS + lumaWE;
 +    float edgeHorz1 = (-2.0 * lumaM) + lumaNS;
 +    float edgeVert1 = (-2.0 * lumaM) + lumaWE;
 +/*--------------------------------------------------------------------------*/
 +    float lumaNESE = lumaNE + lumaSE;
 +    float lumaNWNE = lumaNW + lumaNE;
 +    float edgeHorz2 = (-2.0 * lumaE) + lumaNESE;
 +    float edgeVert2 = (-2.0 * lumaN) + lumaNWNE;
 +/*--------------------------------------------------------------------------*/
 +    float lumaNWSW = lumaNW + lumaSW;
 +    float lumaSWSE = lumaSW + lumaSE;
 +    float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);
 +    float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);
 +    float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;
 +    float edgeVert3 = (-2.0 * lumaS) + lumaSWSE;
 +    float edgeHorz = abs(edgeHorz3) + edgeHorz4;
 +    float edgeVert = abs(edgeVert3) + edgeVert4;
 +/*--------------------------------------------------------------------------*/
 +    float subpixNWSWNESE = lumaNWSW + lumaNESE;
 +    float lengthSign = fxaaQualityRcpFrame.x;
 +    bool horzSpan = edgeHorz >= edgeVert;
 +    float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;
 +/*--------------------------------------------------------------------------*/
 +    if(!horzSpan) lumaN = lumaW;
 +    if(!horzSpan) lumaS = lumaE;
 +    if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;
 +    float subpixB = (subpixA * (1.0/12.0)) - lumaM;
 +/*--------------------------------------------------------------------------*/
 +    float gradientN = lumaN - lumaM;
 +    float gradientS = lumaS - lumaM;
 +    float lumaNN = lumaN + lumaM;
 +    float lumaSS = lumaS + lumaM;
 +    bool pairN = abs(gradientN) >= abs(gradientS);
 +    float gradient = max(abs(gradientN), abs(gradientS));
 +    if(pairN) lengthSign = -lengthSign;
 +    float subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);
 +/*--------------------------------------------------------------------------*/
 +    vec2 posB;
 +    posB.x = posM.x;
 +    posB.y = posM.y;
 +    vec2 offNP;
 +    offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
 +    offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
 +    if(!horzSpan) posB.x += lengthSign * 0.5;
 +    if( horzSpan) posB.y += lengthSign * 0.5;
 +/*--------------------------------------------------------------------------*/
 +    vec2 posN;
 +    posN.x = posB.x - offNP.x * FXAA_QUALITY__P0;
 +    posN.y = posB.y - offNP.y * FXAA_QUALITY__P0;
 +    vec2 posP;
 +    posP.x = posB.x + offNP.x * FXAA_QUALITY__P0;
 +    posP.y = posB.y + offNP.y * FXAA_QUALITY__P0;
 +    float subpixD = ((-2.0)*subpixC) + 3.0;
 +    float lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));
 +    float subpixE = subpixC * subpixC;
 +    float lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));
 +/*--------------------------------------------------------------------------*/
 +    if(!pairN) lumaNN = lumaSS;
 +    float gradientScaled = gradient * 1.0/4.0;
 +    float lumaMM = lumaM - lumaNN * 0.5;
 +    float subpixF = subpixD * subpixE;
 +    bool lumaMLTZero = lumaMM < 0.0;
 +/*--------------------------------------------------------------------------*/
 +    lumaEndN -= lumaNN * 0.5;
 +    lumaEndP -= lumaNN * 0.5;
 +    bool doneN = abs(lumaEndN) >= gradientScaled;
 +    bool doneP = abs(lumaEndP) >= gradientScaled;
 +    if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1;
 +    if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1;
 +    bool doneNP = (!doneN) || (!doneP);
 +    if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1;
 +    if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1;
 +/*--------------------------------------------------------------------------*/
 +    if(doneNP) {
 +        if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 +        if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 +        if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 +        if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 +        doneN = abs(lumaEndN) >= gradientScaled;
 +        doneP = abs(lumaEndP) >= gradientScaled;
 +        if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2;
 +        if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2;
 +        doneNP = (!doneN) || (!doneP);
 +        if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2;
 +        if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2;
 +/*--------------------------------------------------------------------------*/
 +        #if (FXAA_QUALITY__PS > 3)
 +        if(doneNP) {
 +            if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 +            if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 +            if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 +            if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 +            doneN = abs(lumaEndN) >= gradientScaled;
 +            doneP = abs(lumaEndP) >= gradientScaled;
 +            if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3;
 +            if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3;
 +            doneNP = (!doneN) || (!doneP);
 +            if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3;
 +            if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3;
 +/*--------------------------------------------------------------------------*/
 +            #if (FXAA_QUALITY__PS > 4)
 +            if(doneNP) {
 +                if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 +                if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 +                if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 +                if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 +                doneN = abs(lumaEndN) >= gradientScaled;
 +                doneP = abs(lumaEndP) >= gradientScaled;
 +                if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4;
 +                if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4;
 +                doneNP = (!doneN) || (!doneP);
 +                if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4;
 +                if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4;
 +/*--------------------------------------------------------------------------*/
 +                #if (FXAA_QUALITY__PS > 5)
 +                if(doneNP) {
 +                    if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 +                    if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 +                    if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 +                    if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 +                    doneN = abs(lumaEndN) >= gradientScaled;
 +                    doneP = abs(lumaEndP) >= gradientScaled;
 +                    if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5;
 +                    if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5;
 +                    doneNP = (!doneN) || (!doneP);
 +                    if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5;
 +                    if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5;
 +/*--------------------------------------------------------------------------*/
 +                    #if (FXAA_QUALITY__PS > 6)
 +                    if(doneNP) {
 +                        if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 +                        if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 +                        if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 +                        if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 +                        doneN = abs(lumaEndN) >= gradientScaled;
 +                        doneP = abs(lumaEndP) >= gradientScaled;
 +                        if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6;
 +                        if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6;
 +                        doneNP = (!doneN) || (!doneP);
 +                        if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6;
 +                        if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6;
 +/*--------------------------------------------------------------------------*/
 +                        #if (FXAA_QUALITY__PS > 7)
 +                        if(doneNP) {
 +                            if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 +                            if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 +                            if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 +                            if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 +                            doneN = abs(lumaEndN) >= gradientScaled;
 +                            doneP = abs(lumaEndP) >= gradientScaled;
 +                            if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7;
 +                            if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7;
 +                            doneNP = (!doneN) || (!doneP);
 +                            if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7;
 +                            if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7;
 +/*--------------------------------------------------------------------------*/
 +    #if (FXAA_QUALITY__PS > 8)
 +    if(doneNP) {
 +        if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 +        if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 +        if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 +        if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 +        doneN = abs(lumaEndN) >= gradientScaled;
 +        doneP = abs(lumaEndP) >= gradientScaled;
 +        if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8;
 +        if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8;
 +        doneNP = (!doneN) || (!doneP);
 +        if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8;
 +        if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8;
 +/*--------------------------------------------------------------------------*/
 +        #if (FXAA_QUALITY__PS > 9)
 +        if(doneNP) {
 +            if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 +            if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 +            if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 +            if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 +            doneN = abs(lumaEndN) >= gradientScaled;
 +            doneP = abs(lumaEndP) >= gradientScaled;
 +            if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9;
 +            if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9;
 +            doneNP = (!doneN) || (!doneP);
 +            if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9;
 +            if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9;
 +/*--------------------------------------------------------------------------*/
 +            #if (FXAA_QUALITY__PS > 10)
 +            if(doneNP) {
 +                if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 +                if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 +                if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 +                if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 +                doneN = abs(lumaEndN) >= gradientScaled;
 +                doneP = abs(lumaEndP) >= gradientScaled;
 +                if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10;
 +                if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10;
 +                doneNP = (!doneN) || (!doneP);
 +                if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10;
 +                if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10;
 +/*--------------------------------------------------------------------------*/
 +                #if (FXAA_QUALITY__PS > 11)
 +                if(doneNP) {
 +                    if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 +                    if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 +                    if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 +                    if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 +                    doneN = abs(lumaEndN) >= gradientScaled;
 +                    doneP = abs(lumaEndP) >= gradientScaled;
 +                    if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11;
 +                    if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11;
 +                    doneNP = (!doneN) || (!doneP);
 +                    if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11;
 +                    if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11;
 +/*--------------------------------------------------------------------------*/
 +                    #if (FXAA_QUALITY__PS > 12)
 +                    if(doneNP) {
 +                        if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
 +                        if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
 +                        if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
 +                        if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
 +                        doneN = abs(lumaEndN) >= gradientScaled;
 +                        doneP = abs(lumaEndP) >= gradientScaled;
 +                        if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12;
 +                        if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12;
 +                        doneNP = (!doneN) || (!doneP);
 +                        if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12;
 +                        if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12;
 +/*--------------------------------------------------------------------------*/
 +                    }
 +                    #endif
 +/*--------------------------------------------------------------------------*/
 +                }
 +                #endif
 +/*--------------------------------------------------------------------------*/
 +            }
 +            #endif
 +/*--------------------------------------------------------------------------*/
 +        }
 +        #endif
 +/*--------------------------------------------------------------------------*/
 +    }
 +    #endif
 +/*--------------------------------------------------------------------------*/
 +                        }
 +                        #endif
 +/*--------------------------------------------------------------------------*/
 +                    }
 +                    #endif
 +/*--------------------------------------------------------------------------*/
 +                }
 +                #endif
 +/*--------------------------------------------------------------------------*/
 +            }
 +            #endif
 +/*--------------------------------------------------------------------------*/
 +        }
 +        #endif
 +/*--------------------------------------------------------------------------*/
 +    }
 +/*--------------------------------------------------------------------------*/
 +    float dstN = posM.x - posN.x;
 +    float dstP = posP.x - posM.x;
 +    if(!horzSpan) dstN = posM.y - posN.y;
 +    if(!horzSpan) dstP = posP.y - posM.y;
 +/*--------------------------------------------------------------------------*/
 +    bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;
 +    float spanLength = (dstP + dstN);
 +    bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;
 +    float spanLengthRcp = 1.0/spanLength;
 +/*--------------------------------------------------------------------------*/
 +    bool directionN = dstN < dstP;
 +    float dst = min(dstN, dstP);
 +    bool goodSpan = directionN ? goodSpanN : goodSpanP;
 +    float subpixG = subpixF * subpixF;
 +    float pixelOffset = (dst * (-spanLengthRcp)) + 0.5;
 +    float subpixH = subpixG * fxaaQualitySubpix;
 +/*--------------------------------------------------------------------------*/
 +    float pixelOffsetGood = goodSpan ? pixelOffset : 0.0;
 +    float pixelOffsetSubpix = max(pixelOffsetGood, subpixH);
 +    if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;
 +    if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;
 +    return vec4(FxaaTexTop(tex, posM).xyz, lumaM);
 +}
 +/*==========================================================================*/
index f91e7d42bca9230f550f5bf1f4743c9741321e7e,ac896216e5108750c372a460ab5ddc7f27c0b390..e2e110ffc3107e764054e1c5f085c84e2bf0954d
  
  #define GLA_PIXEL_OFS 0.375f
  
 -
 -BLI_INLINE void glTranslate3iv(const int vec[3])    { glTranslatef(UNPACK3_EX((const float), vec, ));       }
 -BLI_INLINE void glTranslate2iv(const int vec[2])    { glTranslatef(UNPACK2_EX((const float), vec, ), 0.0f); }
 -BLI_INLINE void glTranslate3fv(const float vec[3])  { glTranslatef(UNPACK3(vec));       }
 -BLI_INLINE void glTranslate2fv(const float vec[2])  { glTranslatef(UNPACK2(vec), 0.0f); }
 -
 -BLI_INLINE void glScale3iv(const int vec[3])    { glTranslatef(UNPACK3_EX((const float), vec, ));       }
 -BLI_INLINE void glScale2iv(const int vec[2])    { glTranslatef(UNPACK2_EX((const float), vec, ), 0.0f); }
 -BLI_INLINE void glScale3fv(const float vec[3])  { glScalef(UNPACK3(vec));      }
 -BLI_INLINE void glScale2fv(const float vec[2])  { glScalef(UNPACK2(vec), 0.0); }
 -
 -/* v2 versions don't make much sense for rotation */
 -BLI_INLINE void glRotate3fv(const float angle, const float vec[3])   { glRotatef(angle, UNPACK3(vec)); }
 -
  #endif /* #ifdef __BIF_GL_H__ */
index 01ca217fc0a9c865e5b6c2082b0381a9ecce8d64,0000000000000000000000000000000000000000..55db99236e0136acfa2f61e60086d38841eb82c0
mode 100644,000000..100644
--- /dev/null
@@@ -1,112 -1,0 +1,111 @@@
 +/*
 + * ***** 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.
 + *
 + * Contributor(s): none yet.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +/** \file manipulator_library_intern.h
 + *  \ingroup wm
 + */
 +
 +#ifndef __MANIPULATOR_LIBRARY_INTERN_H__
 +#define __MANIPULATOR_LIBRARY_INTERN_H__
 +
 +/* distance around which manipulators respond to input (and get highlighted) */
 +#define MANIPULATOR_HOTSPOT 14.0f
 +
 +/**
 + * Data for common interactions. Used in manipulator_library_utils.c functions.
 + */
 +typedef struct ManipulatorCommonData {
 +      int flag;
 +
 +      float range_fac;      /* factor for arrow min/max distance */
 +      float offset;
 +
 +      /* property range for constrained manipulators */
 +      float range;
 +      /* min/max value for constrained manipulators */
 +      float min, max;
 +} ManipulatorCommonData;
 +
 +typedef struct ManipulatorInteraction {
 +      float init_value; /* initial property value */
 +      float init_mval[2];
 +      float init_offset;
 +      float init_matrix_final[4][4];
 +      float init_matrix_basis[4][4];
 +
 +      /* offset of last handling step */
 +      float prev_offset;
 +      /* Total offset added by precision tweaking.
 +       * Needed to allow toggling precision on/off without causing jumps */
 +      float precision_offset;
 +} ManipulatorInteraction;
 +
 +/* ManipulatorCommonData->flag  */
 +enum {
 +      MANIPULATOR_CUSTOM_RANGE_SET = (1 << 0),
 +};
 +
 +
 +float manipulator_offset_from_value(
 +        ManipulatorCommonData *data, const float value,
 +        const bool constrained, const bool inverted);
 +float manipulator_value_from_offset(
 +        ManipulatorCommonData *data, ManipulatorInteraction *inter, const float offset,
 +        const bool constrained, const bool inverted, const bool use_precision);
 +
 +void manipulator_property_data_update(
 +        struct wmManipulator *mpr, ManipulatorCommonData *data, wmManipulatorProperty *mpr_prop,
 +        const bool constrained, const bool inverted);
 +
 +void  manipulator_property_value_reset(
 +        bContext *C, const struct wmManipulator *mpr, ManipulatorInteraction *inter, wmManipulatorProperty *mpr_prop);
 +
 +
 +/* -------------------------------------------------------------------- */
 +
 +void manipulator_color_get(
 +        const struct wmManipulator *mpr, const bool highlight,
 +        float r_color[4]);
 +
 +bool manipulator_window_project_2d(
 +        bContext *C, const struct wmManipulator *mpr, const float mval[2], int axis, bool use_offset,
 +        float r_co[2]);
 +
 +bool manipulator_window_project_3d(
 +        bContext *C, const struct wmManipulator *mpr, const float mval[2], bool use_offset,
 +        float r_co[3]);
 +
 +/* -------------------------------------------------------------------- */
 +/* Manipulator drawing */
 +
 +#include "manipulator_geometry.h"
 +
 +void wm_manipulator_geometryinfo_draw(const struct ManipulatorGeomInfo *info, const bool select, const float color[4]);
 +void wm_manipulator_vec_draw(
 +        const float color[4], const float (*verts)[3], uint vert_count,
 +        uint pos, uint primitive_type);
 +
 +
 +#endif  /* __MANIPULATOR_LIBRARY_INTERN_H__ */
index cccf484f29d4652ebe239a809ab399068280baae,0000000000000000000000000000000000000000..12f07611722c793b08421d07630a19186d093295
mode 100644,000000..100644
--- /dev/null
@@@ -1,151 -1,0 +1,150 @@@
 +/*
 + * ***** 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.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +/** \file blender/editors/manipulator_library/manipulator_library_presets.c
 + *  \ingroup wm
 + *
 + * \name Manipulator Lib Presets
 + *
 + * \brief Preset shapes that can be drawn from any manipulator type.
 + */
 +
 +#include "MEM_guardedalloc.h"
 +
 +#include "BLI_math.h"
 +
 +#include "DNA_view3d_types.h"
 +#include "DNA_object_types.h"
 +
 +#include "BKE_context.h"
 +
 +#include "BIF_gl.h"
 +
 +#include "GPU_draw.h"
 +#include "GPU_immediate.h"
 +#include "GPU_immediate_util.h"
 +#include "GPU_matrix.h"
 +#include "GPU_select.h"
 +
 +#include "DEG_depsgraph.h"
 +
 +#include "RNA_access.h"
 +
 +#include "WM_types.h"
 +#include "WM_api.h"
 +
 +#include "ED_view3d.h"
 +#include "ED_screen.h"
 +
 +/* own includes */
 +#include "ED_manipulator_library.h"  /* own include */
 +#include "manipulator_library_intern.h"  /* own include */
 +
 +/* TODO, this is to be used by RNA. might move to ED_manipulator_library */
 +
 +/**
 + * Given a single axis, orient the matrix to a different direction.
 + */
 +static void single_axis_convert(
 +        int src_axis, float src_mat[4][4],
 +        int dst_axis, float dst_mat[4][4])
 +{
 +      copy_m4_m4(dst_mat, src_mat);
 +      if (src_axis == dst_axis) {
 +              return;
 +      }
 +
 +      float rotmat[3][3];
 +      mat3_from_axis_conversion_single(src_axis, dst_axis, rotmat);
 +      transpose_m3(rotmat);
 +      mul_m4_m4m3(dst_mat, src_mat, rotmat);
 +}
 +
 +/**
 + * Use for all geometry.
 + */
 +static void ed_manipulator_draw_preset_geometry(
 +        const struct wmManipulator *mpr, float mat[4][4], int select_id,
 +        const ManipulatorGeomInfo *info)
 +{
 +      const bool is_select = (select_id != -1);
 +      const bool is_highlight = is_select && (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
 +
 +      float color[4];
 +      manipulator_color_get(mpr, is_highlight, color);
 +
 +      if (is_select) {
 +              GPU_select_load_id(select_id);
 +      }
 +
 +      gpuPushMatrix();
 +      gpuMultMatrix(mat);
 +      wm_manipulator_geometryinfo_draw(info, is_select, color);
 +      gpuPopMatrix();
 +
 +      if (is_select) {
 +              GPU_select_load_id(-1);
 +      }
 +}
 +
 +void ED_manipulator_draw_preset_box(
 +        const struct wmManipulator *mpr, float mat[4][4], int select_id)
 +{
 +      ed_manipulator_draw_preset_geometry(mpr, mat, select_id, &wm_manipulator_geom_data_cube);
 +}
 +
 +void ED_manipulator_draw_preset_arrow(
 +        const struct wmManipulator *mpr, float mat[4][4], int axis, int select_id)
 +{
 +      float mat_rotate[4][4];
 +      single_axis_convert(OB_POSZ, mat, axis, mat_rotate);
 +      ed_manipulator_draw_preset_geometry(mpr, mat_rotate, select_id, &wm_manipulator_geom_data_arrow);
 +}
 +
 +void ED_manipulator_draw_preset_circle(
 +        const struct wmManipulator *mpr, float mat[4][4], int axis, int select_id)
 +{
 +      float mat_rotate[4][4];
 +      single_axis_convert(OB_POSZ, mat, axis, mat_rotate);
 +      ed_manipulator_draw_preset_geometry(mpr, mat_rotate, select_id, &wm_manipulator_geom_data_dial);
 +}
 +
 +void ED_manipulator_draw_preset_facemap(
 +        const bContext *C, const struct wmManipulator *mpr, struct Scene *scene, Object *ob,  const int facemap, int select_id)
 +{
 +      const bool is_select = (select_id != -1);
 +      const bool is_highlight = is_select && (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
 +
 +      float color[4];
 +      manipulator_color_get(mpr, is_highlight, color);
 +
 +      if (is_select) {
 +              GPU_select_load_id(select_id);
 +      }
 +
 +      gpuPushMatrix();
 +      gpuMultMatrix(ob->obmat);
 +      ED_draw_object_facemap(CTX_data_depsgraph(C), scene, ob, color, facemap);
 +      gpuPopMatrix();
 +
 +      if (is_select) {
 +              GPU_select_load_id(-1);
 +      }
 +}
index d47291ca82f3a536667f797675cb13c9bd4631a7,e1042f17229fc5692efc4f95288758289b392cc9..04632838cf3f5299af7f3e8d5a6bed20c6b953da
@@@ -1259,5 -1303,6 +1259,4 @@@ void ED_preview_kill_jobs(wmWindowManag
  {
        if (wm)
                WM_jobs_kill(wm, NULL, common_preview_startjob);
 -
 -      ED_viewport_render_kill_jobs(wm, bmain, false);
  }
index b7e6508117ec2fb5592504f59e46470e181a315e,ceb4c0b27ba18d77ab47eadc0ba9f403099136a0..a78617fde8c26900ff15d8b3b9cac0aef5b98ffa
@@@ -370,5 -563,15 +370,4 @@@ void ED_render_id_flush_update(const DE
                        render_engine_flag_changed(bmain, RE_ENGINE_UPDATE_OTHER);
                        break;
        }
 -
 -}
 -
 -
 -void ED_render_internal_init(void)
 -{
 -      RenderEngineType *ret = RE_engines_find(RE_engine_id_BLENDER_RENDER);
 -
 -      ret->view_update = render_view3d_update;
 -      ret->view_draw = render_view3d_draw;
 -
  }
index 2e1a448edf09196ffe9e5c7a20b89ddd01daf215,77623974d0a439953e2de1693285281c6050a961..aab7b39484d9f1d2ade82158b6bedf0f2cdebee2
@@@ -98,7 -111,6 +98,6 @@@ void buttons_texture_context_compute(co
  /* buttons_ops.c */
  void BUTTONS_OT_file_browse(struct wmOperatorType *ot);
  void BUTTONS_OT_directory_browse(struct wmOperatorType *ot);
 -void BUTTONS_OT_toolbox(struct wmOperatorType *ot);
 +void BUTTONS_OT_context_menu(struct wmOperatorType *ot);
  
  #endif /* __BUTTONS_INTERN_H__ */
index 786172ca18e15c267eae5fc1bf7c76d924f3ed3c,9574e82505fc7d3ba3962f42d2f09339ec92afeb..20308783a7fc8fa82414ffbd74945e069c5b1591
@@@ -554,20 -154,4 +554,19 @@@ void outliner_keymap(wmKeyConfig *keyco
  
        WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_add_selected", DKEY, KM_PRESS, 0, 0);
        WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_delete_selected", DKEY, KM_PRESS, KM_ALT, 0);
 +
 +      WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_new", CKEY, KM_PRESS, 0, 0);
 +      WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_delete", XKEY, KM_PRESS, 0, 0);
 +
 +      WM_keymap_verify_item(keymap, "OBJECT_OT_move_to_collection", MKEY, KM_PRESS, 0, 0);
 +      WM_keymap_verify_item(keymap, "OBJECT_OT_link_to_collection", MKEY, KM_PRESS, KM_SHIFT, 0);
 +
 +      kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0);
 +      RNA_boolean_set(kmi->ptr, "select", false);
 +      kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0);
 +      RNA_boolean_set(kmi->ptr, "unselected", false);
 +      kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0);
 +      RNA_boolean_set(kmi->ptr, "unselected", true);
 +
 +      outliner_item_drag_drop_modal_keymap(keyconf);
  }
index 1ac628a8b54ed8bce112fbdf73003d78e15c2924,97c42cc11e00cf197c46cb739f3d3db831a53d30..bf53861185213cf8387c2bd34d2a11f522dcd4fa
@@@ -1759,12 -1699,4 +1759,10 @@@ void draw_timeline_seq(const bContext *
        scrollers = UI_view2d_scrollers_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_UNIT_VALUES, V2D_GRID_CLAMP);
        UI_view2d_scrollers_draw(C, v2d, scrollers);
        UI_view2d_scrollers_free(scrollers);
 +
 +      /* draw current frame number-indicator on top of scrollers */
 +      if ((sseq->flag & SEQ_NO_DRAW_CFRANUM) == 0) {
 +              UI_view2d_view_orthoSpecial(ar, v2d, 1);
 +              ANIM_draw_cfra_number(C, v2d, cfra_flag);
 +      }
  }
index 5ecef03e475836dba477fcd3ad15bc8a382f0a36,c10f8f0ce1648040f86c0d9247c20b814c04ca99..bca5faa314a7d2c1ca8d834a9c3d7582f0be42e0
@@@ -692,130 -8487,73 +692,129 @@@ void draw_object_backbufsel
  }
  
  
 -/* ************* draw object instances for bones, for example ****************** */
 -/*               assumes all matrices/etc set OK */
 -
 -/* helper function for drawing object instances - meshes */
 -static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d,
 -                                      Object *ob, const short dt, int outline)
 +void ED_draw_object_facemap(
 +        Depsgraph *depsgraph, Scene *scene, Object *ob, const float col[4], const int facemap)
  {
 -      Mesh *me = ob->data;
 -      DerivedMesh *dm = NULL, *edm = NULL;
 +      DerivedMesh *dm = NULL;
  
 -      if (ob->mode & OB_MODE_EDIT) {
 -              edm = editbmesh_get_derived_base(ob, me->edit_btmesh, CD_MASK_BAREMESH);
 -              DM_update_materials(edm, ob);
 -      }
 -      else {
 -              dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
 -              DM_update_materials(dm, ob);
 +      /* happens on undo */
 +      if (ob->type != OB_MESH || !ob->data)
 +              return;
 +
 +      /* Temporary, happens on undo, would resolve but will eventually move away from DM. */
 +      if (ob->derivedFinal == NULL) {
 +              return;
        }
  
 -      if (dt <= OB_WIRE) {
 -              if (dm)
 -                      dm->drawEdges(dm, 1, 0);
 -              else if (edm)
 -                      edm->drawEdges(edm, 1, 0);
 +      dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH);
 +      if (!dm || !CustomData_has_layer(&dm->polyData, CD_FACEMAP))
 +              return;
 +
 +
 +      glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
 +
 +#if 0
 +      DM_update_materials(dm, ob);
 +
 +      /* add polygon offset so we draw above the original surface */
 +      glPolygonOffset(1.0, 1.0);
 +
 +      GPU_facemap_setup(dm);
 +
 +      glColor4fv(col);
 +
 +      gpuPushAttrib(GL_ENABLE_BIT);
 +      GPU_blend(true);
 +      glDisable(GL_LIGHTING);
 +
 +      /* always draw using backface culling */
 +      glEnable(GL_CULL_FACE);
 +      glCullFace(GL_BACK);
 +
 +      if (dm->drawObject->facemapindices) {
 +              glDrawElements(GL_TRIANGLES, dm->drawObject->facemap_count[facemap] * 3, GL_UNSIGNED_INT,
 +                             (int *)NULL + dm->drawObject->facemap_start[facemap] * 3);
        }
 -      else {
 -              if (outline)
 -                      draw_mesh_object_outline(v3d, ob, dm ? dm : edm);
 +      gpuPopAttrib();
  
 -              if (dm) {
 -                      bool glsl = draw_glsl_material(scene, ob, v3d, dt);
 -                      GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
 -              }
 +      GPU_buffers_unbind();
 +
 +      glPolygonOffset(0.0, 0.0);
 +
 +#else
 +
 +      /* Just to create the data to pass to immediate mode, grr! */
 +      Mesh *me = ob->data;
 +      const int *facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP);
 +      if (facemap_data) {
 +              Gwn_VertFormat *format = immVertexFormat();
 +              unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
 +
 +              immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
 +              immUniformColor4fv(col);
 +
 +              /* XXX, alpha isn't working yet, not sure why. */
 +              GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
 +              GPU_blend(true);
  
 -              glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
 +              MVert *mvert;
  
 -              if (dm) {
 -                      dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind);
 -                      GPU_end_object_materials();
 +              MPoly *mpoly;
 +              int    mpoly_len;
 +
 +              MLoop *mloop;
 +              int    mloop_len;
 +
 +              if (dm && CustomData_has_layer(&dm->polyData, CD_FACEMAP)) {
 +                      mvert = dm->getVertArray(dm);
 +                      mpoly = dm->getPolyArray(dm);
 +                      mloop = dm->getLoopArray(dm);
 +
 +                      mpoly_len = dm->getNumPolys(dm);
 +                      mloop_len = dm->getNumLoops(dm);
 +
 +                      facemap_data = CustomData_get_layer(&dm->polyData, CD_FACEMAP);
                }
 -              else if (edm)
 -                      edm->drawMappedFaces(edm, NULL, GPU_object_material_bind, NULL, NULL, DM_DRAW_NEED_NORMALS);
 +              else {
 +                      mvert = me->mvert;
 +                      mpoly = me->mpoly;
 +                      mloop = me->mloop;
  
 -              GPU_object_material_unbind();
 -      }
 +                      mpoly_len = me->totpoly;
 +                      mloop_len = me->totloop;
  
 -      if (edm) edm->release(edm);
 -      if (dm) dm->release(dm);
 -}
 +                      facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP);
 +              }
  
 -void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline)
 -{
 -      if (ob == NULL)
 -              return;
 +              /* use gawain immediate mode fore now */
 +              const int looptris_len = poly_to_tri_count(mpoly_len, mloop_len);
 +              immBeginAtMost(GWN_PRIM_TRIS, looptris_len * 3);
  
 -      switch (ob->type) {
 -              case OB_MESH:
 -                      draw_object_mesh_instance(scene, v3d, rv3d, ob, dt, outline);
 -                      break;
 -              case OB_EMPTY:
 -                      if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
 -                              /* CONSTCOLOR == no wire outline */
 -                              draw_empty_image(ob, DRAW_CONSTCOLOR, NULL, v3d->multiview_eye);
 -                      }
 -                      else {
 -                              drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype);
 +              MPoly *mp;
 +              int i;
 +              for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) {
 +                      if (facemap_data[i] == facemap) {
 +                              /* Weak, fan-fill, use until we have derived-mesh replaced. */
 +                              const MLoop *ml_start = &mloop[mp->loopstart];
 +                              const MLoop *ml_a = ml_start + 1;
 +                              const MLoop *ml_b = ml_start + 2;
 +                              for (int j = 2; j < mp->totloop; j++) {
 +                                      immVertex3fv(pos, mvert[ml_start->v].co);
 +                                      immVertex3fv(pos, mvert[ml_a->v].co);
 +                                      immVertex3fv(pos, mvert[ml_b->v].co);
 +
 +                                      ml_a++;
 +                                      ml_b++;
 +                              }
                        }
 -                      break;
 +              }
 +              immEnd();
 +
 +              immUnbindProgram();
 +
 +              GPU_blend(false);
        }
 +#endif
 +
 +      dm->release(dm);
  }
index 305085be370345fa03effa67ed57c8d6dc074898,0000000000000000000000000000000000000000..b42f49e6d1cf7e9d9be2e284f6aca0cd0cdecf23
mode 100644,000000..100644
--- /dev/null
@@@ -1,123 -1,0 +1,122 @@@
 +/*
 + * ***** 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.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +/** \file blender/editors/space_view3d/view3d_manipulator_forcefield.c
 + *  \ingroup spview3d
 + */
 +
 +
 +#include "BLI_blenlib.h"
 +#include "BLI_math.h"
 +#include "BLI_utildefines.h"
 +
 +#include "BKE_context.h"
 +#include "BKE_object.h"
 +
 +#include "DNA_object_types.h"
 +#include "DNA_object_force_types.h"
 +
 +#include "ED_screen.h"
 +#include "ED_manipulator_library.h"
 +
 +#include "UI_resources.h"
 +
 +#include "MEM_guardedalloc.h"
 +
 +#include "RNA_access.h"
 +
 +#include "WM_api.h"
 +#include "WM_types.h"
 +
 +#include "view3d_intern.h"  /* own include */
 +
 +/* -------------------------------------------------------------------- */
 +
 +/** \name Force Field Manipulators
 + * \{ */
 +
 +static bool WIDGETGROUP_forcefield_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
 +{
 +      View3D *v3d = CTX_wm_view3d(C);
 +      if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
 +              return false;
 +      }
 +
 +      Object *ob = CTX_data_active_object(C);
 +
 +      return (ob && ob->pd && ob->pd->forcefield);
 +}
 +
 +static void WIDGETGROUP_forcefield_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
 +{
 +      /* only wind effector for now */
 +      wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__);
 +      mgroup->customdata = wwrapper;
 +
 +      wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL);
 +      wmManipulator *mpr = wwrapper->manipulator;
 +      RNA_enum_set(mpr->ptr, "transform",  ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED);
 +      ED_manipulator_arrow3d_set_ui_range(mpr, -200.0f, 200.0f);
 +      ED_manipulator_arrow3d_set_range_fac(mpr, 6.0f);
 +
 +      UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
 +      UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
 +}
 +
 +static void WIDGETGROUP_forcefield_refresh(const bContext *C, wmManipulatorGroup *mgroup)
 +{
 +      wmManipulatorWrapper *wwrapper = mgroup->customdata;
 +      wmManipulator *mpr = wwrapper->manipulator;
 +      Object *ob = CTX_data_active_object(C);
 +      PartDeflect *pd = ob->pd;
 +
 +      if (pd->forcefield == PFIELD_WIND) {
 +              const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f;
 +              const float ofs[3] = {0.0f, -size, 0.0f};
 +              PointerRNA field_ptr;
 +
 +              RNA_pointer_create(&ob->id, &RNA_FieldSettings, pd, &field_ptr);
 +              WM_manipulator_set_matrix_location(mpr, ob->obmat[3]);
 +              WM_manipulator_set_matrix_rotation_from_z_axis(mpr, ob->obmat[2]);
 +              WM_manipulator_set_matrix_offset_location(mpr, ofs);
 +              WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
 +              WM_manipulator_target_property_def_rna(mpr, "offset", &field_ptr, "strength", -1);
 +      }
 +      else {
 +              WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true);
 +      }
 +}
 +
 +void VIEW3D_WGT_force_field(wmManipulatorGroupType *wgt)
 +{
 +      wgt->name = "Force Field Widgets";
 +      wgt->idname = "VIEW3D_WGT_force_field";
 +
 +      wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
 +                    WM_MANIPULATORGROUPTYPE_3D |
 +                    WM_MANIPULATORGROUPTYPE_SCALE |
 +                    WM_MANIPULATORGROUPTYPE_DEPTH_3D);
 +
 +      wgt->poll = WIDGETGROUP_forcefield_poll;
 +      wgt->setup = WIDGETGROUP_forcefield_setup;
 +      wgt->refresh = WIDGETGROUP_forcefield_refresh;
 +}
 +
 +/** \} */
Simple merge
Simple merge
Simple merge
index d8ec6b5d6d1e165f351ca90d30bc967672db0b9b,0000000000000000000000000000000000000000..de5439c56386fe37c839a0bdba73af128c2ff1e4
mode 100644,000000..100644
--- /dev/null
@@@ -1,44 -1,0 +1,43 @@@
 +/*
 + * ***** 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.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +/** \file gpu_shader_private.h
 + *  \ingroup gpu
 + */
 +
 +#ifndef __GPU_SHADER_PRIVATE_H__
 +#define __GPU_SHADER_PRIVATE_H__
 +
 +#include "GPU_glew.h"
 +#include "gawain/gwn_shader_interface.h"
 +
 +struct GPUShader {
 +      GLuint program;  /* handle for full program (links shader stages below) */
 +
 +      GLuint vertex;   /* handle for vertex shader */
 +      GLuint geometry; /* handle for geometry shader */
 +      GLuint fragment; /* handle for fragment shader */
 +
 +      Gwn_ShaderInterface *interface; /* cached uniform & attrib interface for shader */
 +
 +      int feedback_transform_type;
 +};
 +
 +#endif  /* __GPU_SHADER_PRIVATE_H__ */
Simple merge
index f3091ae5ee107e8240a2bab53d98077a3e25abca,0000000000000000000000000000000000000000..a14699691a6050ed81469ccbd079e2477b9f7299
mode 100644,000000..100644
--- /dev/null
@@@ -1,225 -1,0 +1,224 @@@
 +/*
 + * ***** 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.
 + *
 + * Contributor(s): Blender Foundation.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +/** \file blender/makesrna/intern/rna_lightprobe.c
 + *  \ingroup RNA
 + */
 +
 +#include <stdlib.h>
 +
 +#include "RNA_define.h"
 +#include "RNA_enum_types.h"
 +
 +#include "rna_internal.h"
 +
 +#include "DNA_lightprobe_types.h"
 +
 +#include "WM_types.h"
 +
 +#ifdef RNA_RUNTIME
 +
 +#include "MEM_guardedalloc.h"
 +
 +#include "BKE_main.h"
 +#include "DEG_depsgraph.h"
 +
 +#include "DNA_object_types.h"
 +#include "DNA_group_types.h"
 +
 +#include "WM_api.h"
 +
 +static void rna_LightProbe_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
 +{
 +      DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
 +}
 +
 +#else
 +
 +static EnumPropertyItem parallax_type_items[] = {
 +      {LIGHTPROBE_SHAPE_ELIPSOID, "ELIPSOID", ICON_NONE, "Sphere", ""},
 +      {LIGHTPROBE_SHAPE_BOX, "BOX", ICON_NONE, "Box", ""},
 +      {0, NULL, 0, NULL, NULL}
 +};
 +
 +static EnumPropertyItem lightprobe_type_items[] = {
 +      {LIGHTPROBE_TYPE_CUBE, "CUBEMAP", ICON_LIGHTPROBE_CUBEMAP, "Reflection Cubemap", "Capture reflections"},
 +      {LIGHTPROBE_TYPE_PLANAR, "PLANAR", ICON_LIGHTPROBE_PLANAR, "Reflection Plane", ""},
 +      {LIGHTPROBE_TYPE_GRID, "GRID", ICON_LIGHTPROBE_GRID, "Irradiance Volume", "Volume used for precomputing indirect lighting"},
 +      {0, NULL, 0, NULL, NULL}
 +};
 +
 +static void rna_def_lightprobe(BlenderRNA *brna)
 +{
 +      StructRNA *srna;
 +      PropertyRNA *prop;
 +
 +      srna = RNA_def_struct(brna, "LightProbe", "ID");
 +      RNA_def_struct_ui_text(srna, "LightProbe", "Light Probe data-block for lighting capture objects");
 +      RNA_def_struct_ui_icon(srna, ICON_LIGHTPROBE_CUBEMAP);
 +
 +      prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
 +      RNA_def_property_enum_items(prop, lightprobe_type_items);
 +      RNA_def_property_ui_text(prop, "Type", "Type of light probe");
 +      RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 +
 +      prop = RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_DISTANCE);
 +      RNA_def_property_float_sdna(prop, NULL, "clipsta");
 +      RNA_def_property_range(prop, 1e-6f, FLT_MAX);
 +      RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
 +      RNA_def_property_ui_text(prop, "Clip Start",
 +                               "Probe clip start, below which objects will not appear in reflections");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
 +
 +      prop = RNA_def_property(srna, "clip_end", PROP_FLOAT, PROP_DISTANCE);
 +      RNA_def_property_float_sdna(prop, NULL, "clipend");
 +      RNA_def_property_range(prop, 1e-6f, FLT_MAX);
 +      RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
 +      RNA_def_property_ui_text(prop, "Clip End",
 +                               "Probe clip end, beyond which objects will not appear in reflections");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
 +
 +      prop = RNA_def_property(srna, "show_clip", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_SHOW_CLIP_DIST);
 +      RNA_def_property_ui_text(prop, "Clipping", "Show the clipping distances in the 3D view");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
 +
 +      prop = RNA_def_property(srna, "influence_type", PROP_ENUM, PROP_NONE);
 +      RNA_def_property_enum_sdna(prop, NULL, "attenuation_type");
 +      RNA_def_property_enum_items(prop, parallax_type_items);
 +      RNA_def_property_ui_text(prop, "Type", "Type of parallax volume");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
 +
 +      prop = RNA_def_property(srna, "show_influence", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_SHOW_INFLUENCE);
 +      RNA_def_property_ui_text(prop, "Influence", "Show the influence volume in the 3D view");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
 +
 +      prop = RNA_def_property(srna, "influence_distance", PROP_FLOAT, PROP_DISTANCE);
 +      RNA_def_property_float_sdna(prop, NULL, "distinf");
 +      RNA_def_property_range(prop, 0.0f, FLT_MAX);
 +      RNA_def_property_ui_text(prop, "Influence Distance", "Influence distance of the probe");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
 +
 +      prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_FACTOR);
 +      RNA_def_property_range(prop, 0.0f, 1.0f);
 +      RNA_def_property_ui_text(prop, "Falloff", "Control how fast the probe influence decreases");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
 +
 +      prop = RNA_def_property(srna, "use_custom_parallax", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_CUSTOM_PARALLAX);
 +      RNA_def_property_ui_text(prop, "Use Custom Parallax", "Enable custom settings for the parallax correction volume");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
 +
 +      prop = RNA_def_property(srna, "show_parallax", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_SHOW_PARALLAX);
 +      RNA_def_property_ui_text(prop, "Parallax", "Show the parallax correction volume in the 3D view");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
 +
 +      prop = RNA_def_property(srna, "parallax_type", PROP_ENUM, PROP_NONE);
 +      RNA_def_property_enum_items(prop, parallax_type_items);
 +      RNA_def_property_ui_text(prop, "Type", "Type of parallax volume");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
 +
 +      prop = RNA_def_property(srna, "parallax_distance", PROP_FLOAT, PROP_DISTANCE);
 +      RNA_def_property_float_sdna(prop, NULL, "distpar");
 +      RNA_def_property_range(prop, 0.0f, FLT_MAX);
 +      RNA_def_property_ui_text(prop, "Parallax Radius", "Lowest corner of the parallax bounding box");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
 +
 +      /* irradiance grid */
 +      prop = RNA_def_property(srna, "grid_resolution_x", PROP_INT, PROP_NONE);
 +      RNA_def_property_range(prop, 1, 256);
 +      RNA_def_property_ui_text(prop, "Resolution X", "Number of sample along the x axis of the volume");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
 +
 +      prop = RNA_def_property(srna, "grid_resolution_y", PROP_INT, PROP_NONE);
 +      RNA_def_property_range(prop, 1, 256);
 +      RNA_def_property_ui_text(prop, "Resolution Y", "Number of sample along the y axis of the volume");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
 +
 +      prop = RNA_def_property(srna, "grid_resolution_z", PROP_INT, PROP_NONE);
 +      RNA_def_property_range(prop, 1, 256);
 +      RNA_def_property_ui_text(prop, "Resolution Z", "Number of sample along the z axis of the volume");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
 +
 +      prop = RNA_def_property(srna, "visibility_buffer_bias", PROP_FLOAT, PROP_NONE);
 +      RNA_def_property_float_sdna(prop, NULL, "vis_bias");
 +      RNA_def_property_range(prop, 0.001f, 9999.0f);
 +      RNA_def_property_ui_range(prop, 0.001f, 5.0f, 1.0, 3);
 +      RNA_def_property_ui_text(prop, "Visibility Bias", "Bias for reducing self shadowing");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
 +
 +      prop = RNA_def_property(srna, "visibility_bleed_bias", PROP_FLOAT, PROP_NONE);
 +      RNA_def_property_float_sdna(prop, NULL, "vis_bleedbias");
 +      RNA_def_property_range(prop, 0.0f, 1.0f);
 +      RNA_def_property_ui_text(prop, "Visibility Bleed Bias", "Bias for reducing light-bleed on variance shadow maps");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
 +
 +      prop = RNA_def_property(srna, "visibility_blur", PROP_FLOAT, PROP_NONE);
 +      RNA_def_property_float_sdna(prop, NULL, "vis_blur");
 +      RNA_def_property_range(prop, 0.0f, 1.0f);
 +      RNA_def_property_ui_text(prop, "Visibility Blur", "Filter size of the visibilty blur");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
 +
 +      prop = RNA_def_property(srna, "intensity", PROP_FLOAT, PROP_NONE);
 +      RNA_def_property_float_sdna(prop, NULL, "intensity");
 +      RNA_def_property_range(prop, 0.0f, FLT_MAX);
 +      RNA_def_property_ui_range(prop, 0.0f, 3.0f, 1.0, 3);
 +      RNA_def_property_ui_text(prop, "Intensity", "Modify the intensity of the lighting captured by this probe");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
 +
 +      prop = RNA_def_property(srna, "visibility_collection", PROP_POINTER, PROP_NONE);
 +      RNA_def_property_struct_type(prop, "Collection");
 +      RNA_def_property_pointer_sdna(prop, NULL, "visibility_grp");
 +      RNA_def_property_flag(prop, PROP_EDITABLE);
 +      RNA_def_property_ui_text(prop, "Visibility Collection", "Restrict objects visible for this probe");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
 +
 +      prop = RNA_def_property(srna, "invert_visibility_collection", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_INVERT_GROUP);
 +      RNA_def_property_flag(prop, PROP_EDITABLE);
 +      RNA_def_property_ui_text(prop, "Invert Collection", "Invert visibility collection");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
 +
 +      /* Data preview */
 +      prop = RNA_def_property(srna, "show_data", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_SHOW_DATA);
 +      RNA_def_property_ui_text(prop, "Show Data", "Show captured lighting data into the 3D view for debuging purpose");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
 +
 +      prop = RNA_def_property(srna, "data_draw_size", PROP_FLOAT, PROP_NONE);
 +      RNA_def_property_range(prop, 0.05f, 10.0f);
 +      RNA_def_property_ui_text(prop, "Data Draw Size", "Size of the spheres to debug captured light");
 +      RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
 +
 +      /* common */
 +      rna_def_animdata_common(srna);
 +}
 +
 +
 +void RNA_def_lightprobe(BlenderRNA *brna)
 +{
 +      rna_def_lightprobe(brna);
 +}
 +
 +#endif
Simple merge
index 9df4e81ec556d762dbe8f198275f55bf9246f1bf,0000000000000000000000000000000000000000..3703ea92fa712ef0f79e6540ca30cd9d78863a45
mode 100644,000000..100644
--- /dev/null
@@@ -1,236 -1,0 +1,235 @@@
 +/*
 + * ***** 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.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +/** \file blender/python/intern/bpy_manipulator_wrap.c
 + *  \ingroup pythonintern
 + *
 + * This file is so Python can define widget-group's that C can call into.
 + * The generic callback functions for Python widget-group are defines in
 + * 'rna_wm.c', some calling into functions here to do python specific
 + * functionality.
 + *
 + * \note This follows 'bpy_operator_wrap.c' very closely.
 + * Keep in sync unless there is good reason not to!
 + */
 +
 +#include <Python.h>
 +
 +#include "BLI_utildefines.h"
 +
 +#include "WM_api.h"
 +#include "WM_types.h"
 +
 +#include "RNA_access.h"
 +#include "RNA_define.h"
 +#include "RNA_enum_types.h"
 +
 +#include "bpy_rna.h"
 +#include "bpy_intern_string.h"
 +#include "bpy_manipulator_wrap.h"  /* own include */
 +
 +/* we may want to add, but not now */
 +
 +/* -------------------------------------------------------------------- */
 +
 +/** \name Manipulator
 + * \{ */
 +
 +
 +static bool bpy_manipulatortype_target_property_def(
 +        wmManipulatorType *wt, PyObject *item)
 +{
 +      /* Note: names based on 'rna_rna.c' */
 +      PyObject *empty_tuple = PyTuple_New(0);
 +
 +      struct {
 +              char *id;
 +              char *type_id; int type;
 +              int array_length;
 +      } params = {
 +              .id = NULL, /* not optional */
 +              .type = PROP_FLOAT,
 +              .type_id = NULL,
 +              .array_length = 1,
 +      };
 +
 +      static const char * const _keywords[] = {"id", "type", "array_length", NULL};
 +      static _PyArg_Parser _parser = {"|$ssi:register_class", _keywords, 0};
 +      if (!_PyArg_ParseTupleAndKeywordsFast(
 +              empty_tuple, item,
 +              &_parser,
 +              &params.id,
 +              &params.type_id,
 +              &params.array_length))
 +      {
 +              goto fail;
 +      }
 +
 +      if (params.id == NULL) {
 +              PyErr_SetString(PyExc_ValueError, "'id' argument not given");
 +              goto fail;
 +      }
 +
 +      if ((params.type_id != NULL) &&
 +          pyrna_enum_value_from_id(
 +              rna_enum_property_type_items, params.type_id, &params.type, "'type' enum value") == -1)
 +      {
 +              goto fail;
 +      }
 +      else {
 +              params.type = rna_enum_property_type_items[params.type].value;
 +      }
 +
 +      if ((params.array_length < 1 || params.array_length > RNA_MAX_ARRAY_LENGTH)) {
 +              PyErr_SetString(PyExc_ValueError, "'array_length' out of range");
 +              goto fail;
 +      }
 +
 +      WM_manipulatortype_target_property_def(wt, params.id, params.type, params.array_length);
 +      Py_DECREF(empty_tuple);
 +      return true;
 +
 +fail:
 +      Py_DECREF(empty_tuple);
 +      return false;
 +}
 +
 +static void manipulator_properties_init(wmManipulatorType *wt)
 +{
 +      PyTypeObject *py_class = wt->ext.data;
 +      RNA_struct_blender_type_set(wt->ext.srna, wt);
 +
 +      /* only call this so pyrna_deferred_register_class gives a useful error
 +       * WM_operatortype_append_ptr will call RNA_def_struct_identifier
 +       * later */
 +      RNA_def_struct_identifier_no_struct_map(wt->srna, wt->idname);
 +
 +      if (pyrna_deferred_register_class(wt->srna, py_class) != 0) {
 +              PyErr_Print(); /* failed to register operator props */
 +              PyErr_Clear();
 +      }
 +
 +      /* Extract target property definitions from 'bl_target_properties' */
 +      {
 +              /* picky developers will notice that 'bl_targets' won't work with inheritance
 +               * get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal) - campbell */
 +              PyObject *py_class_dict = py_class->tp_dict;
 +              PyObject *bl_target_properties = PyDict_GetItem(py_class_dict, bpy_intern_str_bl_target_properties);
 +
 +              /* Some widgets may only exist to activate operators. */
 +              if (bl_target_properties != NULL) {
 +                      PyObject *bl_target_properties_fast;
 +                      if (!(bl_target_properties_fast = PySequence_Fast(
 +                                bl_target_properties, "bl_target_properties sequence")))
 +                      {
 +                              /* PySequence_Fast sets the error */
 +                              PyErr_Print();
 +                              PyErr_Clear();
 +                              return;
 +                      }
 +
 +                      const uint items_len = PySequence_Fast_GET_SIZE(bl_target_properties_fast);
 +                      PyObject **items = PySequence_Fast_ITEMS(bl_target_properties_fast);
 +
 +                      for (uint i = 0; i < items_len; i++) {
 +                              if (!bpy_manipulatortype_target_property_def(wt, items[i])) {
 +                                      PyErr_Print();
 +                                      PyErr_Clear();
 +                                      break;
 +                              }
 +                      }
 +
 +                      Py_DECREF(bl_target_properties_fast);
 +              }
 +      }
 +}
 +
 +void BPY_RNA_manipulator_wrapper(wmManipulatorType *wt, void *userdata)
 +{
 +      /* take care not to overwrite anything set in
 +       * WM_manipulatormaptype_group_link_ptr before opfunc() is called */
 +      StructRNA *srna = wt->srna;
 +      *wt = *((wmManipulatorType *)userdata);
 +      wt->srna = srna; /* restore */
 +
 +      /* don't do translations here yet */
 +#if 0
 +      /* Use i18n context from ext.srna if possible (py manipulatorgroups). */
 +      if (wt->ext.srna) {
 +              RNA_def_struct_translation_context(wt->srna, RNA_struct_translation_context(wt->ext.srna));
 +      }
 +#endif
 +
 +      wt->struct_size = sizeof(wmManipulator);
 +
 +      manipulator_properties_init(wt);
 +}
 +
 +/** \} */
 +
 +
 +/* -------------------------------------------------------------------- */
 +
 +/** \name Manipulator Group
 + * \{ */
 +
 +static void manipulatorgroup_properties_init(wmManipulatorGroupType *wgt)
 +{
 +#ifdef USE_SRNA
 +      PyTypeObject *py_class = wgt->ext.data;
 +#endif
 +      RNA_struct_blender_type_set(wgt->ext.srna, wgt);
 +
 +#ifdef USE_SRNA
 +      /* only call this so pyrna_deferred_register_class gives a useful error
 +       * WM_operatortype_append_ptr will call RNA_def_struct_identifier
 +       * later */
 +      RNA_def_struct_identifier(wgt->srna, wgt->idname);
 +
 +      if (pyrna_deferred_register_class(wgt->srna, py_class) != 0) {
 +              PyErr_Print(); /* failed to register operator props */
 +              PyErr_Clear();
 +      }
 +#endif
 +}
 +
 +void BPY_RNA_manipulatorgroup_wrapper(wmManipulatorGroupType *wgt, void *userdata)
 +{
 +      /* take care not to overwrite anything set in
 +       * WM_manipulatormaptype_group_link_ptr before opfunc() is called */
 +#ifdef USE_SRNA
 +      StructRNA *srna = wgt->srna;
 +#endif
 +      *wgt = *((wmManipulatorGroupType *)userdata);
 +#ifdef USE_SRNA
 +      wgt->srna = srna; /* restore */
 +#endif
 +
 +#ifdef USE_SRNA
 +      /* Use i18n context from ext.srna if possible (py manipulatorgroups). */
 +      if (wgt->ext.srna) {
 +              RNA_def_struct_translation_context(wgt->srna, RNA_struct_translation_context(wgt->ext.srna));
 +      }
 +#endif
 +
 +      manipulatorgroup_properties_init(wgt);
 +}
 +
 +/** \} */
index 3f739e260592086fbf113202096f5ec1f245686b,0000000000000000000000000000000000000000..3e4153502287d5f4cdc690fb2f1e2dca83b6224d
mode 100644,000000..100644
--- /dev/null
@@@ -1,36 -1,0 +1,35 @@@
 +/*
 + * ***** 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.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +/** \file blender/python/intern/bpy_manipulator_wrap.h
 + *  \ingroup pythonintern
 + */
 +
 +#ifndef __BPY_MANIPULATOR_WRAP_H__
 +#define __BPY_MANIPULATOR_WRAP_H__
 +
 +struct wmManipulatorType;
 +struct wmManipulatorGroupType;
 +
 +/* exposed to rna/wm api */
 +void BPY_RNA_manipulator_wrapper(struct wmManipulatorType *wt, void *userdata);
 +void BPY_RNA_manipulatorgroup_wrapper(struct wmManipulatorGroupType *wgt, void *userdata);
 +
 +#endif  /* __BPY_MANIPULATOR_WRAP_H__ */
index 941d6b760dc701e663730a793649fd7ed522300f,0000000000000000000000000000000000000000..b76ecafe6f09e3ca11981ed9aab5b27f91de2803
mode 100644,000000..100644
--- /dev/null
@@@ -1,400 -1,0 +1,399 @@@
 +/*
 + * ***** 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.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +/** \file blender/python/intern/bpy_msgbus.c
 + *  \ingroup pythonintern
 + * This file defines '_bpy_msgbus' module, exposed as 'bpy.msgbus'.
 + */
 +
 +#include <Python.h>
 +
 +#include "../generic/python_utildefines.h"
 +#include "../generic/py_capi_utils.h"
 +#include "../mathutils/mathutils.h"
 +
 +#include "BLI_utildefines.h"
 +
 +#include "BKE_context.h"
 +
 +#include "WM_api.h"
 +#include "WM_types.h"
 +#include "WM_message.h"
 +
 +#include "RNA_access.h"
 +#include "RNA_define.h"
 +#include "RNA_enum_types.h"
 +
 +#include "bpy_capi_utils.h"
 +#include "bpy_rna.h"
 +#include "bpy_intern_string.h"
 +#include "bpy_manipulator_wrap.h"  /* own include */
 +
 +
 +#include "bpy_msgbus.h"  /* own include */
 +
 +
 +/* -------------------------------------------------------------------- */
 +/** \name Internal Utils
 + * \{ */
 +
 +#define BPY_MSGBUS_RNA_MSGKEY_DOC \
 +"   :arg key: Represents the type of data being subscribed to\n" \
 +"\n" \
 +"      Arguments include\n" \
 +"      - :class:`bpy.types.Property` instance.\n" \
 +"      - :class:`bpy.types.Struct` type.\n" \
 +"      - (:class:`bpy.types.Struct`, str) type and property name.\n" \
 +"   :type key: Muliple\n"
 +
 +/**
 + * There are multiple ways we can get RNA from Python,
 + * it's also possible to register a type instead of an instance.
 + *
 + * This function handles converting Python to RNA subscription information.
 + *
 + * \param py_sub: See #BPY_MSGBUS_RNA_MSGKEY_DOC for description.
 + * \param msg_key_params: Message key with all members zeroed out.
 + * \return -1 on failure, 0 on success.
 + */
 +static int py_msgbus_rna_key_from_py(
 +        PyObject *py_sub,
 +        wmMsgParams_RNA *msg_key_params,
 +        const char *error_prefix)
 +{
 +
 +      /* Allow common case, object rotation, location - etc. */
 +      if (BaseMathObject_CheckExact(py_sub)) {
 +              BaseMathObject *py_sub_math = (BaseMathObject *)py_sub;
 +              if (py_sub_math->cb_user == NULL) {
 +                      PyErr_Format(
 +                              PyExc_TypeError,
 +                              "%s: math argument has no owner",
 +                              error_prefix);
 +                      return -1;
 +              }
 +              py_sub = py_sub_math->cb_user;
 +              /* Common case will use BPy_PropertyRNA_Check below. */
 +      }
 +
 +      if (BPy_PropertyRNA_Check(py_sub)) {
 +              BPy_PropertyRNA *data_prop = (BPy_PropertyRNA *)py_sub;
 +              PYRNA_PROP_CHECK_INT(data_prop);
 +              msg_key_params->ptr = data_prop->ptr;
 +              msg_key_params->prop = data_prop->prop;
 +      }
 +      else if (BPy_StructRNA_Check(py_sub)) {
 +              /* note, this isn't typically used since we don't edit structs directly. */
 +              BPy_StructRNA *data_srna = (BPy_StructRNA *)py_sub;
 +              PYRNA_STRUCT_CHECK_INT(data_srna);
 +              msg_key_params->ptr = data_srna->ptr;
 +      }
 +      /* TODO - property / type, not instance. */
 +      else if (PyType_Check(py_sub)) {
 +              StructRNA *data_type = pyrna_struct_as_srna(py_sub, false, error_prefix);
 +              if (data_type == NULL) {
 +                      return -1;
 +              }
 +              msg_key_params->ptr.type = data_type;
 +      }
 +      else if (PyTuple_CheckExact(py_sub)) {
 +              if (PyTuple_GET_SIZE(py_sub) == 2) {
 +                      PyObject *data_type_py = PyTuple_GET_ITEM(py_sub, 0);
 +                      PyObject *data_prop_py = PyTuple_GET_ITEM(py_sub, 1);
 +                      StructRNA *data_type = pyrna_struct_as_srna(data_type_py, false, error_prefix);
 +                      if (data_type == NULL) {
 +                              return -1;
 +                      }
 +                      if (!PyUnicode_CheckExact(data_prop_py)) {
 +                              PyErr_Format(
 +                                      PyExc_TypeError,
 +                                      "%s: expected property to be a string",
 +                                      error_prefix);
 +                              return -1;
 +                      }
 +                      PointerRNA data_type_ptr = { .type = data_type, };
 +                      const char *data_prop_str = _PyUnicode_AsString(data_prop_py);
 +                      PropertyRNA *data_prop = RNA_struct_find_property(&data_type_ptr, data_prop_str);
 +
 +                      if (data_prop == NULL) {
 +                              PyErr_Format(
 +                                      PyExc_TypeError,
 +                                      "%s: struct %.200s does not contain property %.200s",
 +                                      error_prefix,
 +                                      RNA_struct_identifier(data_type),
 +                                      data_prop_str);
 +                              return -1;
 +                      }
 +
 +                      msg_key_params->ptr.type = data_type;
 +                      msg_key_params->prop = data_prop;
 +              }
 +              else {
 +                      PyErr_Format(
 +                              PyExc_ValueError,
 +                              "%s: Expected a pair (type, property_id)",
 +                              error_prefix);
 +                      return -1;
 +              }
 +      }
 +      return 0;
 +}
 +
 +/** \} */
 +
 +/* -------------------------------------------------------------------- */
 +/** \name Internal Callbacks
 + * \{ */
 +
 +#define BPY_MSGBUS_USER_DATA_LEN 2
 +
 +/* Follow wmMsgNotifyFn spec */
 +static void bpy_msgbus_notify(
 +        bContext *C, wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
 +{
 +      PyGILState_STATE gilstate;
 +      bpy_context_set(C, &gilstate);
 +
 +      PyObject *user_data = msg_val->user_data;
 +      BLI_assert(PyTuple_GET_SIZE(user_data) == BPY_MSGBUS_USER_DATA_LEN);
 +
 +      PyObject *callback_args = PyTuple_GET_ITEM(user_data, 0);
 +      PyObject *callback_notify = PyTuple_GET_ITEM(user_data, 1);
 +
 +      const bool is_write_ok = pyrna_write_check();
 +      if (!is_write_ok) {
 +              pyrna_write_set(true);
 +      }
 +
 +      PyObject *ret = PyObject_CallObject(callback_notify, callback_args);
 +
 +      if (ret == NULL) {
 +              PyC_Err_PrintWithFunc(callback_notify);
 +      }
 +      else {
 +              if (ret != Py_None) {
 +                      PyErr_SetString(PyExc_ValueError, "the return value must be None");
 +                      PyC_Err_PrintWithFunc(callback_notify);
 +              }
 +              Py_DECREF(ret);
 +      }
 +
 +      bpy_context_clear(C, &gilstate);
 +
 +      if (!is_write_ok) {
 +              pyrna_write_set(false);
 +      }
 +}
 +
 +/* Follow wmMsgSubscribeValueFreeDataFn spec */
 +static void bpy_msgbus_subscribe_value_free_data(
 +        struct wmMsgSubscribeKey *UNUSED(msg_key), struct wmMsgSubscribeValue *msg_val)
 +{
 +      PyGILState_STATE gilstate = PyGILState_Ensure();
 +      Py_DECREF(msg_val->owner);
 +      Py_DECREF(msg_val->user_data);
 +      PyGILState_Release(gilstate);
 +}
 +
 +/** \} */
 +
 +/* -------------------------------------------------------------------- */
 +/** \name Public Message Bus API
 + * \{ */
 +
 +PyDoc_STRVAR(bpy_msgbus_subscribe_rna_doc,
 +".. function:: subscribe_rna(data, owner, args, notify)\n"
 +"\n"
 +BPY_MSGBUS_RNA_MSGKEY_DOC
 +"   :arg owner: Handle for this subscription (compared by identity).\n"
 +"   :type owner: Any type.\n"
 +"\n"
 +"   Returns a new vector int property definition.\n"
 +);
 +static PyObject *bpy_msgbus_subscribe_rna(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
 +{
 +      const char *error_prefix = "subscribe_rna";
 +      PyObject *py_sub = NULL;
 +      PyObject *py_owner = NULL;
 +      PyObject *callback_args = NULL;
 +      PyObject *callback_notify = NULL;
 +
 +      enum {
 +              IS_PERSISTENT = (1 << 0),
 +      };
 +      PyObject *py_options = NULL;
 +      EnumPropertyItem py_options_enum[] = {
 +              {IS_PERSISTENT, "PERSISTENT", 0, ""},
 +              {0, NULL, 0, NULL, NULL}
 +      };
 +      int options = 0;
 +
 +      static const char *_keywords[] = {
 +              "key",
 +              "owner",
 +              "args",
 +              "notify",
 +              "options",
 +              NULL,
 +      };
 +      static _PyArg_Parser _parser = {"$OOO!OO!:subscribe_rna", _keywords, 0};
 +      if (!_PyArg_ParseTupleAndKeywordsFast(
 +              args, kw, &_parser,
 +              &py_sub, &py_owner,
 +              &PyTuple_Type, &callback_args,
 +              &callback_notify,
 +              &PySet_Type, &py_options))
 +      {
 +              return NULL;
 +      }
 +
 +      if (py_options &&
 +          (pyrna_set_to_enum_bitfield(py_options_enum, py_options, &options, error_prefix)) == -1)
 +      {
 +              return NULL;
 +      }
 +
 +      /* Note: we may want to have a way to pass this in. */
 +      bContext *C = (bContext *)BPy_GetContext();
 +      struct wmMsgBus *mbus = CTX_wm_message_bus(C);
 +      wmMsgParams_RNA msg_key_params = {{{0}}};
 +
 +      wmMsgSubscribeValue msg_val_params = {0};
 +
 +      if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) {
 +              return NULL;
 +      }
 +
 +      if (!PyFunction_Check(callback_notify)) {
 +              PyErr_Format(
 +                      PyExc_TypeError,
 +                      "notify expects a function, found %.200s",
 +                      Py_TYPE(callback_notify)->tp_name);
 +              return NULL;
 +      }
 +
 +      if (options != 0) {
 +              if (options & IS_PERSISTENT) {
 +                      msg_val_params.is_persistent = true;
 +              }
 +      }
 +
 +      /* owner can be anything. */
 +      {
 +              msg_val_params.owner = py_owner;
 +              Py_INCREF(py_owner);
 +      }
 +
 +      {
 +              PyObject *user_data = PyTuple_New(2);
 +              PyTuple_SET_ITEMS(
 +                      user_data,
 +                      Py_INCREF_RET(callback_args),
 +                      Py_INCREF_RET(callback_notify));
 +              msg_val_params.user_data = user_data;
 +      }
 +
 +      msg_val_params.notify = bpy_msgbus_notify;
 +      msg_val_params.free_data = bpy_msgbus_subscribe_value_free_data;
 +
 +      WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_val_params, __func__);
 +
 +      WM_msg_dump(mbus, __func__);
 +
 +      Py_RETURN_NONE;
 +}
 +
 +PyDoc_STRVAR(bpy_msgbus_publish_rna_doc,
 +".. function:: publish_rna(data, owner, args, notify)\n"
 +"\n"
 +BPY_MSGBUS_RNA_MSGKEY_DOC
 +"\n"
 +"   Notify subscribers of changes to this property\n"
 +"   (this typically doesn't need to be called explicitly since changes will automatically publish updates).\n"
 +"   In some cases it may be useful to publish changes explicitly using more general keys.\n"
 +);
 +static PyObject *bpy_msgbus_publish_rna(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
 +{
 +      const char *error_prefix = "publish_rna";
 +      PyObject *py_sub = NULL;
 +
 +      static const char *_keywords[] = {
 +              "key",
 +              NULL,
 +      };
 +      static _PyArg_Parser _parser = {"$O:publish_rna", _keywords, 0};
 +      if (!_PyArg_ParseTupleAndKeywordsFast(
 +              args, kw, &_parser,
 +              &py_sub))
 +      {
 +              return NULL;
 +      }
 +
 +      /* Note: we may want to have a way to pass this in. */
 +      bContext *C = (bContext *)BPy_GetContext();
 +      struct wmMsgBus *mbus = CTX_wm_message_bus(C);
 +      wmMsgParams_RNA msg_key_params = {{{0}}};
 +
 +      if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) {
 +              return NULL;
 +      }
 +
 +      WM_msg_publish_rna_params(mbus, &msg_key_params);
 +
 +      Py_RETURN_NONE;
 +}
 +
 +PyDoc_STRVAR(bpy_msgbus_clear_by_owner_doc,
 +".. function:: clear_by_owner(owner)\n"
 +"\n"
 +"   Clear all subscribers using this owner.\n"
 +);
 +static PyObject *bpy_msgbus_clear_by_owner(PyObject *UNUSED(self), PyObject *py_owner)
 +{
 +      bContext *C = (bContext *)BPy_GetContext();
 +      struct wmMsgBus *mbus = CTX_wm_message_bus(C);
 +      WM_msgbus_clear_by_owner(mbus, py_owner);
 +      Py_RETURN_NONE;
 +}
 +
 +static struct PyMethodDef BPy_msgbus_methods[] = {
 +      {"subscribe_rna", (PyCFunction)bpy_msgbus_subscribe_rna, METH_VARARGS | METH_KEYWORDS, bpy_msgbus_subscribe_rna_doc},
 +      {"publish_rna", (PyCFunction)bpy_msgbus_publish_rna, METH_VARARGS | METH_KEYWORDS, bpy_msgbus_publish_rna_doc},
 +      {"clear_by_owner", (PyCFunction)bpy_msgbus_clear_by_owner, METH_O, bpy_msgbus_clear_by_owner_doc},
 +      {NULL, NULL, 0, NULL}
 +};
 +
 +static struct PyModuleDef _bpy_msgbus_def = {
 +      PyModuleDef_HEAD_INIT,
 +      .m_name = "msgbus",
 +      .m_methods = BPy_msgbus_methods,
 +};
 +
 +
 +PyObject *BPY_msgbus_module(void)
 +{
 +      PyObject *submodule;
 +
 +      submodule = PyModule_Create(&_bpy_msgbus_def);
 +
 +      return submodule;
 +}
 +
 +/** \} */
Simple merge
index 2de355b92a544e872a19f5bcd9faef7c77ef3535,47874a9a1352ea9c641284dcfee682ed9d592da0..0620ca6d11d0775126dcb032571618e8a4dc3775
@@@ -190,8 -175,6 +190,7 @@@ RenderEngineType *RE_engines_find(cons
  
  rcti* RE_engine_get_current_tiles(struct Render *re, int *r_total_tiles, bool *r_needs_free);
  struct RenderData *RE_engine_get_render_data(struct Render *re);
 -void RE_bake_engine_set_engine_parameters(struct Render *re, struct Main *bmain, struct Scene *scene);
 +void RE_bake_engine_set_engine_parameters(
 +        struct Render *re, struct Main *bmain, struct Scene *scene);
  
  #endif /* __RE_ENGINE_H__ */
index b8732e7cc5caaa7a90b8c4e35cb272f8e9bd9184,36773b4c73eb8466b51e73ed9914bf77d8d774c3..22a2176e16c7249b577b47f0908d1c7a80b93b1b
@@@ -39,5 -43,5 +39,4 @@@ void RE_parts_init(Render *re)
  void RE_parts_free(Render *re);
  void RE_parts_clamp(Render *re);
  
 -
  #endif /* __INITRENDER_H__ */
index eebecc531011ceb2c580d22b252bc5f29d8d57b9,7713c9c7fba48027292cc3d2081d38aec0489c42..3096949b49fe734e8aeb48bef50970b1c573a464
@@@ -115,28 -117,4 +115,27 @@@ void render_result_views_shallowcopy(st
  void render_result_views_shallowdelete(struct RenderResult *rr);
  bool render_result_has_views(struct RenderResult *rr);
  
 +#define FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re_, iter_)    \
 +{                                                         \
 +      int nr_;                                              \
 +      ViewLayer *iter_;                                     \
 +      for (nr_ = 0, iter_ = (re_)->view_layers.first;       \
 +           iter_ != NULL;                                   \
 +          iter_ = iter_->next, nr_++)                       \
 +      {                                                     \
 +              if ((re_)->r.scemode & R_SINGLE_LAYER) {          \
 +                      if (nr_ != re->active_view_layer) {           \
 +                              continue;                                 \
 +                      }                                             \
 +              }                                                 \
 +              else {                                            \
 +                      if ((iter_->flag & VIEW_LAYER_RENDER) == 0) { \
 +                              continue;                                 \
 +                      }                                             \
 +              }
 +
 +#define FOREACH_VIEW_LAYER_TO_RENDER_END                  \
 +      }                                                     \
 +} ((void)0)
 +
  #endif /* __RENDER_RESULT_H__ */
index 34535fba1e0b45fbd12d2669e78bc040e7a44b5c,64e6aa54a9e954820bbe9009b8089fa43f8c09bb..117b82570e746b632741a0a35d7c5b4a87d6a450
@@@ -155,18 -274,414 +155,17 @@@ struct Render 
  
        struct ReportList *reports;
  
 -      struct ImagePool *pool;
 -      struct EvaluationContext *eval_ctx;
 -
        void **movie_ctx_arr;
        char viewname[MAX_NAME];
 -};
 -
 -/* ------------------------------------------------------------------------- */
 -
 -struct ISBData;
 -
 -typedef struct DeepSample {
 -      int z;
 -      float v;
 -} DeepSample;
 -
 -typedef struct ShadSampleBuf {
 -      struct ShadSampleBuf *next, *prev;
 -      intptr_t *zbuf;
 -      char *cbuf;
 -      DeepSample **deepbuf;
 -      int *totbuf;
 -} ShadSampleBuf;
 -
 -typedef struct ShadBuf {
 -      /* regular shadowbuffer */
 -      short samp, shadhalostep, totbuf;
 -      float persmat[4][4];
 -      float viewmat[4][4];
 -      float winmat[4][4];
 -      float *jit, *weight;
 -      float d, clipend, pixsize, soft, compressthresh;
 -      int co[3];
 -      int size, bias;
 -      ListBase buffers;
 -
 -      /* irregular shadowbufer, result stored per thread */
 -      struct ISBData *isb_result[BLENDER_MAX_THREADS];
 -} ShadBuf;
 -
 -/* ------------------------------------------------------------------------- */
 -
 -typedef struct ObjectRen {
 -      struct ObjectRen *next, *prev;
 -      struct Object *ob, *par;
 -      struct Scene *sce;
 -      int index, psysindex, flag, lay;
 -
 -      float boundbox[2][3];
 -
 -      int totvert, totvlak, totstrand, tothalo;
 -      int vertnodeslen, vlaknodeslen, strandnodeslen, blohalen;
 -      struct VertTableNode *vertnodes;
 -      struct VlakTableNode *vlaknodes;
 -      struct StrandTableNode *strandnodes;
 -      struct HaloRen **bloha;
 -      struct StrandBuffer *strandbuf;
 -
 -      char (*mtface)[MAX_CUSTOMDATA_LAYER_NAME];
 -      char (*mcol)[MAX_CUSTOMDATA_LAYER_NAME];
 -      int  actmtface, actmcol, bakemtface;
 -
 -      short tangent_mask; /* which tangent layer should be calculated */
 -
 -      float obmat[4][4];      /* only used in convertblender.c, for instancing */
 -
 -      /* used on makeraytree */
 -      struct RayObject *raytree;
 -      struct RayFace *rayfaces;
 -      struct VlakPrimitive *rayprimitives;
 -      struct ObjectInstanceRen *rayobi;
 -
 -} ObjectRen;
 -
 -typedef struct ObjectInstanceRen {
 -      struct ObjectInstanceRen *next, *prev;
 -
 -      ObjectRen *obr;
 -      Object *ob, *par;
 -      int index, psysindex, lay;
 -
 -      float mat[4][4], imat[4][4];
 -      float nmat[3][3]; /* nmat is inverse mat tranposed */
 -
 -      float obmat[4][4], obinvmat[4][4];
 -      float localtoviewmat[4][4], localtoviewinvmat[4][4];
 -
 -      short flag;
  
 -      float dupliorco[3], dupliuv[2];
 -      float (*duplitexmat)[4];
 -
 -      struct VolumePrecache *volume_precache;
 -
 -      float *vectors; /* (RE_WINSPEED_ELEMS * VertRen.index) */
 -      int totvector;
 -
 -      /* used on makeraytree */
 -      struct RayObject *raytree;
 -      int transform_primitives;
 -
 -      /* Particle info */
 -      float part_index;
 -      float part_age;
 -      float part_lifetime;
 -      float part_size;
 -      float part_co[3];
 -      float part_vel[3];
 -      float part_avel[3];
 -
 -      unsigned int random_id;
 -} ObjectInstanceRen;
 -
 -/* ------------------------------------------------------------------------- */
 -
 -typedef struct VertRen {
 -      float co[3];
 -      float n[3];
 -      float *orco;
 -      unsigned int flag;      /* in use for clipping zbuffer parts, temp setting stuff in convertblender.c
 -                                               * only an 'int' because of alignment, could be a char too */
 -      float accum;            /* accum for radio weighting, and for strand texco static particles */
 -      int index;                      /* index allows extending vertren with any property */
 -} VertRen;
 -
 -/* ------------------------------------------------------------------------- */
 -
 -struct halosort {
 -      struct HaloRen *har;
 -      int z;
 +      /* TODO replace by a whole draw manager. */
 +      void *gl_context;
 +      void *gwn_context;
  };
  
 -/* ------------------------------------------------------------------------- */
 -struct Material;
 -struct ImagePool;
 -
 -typedef struct RadFace {
 -      float unshot[3], totrad[3];
 -      float norm[3], cent[3], area;
 -      int flag;
 -} RadFace;
 -
 -typedef struct VlakRen {
 -      struct VertRen *v1, *v2, *v3, *v4;      /* keep in order for ** addressing */
 -      float n[3];
 -      struct Material *mat;
 -      char puno;
 -      char flag, ec;
 -#ifdef WITH_FREESTYLE
 -      char freestyle_edge_mark;
 -      char freestyle_face_mark;
 -#endif
 -      int index;
 -} VlakRen;
 -
 -typedef struct HaloRen {
 -      short miny, maxy;
 -      float alfa, xs, ys, rad, radsq, sin, cos, co[3], no[3];
 -      float hard, b, g, r;
 -      int zs, zd;
 -      int zBufDist;   /* depth in the z-buffer coordinate system */
 -      char starpoints, type, add, tex;
 -      char linec, ringc, seed;
 -      short flarec; /* used to be a char. why ?*/
 -      float hasize;
 -      int pixels;
 -      unsigned int lay;
 -      struct Material *mat;
 -      struct ImagePool *pool;
 -      bool skip_load_image, texnode_preview;
 -} HaloRen;
 -
 -/* ------------------------------------------------------------------------- */
 -
 -typedef struct StrandVert {
 -      float co[3];
 -      float strandco;
 -} StrandVert;
 -
 -typedef struct StrandSurface {
 -      struct StrandSurface *next, *prev;
 -      ObjectRen obr;
 -      int (*face)[4];
 -      float (*co)[3];
 -      /* for occlusion caching */
 -      float (*ao)[3];
 -      float (*env)[3];
 -      float (*indirect)[3];
 -      /* for speedvectors */
 -      float (*prevco)[3], (*nextco)[3];
 -      int totvert, totface;
 -} StrandSurface;
 -
 -typedef struct StrandBound {
 -      int start, end;
 -      float boundbox[2][3];
 -} StrandBound;
 -
 -typedef struct StrandBuffer {
 -      struct StrandBuffer *next, *prev;
 -      struct StrandVert *vert;
 -      struct StrandBound *bound;
 -      int totvert, totbound;
 -
 -      struct ObjectRen *obr;
 -      struct Material *ma;
 -      struct StrandSurface *surface;
 -      unsigned int lay;
 -      int overrideuv;
 -      int flag, maxdepth;
 -      float adaptcos, minwidth, widthfade;
 -
 -      float maxwidth; /* for cliptest of strands in blender unit */
 -
 -      float winmat[4][4];
 -      int winx, winy;
 -} StrandBuffer;
 -
 -typedef struct StrandRen {
 -      StrandVert *vert;
 -      StrandBuffer *buffer;
 -      int totvert, flag;
 -      int clip, index;
 -      float orco[3];
 -} StrandRen;
 -
 -/* ------------------------------------------------------------------------- */
 -
 -typedef struct VolumeOb {
 -      struct VolumeOb *next, *prev;
 -      struct Material *ma;
 -      struct ObjectRen *obr;
 -} VolumeOb;
 -
 -typedef struct MatInside {
 -      struct MatInside *next, *prev;
 -      struct Material *ma;
 -      struct ObjectInstanceRen *obi;
 -} MatInside;
 -
 -typedef struct VolPrecachePart {
 -      struct VolPrecachePart *next, *prev;
 -      struct RayObject *tree;
 -      struct ShadeInput *shi;
 -      struct ObjectInstanceRen *obi;
 -      float viewmat[4][4];
 -      int num;
 -      int minx, maxx;
 -      int miny, maxy;
 -      int minz, maxz;
 -      int res[3];
 -      float bbmin[3];
 -      float voxel[3];
 -      struct Render *re;
 -} VolPrecachePart;
 -
 -typedef struct VolumePrecache {
 -      int res[3];
 -      float *bbmin, *bbmax;
 -      float *data_r;
 -      float *data_g;
 -      float *data_b;
 -} VolumePrecache;
 -
 -/* ------------------------------------------------------------------------- */
 -
 -struct LampRen;
 -struct MTex;
 -
 -/**
 - * For each lamp in a scene, a LampRen is created. It determines the
 - * properties of a lightsource.
 - */
 -
 -typedef struct LampShadowSubSample {
 -      int samplenr;
 -      float shadfac[4];       /* rgba shadow */
 -} LampShadowSubSample;
 -
 -typedef struct LampShadowSample {
 -      LampShadowSubSample s[16];      /* MAX OSA */
 -} LampShadowSample;
 -
 -typedef struct LampRen {
 -      struct LampRen *next, *prev;
 -
 -      float xs, ys, dist;
 -      float co[3];
 -      short type;
 -      int mode;
 -      float r, g, b, k;
 -      float shdwr, shdwg, shdwb;
 -      float energy, haint;
 -      int lay;
 -      float spotsi, spotbl;
 -      float vec[3];
 -      float xsp, ysp, distkw, inpr;
 -      float halokw, halo;
 -
 -      short falloff_type;
 -      float ld1, ld2;
 -      float coeff_const, coeff_lin, coeff_quad;
 -      struct CurveMapping *curfalloff;
 -
 -      /* copied from Lamp, to decouple more rendering stuff */
 -      /** Size of the shadowbuffer */
 -      short bufsize;
 -      /** Number of samples for the shadows */
 -      short samp;
 -      /** Softness factor for shadow */
 -      float soft;
 -      /** amount of subsample buffers and type of filter for sampling */
 -      short buffers, filtertype;
 -      /** shadow buffer type (regular, irregular) */
 -      short buftype;
 -      /** autoclip */
 -      short bufflag;
 -      /** shadow plus halo: detail level */
 -      short shadhalostep;
 -      /** Near clip of the lamp */
 -      float clipsta;
 -      /** Far clip of the lamp */
 -      float clipend;
 -      /** A small depth offset to prevent self-shadowing. */
 -      float bias;
 -      /* Compression threshold for deep shadow maps */
 -      float compressthresh;
 -
 -      short ray_samp, ray_sampy, ray_sampz, ray_samp_method, ray_samp_type, area_shape, ray_totsamp;
 -      short xold[BLENDER_MAX_THREADS], yold[BLENDER_MAX_THREADS];     /* last jitter table for area lights */
 -      float area_size, area_sizey, area_sizez;
 -      float adapt_thresh;
 -
 -      /* sun/sky */
 -      struct SunSky *sunsky;
 -
 -      struct ShadBuf *shb;
 -      float *jitter;
 -
 -      float imat[3][3];
 -      float spottexfac;
 -      float sh_invcampos[3], sh_zfac; /* sh_= spothalo */
 -
 -      float lampmat[4][4];    /* worls space lamp matrix, used for scene rotation */
 -
 -      float mat[3][3];        /* 3x3 part from lampmat x viewmat */
 -      float area[8][3], areasize;
 -
 -      /* passes & node shader support: all shadow info for a pixel */
 -      LampShadowSample *shadsamp;
 -
 -      /* ray optim */
 -      struct RayObject *last_hit[BLENDER_MAX_THREADS];
 -
 -      struct MTex *mtex[MAX_MTEX];
 -
 -      /* threading */
 -      int thread_assigned;
 -      int thread_ready;
 -} LampRen;
 -
  /* **************** defines ********************* */
  
 -/* R.r.mode flag is same as for renderdata */
 -
  /* R.flag */
 -#define R_ZTRA                        1
 -#define R_HALO                        2
 -#define R_SEC_FIELD           4
 -#define R_LAMPHALO            8
 -#define R_NEED_TANGENT        16
 -#define R_BAKE_TRACE  32
 -#define R_BAKING              64
 -#define R_ANIMATION           128
 -#define R_NEED_VCOL           256
 -
 -/* vlakren->flag (vlak = face in dutch) char!!! */
 -#define R_SMOOTH              1
 -#define R_HIDDEN              2
 -/* strand flag, means special handling */
 -#define R_STRAND              4
 -#define R_FULL_OSA            8
 -#define R_FACE_SPLIT  16
 -/* Tells render to divide face other way. */
 -#define R_DIVIDE_24           32
 -/* vertex normals are tangent or view-corrected vector, for hair strands */
 -#define R_TANGENT             64
 -#define R_TRACEBLE            128
 -
 -/* vlakren->freestyle_edge_mark */
 -#ifdef WITH_FREESTYLE
 -#  define R_EDGE_V1V2         1
 -#  define R_EDGE_V2V3         2
 -#  define R_EDGE_V3V4         4
 -#  define R_EDGE_V3V1         4
 -#  define R_EDGE_V4V1         8
 -#endif
 -
 -/* strandbuffer->flag */
 -#define R_STRAND_BSPLINE      1
 -#define R_STRAND_B_UNITS      2
 -
 -/* objectren->flag */
 -#define R_INSTANCEABLE                1
 -
 -/* objectinstance->flag */
 -#define R_DUPLI_TRANSFORMED   1
 -#define R_ENV_TRANSFORMED     2
 -#define R_TRANSFORMED         (1|2)
 +#define R_ANIMATION           1
  
  #endif /* __RENDER_TYPES_H__ */
index 0654a4f8df6661a685a243b0530c0ab6645ee8a9,50ad78b5be782974cbd4a75e662de667ee8fb6d3..0acc7d091e37a1c111ac3bbfe73f0a64b125ac21
@@@ -48,5 -128,23 +48,4 @@@ void zbuf_free_span(struct ZSpan *zspan
  void zspan_scanconvert(struct ZSpan *zpan, void *handle, float *v1, float *v2, float *v3,
                         void (*func)(void *, int, int, float, float) );
  
 -/* exported to edge render... */
 -void zbufclip(struct ZSpan *zspan, int obi, int zvlnr,
 -              const float f1[4], const float f2[4], const float f3[4],
 -              const int c1, const int c2, const int c3);
 -void zbuf_alloc_span(struct ZSpan *zspan, int rectx, int recty, float clipcrop);
 -void zbufclipwire(struct ZSpan *zspan, int obi, int zvlnr, int ec,
 -                  const float ho1[4], const float ho2[4], const float ho3[4], const float ho4[4],
 -                  const int c1, const int c2, const int c3, const int c4);
 -
 -/* exported to shadeinput.c */
 -void zbuf_make_winmat(Render *re, float winmat[4][4]);
 -void zbuf_render_project(float winmat[4][4], const float co[3], float ho[4]);
 -
 -/* should not really be exposed, bad! */
 -void hoco_to_zco(ZSpan *zspan, float zco[3], const float hoco[4]);
 -void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) );
 -void zbufsinglewire(ZSpan *zspan, int obi, int zvlnr, const float ho1[4], const float ho2[4]);
 -
  #endif
index c025a1fdef765cf9190e18e29f091a5a3f357245,635bfc58425d206ee08f05b09dfbd99495ad02f8..f51c472da8f2bf8183e753d6a2011c8afac1da72
@@@ -959,8 -1099,3 +959,7 @@@ void RE_point_density_free(struct Point
  {
        free_pointdensity(pd);
  }
 +
 +void RE_point_density_fix_linking(void)
 +{
 +}
index 99da5b3ca015dc9f96ea8e7c4c75b5fb97f42ca8,8450098d733470ba8b8be375b9de70677e004478..2841d96025ecfd96ade3b0e0145199ab89ebf239
@@@ -1445,66 -1652,2333 +1445,65 @@@ float texture_value_blend(float tex, fl
        return in;
  }
  
 -static void texco_mapping(ShadeInput *shi, Tex *tex, MTex *mtex,
 -                          const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3])
 -{
 -      /* new: first swap coords, then map, then trans/scale */
 -      if (tex->type == TEX_IMAGE) {
 -              /* placement */
 -              texvec[0] = mtex->projx ? co[mtex->projx - 1] : 0.f;
 -              texvec[1] = mtex->projy ? co[mtex->projy - 1] : 0.f;
 -              texvec[2] = mtex->projz ? co[mtex->projz - 1] : 0.f;
 -
 -              if (shi->osatex) {
 -                      if (mtex->projx) {
 -                              dxt[0] = dx[mtex->projx - 1];
 -                              dyt[0] = dy[mtex->projx - 1];
 -                      }
 -                      else dxt[0] = dyt[0] = 0.f;
 -                      if (mtex->projy) {
 -                              dxt[1] = dx[mtex->projy - 1];
 -                              dyt[1] = dy[mtex->projy - 1];
 -                      }
 -                      else dxt[1] = dyt[1] = 0.f;
 -                      if (mtex->projz) {
 -                              dxt[2] = dx[mtex->projz - 1];
 -                              dyt[2] = dy[mtex->projz - 1];
 -                      }
 -                      else dxt[2] = dyt[2] = 0.f;
 -              }
 -              do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt);
 -
 -              /* translate and scale */
 -              texvec[0] = mtex->size[0]*(texvec[0] - 0.5f) + mtex->ofs[0] + 0.5f;
 -              texvec[1] = mtex->size[1]*(texvec[1] - 0.5f) + mtex->ofs[1] + 0.5f;
 -              if (shi->osatex) {
 -                      dxt[0] = mtex->size[0] * dxt[0];
 -                      dxt[1] = mtex->size[1] * dxt[1];
 -                      dyt[0] = mtex->size[0] * dyt[0];
 -                      dyt[1] = mtex->size[1] * dyt[1];
 -              }
 -
 -              /* problem: repeat-mirror is not a 'repeat' but 'extend' in imagetexture.c */
 -              /* TXF: bug was here, only modify texvec when repeat mode set, old code affected other modes too.
 -               * New texfilters solve mirroring differently so that it also works correctly when
 -               * textures are scaled (sizeXYZ) as well as repeated. See also modification in do_2d_mapping().
 -               * (since currently only done in osa mode, results will look incorrect without osa TODO) */
 -              if (tex->extend == TEX_REPEAT && (tex->flag & TEX_REPEAT_XMIR)) {
 -                      if (tex->texfilter == TXF_BOX)
 -                              texvec[0] -= floorf(texvec[0]);  /* this line equivalent to old code, same below */
 -                      else if (texvec[0] < 0.f || texvec[0] > 1.f) {
 -                              const float tx = 0.5f*texvec[0];
 -                              texvec[0] = 2.f*(tx - floorf(tx));
 -                              if (texvec[0] > 1.f) texvec[0] = 2.f - texvec[0];
 -                      }
 -              }
 -              if (tex->extend == TEX_REPEAT && (tex->flag & TEX_REPEAT_YMIR)) {
 -                      if (tex->texfilter == TXF_BOX)
 -                              texvec[1] -= floorf(texvec[1]);
 -                      else if (texvec[1] < 0.f || texvec[1] > 1.f) {
 -                              const float ty = 0.5f*texvec[1];
 -                              texvec[1] = 2.f*(ty - floorf(ty));
 -                              if (texvec[1] > 1.f) texvec[1] = 2.f - texvec[1];
 -                      }
 -              }
 -
 -      }
 -      else {  /* procedural */
 -              /* placement */
 -              texvec[0] = mtex->size[0]*(mtex->projx ? (co[mtex->projx - 1] + mtex->ofs[0]) : mtex->ofs[0]);
 -              texvec[1] = mtex->size[1]*(mtex->projy ? (co[mtex->projy - 1] + mtex->ofs[1]) : mtex->ofs[1]);
 -              texvec[2] = mtex->size[2]*(mtex->projz ? (co[mtex->projz - 1] + mtex->ofs[2]) : mtex->ofs[2]);
 -
 -              if (shi->osatex) {
 -                      if (mtex->projx) {
 -                              dxt[0] = mtex->size[0]*dx[mtex->projx - 1];
 -                              dyt[0] = mtex->size[0]*dy[mtex->projx - 1];
 -                      }
 -                      else dxt[0] = dyt[0] = 0.f;
 -                      if (mtex->projy) {
 -                              dxt[1] = mtex->size[1]*dx[mtex->projy - 1];
 -                              dyt[1] = mtex->size[1]*dy[mtex->projy - 1];
 -                      }
 -                      else dxt[1] = dyt[1] = 0.f;
 -                      if (mtex->projz) {
 -                              dxt[2] = mtex->size[2]*dx[mtex->projz - 1];
 -                              dyt[2] = mtex->size[2]*dy[mtex->projz - 1];
 -                      }
 -                      else dxt[2]= dyt[2] = 0.f;
 -              }
 -
 -              if (mtex->tex->type == TEX_ENVMAP) {
 -                      EnvMap *env = tex->env;
 -                      if (!env->object) {
 -                              // env->object is a view point for envmap rendering
 -                              // if it's not set, return the result depending on the world_space_shading flag
 -                              if (BKE_scene_use_world_space_shading(R.scene)) {
 -                                      mul_mat3_m4_v3(R.viewinv, texvec);
 -                                      if (shi->osatex) {
 -                                              mul_mat3_m4_v3(R.viewinv, dxt);
 -                                              mul_mat3_m4_v3(R.viewinv, dyt);
 -                                      }
 -                              }
 -                      }
 -              }
 -      }
 -}
 -
 -/* Bump code from 2.5 development cycle, has a number of bugs, but here for compatibility */
 -
 -typedef struct CompatibleBump {
 -      float nu[3], nv[3], nn[3];
 -      float dudnu, dudnv, dvdnu, dvdnv;
 -      bool nunvdone;
 -} CompatibleBump;
 -
 -static void compatible_bump_init(CompatibleBump *compat_bump)
 -{
 -      memset(compat_bump, 0, sizeof(*compat_bump));
 -
 -      compat_bump->dudnu = 1.0f;
 -      compat_bump->dvdnv = 1.0f;
 -}
 -
 -static void compatible_bump_uv_derivs(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, int i)
 -{
 -      /* uvmapping only, calculation of normal tangent u/v partial derivatives
 -       * (should not be here, dudnu, dudnv, dvdnu & dvdnv should probably be part of ShadeInputUV struct,
 -       *  nu/nv in ShadeInput and this calculation should then move to shadeinput.c,
 -       * shade_input_set_shade_texco() func.) */
 -
 -      /* NOTE: test for shi->obr->ob here,
 -       * since vlr/obr/obi can be 'fake' when called from fastshade(), another reason to move it.. */
 -
 -      /* NOTE: shi->v1 is NULL when called from displace_render_vert,
 -       * assigning verts in this case is not trivial because the shi quad face side is not know. */
 -      if ((mtex->texflag & MTEX_COMPAT_BUMP) && shi->obr && shi->obr->ob && shi->v1) {
 -              if (mtex->mapto & (MAP_NORM|MAP_WARP) && !((mtex->tex->type==TEX_IMAGE) && (mtex->tex->imaflag & TEX_NORMALMAP))) {
 -                      MTFace* tf = RE_vlakren_get_tface(shi->obr, shi->vlr, i, NULL, 0);
 -                      int j1 = shi->i1, j2 = shi->i2, j3 = shi->i3;
 -
 -                      vlr_set_uv_indices(shi->vlr, &j1, &j2, &j3);
 -
 -                      /* compute ortho basis around normal */
 -                      if (!compat_bump->nunvdone) {
 -                              /* render normal is negated */
 -                              compat_bump->nn[0] = -shi->vn[0];
 -                              compat_bump->nn[1] = -shi->vn[1];
 -                              compat_bump->nn[2] = -shi->vn[2];
 -                              ortho_basis_v3v3_v3(compat_bump->nu, compat_bump->nv, compat_bump->nn);
 -                              compat_bump->nunvdone = true;
 -                      }
 -
 -                      if (tf) {
 -                              const float *uv1 = tf->uv[j1], *uv2 = tf->uv[j2], *uv3 = tf->uv[j3];
 -                              const float an[3] = {fabsf(compat_bump->nn[0]), fabsf(compat_bump->nn[1]), fabsf(compat_bump->nn[2])};
 -                              const int a1 = (an[0] > an[1] && an[0] > an[2]) ? 1 : 0;
 -                              const int a2 = (an[2] > an[0] && an[2] > an[1]) ? 1 : 2;
 -                              const float dp1_a1 = shi->v1->co[a1] - shi->v3->co[a1];
 -                              const float dp1_a2 = shi->v1->co[a2] - shi->v3->co[a2];
 -                              const float dp2_a1 = shi->v2->co[a1] - shi->v3->co[a1];
 -                              const float dp2_a2 = shi->v2->co[a2] - shi->v3->co[a2];
 -                              const float du1 = uv1[0] - uv3[0], du2 = uv2[0] - uv3[0];
 -                              const float dv1 = uv1[1] - uv3[1], dv2 = uv2[1] - uv3[1];
 -                              const float dpdu_a1 = dv2*dp1_a1 - dv1*dp2_a1;
 -                              const float dpdu_a2 = dv2*dp1_a2 - dv1*dp2_a2;
 -                              const float dpdv_a1 = du1*dp2_a1 - du2*dp1_a1;
 -                              const float dpdv_a2 = du1*dp2_a2 - du2*dp1_a2;
 -                              float d = dpdu_a1*dpdv_a2 - dpdv_a1*dpdu_a2;
 -                              float uvd = du1*dv2 - dv1*du2;
 -
 -                              if (uvd == 0.f) uvd = 1e-5f;
 -                              if (d == 0.f) d = 1e-5f;
 -                              d = uvd / d;
 -
 -                              compat_bump->dudnu = (dpdv_a2*compat_bump->nu[a1] - dpdv_a1*compat_bump->nu[a2])*d;
 -                              compat_bump->dvdnu = (dpdu_a1*compat_bump->nu[a2] - dpdu_a2*compat_bump->nu[a1])*d;
 -                              compat_bump->dudnv = (dpdv_a2*compat_bump->nv[a1] - dpdv_a1*compat_bump->nv[a2])*d;
 -                              compat_bump->dvdnv = (dpdu_a1*compat_bump->nv[a2] - dpdu_a2*compat_bump->nv[a1])*d;
 -                      }
 -              }
 -      }
 -}
 -
 -static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres,
 -                                   float Tnor, const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3],
 -                                   struct ImagePool *pool, const bool skip_load_image)
 -{
 -      TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL};  /* temp TexResult */
 -      float tco[3], texv[3], cd, ud, vd, du, dv, idu, idv;
 -      const int fromrgb = ((tex->type == TEX_IMAGE) || ((tex->flag & TEX_COLORBAND)!=0));
 -      const float bf = -0.04f*Tnor*mtex->norfac;
 -      int rgbnor;
 -      /* disable internal bump eval */
 -      float *nvec = texres->nor;
 -      texres->nor = NULL;
 -      /* du & dv estimates, constant value defaults */
 -      du = dv = 0.01f;
 -
 -      /* compute ortho basis around normal */
 -      if (!compat_bump->nunvdone) {
 -              /* render normal is negated */
 -              negate_v3_v3(compat_bump->nn, shi->vn);
 -              ortho_basis_v3v3_v3(compat_bump->nu, compat_bump->nv, compat_bump->nn);
 -              compat_bump->nunvdone = true;
 -      }
 -
 -      /* two methods, either constant based on main image resolution,
 -       * (which also works without osa, though of course not always good (or even very bad) results),
 -       * or based on tex derivative max values (osa only). Not sure which is best... */
 -
 -      if (!shi->osatex && (tex->type == TEX_IMAGE) && tex->ima) {
 -              /* in case we have no proper derivatives, fall back to
 -               * computing du/dv it based on image size */
 -              ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
 -              if (ibuf) {
 -                      du = 1.f/(float)ibuf->x;
 -                      dv = 1.f/(float)ibuf->y;
 -              }
 -              BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
 -      }
 -      else if (shi->osatex) {
 -              /* we have derivatives, can compute proper du/dv */
 -              if (tex->type == TEX_IMAGE) {   /* 2d image, use u & v max. of dx/dy 2d vecs */
 -                      const float adx[2] = {fabsf(dx[0]), fabsf(dx[1])};
 -                      const float ady[2] = {fabsf(dy[0]), fabsf(dy[1])};
 -                      du = MAX2(adx[0], ady[0]);
 -                      dv = MAX2(adx[1], ady[1]);
 -              }
 -              else {  /* 3d procedural, estimate from all dx/dy elems */
 -                      const float adx[3] = {fabsf(dx[0]), fabsf(dx[1]), fabsf(dx[2])};
 -                      const float ady[3] = {fabsf(dy[0]), fabsf(dy[1]), fabsf(dy[2])};
 -                      du = max_fff(adx[0], adx[1], adx[2]);
 -                      dv = max_fff(ady[0], ady[1], ady[2]);
 -              }
 -      }
 -
 -      /* center, main return value */
 -      texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
 -      rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool, skip_load_image);
 -      cd = fromrgb ? (texres->tr + texres->tg + texres->tb) / 3.0f : texres->tin;
 -
 -      if (mtex->texco == TEXCO_UV) {
 -              /* for the uv case, use the same value for both du/dv,
 -               * since individually scaling the normal derivatives makes them useless... */
 -              du = min_ff(du, dv);
 -              idu = (du < 1e-5f) ? bf : (bf/du);
 -
 -              /* +u val */
 -              tco[0] = co[0] + compat_bump->dudnu*du;
 -              tco[1] = co[1] + compat_bump->dvdnu*du;
 -              tco[2] = 0.f;
 -              texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
 -              multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
 -              ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
 -
 -              /* +v val */
 -              tco[0] = co[0] + compat_bump->dudnv*du;
 -              tco[1] = co[1] + compat_bump->dvdnv*du;
 -              tco[2] = 0.f;
 -              texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
 -              multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
 -              vd = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
 -      }
 -      else {
 -              float tu[3], tv[3];
 -
 -              copy_v3_v3(tu, compat_bump->nu);
 -              copy_v3_v3(tv, compat_bump->nv);
 -
 -              idu = (du < 1e-5f) ? bf : (bf/du);
 -              idv = (dv < 1e-5f) ? bf : (bf/dv);
 -
 -              if ((mtex->texco == TEXCO_ORCO) && shi->obr && shi->obr->ob) {
 -                      mul_mat3_m4_v3(shi->obr->ob->imat_ren, tu);
 -                      mul_mat3_m4_v3(shi->obr->ob->imat_ren, tv);
 -                      normalize_v3(tu);
 -                      normalize_v3(tv);
 -              }
 -              else if (mtex->texco == TEXCO_GLOB) {
 -                      mul_mat3_m4_v3(R.viewinv, tu);
 -                      mul_mat3_m4_v3(R.viewinv, tv);
 -              }
 -              else if (mtex->texco == TEXCO_OBJECT && mtex->object) {
 -                      mul_mat3_m4_v3(mtex->object->imat_ren, tu);
 -                      mul_mat3_m4_v3(mtex->object->imat_ren, tv);
 -                      normalize_v3(tu);
 -                      normalize_v3(tv);
 -              }
 -
 -              /* +u val */
 -              tco[0] = co[0] + tu[0]*du;
 -              tco[1] = co[1] + tu[1]*du;
 -              tco[2] = co[2] + tu[2]*du;
 -              texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
 -              multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
 -              ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
 -
 -              /* +v val */
 -              tco[0] = co[0] + tv[0]*dv;
 -              tco[1] = co[1] + tv[1]*dv;
 -              tco[2] = co[2] + tv[2]*dv;
 -              texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
 -              multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
 -              vd = idv*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
 -      }
 -
 -      /* bumped normal */
 -      compat_bump->nu[0] += ud*compat_bump->nn[0];
 -      compat_bump->nu[1] += ud*compat_bump->nn[1];
 -      compat_bump->nu[2] += ud*compat_bump->nn[2];
 -      compat_bump->nv[0] += vd*compat_bump->nn[0];
 -      compat_bump->nv[1] += vd*compat_bump->nn[1];
 -      compat_bump->nv[2] += vd*compat_bump->nn[2];
 -      cross_v3_v3v3(nvec, compat_bump->nu, compat_bump->nv);
 -
 -      nvec[0] = -nvec[0];
 -      nvec[1] = -nvec[1];
 -      nvec[2] = -nvec[2];
 -      texres->nor = nvec;
 -
 -      rgbnor |= TEX_NOR;
 -      return rgbnor;
 -}
 -
 -/* Improved bump code from later in 2.5 development cycle */
 -
 -typedef struct NTapBump {
 -      int init_done;
 -      int iPrevBumpSpace;     /* 0: uninitialized, 1: objectspace, 2: texturespace, 4: viewspace */
 -      /* bumpmapping */
 -      float vNorg[3]; /* backup copy of shi->vn */
 -      float vNacc[3]; /* original surface normal minus the surface gradient of every bump map which is encountered */
 -      float vR1[3], vR2[3]; /* cross products (sigma_y, original_normal), (original_normal, sigma_x) */
 -      float sgn_det; /* sign of the determinant of the matrix {sigma_x, sigma_y, original_normal} */
 -      float fPrevMagnitude; /* copy of previous magnitude, used for multiple bumps in different spaces */
 -} NTapBump;
 -
 -static void ntap_bump_init(NTapBump *ntap_bump)
 -{
 -      memset(ntap_bump, 0, sizeof(*ntap_bump));
 -}
 +/* ------------------------------------------------------------------------- */
  
 -static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres,
 -                             float Tnor, const float co[3], const float dx[3], const float dy[3],
 -                             float texvec[3], float dxt[3], float dyt[3], struct ImagePool *pool,
 -                             const bool skip_load_image)
 +int externtex(const MTex *mtex,
 +              const float vec[3],
 +              float *tin, float *tr, float *tg, float *tb, float *ta,
 +              const int thread,
 +              struct ImagePool *pool,
 +              const bool skip_load_image,
 +              const bool texnode_preview)
  {
 -      TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL};        /* temp TexResult */
 -
 -      const int fromrgb = ((tex->type == TEX_IMAGE) || ((tex->flag & TEX_COLORBAND)!=0));
 -
 -      /* The negate on Hscale is done because the
 -       * normal in the renderer points inward which corresponds
 -       * to inverting the bump map. The normals are generated
 -       * this way in calc_vertexnormals(). Should this ever change
 -       * this negate must be removed. */
 -      float Hscale = -Tnor*mtex->norfac;
 -
 -      int dimx=512, dimy=512;
 -      const int imag_tspace_dimension_x = 1024;  /* only used for texture space variant */
 -      float aspect = 1.0f;
 -
 -      /* 2 channels for 2D texture and 3 for 3D textures. */
 -      const int nr_channels = (mtex->texco == TEXCO_UV)? 2 : 3;
 -      int c, rgbnor, iBumpSpace;
 -      float dHdx, dHdy;
 -      int found_deriv_map = (tex->type==TEX_IMAGE) && (tex->imaflag & TEX_DERIVATIVEMAP);
 -
 -      /* disable internal bump eval in sampler, save pointer */
 -      float *nvec = texres->nor;
 -      texres->nor = NULL;
 -
 -      if (found_deriv_map==0) {
 -              if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) {
 -                      if (tex->ima)
 -                              Hscale *= 13.0f; /* appears to be a sensible default value */
 -              }
 -              else
 -                      Hscale *= 0.1f; /* factor 0.1 proved to look like the previous bump code */
 -      }
 -
 -      if ( !ntap_bump->init_done ) {
 -              copy_v3_v3(ntap_bump->vNacc, shi->vn);
 -              copy_v3_v3(ntap_bump->vNorg, shi->vn);
 -              ntap_bump->fPrevMagnitude = 1.0f;
 -              ntap_bump->iPrevBumpSpace = 0;
 -
 -              ntap_bump->init_done = true;
 -      }
 -
 -      /* resolve image dimensions */
 -      if (found_deriv_map || (mtex->texflag&MTEX_BUMP_TEXTURESPACE)!=0) {
 -              ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
 -              if (ibuf) {
 -                      dimx = ibuf->x;
 -                      dimy = ibuf->y;
 -                      aspect = ((float) dimy) / dimx;
 -              }
 -              BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
 -      }
 +      Tex *tex;
 +      TexResult texr;
 +      float dxt[3], dyt[3], texvec[3];
 +      int rgb;
  
 -      if (found_deriv_map) {
 -              float dBdu, dBdv, auto_bump = 1.0f;
 -              float s = 1;            /* negate this if flipped texture coordinate */
 -              texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
 -              rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool, skip_load_image);
 +      tex= mtex->tex;
 +      if (tex==NULL) return 0;
 +      texr.nor= NULL;
  
 -              if (shi->obr->ob->derivedFinal) {
 -                      auto_bump = shi->obr->ob->derivedFinal->auto_bump_scale;
 -              }
 +      /* placement */
 +      if (mtex->projx) texvec[0]= mtex->size[0]*(vec[mtex->projx-1]+mtex->ofs[0]);
 +      else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
  
 -              {
 -                      float fVirtDim = sqrtf(fabsf((float) (dimx*dimy)*mtex->size[0]*mtex->size[1]));
 -                      auto_bump /= MAX2(fVirtDim, FLT_EPSILON);
 -              }
 +      if (mtex->projy) texvec[1]= mtex->size[1]*(vec[mtex->projy-1]+mtex->ofs[1]);
 +      else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
  
 -              /* this variant using a derivative map is described here
 -               * http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html */
 -              dBdu = auto_bump*Hscale*dimx*(2*texres->tr-1);
 -              dBdv = auto_bump*Hscale*dimy*(2*texres->tg-1);
 +      if (mtex->projz) texvec[2]= mtex->size[2]*(vec[mtex->projz-1]+mtex->ofs[2]);
 +      else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
  
 -              dHdx = dBdu*dxt[0] + s * dBdv*dxt[1];
 -              dHdy = dBdu*dyt[0] + s * dBdv*dyt[1];
 +      /* texture */
 +      if (tex->type==TEX_IMAGE) {
 +              do_2d_mapping(mtex, texvec, NULL, dxt, dyt);
        }
 -      else if (!(mtex->texflag & MTEX_5TAP_BUMP)) {
 -              /* compute height derivatives with respect to output image pixel coordinates x and y */
 -              float STll[3], STlr[3], STul[3];
 -              float Hll, Hlr, Hul;
 -
 -              texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
 -
 -              for (c=0; c<nr_channels; c++) {
 -                      /* dx contains the derivatives (du/dx, dv/dx)
 -                       * dy contains the derivatives (du/dy, dv/dy) */
 -                      STll[c] = texvec[c];
 -                      STlr[c] = texvec[c]+dxt[c];
 -                      STul[c] = texvec[c]+dyt[c];
 -              }
 -
 -              /* clear unused derivatives */
 -              for (c=nr_channels; c<3; c++) {
 -                      STll[c] = 0.0f;
 -                      STlr[c] = 0.0f;
 -                      STul[c] = 0.0f;
 -              }
  
 -              /* use texres for the center sample, set rgbnor */
 -              rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres, pool, skip_load_image);
 -              Hll = (fromrgb) ? IMB_colormanagement_get_luminance(&texres->tr) : texres->tin;
 -
 -              /* use ttexr for the other 2 taps */
 -              multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr, pool, skip_load_image);
 -              Hlr = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
 -
 -              multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr, pool, skip_load_image);
 -              Hul = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
 +      rgb = multitex(tex,
 +                     texvec,
 +                     dxt, dyt,
 +                     0, &texr,
 +                     thread,
 +                     mtex->which_output,
 +                     pool,
 +                     skip_load_image,
 +                     texnode_preview,
 +                     true);
  
 -              dHdx = Hscale*(Hlr - Hll);
 -              dHdy = Hscale*(Hul - Hll);
 +      if (rgb) {
 +              texr.tin = IMB_colormanagement_get_luminance(&texr.tr);
        }
        else {
 -              /* same as above, but doing 5 taps, increasing quality at cost of speed */
 -              float STc[3], STl[3], STr[3], STd[3], STu[3];
 -              float /* Hc, */ /* UNUSED */  Hl, Hr, Hd, Hu;
 -
 -              texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
 -
 -              for (c=0; c<nr_channels; c++) {
 -                      STc[c] = texvec[c];
 -                      STl[c] = texvec[c] - 0.5f*dxt[c];
 -                      STr[c] = texvec[c] + 0.5f*dxt[c];
 -                      STd[c] = texvec[c] - 0.5f*dyt[c];
 -                      STu[c] = texvec[c] + 0.5f*dyt[c];
 -              }
 -
 -              /* clear unused derivatives */
 -              for (c=nr_channels; c<3; c++) {
 -                      STc[c] = 0.0f;
 -                      STl[c] = 0.0f;
 -                      STr[c] = 0.0f;
 -                      STd[c] = 0.0f;
 -                      STu[c] = 0.0f;
 -              }
 -
 -              /* use texres for the center sample, set rgbnor */
 -              rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres, pool, skip_load_image);
 -              /* Hc = (fromrgb) ? IMB_colormanagement_get_luminance(&texres->tr) : texres->tin; */ /* UNUSED */
 -
 -              /* use ttexr for the other taps */
 -              multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr, pool, skip_load_image);
 -              Hl = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
 -              multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr, pool, skip_load_image);
 -              Hr = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
 -              multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr, pool, skip_load_image);
 -              Hd = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
 -              multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr, pool, skip_load_image);
 -              Hu = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
 -
 -              dHdx = Hscale*(Hr - Hl);
 -              dHdy = Hscale*(Hu - Hd);
 -      }
 -
 -      /* restore pointer */
 -      texres->nor = nvec;
 -
 -      /* replaced newbump with code based on listing 1 and 2 of
 -       * [Mik10] Mikkelsen M. S.: Bump Mapping Unparameterized Surfaces on the GPU.
 -       * -> http://jbit.net/~sparky/sfgrad_bump/mm_sfgrad_bump.pdf */
 -
 -      if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE )
 -              iBumpSpace = 1;
 -      else if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
 -              iBumpSpace = 2;
 -      else
 -              iBumpSpace = 4; /* ViewSpace */
 -
 -      if ( ntap_bump->iPrevBumpSpace != iBumpSpace ) {
 -
 -              /* initialize normal perturbation vectors */
 -              int xyz;
 -              float fDet, abs_fDet, fMagnitude;
 -              /* object2view and inverted matrix */
 -              float obj2view[3][3], view2obj[3][3], tmp[4][4];
 -              /* local copies of derivatives and normal */
 -              float dPdx[3], dPdy[3], vN[3];
 -              copy_v3_v3(dPdx, shi->dxco);
 -              copy_v3_v3(dPdy, shi->dyco);
 -              copy_v3_v3(vN, ntap_bump->vNorg);
 -
 -              if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) {
 -                      /* TODO: these calculations happen for every pixel!
 -                       *      -> move to shi->obi */
 -                      mul_m4_m4m4(tmp, R.viewmat, shi->obr->ob->obmat);
 -                      copy_m3_m4(obj2view, tmp); /* use only upper left 3x3 matrix */
 -                      invert_m3_m3(view2obj, obj2view);
 -
 -                      /* generate the surface derivatives in object space */
 -                      mul_m3_v3(view2obj, dPdx);
 -                      mul_m3_v3(view2obj, dPdy);
 -                      /* generate the unit normal in object space */
 -                      mul_transposed_m3_v3(obj2view, vN);
 -                      normalize_v3(vN);
 -              }
 -
 -              cross_v3_v3v3(ntap_bump->vR1, dPdy, vN);
 -              cross_v3_v3v3(ntap_bump->vR2, vN, dPdx);
 -              fDet = dot_v3v3(dPdx, ntap_bump->vR1);
 -              ntap_bump->sgn_det = (fDet < 0)? -1.0f: 1.0f;
 -              abs_fDet = ntap_bump->sgn_det * fDet;
 -
 -              if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) {
 -                      if (tex->ima) {
 -                              /* crazy hack solution that gives results similar to normal mapping - part 1 */
 -                              normalize_v3(ntap_bump->vR1);
 -                              normalize_v3(ntap_bump->vR2);
 -                              abs_fDet = 1.0f;
 -                      }
 -              }
 -
 -              fMagnitude = abs_fDet;
 -              if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) {
 -                      /* pre do transform of texres->nor by the inverse transposed of obj2view */
 -                      mul_transposed_m3_v3(view2obj, vN);
 -                      mul_transposed_m3_v3(view2obj, ntap_bump->vR1);
 -                      mul_transposed_m3_v3(view2obj, ntap_bump->vR2);
 -
 -                      fMagnitude *= len_v3(vN);
 -              }
 -
 -              if (ntap_bump->fPrevMagnitude > 0.0f)
 -                      for (xyz=0; xyz<3; xyz++)
 -                              ntap_bump->vNacc[xyz] *= fMagnitude / ntap_bump->fPrevMagnitude;
 -
 -              ntap_bump->fPrevMagnitude = fMagnitude;
 -              ntap_bump->iPrevBumpSpace = iBumpSpace;
 -      }
 -
 -      if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) {
 -              if (tex->ima) {
 -                      /* crazy hack solution that gives results similar to normal mapping - part 2 */
 -                      float vec[2];
 -                      const float imag_tspace_dimension_y = aspect*imag_tspace_dimension_x;
 -
 -                      vec[0] = imag_tspace_dimension_x*dxt[0];
 -                      vec[1] = imag_tspace_dimension_y*dxt[1];
 -                      dHdx *= 1.0f/len_v2(vec);
 -                      vec[0] = imag_tspace_dimension_x*dyt[0];
 -                      vec[1] = imag_tspace_dimension_y*dyt[1];
 -                      dHdy *= 1.0f/len_v2(vec);
 -              }
 +              texr.tr= mtex->r;
 +              texr.tg= mtex->g;
 +              texr.tb= mtex->b;
        }
  
 -      /* subtract the surface gradient from vNacc */
 -      for (c=0; c<3; c++) {
 -              float vSurfGrad_compi = ntap_bump->sgn_det * (dHdx * ntap_bump->vR1[c] + dHdy * ntap_bump->vR2[c]);
 -              ntap_bump->vNacc[c] -= vSurfGrad_compi;
 -              texres->nor[c] = ntap_bump->vNacc[c]; /* copy */
 -      }
 +      *tin= texr.tin;
 +      *tr= texr.tr;
 +      *tg= texr.tg;
 +      *tb= texr.tb;
 +      *ta= texr.ta;
  
 -      rgbnor |= TEX_NOR;
 -      return rgbnor;
 +      return (rgb != 0);
  }
 -
 -void do_material_tex(ShadeInput *shi, Render *re)
 -{
 -      const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0;
 -      CompatibleBump compat_bump;
 -      NTapBump ntap_bump;
 -      MTex *mtex;
 -      Tex *tex;
 -      TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
 -      float *co = NULL, *dx = NULL, *dy = NULL;
 -      float fact, facm, factt, facmm, stencilTin=1.0;
 -      float texvec[3], dxt[3], dyt[3], tempvec[3], norvec[3], warpvec[3]={0.0f, 0.0f, 0.0f}, Tnor=1.0;
 -      int tex_nr, rgbnor= 0;
 -      bool warp_done = false, use_compat_bump = false, use_ntap_bump = false;
 -      bool found_nmapping = false, found_deriv_map = false;
 -      bool iFirstTimeNMap = true;
 -
 -      compatible_bump_init(&compat_bump);
 -      ntap_bump_init(&ntap_bump);
 -
 -      if (re->r.scemode & R_NO_TEX) return;
 -      /* here: test flag if there's a tex (todo) */
 -
 -      for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
 -
 -              /* separate tex switching */
 -              if (shi->mat->septex & (1<<tex_nr)) continue;
 -
 -              if (shi->mat->mtex[tex_nr]) {
 -                      mtex= shi->mat->mtex[tex_nr];
 -
 -                      tex= mtex->tex;
 -                      if (tex == NULL) continue;
 -
 -                      found_deriv_map = (tex->type==TEX_IMAGE) && (tex->imaflag & TEX_DERIVATIVEMAP);
 -                      use_compat_bump= (mtex->texflag & MTEX_COMPAT_BUMP) != 0;
 -                      use_ntap_bump = ((mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP|MTEX_BICUBIC_BUMP))!=0 || found_deriv_map!=0) ? true : false;
 -
 -                      /* XXX texture node trees don't work for this yet */
 -                      if (tex->nodetree && tex->use_nodes) {
 -                              use_compat_bump = false;
 -                              use_ntap_bump = false;
 -                      }
 -
 -                      /* case displacement mapping */
 -                      if (shi->osatex == 0 && use_ntap_bump) {
 -                              use_ntap_bump = false;
 -                              use_compat_bump = true;
 -                      }
 -
 -                      /* case ocean */
 -                      if (tex->type == TEX_OCEAN) {
 -                              use_ntap_bump = false;
 -                              use_compat_bump = false;
 -                      }
 -
 -                      /* which coords */
 -                      if (mtex->texco==TEXCO_ORCO) {
 -                              if (mtex->texflag & MTEX_DUPLI_MAPTO) {
 -                                      co= shi->duplilo; dx= dxt; dy= dyt;
 -                                      dxt[0]= dxt[1]= dxt[2]= 0.0f;
 -                                      dyt[0]= dyt[1]= dyt[2]= 0.0f;
 -                              }
 -                              else {
 -                                      co= shi->lo; dx= shi->dxlo; dy= shi->dylo;
 -                              }
 -                      }
 -                      else if (mtex->texco==TEXCO_OBJECT) {
 -                              Object *ob= mtex->object;
 -                              if (ob) {
 -                                      co= tempvec;
 -                                      dx= dxt;
 -                                      dy= dyt;
 -                                      copy_v3_v3(tempvec, shi->co);
 -                                      if (mtex->texflag & MTEX_OB_DUPLI_ORIG)
 -                                              if (shi->obi && shi->obi->duplitexmat)
 -                                                      mul_m4_v3(shi->obi->duplitexmat, tempvec);
 -                                      mul_m4_v3(ob->imat_ren, tempvec);
 -                                      if (shi->osatex) {
 -                                              copy_v3_v3(dxt, shi->dxco);
 -                                              copy_v3_v3(dyt, shi->dyco);
 -                                              mul_mat3_m4_v3(ob->imat_ren, dxt);
 -                                              mul_mat3_m4_v3(ob->imat_ren, dyt);
 -                                      }
 -                              }
 -                              else {
 -                                      /* if object doesn't exist, do not use orcos (not initialized) */
 -                                      co= shi->co;
 -                                      dx= shi->dxco; dy= shi->dyco;
 -                              }
 -                      }
 -                      else if (mtex->texco==TEXCO_REFL) {
 -                              calc_R_ref(shi);
 -                              co= shi->ref; dx= shi->dxref; dy= shi->dyref;
 -                      }
 -                      else if (mtex->texco==TEXCO_NORM) {
 -                              co= shi->orn; dx= shi->dxno; dy= shi->dyno;
 -                      }
 -                      else if (mtex->texco==TEXCO_TANGENT) {
 -                              co= shi->tang; dx= shi->dxno; dy= shi->dyno;
 -                      }
 -                      else if (mtex->texco==TEXCO_GLOB) {
 -                              co= shi->gl; dx= shi->dxgl; dy= shi->dygl;
 -                      }
 -                      else if (mtex->texco==TEXCO_UV) {
 -                              if (mtex->texflag & MTEX_DUPLI_MAPTO) {
 -                                      co= shi->dupliuv; dx= dxt; dy= dyt;
 -                                      dxt[0]= dxt[1]= dxt[2]= 0.0f;
 -                                      dyt[0]= dyt[1]= dyt[2]= 0.0f;
 -                              }
 -                              else {
 -                                      ShadeInputUV *suv= &shi->uv[shi->actuv];
 -                                      int i = shi->actuv;
 -
 -                                      if (mtex->uvname[0] != 0) {
 -                                              for (i = 0; i < shi->totuv; i++) {
 -                                                      if (STREQ(shi->uv[i].name, mtex->uvname)) {
 -                                                              suv= &shi->uv[i];
 -                                                              break;
 -                                                      }
 -                                              }
 -                                      }
 -
 -                                      co= suv->uv;
 -                                      dx= suv->dxuv;
 -                                      dy= suv->dyuv;
 -
 -                                      compatible_bump_uv_derivs(&compat_bump, shi, mtex, i);
 -                              }
 -                      }
 -                      else if (mtex->texco==TEXCO_WINDOW) {
 -                              co= shi->winco; dx= shi->dxwin; dy= shi->dywin;
 -                      }
 -                      else if (mtex->texco==TEXCO_STRAND) {
 -                              co= tempvec; dx= dxt; dy= dyt;
 -                              co[0]= shi->strandco;
 -                              co[1]= co[2]= 0.0f;
 -                              dx[0]= shi->dxstrand;
 -                              dx[1]= dx[2]= 0.0f;
 -                              dy[0]= shi->dystrand;
 -                              dy[1]= dy[2]= 0.0f;
 -                      }
 -                      else if (mtex->texco==TEXCO_STRESS) {
 -                              co= tempvec; dx= dxt; dy= dyt;
 -                              co[0]= shi->stress;
 -                              co[1]= co[2]= 0.0f;
 -                              dx[0]= 0.0f;
 -                              dx[1]= dx[2]= 0.0f;
 -                              dy[0]= 0.0f;
 -                              dy[1]= dy[2]= 0.0f;
 -                      }
 -                      else {
 -                              continue;  /* can happen when texco defines disappear and it renders old files */
 -                      }
 -
 -                      /* the pointer defines if bumping happens */
 -                      if (mtex->mapto & (MAP_NORM|MAP_WARP)) {
 -                              texres.nor= norvec;
 -                              norvec[0]= norvec[1]= norvec[2]= 0.0;
 -                      }
 -                      else texres.nor= NULL;
 -
 -                      if (warp_done) {
 -                              add_v3_v3v3(tempvec, co, warpvec);
 -                              co= tempvec;
 -                      }
 -
 -                      /* XXX texture node trees don't work for this yet */
 -                      if (texres.nor && !((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP))) {
 -                              if (use_compat_bump) {
 -                                      rgbnor = compatible_bump_compute(&compat_bump, shi, mtex, tex,
 -                                                                       &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
 -                                                                       re->pool, skip_load_image);
 -                              }
 -                              else if (use_ntap_bump) {
 -                                      rgbnor = ntap_bump_compute(&ntap_bump, shi, mtex, tex,
 -                                                                 &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
 -                                                                 re->pool, skip_load_image);
 -                              }
 -                              else {
 -                                      texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
 -                                      rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool, skip_load_image);
 -                              }
 -                      }
 -                      else {
 -                              texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
 -                              rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool, skip_load_image);
 -                      }
 -
 -                      /* texture output */
 -
 -                      if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
 -                              texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
 -                              rgbnor -= TEX_RGB;
 -                      }
 -                      if (mtex->texflag & MTEX_NEGATIVE) {
 -                              if (rgbnor & TEX_RGB) {
 -                                      texres.tr= 1.0f-texres.tr;
 -                                      texres.tg= 1.0f-texres.tg;
 -                                      texres.tb= 1.0f-texres.tb;
 -                              }
 -                              texres.tin= 1.0f-texres.tin;
 -                      }
 -                      if (mtex->texflag & MTEX_STENCIL) {
 -                              if (rgbnor & TEX_RGB) {
 -                                      fact= texres.ta;
 -                                      texres.ta*= stencilTin;
 -                                      stencilTin*= fact;
 -                              }
 -                              else {
 -                                      fact= texres.tin;
 -                                      texres.tin*= stencilTin;
 -                                      stencilTin*= fact;
 -                              }
 -                      }
 -                      else {
 -                              Tnor*= stencilTin;
 -                      }
 -
 -                      if (texres.nor) {
 -                              if ((rgbnor & TEX_NOR)==0) {
 -                                      /* make our own normal */
 -                                      if (rgbnor & TEX_RGB) {
 -                                              copy_v3_v3(texres.nor, &texres.tr);
 -                                      }
 -                                      else {
 -                                              float co_nor= 0.5f * cosf(texres.tin - 0.5f);
 -                                              float si = 0.5f * sinf(texres.tin - 0.5f);
 -                                              float f1, f2;
 -
 -                                              f1= shi->vn[0];
 -                                              f2= shi->vn[1];
 -                                              texres.nor[0]= f1*co_nor+f2*si;
 -                                              f1= shi->vn[1];
 -                                              f2= shi->vn[2];
 -                                              texres.nor[1]= f1*co_nor+f2*si;
 -                                              texres.nor[2]= f2*co_nor-f1*si;
 -                                      }
 -                              }
 -                              /* warping, local space */
 -                              if (mtex->mapto & MAP_WARP) {
 -                                      float *warpnor= texres.nor, warpnor_[3];
 -
 -                                      if (use_ntap_bump) {
 -                                              copy_v3_v3(warpnor_, texres.nor);
 -                                              warpnor= warpnor_;
 -                                              normalize_v3(warpnor_);
 -                                      }
 -                                      warpvec[0]= mtex->warpfac*warpnor[0];
 -                                      warpvec[1]= mtex->warpfac*warpnor[1];
 -                                      warpvec[2]= mtex->warpfac*warpnor[2];
 -                                      warp_done = true;
 -                              }
 -#if 0
 -                              if (mtex->texflag & MTEX_VIEWSPACE) {
 -                                      /* rotate to global coords */
 -                                      if (mtex->texco==TEXCO_ORCO || mtex->texco==TEXCO_UV) {
 -                                              if (shi->vlr && shi->obr && shi->obr->ob) {
 -                                                      float len= normalize_v3(texres.nor);
 -                                                      /* can be optimized... (ton) */
 -                                                      mul_mat3_m4_v3(shi->obr->ob->obmat, texres.nor);
 -                                                      mul_mat3_m4_v3(re->viewmat, texres.nor);
 -                                                      normalize_v3_length(texres.nor, len);
 -                                              }
 -                                      }
 -                              }
 -#endif
 -                      }
 -
 -                      /* mapping */
 -                      if (mtex->mapto & (MAP_COL | MAP_COLSPEC | MAP_COLMIR)) {
 -                              float tcol[3];
 -
 -                              /* stencil maps on the texture control slider, not texture intensity value */
 -                              copy_v3_v3(tcol, &texres.tr);
 -
 -                              if ((rgbnor & TEX_RGB) == 0) {
 -                                      copy_v3_v3(tcol, &mtex->r);
 -                              }
 -                              else if (mtex->mapto & MAP_ALPHA) {
 -                                      texres.tin = stencilTin;
 -                              }
 -                              else {
 -                                      texres.tin = texres.ta;
 -                              }
 -
 -                              /* inverse gamma correction */
 -                              if (tex->type==TEX_IMAGE) {
 -                                      Image *ima = tex->ima;
 -                                      ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, re->pool);
 -
 -                                      /* don't linearize float buffers, assumed to be linear */
 -                                      if (ibuf != NULL &&
 -                                          ibuf->rect_float == NULL &&
 -                                          (rgbnor & TEX_RGB) &&
 -                                          R.scene_color_manage)
 -                                      {
 -                                              IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace);
 -                                      }
 -
 -                                      BKE_image_pool_release_ibuf(ima, ibuf, re->pool);
 -                              }
 -
 -                              if (mtex->mapto & MAP_COL) {
 -                                      float colfac= mtex->colfac*stencilTin;
 -                                      texture_rgb_blend(&shi->r, tcol, &shi->r, texres.tin, colfac, mtex->blendtype);
 -                              }
 -                              if (mtex->mapto & MAP_COLSPEC) {
 -                                      float colspecfac= mtex->colspecfac*stencilTin;
 -                                      texture_rgb_blend(&shi->specr, tcol, &shi->specr, texres.tin, colspecfac, mtex->blendtype);
 -                              }
 -                              if (mtex->mapto & MAP_COLMIR) {
 -                                      float mirrfac= mtex->mirrfac*stencilTin;
 -
 -                                      /* exception for envmap only */
 -                                      if (tex->type==TEX_ENVMAP && mtex->blendtype==MTEX_BLEND) {
 -                                              fact= texres.tin*mirrfac;
 -                                              facm= 1.0f- fact;
 -                                              shi->refcol[0]= fact + facm*shi->refcol[0];
 -                                              shi->refcol[1]= fact*tcol[0] + facm*shi->refcol[1];
 -                                              shi->refcol[2]= fact*tcol[1] + facm*shi->refcol[2];
 -                                              shi->refcol[3]= fact*tcol[2] + facm*shi->refcol[3];
 -                                      }
 -                                      else {
 -                                              texture_rgb_blend(&shi->mirr, tcol, &shi->mirr, texres.tin, mirrfac, mtex->blendtype);
 -                                      }
 -                              }
 -                      }
 -                      if ( (mtex->mapto & MAP_NORM) ) {
 -                              if (texres.nor) {
 -                                      float norfac= mtex->norfac;
 -
 -                                      /* we need to code blending modes for normals too once.. now 1 exception hardcoded */
 -
 -                                      if ((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP)) {
 -
 -                                              found_nmapping = 1;
 -
 -                                              /* qdn: for normalmaps, to invert the normalmap vector,
 -                                               * it is better to negate x & y instead of subtracting the vector as was done before */
 -                                              if (norfac < 0.0f) {
 -                                                      texres.nor[0] = -texres.nor[0];
 -                                                      texres.nor[1] = -texres.nor[1];
 -                                              }
 -                                              fact = Tnor*fabsf(norfac);
 -                                              if (fact>1.f) fact = 1.f;
 -                                              facm = 1.f-fact;
 -                                              if (mtex->normapspace == MTEX_NSPACE_TANGENT) {
 -                                                      /* qdn: tangent space */
 -                                                      float B[3], tv[3];
 -                                                      const float *no = iFirstTimeNMap ? shi->nmapnorm : shi->vn;
 -                                                      iFirstTimeNMap = false;
 -                                                      cross_v3_v3v3(B, no, shi->nmaptang);    /* bitangent */
 -                                                      mul_v3_fl(B, shi->nmaptang[3]);
 -                                                      /* transform norvec from tangent space to object surface in camera space */
 -                                                      tv[0] = texres.nor[0]*shi->nmaptang[0] + texres.nor[1]*B[0] + texres.nor[2]*no[0];
 -                                                      tv[1] = texres.nor[0]*shi->nmaptang[1] + texres.nor[1]*B[1] + texres.nor[2]*no[1];
 -                                                      tv[2] = texres.nor[0]*shi->nmaptang[2] + texres.nor[1]*B[2] + texres.nor[2]*no[2];
 -                                                      shi->vn[0]= facm*no[0] + fact*tv[0];
 -                                                      shi->vn[1]= facm*no[1] + fact*tv[1];
 -                                                      shi->vn[2]= facm*no[2] + fact*tv[2];
 -                                              }
 -                                              else {
 -                                                      float nor[3];
 -
 -                                                      copy_v3_v3(nor, texres.nor);
 -
 -                                                      if (mtex->normapspace == MTEX_NSPACE_CAMERA) {
 -                                                              /* pass */
 -                                                      }
 -                                                      else if (mtex->normapspace == MTEX_NSPACE_WORLD) {
 -                                                              mul_mat3_m4_v3(re->viewmat, nor);
 -                                                      }
 -                                                      else if (mtex->normapspace == MTEX_NSPACE_OBJECT) {
 -                                                              if (shi->obr && shi->obr->ob)
 -                                                                      mul_mat3_m4_v3(shi->obr->ob->obmat, nor);
 -                                                              mul_mat3_m4_v3(re->viewmat, nor);
 -                                                      }
 -
 -                                                      normalize_v3(nor);
 -
 -                                                      /* qdn: worldspace */
 -                                                      shi->vn[0]= facm*shi->vn[0] + fact*nor[0];
 -                                                      shi->vn[1]= facm*shi->vn[1] + fact*nor[1];
 -                                                      shi->vn[2]= facm*shi->vn[2] + fact*nor[2];
 -                                              }
 -                                      }
 -                                      else {
 -                                              /* XXX texture node trees don't work for this yet */
 -                                              if (use_compat_bump || use_ntap_bump) {
 -                                                      shi->vn[0] = texres.nor[0];
 -                                                      shi->vn[1] = texres.nor[1];
 -                                                      shi->vn[2] = texres.nor[2];
 -                                              }
 -                                              else {
 -                                                      float nor[3], dot;
 -
 -                                                      if (shi->mat->mode & MA_TANGENT_V) {
 -                                                              shi->tang[0]+= Tnor*norfac*texres.nor[0];
 -                                                              shi->tang[1]+= Tnor*norfac*texres.nor[1];
 -                                                              shi->tang[2]+= Tnor*norfac*texres.nor[2];
 -                                                      }
 -
 -                                                      /* prevent bump to become negative normal */
 -                                                      nor[0]= Tnor*norfac*texres.nor[0];
 -                                                      nor[1]= Tnor*norfac*texres.nor[1];
 -                                                      nor[2]= Tnor*norfac*texres.nor[2];
 -
 -                                                      dot= 0.5f + 0.5f * dot_v3v3(nor, shi->vn);
 -
 -                                                      shi->vn[0]+= dot*nor[0];
 -                                                      shi->vn[1]+= dot*nor[1];
 -                                                      shi->vn[2]+= dot*nor[2];
 -                                              }
 -                                      }
 -                                      normalize_v3(shi->vn);
 -
 -                                      /* this makes sure the bump is passed on to the next texture */
 -                                      shi->orn[0]= -shi->vn[0];
 -                                      shi->orn[1]= -shi->vn[1];
 -                                      shi->orn[2]= -shi->vn[2];
 -                              }
 -                      }
 -
 -                      if ( mtex->mapto & MAP_DISPLACE ) {
 -                              /* Now that most textures offer both Nor and Intensity, allow  */
 -                              /* both to work, and let user select with slider.   */
 -                              if (texres.nor) {
 -                                      float norfac= mtex->norfac;
 -
 -                                      shi->displace[0]+= 0.2f*Tnor*norfac*texres.nor[0];
 -                                      shi->displace[1]+= 0.2f*Tnor*norfac*texres.nor[1];
 -                                      shi->displace[2]+= 0.2f*Tnor*norfac*texres.nor[2];
 -                              }
 -
 -                              if (rgbnor & TEX_RGB) {
 -                                      texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
 -                              }
 -
 -                              factt= (0.5f-texres.tin)*mtex->dispfac*stencilTin; facmm= 1.0f-factt;
 -
 -                              if (mtex->blendtype==MTEX_BLEND) {
 -                                      shi->displace[0]= factt*shi->vn[0] + facmm*shi->displace[0];
 -                                      shi->displace[1]= factt*shi->vn[1] + facmm*shi->displace[1];
 -                                      shi->displace[2]= factt*shi->vn[2] + facmm*shi->displace[2];
 -                              }
 -                              else if (mtex->blendtype==MTEX_MUL) {
 -                                      shi->displace[0]*= factt*shi->vn[0];
 -                                      shi->displace[1]*= factt*shi->vn[1];
 -                                      shi->displace[2]*= factt*shi->vn[2];
 -                              }
 -                              else { /* add or sub */
 -                                      if (mtex->blendtype==MTEX_SUB) factt= -factt;
 -                                      shi->displace[0]+= factt*shi->vn[0];
 -                                      shi->displace[1]+= factt*shi->vn[1];
 -                                      shi->displace[2]+= factt*shi->vn[2];
 -                              }
 -                      }
 -
 -                      if (mtex->mapto & MAP_VARS) {
 -                              /* stencil maps on the texture control slider, not texture intensity value */
 -
 -                              if (rgbnor & TEX_RGB) {
 -                                      if (texres.talpha) texres.tin = texres.ta;
 -                                      else               texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
 -                              }
 -
 -                              if (mtex->mapto & MAP_REF) {
 -                                      float difffac= mtex->difffac*stencilTin;
 -
 -                                      shi->refl= texture_value_blend(mtex->def_var, shi->refl, texres.tin, difffac, mtex->blendtype);
 -                                      if (shi->refl<0.0f) shi->refl= 0.0f;
 -                              }
 -                              if (mtex->mapto & MAP_SPEC) {
 -                                      float specfac= mtex->specfac*stencilTin;
 -
 -                                      shi->spec= texture_value_blend(mtex->def_var, shi->spec, texres.tin, specfac, mtex->blendtype);
 -                                      if (shi->spec<0.0f) shi->spec= 0.0f;
 -                              }
 -                              if (mtex->mapto & MAP_EMIT) {
 -                                      float emitfac= mtex->emitfac*stencilTin;
 -
 -                                      shi->emit= texture_value_blend(mtex->def_var, shi->emit, texres.tin, emitfac, mtex->blendtype);
 -                                      if (shi->emit<0.0f) shi->emit= 0.0f;
 -                              }
 -                              if (mtex->mapto & MAP_ALPHA) {
 -                                      float alphafac= mtex->alphafac*stencilTin;
 -
 -                                      shi->alpha= texture_value_blend(mtex->def_var, shi->alpha, texres.tin, alphafac, mtex->blendtype);
 -                                      if (shi->alpha<0.0f) shi->alpha= 0.0f;
 -                                      else if (shi->alpha>1.0f) shi->alpha= 1.0f;
 -                              }
 -                              if (mtex->mapto & MAP_HAR) {
 -                                      float har;  /* have to map to 0-1 */
 -                                      float hardfac= mtex->hardfac*stencilTin;
 -
 -                                      har= ((float)shi->har)/128.0f;
 -                                      har= 128.0f*texture_value_blend(mtex->def_var, har, texres.tin, hardfac, mtex->blendtype);
 -
 -                                      if (har<1.0f) shi->har= 1;
 -                                      else if (har>511) shi->har= 511;
 -                                      else shi->har= (int)har;
 -                              }
 -                              if (mtex->mapto & MAP_RAYMIRR) {
 -                                      float raymirrfac= mtex->raymirrfac*stencilTin;
 -
 -                                      shi->ray_mirror= texture_value_blend(mtex->def_var, shi->ray_mirror, texres.tin, raymirrfac, mtex->blendtype);
 -                                      if (shi->ray_mirror<0.0f) shi->ray_mirror= 0.0f;
 -                                      else if (shi->ray_mirror>1.0f) shi->ray_mirror= 1.0f;
 -                              }
 -                              if (mtex->mapto & MAP_TRANSLU) {
 -                                      float translfac= mtex->translfac*stencilTin;
 -
 -                                      shi->translucency= texture_value_blend(mtex->def_var, shi->translucency, texres.tin, translfac, mtex->blendtype);
 -                                      if (shi->translucency<0.0f) shi->translucency= 0.0f;
 -                                      else if (shi->translucency>1.0f) shi->translucency= 1.0f;
 -                              }
 -                              if (mtex->mapto & MAP_AMB) {
 -                                      float ambfac= mtex->ambfac*stencilTin;
 -
 -                                      shi->amb= texture_value_blend(mtex->def_var, shi->amb, texres.tin, ambfac, mtex->blendtype);
 -                                      if (shi->amb<0.0f) shi->amb= 0.0f;
 -                                      else if (shi->amb>1.0f) shi->amb= 1.0f;
 -
 -                                      shi->ambr= shi->amb*re->wrld.ambr;
 -                                      shi->ambg= shi->amb*re->wrld.ambg;
 -                                      shi->ambb= shi->amb*re->wrld.ambb;
 -                              }
 -                      }
 -              }
 -      }
 -      if ((use_compat_bump || use_ntap_bump || found_nmapping) && (shi->mat->mode & MA_TANGENT_V) != 0) {
 -              const float fnegdot = -dot_v3v3(shi->vn, shi->tang);
 -              /* apply Gram-Schmidt projection */
 -              madd_v3_v3fl(shi->tang,  shi->vn, fnegdot);
 -              normalize_v3(shi->tang);
 -      }
 -}
 -
 -
 -void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_r[3], float *val, Render *re)
 -{
 -      const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
 -      const bool texnode_preview = (re->r.scemode & R_TEXNODE_PREVIEW) != 0;
 -      MTex *mtex;
 -      Tex *tex;
 -      TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
 -      int tex_nr, rgbnor= 0;
 -      float co[3], texvec[3];
 -      float fact, stencilTin=1.0;
 -
 -      if (re->r.scemode & R_NO_TEX) return;
 -      /* here: test flag if there's a tex (todo) */
 -
 -      for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
 -              /* separate tex switching */
 -              if (shi->mat->septex & (1<<tex_nr)) continue;
 -
 -              if (shi->mat->mtex[tex_nr]) {
 -                      mtex= shi->mat->mtex[tex_nr];
 -                      tex= mtex->tex;
 -                      if (tex == NULL) continue;
 -
 -                      /* only process if this texture is mapped
 -                       * to one that we're interested in */
 -                      if (!(mtex->mapto & mapto_flag)) continue;
 -
 -                      /* which coords */
 -                      if (mtex->texco==TEXCO_OBJECT) {
 -                              Object *ob= mtex->object;
 -                              if (ob) {
 -                                      copy_v3_v3(co, xyz);
 -                                      if (mtex->texflag & MTEX_OB_DUPLI_ORIG) {
 -                                              if (shi->obi && shi->obi->duplitexmat)
 -                                                      mul_m4_v3(shi->obi->duplitexmat, co);
 -                                      }
 -                                      mul_m4_v3(ob->imat_ren, co);
 -
 -                                      if (mtex->texflag & MTEX_MAPTO_BOUNDS && ob->bb) {
 -                                              /* use bb vec[0] as min and bb vec[6] as max */
 -                                              co[0] = (co[0] - ob->bb->vec[0][0]) / (ob->bb->vec[6][0]-ob->bb->vec[0][0]) * 2.0f - 1.0f;
 -                                              co[1] = (co[1] - ob->bb->vec[0][1]) / (ob->bb->vec[6][1]-ob->bb->vec[0][1]) * 2.0f - 1.0f;
 -                                              co[2] = (co[2] - ob->bb->vec[0][2]) / (ob->bb->vec[6][2]-ob->bb->vec[0][2]) * 2.0f - 1.0f;
 -                                      }
 -                              }
 -                      }
 -                      /* not really orco, but 'local' */
 -                      else if (mtex->texco==TEXCO_ORCO) {
 -
 -                              if (mtex->texflag & MTEX_DUPLI_MAPTO) {
 -                                      copy_v3_v3(co, shi->duplilo);
 -                              }
 -                              else {
 -                                      Object *ob= shi->obi->ob;
 -                                      copy_v3_v3(co, xyz);
 -                                      mul_m4_v3(ob->imat_ren, co);
 -
 -                                      if (mtex->texflag & MTEX_MAPTO_BOUNDS && ob->bb) {
 -                                              /* use bb vec[0] as min and bb vec[6] as max */
 -                                              co[0] = (co[0] - ob->bb->vec[0][0]) / (ob->bb->vec[6][0]-ob->bb->vec[0][0]) * 2.0f - 1.0f;
 -                                              co[1] = (co[1] - ob->bb->vec[0][1]) / (ob->bb->vec[6][1]-ob->bb->vec[0][1]) * 2.0f - 1.0f;
 -                                              co[2] = (co[2] - ob->bb->vec[0][2]) / (ob->bb->vec[6][2]-ob->bb->vec[0][2]) * 2.0f - 1.0f;
 -                                      }
 -                              }
 -                      }
 -                      else if (mtex->texco==TEXCO_GLOB) {
 -                              copy_v3_v3(co, xyz);
 -                              mul_m4_v3(re->viewinv, co);
 -                      }
 -                      else {
 -                              continue;  /* can happen when texco defines disappear and it renders old files */
 -                      }
 -
 -                      texres.nor= NULL;
 -
 -                      if (tex->type == TEX_IMAGE) {
 -                              continue;  /* not supported yet */
 -                              //do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
 -                      }
 -                      else {
 -                              /* placement */
 -                              if (mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]);
 -                              else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
 -
 -                              if (mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]);
 -                              else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
 -
 -                              if (mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]);
 -                              else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
 -                      }
 -
 -                      rgbnor = multitex(tex,
 -                                        texvec,
 -                                        NULL, NULL,
 -                                        0,
 -                                        &texres,
 -                                        shi->thread,
 -                                        mtex->which_output,
 -                                        re->pool,
 -                                        skip_load_image,
 -                                        texnode_preview,
 -                                        true);        /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
 -
 -                      /* texture output */
 -
 -                      if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
 -                              texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
 -                              rgbnor -= TEX_RGB;
 -                      }
 -                      if (mtex->texflag & MTEX_NEGATIVE) {
 -                              if (rgbnor & TEX_RGB) {
 -                                      texres.tr= 1.0f-texres.tr;
 -                                      texres.tg= 1.0f-texres.tg;
 -                                      texres.tb= 1.0f-texres.tb;
 -                              }
 -                              texres.tin= 1.0f-texres.tin;
 -                      }
 -                      if (mtex->texflag & MTEX_STENCIL) {
 -                              if (rgbnor & TEX_RGB) {
 -                                      fact= texres.ta;
 -                                      texres.ta*= stencilTin;
 -                                      stencilTin*= fact;
 -                              }
 -                              else {
 -                                      fact= texres.tin;
 -                                      texres.tin*= stencilTin;
 -                                      stencilTin*= fact;
 -                              }
 -                      }
 -
 -
 -                      if ((mapto_flag & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL)) && (mtex->mapto & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL))) {
 -                              float tcol[3];
 -
 -                              /* stencil maps on the texture control slider, not texture intensity value */
 -
 -                              if ((rgbnor & TEX_RGB) == 0) {
 -                                      copy_v3_v3(tcol, &mtex->r);
 -                              }
 -                              else if (mtex->mapto & MAP_DENSITY) {
 -                                      copy_v3_v3(tcol, &texres.tr);
 -                                      if (texres.talpha) {
 -                                              texres.tin = stencilTin;
 -                                      }
 -                              }
 -                              else {
 -                                      copy_v3_v3(tcol, &texres.tr);
 -                                      if (texres.talpha) {
 -                                              texres.tin= texres.ta;
 -                                      }
 -                              }
 -
 -                              /* used for emit */
 -                              if ((mapto_flag & MAP_EMISSION_COL) && (mtex->mapto & MAP_EMISSION_COL)) {
 -                                      float colemitfac= mtex->colemitfac*stencilTin;
 -                                      texture_rgb_blend(col_r, tcol, col_r, texres.tin, colemitfac, mtex->blendtype);
 -                              }
 -
 -                              if ((mapto_flag & MAP_REFLECTION_COL) && (mtex->mapto & MAP_REFLECTION_COL)) {
 -                                      float colreflfac= mtex->colreflfac*stencilTin;
 -                                      texture_rgb_blend(col_r, tcol, col_r, texres.tin, colreflfac, mtex->blendtype);
 -                              }
 -
 -                              if ((mapto_flag & MAP_TRANSMISSION_COL) && (mtex->mapto & MAP_TRANSMISSION_COL)) {
 -                                      float coltransfac= mtex->coltransfac*stencilTin;
 -                                      texture_rgb_blend(col_r, tcol, col_r, texres.tin, coltransfac, mtex->blendtype);
 -                              }
 -                      }
 -
 -                      if ((mapto_flag & MAP_VARS) && (mtex->mapto & MAP_VARS)) {
 -                              /* stencil maps on the texture control slider, not texture intensity value */
 -
 -                              /* convert RGB to intensity if intensity info isn't provided */
 -                              if (rgbnor & TEX_RGB) {
 -                                      if (texres.talpha)  texres.tin = texres.ta;
 -                                      else