Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / sculpt_paint / paint_image_proj.c
index 44da12c13e54672a215d28c6275cabd46094c619..62bc379241fb873ed998618171ed875ebc6b0975 100644 (file)
@@ -65,7 +65,6 @@
 #include "BKE_colorband.h"
 #include "BKE_context.h"
 #include "BKE_colortools.h"
-#include "BKE_depsgraph.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_idprop.h"
 #include "BKE_brush.h"
 #include "BKE_material.h"
 #include "BKE_mesh.h"
 #include "BKE_mesh_mapping.h"
+#include "BKE_mesh_runtime.h"
 #include "BKE_node.h"
 #include "BKE_paint.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
 #include "BKE_texture.h"
 
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
 #include "UI_interface.h"
 
 #include "ED_object.h"
@@ -227,6 +230,7 @@ typedef struct ProjPaintState {
        View3D *v3d;
        RegionView3D *rv3d;
        ARegion *ar;
+       Depsgraph *depsgraph;
        Scene *scene;
        int source; /* PROJ_SRC_**** */
 
@@ -282,7 +286,6 @@ typedef struct ProjPaintState {
        bool  do_backfacecull;          /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
        bool  do_mask_normal;           /* mask out pixels based on their normals */
        bool  do_mask_cavity;           /* mask out pixels based on cavity */
-       bool  do_new_shading_nodes;     /* cache BKE_scene_use_new_shading_nodes value */
        float normal_angle;             /* what angle to mask at */
        float normal_angle__cos;         /* cos(normal_angle), faster to compare */
        float normal_angle_inner;
@@ -351,28 +354,30 @@ typedef struct ProjPaintState {
 
        SpinLock *tile_lock;
 
-       DerivedMesh    *dm;
-       int  dm_totlooptri;
-       int  dm_totpoly;
-       int  dm_totedge;
-       int  dm_totvert;
-       bool dm_release;
+       Mesh *me_eval;
+       int  totlooptri_eval;
+       int  totpoly_eval;
+       int  totedge_eval;
+       int  totvert_eval;
 
-       const MVert    *dm_mvert;
-       const MEdge    *dm_medge;
-       const MPoly    *dm_mpoly;
-       const MLoop    *dm_mloop;
-       const MLoopTri *dm_mlooptri;
+       const MVert    *mvert_eval;
+       const MEdge    *medge_eval;
+       const MPoly    *mpoly_eval;
+       const MLoop    *mloop_eval;
+       const MLoopTri *mlooptri_eval;
 
-       const MLoopUV  *dm_mloopuv_stencil;
+       const MLoopUV  *mloopuv_stencil_eval;
 
        /**
-        * \note These UV layers are aligned to \a dm_mpoly
+        * \note These UV layers are aligned to \a mpoly_eval
         * but each pointer references the start of the layer,
         * so a loop indirection is needed as well.
         */
-       const MLoopUV **dm_mloopuv;
-       const MLoopUV **dm_mloopuv_clone;    /* other UV map, use for cloning between layers */
+       const MLoopUV **poly_to_loop_uv;
+       const MLoopUV **poly_to_loop_uv_clone;    /* other UV map, use for cloning between layers */
+
+       /* Actual material for each index, either from object or Mesh datablock... */
+       Material **mat_array;
 
        bool use_colormanagement;
 } ProjPaintState;
@@ -438,13 +443,13 @@ typedef struct {
 
 BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_index)
 {
-       return &ps->dm_mpoly[ps->dm_mlooptri[tri_index].poly];
+       return &ps->mpoly_eval[ps->mlooptri_eval[tri_index].poly];
 }
 
 #define PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) \
-       ps->dm_mloop[lt->tri[0]].v, \
-       ps->dm_mloop[lt->tri[1]].v, \
-       ps->dm_mloop[lt->tri[2]].v,
+       ps->mloop_eval[lt->tri[0]].v, \
+       ps->mloop_eval[lt->tri[1]].v, \
+       ps->mloop_eval[lt->tri[2]].v,
 
 #define PS_LOOPTRI_AS_UV_3(uvlayer, lt) \
        uvlayer[lt->poly][lt->tri[0]].uv, \
@@ -466,7 +471,7 @@ BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_
 static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int tri_index)
 {
        const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
-       Material *ma = ps->dm->mat[mp->mat_nr];
+       Material *ma = ps->mat_array[mp->mat_nr];
        return ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
 }
 
@@ -477,7 +482,7 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i
        }
        else {
                const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
-               Material *ma = ps->dm->mat[mp->mat_nr];
+               Material *ma = ps->mat_array[mp->mat_nr];
                TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
                return slot ? slot->ima : ps->canvas_ima;
        }
@@ -486,14 +491,14 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i
 static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int tri_index)
 {
        const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
-       Material *ma = ps->dm->mat[mp->mat_nr];
+       Material *ma = ps->mat_array[mp->mat_nr];
        return ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
 }
 
 static Image *project_paint_face_clone_image(const ProjPaintState *ps, int tri_index)
 {
        const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
-       Material *ma = ps->dm->mat[mp->mat_nr];
+       Material *ma = ps->mat_array[mp->mat_nr];
        TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
        return slot ? slot->ima : ps->clone_ima;
 }
@@ -594,11 +599,11 @@ static int project_paint_PickFace(
 
        for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
                const int tri_index = GET_INT_FROM_POINTER(node->link);
-               const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+               const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
                const float *vtri_ss[3] = {
-                   ps->screenCoords[ps->dm_mloop[lt->tri[0]].v],
-                   ps->screenCoords[ps->dm_mloop[lt->tri[1]].v],
-                   ps->screenCoords[ps->dm_mloop[lt->tri[2]].v],
+                   ps->screenCoords[ps->mloop_eval[lt->tri[0]].v],
+                   ps->screenCoords[ps->mloop_eval[lt->tri[1]].v],
+                   ps->screenCoords[ps->mloop_eval[lt->tri[2]].v],
                };
 
 
@@ -653,8 +658,8 @@ static bool project_paint_PickColor(
        if (tri_index == -1)
                return 0;
 
-       lt = &ps->dm_mlooptri[tri_index];
-       PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->dm_mloopuv, lt);
+       lt = &ps->mlooptri_eval[tri_index];
+       PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->poly_to_loop_uv, lt);
 
        interp_v2_v2v2v2(uv, UNPACK3(lt_tri_uv), w);
 
@@ -810,19 +815,19 @@ static bool project_bucket_point_occluded(
                const int tri_index = GET_INT_FROM_POINTER(bucketFace->link);
 
                if (orig_face != tri_index) {
-                       const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+                       const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
                        const float *vtri_ss[3] = {
-                           ps->screenCoords[ps->dm_mloop[lt->tri[0]].v],
-                           ps->screenCoords[ps->dm_mloop[lt->tri[1]].v],
-                           ps->screenCoords[ps->dm_mloop[lt->tri[2]].v],
+                           ps->screenCoords[ps->mloop_eval[lt->tri[0]].v],
+                           ps->screenCoords[ps->mloop_eval[lt->tri[1]].v],
+                           ps->screenCoords[ps->mloop_eval[lt->tri[2]].v],
                        };
                        float w[3];
 
                        if (do_clip) {
                                const float *vtri_co[3] = {
-                                   ps->dm_mvert[ps->dm_mloop[lt->tri[0]].v].co,
-                                   ps->dm_mvert[ps->dm_mloop[lt->tri[1]].v].co,
-                                   ps->dm_mvert[ps->dm_mloop[lt->tri[2]].v].co,
+                                   ps->mvert_eval[ps->mloop_eval[lt->tri[0]].v].co,
+                                   ps->mvert_eval[ps->mloop_eval[lt->tri[1]].v].co,
+                                   ps->mvert_eval[ps->mloop_eval[lt->tri[2]].v].co,
                                };
                                isect_ret = project_paint_occlude_ptv_clip(
                                        pixelScreenCo, UNPACK3(vtri_ss), UNPACK3(vtri_co),
@@ -1002,8 +1007,8 @@ static bool pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x
 static void project_face_winding_init(const ProjPaintState *ps, const int tri_index)
 {
        /* detect the winding of faces in uv space */
-       const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
-       const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt) };
+       const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
+       const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) };
        float winding = cross_tri_v2(lt_tri_uv[0], lt_tri_uv[1], lt_tri_uv[2]);
 
        if (winding > 0)
@@ -1019,11 +1024,11 @@ static bool check_seam(
         const int orig_face, const int orig_i1_fidx, const int orig_i2_fidx,
         int *other_face, int *orig_fidx)
 {
-       const MLoopTri *orig_lt = &ps->dm_mlooptri[orig_face];
-       const float *orig_lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, orig_lt) };
+       const MLoopTri *orig_lt = &ps->mlooptri_eval[orig_face];
+       const float *orig_lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, orig_lt) };
        /* vert indices from face vert order indices */
-       const unsigned int i1 = ps->dm_mloop[orig_lt->tri[orig_i1_fidx]].v;
-       const unsigned int i2 = ps->dm_mloop[orig_lt->tri[orig_i2_fidx]].v;
+       const unsigned int i1 = ps->mloop_eval[orig_lt->tri[orig_i1_fidx]].v;
+       const unsigned int i2 = ps->mloop_eval[orig_lt->tri[orig_i2_fidx]].v;
        LinkNode *node;
        int i1_fidx = -1, i2_fidx = -1; /* index in face */
 
@@ -1031,7 +1036,7 @@ static bool check_seam(
                const int tri_index = GET_INT_FROM_POINTER(node->link);
 
                if (tri_index != orig_face) {
-                       const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+                       const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
                        const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
                        /* could check if the 2 faces images match here,
                         * but then there wouldn't be a way to return the opposite face's info */
@@ -1044,7 +1049,7 @@ static bool check_seam(
 
                        /* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */
                        if (i2_fidx != -1) {
-                               const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt) };
+                               const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) };
                                Image *tpage = project_paint_face_paint_image(ps, tri_index);
                                Image *orig_tpage = project_paint_face_paint_image(ps, orig_face);
 
@@ -1348,8 +1353,8 @@ static float project_paint_uvpixel_mask(
                Image *other_tpage = ps->stencil_ima;
 
                if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
-                       const MLoopTri *lt_other = &ps->dm_mlooptri[tri_index];
-                       const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt_other) };
+                       const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
+                       const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt_other) };
 
                        /* BKE_image_acquire_ibuf - TODO - this may be slow */
                        unsigned char rgba_ub[4];
@@ -1382,7 +1387,7 @@ static float project_paint_uvpixel_mask(
        }
 
        if (ps->do_mask_cavity) {
-               const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+               const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
                const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
                float ca1, ca2, ca3, ca_mask;
                ca1 = ps->cavities[lt_vtri[0]];
@@ -1397,16 +1402,16 @@ static float project_paint_uvpixel_mask(
 
        /* calculate mask */
        if (ps->do_mask_normal) {
-               const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+               const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
                const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
-               const MPoly *mp = &ps->dm_mpoly[lt->poly];
+               const MPoly *mp = &ps->mpoly_eval[lt->poly];
                float no[3], angle_cos;
 
                if (mp->flag & ME_SMOOTH) {
                        const short *no1, *no2, *no3;
-                       no1 = ps->dm_mvert[lt_vtri[0]].no;
-                       no2 = ps->dm_mvert[lt_vtri[1]].no;
-                       no3 = ps->dm_mvert[lt_vtri[2]].no;
+                       no1 = ps->mvert_eval[lt_vtri[0]].no;
+                       no2 = ps->mvert_eval[lt_vtri[1]].no;
+                       no3 = ps->mvert_eval[lt_vtri[2]].no;
 
                        no[0] = w[0] * no1[0] + w[1] * no2[0] + w[2] * no3[0];
                        no[1] = w[0] * no1[1] + w[1] * no2[1] + w[2] * no3[1];
@@ -1418,9 +1423,9 @@ static float project_paint_uvpixel_mask(
 #if 1
                        /* normalizing per pixel isn't optimal, we could cache or check ps->*/
                        normal_tri_v3(no,
-                                     ps->dm_mvert[lt_vtri[0]].co,
-                                     ps->dm_mvert[lt_vtri[1]].co,
-                                     ps->dm_mvert[lt_vtri[2]].co);
+                                     ps->mvert_eval[lt_vtri[0]].co,
+                                     ps->mvert_eval[lt_vtri[1]].co,
+                                     ps->mvert_eval[lt_vtri[2]].co);
 #else
                        /* don't use because some modifiers dont have normal data (subsurf for eg) */
                        copy_v3_v3(no, (float *)ps->dm->getTessFaceData(ps->dm, tri_index, CD_NORMAL));
@@ -1439,9 +1444,9 @@ static float project_paint_uvpixel_mask(
                        /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */
                        float viewDirPersp[3];
                        const float *co1, *co2, *co3;
-                       co1 = ps->dm_mvert[lt_vtri[0]].co;
-                       co2 = ps->dm_mvert[lt_vtri[1]].co;
-                       co3 = ps->dm_mvert[lt_vtri[2]].co;
+                       co1 = ps->mvert_eval[lt_vtri[0]].co;
+                       co2 = ps->mvert_eval[lt_vtri[1]].co;
+                       co3 = ps->mvert_eval[lt_vtri[2]].co;
 
                        /* Get the direction from the viewPoint to the pixel and normalize */
                        viewDirPersp[0] = (ps->viewPos[0] - (w[0] * co1[0] + w[1] * co2[0] + w[2] * co3[0]));
@@ -1610,13 +1615,13 @@ static ProjPixel *project_paint_uvpixel_init(
 
        /* done with view3d_project_float inline */
        if (ps->tool == PAINT_TOOL_CLONE) {
-               if (ps->dm_mloopuv_clone) {
+               if (ps->poly_to_loop_uv_clone) {
                        ImBuf *ibuf_other;
                        Image *other_tpage = project_paint_face_clone_image(ps, tri_index);
 
                        if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
-                               const MLoopTri *lt_other = &ps->dm_mlooptri[tri_index];
-                               const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv_clone, lt_other) };
+                               const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
+                               const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, lt_other) };
 
                                /* BKE_image_acquire_ibuf - TODO - this may be slow */
 
@@ -2491,8 +2496,7 @@ static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot
 static void project_paint_face_init(
         const ProjPaintState *ps,
         const int thread_index, const int bucket_index, const int tri_index, const int image_index,
-        const rctf *clip_rect, const rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf,
-        const bool clamp_u, const bool clamp_v)
+        const rctf *clip_rect, const rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf)
 {
        /* Projection vars, to get the 3D locations into screen space  */
        MemArena *arena = ps->arena_mt[thread_index];
@@ -2508,9 +2512,9 @@ static void project_paint_face_init(
                ps->projImages + image_index
        };
 
-       const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+       const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
        const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
-       const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt) };
+       const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) };
 
        /* UV/pixel seeking data */
        int x; /* Image X-Pixel */
@@ -2544,9 +2548,9 @@ static void project_paint_face_init(
        const bool do_backfacecull = ps->do_backfacecull;
        const bool do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0;
 
-       vCo[0] = ps->dm_mvert[lt_vtri[0]].co;
-       vCo[1] = ps->dm_mvert[lt_vtri[1]].co;
-       vCo[2] = ps->dm_mvert[lt_vtri[2]].co;
+       vCo[0] = ps->mvert_eval[lt_vtri[0]].co;
+       vCo[1] = ps->mvert_eval[lt_vtri[1]].co;
+       vCo[2] = ps->mvert_eval[lt_vtri[2]].co;
 
 
        /* Use lt_uv_pxoffset instead of lt_tri_uv so we can offset the UV half a pixel
@@ -2599,17 +2603,6 @@ static void project_paint_face_init(
 #endif
 
                if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) {
-
-                       if (clamp_u) {
-                               CLAMP(bounds_px.xmin, 0, ibuf->x);
-                               CLAMP(bounds_px.xmax, 0, ibuf->x);
-                       }
-
-                       if (clamp_v) {
-                               CLAMP(bounds_px.ymin, 0, ibuf->y);
-                               CLAMP(bounds_px.ymax, 0, ibuf->y);
-                       }
-
 #if 0
                        project_paint_undo_tiles_init(&bounds_px, ps->projImages + image_index, tmpibuf,
                                                      tile_width, threaded, ps->do_masking);
@@ -2641,9 +2634,9 @@ static void project_paint_face_init(
                                                if (do_clip || do_3d_mapping) {
                                                        interp_v3_v3v3v3(
                                                                wco,
-                                                               ps->dm_mvert[lt_vtri[0]].co,
-                                                               ps->dm_mvert[lt_vtri[1]].co,
-                                                               ps->dm_mvert[lt_vtri[2]].co,
+                                                               ps->mvert_eval[lt_vtri[0]].co,
+                                                               ps->mvert_eval[lt_vtri[1]].co,
+                                                               ps->mvert_eval[lt_vtri[2]].co,
                                                                w);
                                                        if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, true)) {
                                                                continue; /* Watch out that no code below this needs to run */
@@ -2823,7 +2816,7 @@ static void project_paint_face_init(
                                                                                    !project_bucket_point_occluded(ps, bucketFaceNodes, tri_index, pixelScreenCo))
                                                                                {
                                                                                        /* Only bother calculating the weights if we intersect */
-                                                                                       if (ps->do_mask_normal || ps->dm_mloopuv_clone) {
+                                                                                       if (ps->do_mask_normal || ps->poly_to_loop_uv_clone) {
                                                                                                const float uv_fac = fac1 + (fac * (fac2 - fac1));
 #if 0
                                                                                                /* get the UV on the line since we want to copy the pixels from there for bleeding */
@@ -2926,19 +2919,16 @@ static void project_bucket_init(
        int tri_index, image_index = 0;
        ImBuf *ibuf = NULL;
        Image *tpage_last = NULL, *tpage;
-       Image *ima = NULL;
        ImBuf *tmpibuf = NULL;
 
        if (ps->image_tot == 1) {
                /* Simple loop, no context switching */
                ibuf = ps->projImages[0].ibuf;
-               ima = ps->projImages[0].ima;
 
                for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
                        project_paint_face_init(
                                ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0,
-                               clip_rect, bucket_bounds, ibuf, &tmpibuf,
-                               (ima->tpageflag & IMA_CLAMP_U) != 0, (ima->tpageflag & IMA_CLAMP_V) != 0);
+                               clip_rect, bucket_bounds, ibuf, &tmpibuf);
                }
        }
        else {
@@ -2955,7 +2945,6 @@ static void project_bucket_init(
                                for (image_index = 0; image_index < ps->image_tot; image_index++) {
                                        if (ps->projImages[image_index].ima == tpage_last) {
                                                ibuf = ps->projImages[image_index].ibuf;
-                                               ima = ps->projImages[image_index].ima;
                                                break;
                                        }
                                }
@@ -2964,8 +2953,7 @@ static void project_bucket_init(
 
                        project_paint_face_init(
                                ps, thread_index, bucket_index, tri_index, image_index,
-                               clip_rect, bucket_bounds, ibuf, &tmpibuf,
-                               (ima->tpageflag & IMA_CLAMP_U) != 0, (ima->tpageflag & IMA_CLAMP_V) != 0);
+                               clip_rect, bucket_bounds, ibuf, &tmpibuf);
                }
        }
 
@@ -3081,26 +3069,8 @@ static void project_paint_delayed_face_init(ProjPaintState *ps, const MLoopTri *
 #endif
 }
 
-/**
- * \note when using subsurf or multires, some arrays are thrown away, we need to keep a copy
- */
-static void proj_paint_state_non_cddm_init(ProjPaintState *ps)
-{
-       if (ps->dm->type != DM_TYPE_CDDM) {
-               ps->dm_mvert = MEM_dupallocN(ps->dm_mvert);
-               ps->dm_mpoly = MEM_dupallocN(ps->dm_mpoly);
-               ps->dm_mloop = MEM_dupallocN(ps->dm_mloop);
-               /* looks like these are ok for now.*/
-#if 0
-               ps->dm_mloopuv = MEM_dupallocN(ps->dm_mloopuv);
-               ps->dm_mloopuv_clone = MEM_dupallocN(ps->dm_mloopuv_clone);
-               ps->dm_mloopuv_stencil = MEM_dupallocN(ps->dm_mloopuv_stencil);
-#endif
-       }
-}
-
 static void proj_paint_state_viewport_init(
-        ProjPaintState *ps, const char symmetry_flag)
+        ProjPaintState *ps, const Depsgraph *depsgraph, const char symmetry_flag)
 {
        float mat[3][3];
        float viewmat[4][4];
@@ -3134,7 +3104,7 @@ static void proj_paint_state_viewport_init(
 
                ED_view3d_ob_project_mat_get_from_obmat(ps->rv3d, ps->obmat, ps->projectMat);
 
-               ps->is_ortho = ED_view3d_clip_range_get(ps->v3d, ps->rv3d, &ps->clipsta, &ps->clipend, true);
+               ps->is_ortho = ED_view3d_clip_range_get(ps->depsgraph, ps->v3d, ps->rv3d, &ps->clipsta, &ps->clipend, true);
        }
        else {
                /* re-projection */
@@ -3161,17 +3131,17 @@ static void proj_paint_state_viewport_init(
                        invert_m4_m4(viewinv, viewmat);
                }
                else if (ps->source == PROJ_SRC_IMAGE_CAM) {
-                       Object *cam_ob = ps->scene->camera;
+                       Object *cam_ob_eval = DEG_get_evaluated_object(depsgraph, ps->scene->camera);
                        CameraParams params;
 
                        /* viewmat & viewinv */
-                       copy_m4_m4(viewinv, cam_ob->obmat);
+                       copy_m4_m4(viewinv, cam_ob_eval->obmat);
                        normalize_m4(viewinv);
                        invert_m4_m4(viewmat, viewinv);
 
                        /* window matrix, clipping and ortho */
                        BKE_camera_params_init(&params);
-                       BKE_camera_params_from_object(&params, cam_ob);
+                       BKE_camera_params_from_object(&params, cam_ob_eval);
                        BKE_camera_params_compute_viewplane(&params, ps->winx, ps->winy, 1.0f, 1.0f);
                        BKE_camera_params_compute_matrix(&params);
 
@@ -3218,11 +3188,11 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di
 
        INIT_MINMAX2(ps->screenMin, ps->screenMax);
 
-       ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, "ProjectPaint ScreenVerts");
+       ps->screenCoords = MEM_mallocN(sizeof(float) * ps->totvert_eval * 4, "ProjectPaint ScreenVerts");
        projScreenCo = *ps->screenCoords;
 
        if (ps->is_ortho) {
-               for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) {
+               for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++, projScreenCo += 4) {
                        mul_v3_m4v3(projScreenCo, ps->projectMat, mv->co);
 
                        /* screen space, not clamped */
@@ -3232,7 +3202,7 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di
                }
        }
        else {
-               for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) {
+               for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++, projScreenCo += 4) {
                        copy_v3_v3(projScreenCo, mv->co);
                        projScreenCo[3] = 1.0f;
 
@@ -3293,21 +3263,21 @@ static void proj_paint_state_cavity_init(ProjPaintState *ps)
        int a;
 
        if (ps->do_mask_cavity) {
-               int *counter = MEM_callocN(sizeof(int) * ps->dm_totvert, "counter");
-               float (*edges)[3] = MEM_callocN(sizeof(float) * 3 * ps->dm_totvert, "edges");
-               ps->cavities = MEM_mallocN(sizeof(float) * ps->dm_totvert, "ProjectPaint Cavities");
+               int *counter = MEM_callocN(sizeof(int) * ps->totvert_eval, "counter");
+               float (*edges)[3] = MEM_callocN(sizeof(float) * 3 * ps->totvert_eval, "edges");
+               ps->cavities = MEM_mallocN(sizeof(float) * ps->totvert_eval, "ProjectPaint Cavities");
                cavities = ps->cavities;
 
-               for (a = 0, me = ps->dm_medge; a < ps->dm_totedge; a++, me++) {
+               for (a = 0, me = ps->medge_eval; a < ps->totedge_eval; a++, me++) {
                        float e[3];
-                       sub_v3_v3v3(e, ps->dm_mvert[me->v1].co, ps->dm_mvert[me->v2].co);
+                       sub_v3_v3v3(e, ps->mvert_eval[me->v1].co, ps->mvert_eval[me->v2].co);
                        normalize_v3(e);
                        add_v3_v3(edges[me->v2], e);
                        counter[me->v2]++;
                        sub_v3_v3(edges[me->v1], e);
                        counter[me->v1]++;
                }
-               for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) {
+               for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) {
                        if (counter[a] > 0) {
                                float no[3];
                                mul_v3_fl(edges[a], 1.0f / counter[a]);
@@ -3328,10 +3298,10 @@ static void proj_paint_state_cavity_init(ProjPaintState *ps)
 static void proj_paint_state_seam_bleed_init(ProjPaintState *ps)
 {
        if (ps->seam_bleed_px > 0.0f) {
-               ps->vertFaces = MEM_callocN(sizeof(LinkNode *) * ps->dm_totvert, "paint-vertFaces");
-               ps->faceSeamFlags = MEM_callocN(sizeof(char) * ps->dm_totlooptri, "paint-faceSeamFlags");
-               ps->faceWindingFlags = MEM_callocN(sizeof(char) * ps->dm_totlooptri, "paint-faceWindindFlags");
-               ps->faceSeamUVs = MEM_mallocN(sizeof(float[3][2]) * ps->dm_totlooptri, "paint-faceSeamUVs");
+               ps->vertFaces = MEM_callocN(sizeof(LinkNode *) * ps->totvert_eval, "paint-vertFaces");
+               ps->faceSeamFlags = MEM_callocN(sizeof(char) * ps->totlooptri_eval, "paint-faceSeamFlags");
+               ps->faceWindingFlags = MEM_callocN(sizeof(char) * ps->totlooptri_eval, "paint-faceWindindFlags");
+               ps->faceSeamUVs = MEM_mallocN(sizeof(float[3][2]) * ps->totlooptri_eval, "paint-faceSeamUVs");
        }
 }
 #endif
@@ -3375,9 +3345,9 @@ static void proj_paint_state_vert_flags_init(ProjPaintState *ps)
                float no[3];
                int a;
 
-               ps->vertFlags = MEM_callocN(sizeof(char) * ps->dm_totvert, "paint-vertFlags");
+               ps->vertFlags = MEM_callocN(sizeof(char) * ps->totvert_eval, "paint-vertFlags");
 
-               for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) {
+               for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) {
                        normal_short_to_float_v3(no, mv->no);
                        if (UNLIKELY(ps->is_flip_object)) {
                                negate_v3(no);
@@ -3422,49 +3392,63 @@ static void project_paint_bleed_add_face_user(
 }
 #endif
 
-/* Return true if DM can be painted on, false otherwise */
-static bool proj_paint_state_dm_init(ProjPaintState *ps)
+/* Return true if evaluated mesh can be painted on, false otherwise */
+static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *ps)
 {
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
+       Scene *sce = ps->scene;
+       Object *ob = ps->ob;
+
        /* Workaround for subsurf selection, try the display mesh first */
+       /* XXX Don't think this is easily doable with new system, and not sure why that was needed in the first place :/ */
+#if 0
        if (ps->source == PROJ_SRC_IMAGE_CAM) {
                /* using render mesh, assume only camera was rendered from */
-               ps->dm = mesh_create_derived_render(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MLOOPUV | CD_MASK_MTFACE);
+               ps->dm = mesh_create_derived_render(
+                            depsgraph, ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MLOOPUV | CD_MASK_MTFACE);
                ps->dm_release = true;
        }
        else {
                ps->dm = mesh_get_derived_final(
-                       ps->scene, ps->ob,
+                       depsgraph, ps->scene, ps->ob,
                        ps->scene->customdata_mask | CD_MASK_MLOOPUV | CD_MASK_MTFACE | (ps->do_face_sel ? CD_MASK_ORIGINDEX : 0));
                ps->dm_release = false;
        }
-
-       if (!CustomData_has_layer(&ps->dm->loopData, CD_MLOOPUV)) {
-
-               if (ps->dm_release)
-                       ps->dm->release(ps->dm);
-
-               ps->dm = NULL;
+#endif
+       ps->me_eval = mesh_get_eval_final(
+                         depsgraph, sce, ob,
+                         sce->customdata_mask | CD_MASK_MLOOPUV | CD_MASK_MTFACE | (ps->do_face_sel ? CD_MASK_ORIGINDEX : 0));
+       if (!CustomData_has_layer(&ps->me_eval->ldata, CD_MLOOPUV)) {
+               ps->me_eval = NULL;
                return false;
        }
 
-       DM_update_materials(ps->dm, ps->ob);
-
-       ps->dm_mvert = ps->dm->getVertArray(ps->dm);
-
-       if (ps->do_mask_cavity)
-               ps->dm_medge = ps->dm->getEdgeArray(ps->dm);
+       /* Build final material array, we use this a lot here. */
+       const int totmat = ob->totcol + 1; /* materials start from 1, default material is 0 */
+       ps->mat_array = MEM_malloc_arrayN(totmat, sizeof(*ps->mat_array), __func__);
+       /* We leave last material as empty - rationale here is being able to index
+        * the materials by using the mf->mat_nr directly and leaving the last
+        * material as NULL in case no materials exist on mesh, so indexing will not fail. */
+       for (int i = 0; i < totmat - 1; i++) {
+               ps->mat_array[i] = give_current_material(ob, i + 1);
+       }
+       ps->mat_array[totmat - 1] = NULL;
 
-       ps->dm_mloop = ps->dm->getLoopArray(ps->dm);
-       ps->dm_mpoly = ps->dm->getPolyArray(ps->dm);
+       ps->mvert_eval = ps->me_eval->mvert;
+       if (ps->do_mask_cavity) {
+               ps->medge_eval = ps->me_eval->medge;
+       }
+       ps->mloop_eval = ps->me_eval->mloop;
+       ps->mpoly_eval = ps->me_eval->mpoly;
 
-       ps->dm_mlooptri = ps->dm->getLoopTriArray(ps->dm);
+       ps->totvert_eval = ps->me_eval->totvert;
+       ps->totedge_eval = ps->me_eval->totedge;
+       ps->totpoly_eval = ps->me_eval->totpoly;
 
-       ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
-       ps->dm_totedge = ps->dm->getNumEdges(ps->dm);
-       ps->dm_totpoly = ps->dm->getNumPolys(ps->dm);
-       ps->dm_totlooptri = ps->dm->getNumLoopTri(ps->dm);
+       ps->mlooptri_eval = BKE_mesh_runtime_looptri_ensure(ps->me_eval);
+       ps->totlooptri_eval = ps->me_eval->runtime.looptris.len;
 
-       ps->dm_mloopuv = MEM_mallocN(ps->dm_totpoly * sizeof(MLoopUV *), "proj_paint_mtfaces");
+       ps->poly_to_loop_uv = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces");
 
        return true;
 }
@@ -3483,16 +3467,16 @@ static void proj_paint_layer_clone_init(
 
        /* use clone mtface? */
        if (ps->do_layer_clone) {
-               const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
+               const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
 
-               ps->dm_mloopuv_clone = MEM_mallocN(ps->dm_totpoly * sizeof(MLoopUV *), "proj_paint_mtfaces");
+               ps->poly_to_loop_uv_clone = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces");
 
                if (layer_num != -1)
-                       mloopuv_clone_base = CustomData_get_layer_n(&ps->dm->loopData, CD_MLOOPUV, layer_num);
+                       mloopuv_clone_base = CustomData_get_layer_n(&ps->me_eval->ldata, CD_MLOOPUV, layer_num);
 
                if (mloopuv_clone_base == NULL) {
                        /* get active instead */
-                       mloopuv_clone_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+                       mloopuv_clone_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
                }
 
        }
@@ -3522,17 +3506,17 @@ static bool project_paint_clone_face_skip(
                        if (lc->slot_clone != lc->slot_last_clone) {
                                if (!slot->uvname ||
                                    !(lc->mloopuv_clone_base = CustomData_get_layer_named(
-                                         &ps->dm->loopData, CD_MLOOPUV,
+                                         &ps->me_eval->ldata, CD_MLOOPUV,
                                          lc->slot_clone->uvname)))
                                {
-                                       lc->mloopuv_clone_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+                                       lc->mloopuv_clone_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
                                }
                                lc->slot_last_clone = lc->slot_clone;
                        }
                }
 
                /* will set multiple times for 4+ sided poly */
-               ps->dm_mloopuv_clone[ps->dm_mlooptri[tri_index].poly] = lc->mloopuv_clone_base;
+               ps->poly_to_loop_uv_clone[ps->mlooptri_eval[tri_index].poly] = lc->mloopuv_clone_base;
        }
        return false;
 }
@@ -3549,7 +3533,7 @@ static void proj_paint_face_lookup_init(
 {
        memset(face_lookup, 0, sizeof(*face_lookup));
        if (ps->do_face_sel) {
-               face_lookup->index_mp_to_orig  = ps->dm->getPolyDataArray(ps->dm, CD_ORIGINDEX);
+               face_lookup->index_mp_to_orig = CustomData_get_layer(&ps->me_eval->pdata, CD_ORIGINDEX);
                face_lookup->mpoly_orig = ((Mesh *)ps->ob->data)->mpoly;
        }
 }
@@ -3570,7 +3554,7 @@ static bool project_paint_check_face_sel(
                        mp = &face_lookup->mpoly_orig[orig_index];
                }
                else {
-                       mp = &ps->dm_mpoly[lt->poly];
+                       mp = &ps->mpoly_eval[lt->poly];
                }
 
                return ((mp->flag & ME_FACE_SEL) != 0);
@@ -3684,7 +3668,7 @@ static void project_paint_prepare_all_faces(
        int image_index = -1, tri_index;
        int prev_poly = -1;
 
-       for (tri_index = 0, lt = ps->dm_mlooptri; tri_index < ps->dm_totlooptri; tri_index++, lt++) {
+       for (tri_index = 0, lt = ps->mlooptri_eval; tri_index < ps->totlooptri_eval; tri_index++, lt++) {
                bool is_face_sel;
 
 #ifndef PROJ_DEBUG_NOSEAMBLEED
@@ -3697,13 +3681,13 @@ static void project_paint_prepare_all_faces(
                        slot = project_paint_face_paint_slot(ps, tri_index);
                        /* all faces should have a valid slot, reassert here */
                        if (slot == NULL) {
-                               mloopuv_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+                               mloopuv_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
                                tpage = ps->canvas_ima;
                        }
                        else {
                                if (slot != slot_last) {
-                                       if (!slot->uvname || !(mloopuv_base = CustomData_get_layer_named(&ps->dm->loopData, CD_MLOOPUV, slot->uvname)))
-                                               mloopuv_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+                                       if (!slot->uvname || !(mloopuv_base = CustomData_get_layer_named(&ps->me_eval->ldata, CD_MLOOPUV, slot->uvname)))
+                                               mloopuv_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
                                        slot_last = slot;
                                }
 
@@ -3711,7 +3695,7 @@ static void project_paint_prepare_all_faces(
                                if (slot->ima == ps->stencil_ima) {
                                        /* While this shouldn't be used, face-winding reads all polys.
                                         * It's less trouble to set all faces to valid UV's, avoiding NULL checks all over. */
-                                       ps->dm_mloopuv[lt->poly] = mloopuv_base;
+                                       ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
                                        continue;
                                }
 
@@ -3722,7 +3706,7 @@ static void project_paint_prepare_all_faces(
                        tpage = ps->stencil_ima;
                }
 
-               ps->dm_mloopuv[lt->poly] = mloopuv_base;
+               ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
 
                if (project_paint_clone_face_skip(ps, layer_clone, slot, tri_index)) {
                        continue;
@@ -3753,11 +3737,11 @@ static void project_paint_prepare_all_faces(
                                                if (prev_poly != lt->poly) {
                                                        int iloop;
                                                        bool culled = true;
-                                                       const MPoly *poly = ps->dm_mpoly + lt->poly;
+                                                       const MPoly *poly = ps->mpoly_eval + lt->poly;
                                                        int poly_loops = poly->totloop;
                                                        prev_poly = lt->poly;
                                                        for (iloop = 0; iloop < poly_loops; iloop++) {
-                                                               if (!(ps->vertFlags[ps->dm_mloop[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) {
+                                                               if (!(ps->vertFlags[ps->mloop_eval[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) {
                                                                        culled = false;
                                                                        break;
                                                                }
@@ -3813,7 +3797,7 @@ static void project_paint_prepare_all_faces(
 
 /* run once per stroke before projection painting */
 static void project_paint_begin(
-        ProjPaintState *ps,
+        const bContext *C, ProjPaintState *ps,
         const bool is_multi_view, const char symmetry_flag)
 {
        ProjPaintLayerClone layer_clone;
@@ -3836,7 +3820,7 @@ static void project_paint_begin(
 
        /* paint onto the derived mesh */
        if (ps->is_shared_user == false) {
-               if (!proj_paint_state_dm_init(ps)) {
+               if (!proj_paint_state_mesh_eval_init(C, ps)) {
                        return;
                }
        }
@@ -3845,28 +3829,26 @@ static void project_paint_begin(
        proj_paint_layer_clone_init(ps, &layer_clone);
 
        if (ps->do_layer_stencil || ps->do_stencil_brush) {
-               //int layer_num = CustomData_get_stencil_layer(&ps->dm->loopData, CD_MLOOPUV);
-               int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
+               //int layer_num = CustomData_get_stencil_layer(&ps->me_eval->ldata, CD_MLOOPUV);
+               int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
                if (layer_num != -1)
-                       ps->dm_mloopuv_stencil = CustomData_get_layer_n(&ps->dm->loopData, CD_MLOOPUV, layer_num);
+                       ps->mloopuv_stencil_eval = CustomData_get_layer_n(&ps->me_eval->ldata, CD_MLOOPUV, layer_num);
 
-               if (ps->dm_mloopuv_stencil == NULL) {
+               if (ps->mloopuv_stencil_eval == NULL) {
                        /* get active instead */
-                       ps->dm_mloopuv_stencil = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+                       ps->mloopuv_stencil_eval = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
                }
 
                if (ps->do_stencil_brush)
-                       mloopuv_base = ps->dm_mloopuv_stencil;
+                       mloopuv_base = ps->mloopuv_stencil_eval;
        }
 
        /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
        if (ps->is_shared_user == false) {
-               proj_paint_state_non_cddm_init(ps);
-
                proj_paint_state_cavity_init(ps);
        }
 
-       proj_paint_state_viewport_init(ps, symmetry_flag);
+       proj_paint_state_viewport_init(ps, CTX_data_depsgraph(C), symmetry_flag);
 
        /* calculate vert screen coords
         * run this early so we can calculate the x/y resolution of our bucket rect */
@@ -3913,7 +3895,7 @@ static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2])
        /* setup clone offset */
        if (ps->tool == PAINT_TOOL_CLONE) {
                float projCo[4];
-               copy_v3_v3(projCo, ED_view3d_cursor3d_get(ps->scene, ps->v3d));
+               copy_v3_v3(projCo, ED_view3d_cursor3d_get(ps->scene, ps->v3d)->location);
                mul_m4_v3(ps->obmat_imat, projCo);
 
                projCo[3] = 1.0f;
@@ -3934,7 +3916,7 @@ static void project_paint_end(ProjPaintState *ps)
                ProjPaintImage *projIma;
                for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
                        BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL);
-                       DAG_id_tag_update(&projIma->ima->id, 0);
+                       DEG_id_tag_update(&projIma->ima->id, 0);
                }
        }
 
@@ -3952,14 +3934,17 @@ static void project_paint_end(ProjPaintState *ps)
        MEM_freeN(ps->bucketFlags);
 
        if (ps->is_shared_user == false) {
+               if (ps->mat_array != NULL) {
+                       MEM_freeN(ps->mat_array);
+               }
 
                /* must be set for non-shared */
-               BLI_assert(ps->dm_mloopuv || ps->is_shared_user);
-               if (ps->dm_mloopuv)
-                       MEM_freeN((void *)ps->dm_mloopuv);
+               BLI_assert(ps->poly_to_loop_uv || ps->is_shared_user);
+               if (ps->poly_to_loop_uv)
+                       MEM_freeN((void *)ps->poly_to_loop_uv);
 
                if (ps->do_layer_clone)
-                       MEM_freeN((void *)ps->dm_mloopuv_clone);
+                       MEM_freeN((void *)ps->poly_to_loop_uv_clone);
                if (ps->thread_tot > 1) {
                        BLI_spin_end(ps->tile_lock);
                        MEM_freeN((void *)ps->tile_lock);
@@ -3979,22 +3964,6 @@ static void project_paint_end(ProjPaintState *ps)
                if (ps->do_mask_cavity) {
                        MEM_freeN(ps->cavities);
                }
-
-               /* copy for subsurf/multires, so throw away */
-               if (ps->dm->type != DM_TYPE_CDDM) {
-                       if (ps->dm_mvert) MEM_freeN((void *)ps->dm_mvert);
-                       if (ps->dm_mpoly) MEM_freeN((void *)ps->dm_mpoly);
-                       if (ps->dm_mloop) MEM_freeN((void *)ps->dm_mloop);
-                       /* looks like these don't need copying */
-#if 0
-                       if (ps->dm_mloopuv) MEM_freeN(ps->dm_mloopuv);
-                       if (ps->dm_mloopuv_clone) MEM_freeN(ps->dm_mloopuv_clone);
-                       if (ps->dm_mloopuv_stencil) MEM_freeN(ps->dm_mloopuv_stencil);
-#endif
-               }
-
-               if (ps->dm_release)
-                       ps->dm->release(ps->dm);
        }
 
        if (ps->blurkernel) {
@@ -4869,7 +4838,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
        struct ImagePool *pool;
 
        if (!project_bucket_iter_init(ps, pos)) {
-               return 0;
+               return touch_any;
        }
 
        if (ps->thread_tot > 1)
@@ -4935,16 +4904,16 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
                tri_index = project_paint_PickFace(ps, pos, w);
 
                if (tri_index != -1) {
-                       const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+                       const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
                        const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
                        float world[3];
                        UnifiedPaintSettings *ups = &ps->scene->toolsettings->unified_paint_settings;
 
                        interp_v3_v3v3v3(
                                world,
-                               ps->dm_mvert[lt_vtri[0]].co,
-                               ps->dm_mvert[lt_vtri[1]].co,
-                               ps->dm_mvert[lt_vtri[2]].co,
+                               ps->mvert_eval[lt_vtri[0]].co,
+                               ps->mvert_eval[lt_vtri[1]].co,
+                               ps->mvert_eval[lt_vtri[2]].co,
                                w);
 
                        ups->average_stroke_counter++;
@@ -5019,17 +4988,18 @@ void paint_proj_stroke(
 
        /* clone gets special treatment here to avoid going through image initialization */
        if (ps_handle->is_clone_cursor_pick) {
-               Main *bmain = CTX_data_main(C);
                Scene *scene = ps_handle->scene;
+               struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
                View3D *v3d = CTX_wm_view3d(C);
                ARegion *ar = CTX_wm_region(C);
-               float *cursor = ED_view3d_cursor3d_get(scene, v3d);
+               float *cursor = ED_view3d_cursor3d_get(scene, v3d)->location;
                int mval_i[2] = {(int)pos[0], (int)pos[1]};
 
                view3d_operator_needs_opengl(C);
 
-               if (!ED_view3d_autodist(bmain, scene, ar, v3d, mval_i, cursor, false, NULL))
+               if (!ED_view3d_autodist(depsgraph, ar, v3d, mval_i, cursor, false, NULL)) {
                        return;
+               }
 
                ED_region_tag_redraw(ar);
 
@@ -5085,6 +5055,7 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
        ps->rv3d = CTX_wm_region_view3d(C);
        ps->ar = CTX_wm_region(C);
 
+       ps->depsgraph = CTX_data_depsgraph(C);
        ps->scene = scene;
        ps->ob = ob; /* allow override of active object */
 
@@ -5107,7 +5078,6 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
        else {
                ps->do_backfacecull = ps->do_occlude = ps->do_mask_normal = 0;
        }
-       ps->do_new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); /* only cache the value */
 
        if (ps->tool == PAINT_TOOL_CLONE)
                ps->do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) ? 1 : 0;
@@ -5207,7 +5177,7 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m
 
                project_state_init(C, ob, ps, mode);
 
-               if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) {
+               if (ps->ob == NULL) {
                        ps_handle->ps_views_tot = i + 1;
                        goto fail;
                }
@@ -5231,14 +5201,12 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m
                        PROJ_PAINT_STATE_SHARED_MEMCPY(ps, ps_handle->ps_views[0]);
                }
 
-               project_paint_begin(ps, is_multi_view, symmetry_flag_views[i]);
-
-               paint_proj_begin_clone(ps, mouse);
-
-               if (ps->dm == NULL) {
+               project_paint_begin(C, ps, is_multi_view, symmetry_flag_views[i]);
+               if (ps->me_eval == NULL) {
                        goto fail;
-                       return NULL;
                }
+
+               paint_proj_begin_clone(ps, mouse);
        }
 
        paint_brush_init_tex(ps_handle->brush);
@@ -5309,11 +5277,12 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
 {
        Image *image = BLI_findlink(&CTX_data_main(C)->image, RNA_enum_get(op->ptr, "image"));
        Scene *scene = CTX_data_scene(C);
+       ViewLayer *view_layer = CTX_data_view_layer(C);
        ProjPaintState ps = {NULL};
        int orig_brush_size;
        IDProperty *idgroup;
        IDProperty *view_data = NULL;
-       Object *ob = OBACT;
+       Object *ob = OBACT(view_layer);
        bool uvs, mat, tex;
 
        if (ob == NULL || ob->type != OB_MESH) {
@@ -5383,10 +5352,11 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
        ED_image_undo_push_begin(op->type->name);
 
        /* allocate and initialize spatial data structures */
-       project_paint_begin(&ps, false, 0);
+       project_paint_begin(C, &ps, false, 0);
 
-       if (ps.dm == NULL) {
+       if (ps.me_eval == NULL) {
                BKE_brush_size_set(scene, ps.brush, orig_brush_size);
+               BKE_report(op->reports, RPT_ERROR, "Could not get valid evaluated mesh");
                return OPERATOR_CANCELLED;
        }
        else {
@@ -5441,8 +5411,11 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
        char filename[FILE_MAX];
 
        Main *bmain = CTX_data_main(C);
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        ToolSettings *settings = scene->toolsettings;
+       View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d = CTX_wm_region_view3d(C);
        int w = settings->imapaint.screen_grab_size[0];
        int h = settings->imapaint.screen_grab_size[1];
        int maxsize;
@@ -5456,9 +5429,10 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
        if (h > maxsize) h = maxsize;
 
        ibuf = ED_view3d_draw_offscreen_imbuf(
-               bmain, scene, CTX_wm_view3d(C), CTX_wm_region(C),
+               depsgraph, scene, v3d->drawtype,
+               v3d, CTX_wm_region(C),
                w, h, IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
-               NULL, NULL, err_out);
+               NULL, err_out);
        if (!ibuf) {
                /* Mostly happens when OpenGL offscreen buffer was failed to create, */
                /* but could be other reasons. Should be handled in the future. nazgul */
@@ -5474,9 +5448,6 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
        if (image) {
                /* now for the trickiness. store the view projection here!
                 * re-projection will reuse this */
-               View3D *v3d = CTX_wm_view3d(C);
-               RegionView3D *rv3d = CTX_wm_region_view3d(C);
-
                IDPropertyTemplate val;
                IDProperty *idgroup = IDP_GetProperties(&image->id, 1);
                IDProperty *view_data;
@@ -5490,7 +5461,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
                array = (float *)IDP_Array(view_data);
                memcpy(array, rv3d->winmat, sizeof(rv3d->winmat)); array += sizeof(rv3d->winmat) / sizeof(float);
                memcpy(array, rv3d->viewmat, sizeof(rv3d->viewmat)); array += sizeof(rv3d->viewmat) / sizeof(float);
-               is_ortho = ED_view3d_clip_range_get(v3d, rv3d, &array[0], &array[1], true);
+               is_ortho = ED_view3d_clip_range_get(CTX_data_depsgraph(C), v3d, rv3d, &array[0], &array[1], true);
                /* using float for a bool is dodgy but since its an extra member in the array...
                 * easier then adding a single bool prop */
                array[2] = is_ortho ? 1.0f : 0.0f;
@@ -5590,7 +5561,7 @@ bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *m
        }
 
        me = BKE_mesh_from_object(ob);
-       layernum = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
+       layernum = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
 
        if (layernum == 0) {
                hasuvs = false;
@@ -5629,20 +5600,11 @@ bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *m
 /* Add layer operator */
 
 static const EnumPropertyItem layer_type_items[] = {
-       {MAP_COL, "DIFFUSE_COLOR", 0, "Diffuse Color", ""},
-       {MAP_REF, "DIFFUSE_INTENSITY", 0, "Diffuse Intensity", ""},
-       {MAP_ALPHA, "ALPHA", 0, "Alpha", ""},
-       {MAP_TRANSLU, "TRANSLUCENCY", 0, "Translucency", ""},
-       {MAP_COLSPEC, "SPECULAR_COLOR", 0, "Specular Color", ""},
-       {MAP_SPEC, "SPECULAR_INTENSITY", 0, "Specular Intensity", ""},
-       {MAP_HAR, "SPECULAR_HARDNESS", 0, "Specular Hardness", ""},
-       {MAP_AMB, "AMBIENT", 0, "Ambient", ""},
-       {MAP_EMIT, "EMIT", 0, "Emit", ""},
-       {MAP_COLMIR, "MIRROR_COLOR", 0, "Mirror Color", ""},
-       {MAP_RAYMIRR, "RAYMIRROR", 0, "Ray Mirror", ""},
-       {MAP_NORM, "NORMAL", 0, "Normal", ""},
-       {MAP_WARP, "WARP", 0, "Warp", ""},
-       {MAP_DISPLACE, "DISPLACE", 0, "Displace", ""},
+       {0, "BASE_COLOR", 0, "Base Color", ""},
+       {1, "EMISSION", 0, "Emission", ""},
+       {2, "NORMAL", 0, "Normal", ""},
+       {3, "BUMP", 0, "Bump", ""},
+       {4, "DISPLACEMENT", 0, "Displacement", ""},
        {0, NULL, 0, NULL, NULL}
 };
 
@@ -5677,7 +5639,6 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
        Object *ob = ED_object_active_context(C);
        Scene *scene = CTX_data_scene(C);
        Material *ma;
-       bool is_bi = BKE_scene_uses_blender_internal(scene) || BKE_scene_uses_blender_game(scene);
        Image *ima = NULL;
 
        if (!ob)
@@ -5686,60 +5647,34 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
        ma = give_current_material(ob, ob->actcol);
 
        if (ma) {
+               /* TODO: use type to link to proper socket. */
                Main *bmain = CTX_data_main(C);
 
-               if (!is_bi && BKE_scene_use_new_shading_nodes(scene)) {
-                       bNode *imanode;
-                       bNodeTree *ntree = ma->nodetree;
+               bNode *imanode;
+               bNodeTree *ntree = ma->nodetree;
 
-                       if (!ntree) {
-                               ED_node_shader_default(C, &ma->id);
-                               ntree = ma->nodetree;
-                       }
-
-                       ma->use_nodes = true;
+               if (!ntree) {
+                       ED_node_shader_default(C, &ma->id);
+                       ntree = ma->nodetree;
+               }
 
-                       /* try to add an image node */
-                       imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
+               ma->use_nodes = true;
 
-                       ima = proj_paint_image_create(op, bmain);
-                       imanode->id = &ima->id;
+               /* try to add an image node */
+               imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
 
-                       nodeSetActive(ntree, imanode);
+               ima = proj_paint_image_create(op, bmain);
+               imanode->id = &ima->id;
 
-                       ntreeUpdateTree(CTX_data_main(C), ntree);
-               }
-               else {
-                       MTex *mtex = BKE_texture_mtex_add_id(&ma->id, -1);
-
-                       /* successful creation of mtex layer, now create set */
-                       if (mtex) {
-                               int type = MAP_COL;
-                               char imagename_buff[MAX_ID_NAME - 2];
-                               const char *imagename = DATA_("Diffuse Color");
-
-                               if (op) {
-                                       type = RNA_enum_get(op->ptr, "type");
-                                       RNA_string_get(op->ptr, "name", imagename_buff);
-                                       imagename = imagename_buff;
-                               }
+               nodeSetActive(ntree, imanode);
 
-                               mtex->tex = BKE_texture_add(bmain, imagename);
-                               mtex->mapto = type;
-
-                               if (mtex->tex) {
-                                       ima = mtex->tex->ima = proj_paint_image_create(op, bmain);
-                               }
-
-                               WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, mtex->tex);
-                       }
-               }
+               ntreeUpdateTree(CTX_data_main(C), ntree);
 
                if (ima) {
                        BKE_texpaint_slot_refresh_cache(scene, ma);
                        BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
                        WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
-                       DAG_id_tag_update(&ma->id, 0);
+                       DEG_id_tag_update(&ma->id, 0);
                        ED_area_tag_redraw(CTX_wm_area(C));
 
                        BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
@@ -5826,59 +5761,6 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
        RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
 }
 
-static int texture_paint_delete_texture_paint_slot_exec(bContext *C, wmOperator *UNUSED(op))
-{
-       Object *ob = CTX_data_active_object(C);
-       Scene *scene = CTX_data_scene(C);
-       Material *ma;
-       bool is_bi = BKE_scene_uses_blender_internal(scene) || BKE_scene_uses_blender_game(scene);
-       TexPaintSlot *slot;
-
-       /* not supported for node-based engines */
-       if (!ob || !is_bi)
-               return OPERATOR_CANCELLED;
-
-       ma = give_current_material(ob, ob->actcol);
-
-       if (!ma->texpaintslot || ma->use_nodes)
-               return OPERATOR_CANCELLED;
-
-       slot = ma->texpaintslot + ma->paint_active_slot;
-
-       if (ma->mtex[slot->index]->tex) {
-               id_us_min(&ma->mtex[slot->index]->tex->id);
-
-               if (ma->mtex[slot->index]->tex->ima) {
-                       id_us_min(&ma->mtex[slot->index]->tex->ima->id);
-               }
-       }
-       MEM_freeN(ma->mtex[slot->index]);
-       ma->mtex[slot->index] = NULL;
-
-       BKE_texpaint_slot_refresh_cache(scene, ma);
-       DAG_id_tag_update(&ma->id, 0);
-       WM_event_add_notifier(C, NC_MATERIAL, ma);
-       /* we need a notifier for data change since we change the displayed modifier uvs */
-       WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
-       return OPERATOR_FINISHED;
-}
-
-
-void PAINT_OT_delete_texture_paint_slot(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name = "Delete Texture Paint Slot";
-       ot->description = "Delete selected texture paint slot";
-       ot->idname = "PAINT_OT_delete_texture_paint_slot";
-
-       /* api callbacks */
-       ot->exec = texture_paint_delete_texture_paint_slot_exec;
-       ot->poll = ED_operator_region_view3d_active;
-
-       /* flags */
-       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
 static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
 {
        /* no checks here, poll function does them for us */
@@ -5915,7 +5797,7 @@ static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
 
        BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
 
-       DAG_id_tag_update(ob->data, 0);
+       DEG_id_tag_update(ob->data, 0);
        WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
        WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene);
        return OPERATOR_FINISHED;
@@ -5925,9 +5807,9 @@ static int add_simple_uvs_poll(bContext *C)
 {
        Object *ob = CTX_data_active_object(C);
 
-       if (!ob || ob->type != OB_MESH || ob->mode != OB_MODE_TEXTURE_PAINT)
+       if (!ob || ob->type != OB_MESH || ob->mode != OB_MODE_TEXTURE_PAINT) {
                return false;
-
+       }
        return true;
 }