Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Tue, 11 Apr 2017 00:59:31 +0000 (10:59 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 11 Apr 2017 01:01:16 +0000 (11:01 +1000)
1  2 
source/blender/editors/space_view3d/drawobject.c

index ff8f4e7181876631a342a96fd8010959b092eea1,335d06497298e07ba4baa862786b0225d861fad9..4d00db871da79393ef9d79e213c9d8e4a29745d3
@@@ -4642,657 -4338,169 +4641,656 @@@ static bool draw_mesh_object(Scene *sce
        return retval;
  }
  
 -/* ************** DRAW DISPLIST ****************** */
 -
 -
 -/**
 - * \param dl_type_mask Only draw types matching this mask.
 - * \return true when nothing was drawn
 - */
 -static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask)
 +static void make_color_variations(const unsigned char base_ubyte[4], float low[4], float med[4], float high[4], const bool other_obedit)
  {
 -      if (dlbase == NULL) return true;
 -      
 -      glEnableClientState(GL_VERTEX_ARRAY);
 -      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 +      /* original idea: nice variations (lighter & darker shades) of base color
 +       * current implementation uses input color as high; med & low get closer to background color
 +       */
  
 -      for (DispList *dl = dlbase->first; dl; dl = dl->next) {
 -              if (dl->parts == 0 || dl->nr == 0) {
 -                      continue;
 -              }
 +      float bg[3];
 +      UI_GetThemeColor3fv(TH_BACK, bg);
  
 -              if ((dl_type_mask & (1 << dl->type)) == 0) {
 -                      continue;
 -              }
 -              
 -              const float *data = dl->verts;
 -              int parts;
 +      float base[4];
 +      rgba_uchar_to_float(base, base_ubyte);
  
 -              switch (dl->type) {
 -                      case DL_SEGM:
 +      if (other_obedit) {
 +              /* this object should fade away so user can focus on the object being edited */
 +              interp_v3_v3v3(low, bg, base, 0.1f);
 +              interp_v3_v3v3(med, bg, base, 0.2f);
 +              interp_v3_v3v3(high, bg, base, 0.25f);
 +      }
 +      else {
 +              interp_v3_v3v3(low, bg, base, 0.333f);
 +              interp_v3_v3v3(med, bg, base, 0.667f);
 +              copy_v3_v3(high, base);
 +      }
 +
 +      /* use original alpha */
 +      low[3] = base[3];
 +      med[3] = base[3];
 +      high[3] = base[3];
 +}
  
 -                              glVertexPointer(3, GL_FLOAT, 0, data);
 +static void draw_mesh_fancy_new(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
 +                                const char dt, const unsigned char ob_wire_col[4], const short dflag, const bool other_obedit)
 +{
 +      if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) {
 +              /* too complicated! use existing methods */
 +              /* TODO: move this into a separate depth pre-pass */
 +              draw_mesh_fancy(scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
 +              return;
 +      }
  
 -                              for (parts = 0; parts < dl->parts; parts++)
 -                                      glDrawArrays(GL_LINE_STRIP, parts * dl->nr, dl->nr);
 -                              
 -                              break;
 -                      case DL_POLY:
 +#ifdef WITH_GAMEENGINE
 +      Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, sl) : base->object;
 +#else
 +      Object *ob = base->object;
 +#endif
 +      Mesh *me = ob->data;
 +      eWireDrawMode draw_wire = OBDRAW_WIRE_OFF; /* could be bool draw_wire_overlay */
 +      bool no_edges, no_faces;
 +      DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
 +      const bool is_obact = (ob == OBACT_NEW);
 +      int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0;
  
 -                              glVertexPointer(3, GL_FLOAT, 0, data);
 +      if (!dm)
 +              return;
  
 -                              for (parts = 0; parts < dl->parts; parts++)
 -                                      glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr);
 +      const bool solid = dt >= OB_SOLID;
 +      if (solid) {
 +              DM_update_materials(dm, ob);
 +      }
  
 -                              break;
 -                      case DL_SURF:
 +      /* Check to draw dynamic paint colors (or weights from WeightVG modifiers).
 +       * Note: Last "preview-active" modifier in stack will win! */
 +      if (DM_get_loop_data_layer(dm, CD_PREVIEW_MLOOPCOL) && modifiers_isPreview(ob))
 +              draw_flags |= DRAW_MODIFIERS_PREVIEW;
  
 -                              glVertexPointer(3, GL_FLOAT, 0, data);
 +      /* Unwanted combination */
 +      if (draw_flags & DRAW_FACE_SELECT) {
 +              draw_wire = OBDRAW_WIRE_OFF;
 +      }
 +      else if (ob->dtx & OB_DRAWWIRE) {
 +              draw_wire = OBDRAW_WIRE_ON;
 +      }
  
 -                              for (parts = 0; parts < dl->parts; parts++) {
 -                                      if (dl->flag & DL_CYCL_U)
 -                                              glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr);
 -                                      else
 -                                              glDrawArrays(GL_LINE_STRIP, parts * dl->nr, dl->nr);
 -                              }
 +      /* check polys instead of tessfaces because of dyntopo where tessfaces don't exist */
 +      if (dm->type == DM_TYPE_CCGDM) {
 +              no_edges = !subsurf_has_edges(dm);
 +              no_faces = !subsurf_has_faces(dm);
 +      }
 +      else {
 +              no_edges = (dm->getNumEdges(dm) == 0);
 +              no_faces = (dm->getNumPolys(dm) == 0);
 +      }
  
 -                              for (int nr = 0; nr < dl->nr; nr++) {
 -                                      int ofs = 3 * dl->nr;
 +      if (solid) {
 +              /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
 +              glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
 +      }
  
 -                                      data = (dl->verts) + 3 * nr;
 -                                      parts = dl->parts;
 +      if (dt == OB_BOUNDBOX) {
 +              if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0)
 +                      draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
 +      }
 +      else if ((no_faces && no_edges) ||
 +               ((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob)))
 +      {
 +              glPointSize(1.5f);
 +              // dm->drawVerts(dm);
 +              // TODO: draw smooth round points as a batch
 +      }
 +      else if ((dt == OB_WIRE) || no_faces) {
 +              draw_wire = OBDRAW_WIRE_ON;
  
 -                                      if (dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
 -                                      else glBegin(GL_LINE_STRIP);
 +              /* enable depth for wireframes */
 +              glEnable(GL_DEPTH_TEST);
 +              glDepthFunc(GL_LESS);
  
 -                                      while (parts--) {
 -                                              glVertex3fv(data);
 -                                              data += ofs;
 -                                      }
 -                                      glEnd();
 +              glLineWidth(1.0f);
  
 -#if 0
 -                              /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
 -                              glVertexPointer(3, GL_FLOAT, sizeof(float) * 3 * dl->nr, data + 3 * nr);
 -                              if (dl->flag & DL_CYCL_V)
 -                                      glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
 -                              else
 -                                      glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
 -#endif
 -                              }
 -                              break;
 +#if 1 /* fancy wireframes */
  
 -                      case DL_INDEX3:
 -                              glVertexPointer(3, GL_FLOAT, 0, dl->verts);
 -                              glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index);
 -                              break;
 +              Batch *fancy_edges = BKE_mesh_batch_cache_get_fancy_edges(me);
  
 -                      case DL_INDEX4:
 -                              glVertexPointer(3, GL_FLOAT, 0, dl->verts);
 -                              glDrawElements(GL_QUADS, 4 * dl->parts, GL_UNSIGNED_INT, dl->index);
 -                              break;
 +              if (rv3d->persp == RV3D_ORTHO) {
 +                      Batch_set_builtin_program(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_ORTHO);
 +                      /* set eye vector, transformed to object coords */
 +                      float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */
 +                      mul_m3_v3((float (*)[3])gpuGetNormalMatrixInverse(NULL), eye);
 +                      Batch_Uniform3fv(fancy_edges, "eye", eye);
 +              }
 +              else {
 +                      Batch_set_builtin_program(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_PERSP);
                }
 -      }
 -      
 -      glDisableClientState(GL_VERTEX_ARRAY);
 -      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 -      
 -      return false;
 -}
 -
 -static bool drawDispListwire(ListBase *dlbase, const short ob_type)
 -{
 -      unsigned int dl_mask = 0xffffffff;
  
 -      /* skip fill-faces for curves & fonts */
 -      if (ELEM(ob_type, OB_FONT, OB_CURVE)) {
 -              dl_mask &= ~((1 << DL_INDEX3) | (1 << DL_INDEX4));
 -      }
 +              float frontColor[4];
 +              float backColor[4];
 +              float outlineColor[4];
 +              make_color_variations(ob_wire_col, backColor, frontColor, outlineColor, other_obedit);
  
 -      return drawDispListwire_ex(dlbase, dl_mask);
 -}
 +              Batch_Uniform4fv(fancy_edges, "frontColor", frontColor);
 +              Batch_Uniform4fv(fancy_edges, "backColor", backColor);
 +              Batch_Uniform1b(fancy_edges, "drawFront", true);
 +              Batch_Uniform1b(fancy_edges, "drawBack", true); /* false here = backface cull */
 +              Batch_Uniform1b(fancy_edges, "drawSilhouette", false);
  
 -static bool index3_nors_incr = true;
 +              Batch_draw(fancy_edges);
  
 -static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
 -                              const unsigned char ob_wire_col[4], const bool use_glsl)
 -{
 -      GPUVertexAttribs gattribs;
 -      
 -      if (lb == NULL) return;
 +              /* extra oomph for the silhouette contours */
 +              glLineWidth(2.0f);
 +              Batch_use_program(fancy_edges); /* hack to make the following uniforms stick */
 +              Batch_Uniform1b(fancy_edges, "drawFront", false);
 +              Batch_Uniform1b(fancy_edges, "drawBack", false);
 +              Batch_Uniform1b(fancy_edges, "drawSilhouette", true);
 +              Batch_Uniform4fv(fancy_edges, "silhouetteColor", outlineColor);
  
 -      glEnableClientState(GL_VERTEX_ARRAY);
 +              Batch_draw(fancy_edges);
  
 -      /* track current material, -1 for none (needed for lines) */
 -      short col = -1;
 -      
 -      DispList *dl = lb->first;
 -      while (dl) {
 -              const float *data = dl->verts;
 -              const float *ndata = dl->nors;
 +#else /* simple wireframes */
  
 -              switch (dl->type) {
 -                      case DL_SEGM:
 -                              if (ob->type == OB_SURF) {
 -                                      if (col != -1) {
 -                                              GPU_object_material_unbind();
 -                                              col = -1;
 -                                      }
 +              Batch *batch = MBC_get_all_edges(dm);
 +              Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR);
  
 -                                      if ((dflag & DRAW_CONSTCOLOR) == 0)
 -                                              glColor3ubv(ob_wire_col);
 +              float color[4];
 +              rgba_uchar_to_float(color, ob_wire_col);
  
 -                                      // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
 -                                      // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
 -                                      glBegin(GL_LINE_STRIP);
 -                                      for (int nr = dl->nr; nr; nr--, data += 3)
 -                                              glVertex3fv(data);
 -                                      glEnd();
 -                              }
 -                              break;
 -                      case DL_POLY:
 -                              if (ob->type == OB_SURF) {
 -                                      if (col != -1) {
 -                                              GPU_object_material_unbind();
 -                                              col = -1;
 -                                      }
 +              Batch_Uniform4fv(batch, "color", color);
  
 -                                      /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
 -                                      //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
 -                                      //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
 +              Batch_draw(batch);
 +#endif
 +      }
 +      else if (((is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
 +               check_object_draw_texture(scene, v3d, dt))
 +      {
 +              bool draw_loose = true;
 +
 +              if ((v3d->flag & V3D_SELECT_OUTLINE) &&
 +                  ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
 +                  (base->flag & BASE_SELECTED) &&
 +                  !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
 +                  (draw_wire == OBDRAW_WIRE_OFF))
 +              {
 +                      draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT_NEW));
 +              }
 +
 +              if (draw_glsl_material(scene, sl, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) {
 +                      Paint *p;
 +
 +                      glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
 +
 +                      if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene, sl))) {
 +                              GPUVertexAttribs gattribs;
 +                              float planes[4][4];
 +                              float (*fpl)[4] = NULL;
 +                              const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
 +
 +                              if (ob->sculpt->partial_redraw) {
 +                                      if (ar->do_draw & RGN_DRAW_PARTIAL) {
 +                                              ED_sculpt_redraw_planes_get(planes, ar, ob);
 +                                              fpl = planes;
 +                                              ob->sculpt->partial_redraw = 0;
 +                                      }
 +                              }
 +
 +                              GPU_object_material_bind(1, &gattribs);
 +                              dm->drawFacesSolid(dm, fpl, fast, NULL);
 +                              draw_loose = false;
 +                      }
 +                      else
 +                              dm->drawFacesGLSL(dm, GPU_object_material_bind);
 +
 +                      GPU_object_material_unbind();
 +
 +                      glFrontFace(GL_CCW);
 +
 +                      if (draw_flags & DRAW_FACE_SELECT)
 +                              draw_mesh_face_select(rv3d, me, dm, false);
 +              }
 +              else {
 +                      draw_mesh_textured(scene, sl, v3d, rv3d, ob, dm, draw_flags);
 +              }
 +
 +              if (draw_loose && !(draw_flags & DRAW_FACE_SELECT)) {
 +                      if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
 +                              if ((dflag & DRAW_CONSTCOLOR) == 0) {
 +                                      glColor3ubv(ob_wire_col);
 +                              }
 +                              glLineWidth(1.0f);
 +                              dm->drawLooseEdges(dm);
 +                      }
 +              }
 +      }
 +      else if (dt == OB_SOLID) {
 +              if (draw_flags & DRAW_MODIFIERS_PREVIEW) {
 +                      /* for object selection draws no shade */
 +                      if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) {
 +                              /* TODO: draw basic faces with GPU_SHADER_3D_DEPTH_ONLY */
 +                      }
 +                      else {
 +                              const float specular[3] = {0.47f, 0.47f, 0.47f};
 +
 +                              /* draw outline */
 +                              /* TODO: move this into a separate pass */
 +                              if ((v3d->flag & V3D_SELECT_OUTLINE) &&
 +                                  ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
 +                                  (base->flag & BASE_SELECTED) &&
 +                                  (draw_wire == OBDRAW_WIRE_OFF) &&
 +                                  (ob->sculpt == NULL))
 +                              {
 +                                      draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT_NEW));
 +                              }
 +
 +                              /* materials arent compatible with vertex colors */
 +                              GPU_end_object_materials();
 +
 +                              /* set default specular */
 +                              GPU_basic_shader_colors(NULL, specular, 35, 1.0f);
 +                              GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
 +
 +                              dm->drawMappedFaces(dm, NULL, NULL, NULL, NULL, DM_DRAW_USE_COLORS | DM_DRAW_NEED_NORMALS);
 +
 +                              GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
 +                      }
 +              }
 +              else {
 +                      Paint *p;
 +
 +                      if ((v3d->flag & V3D_SELECT_OUTLINE) &&
 +                          ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
 +                          (base->flag & BASE_SELECTED) &&
 +                          (draw_wire == OBDRAW_WIRE_OFF) &&
 +                          (ob->sculpt == NULL))
 +                      {
 +                              /* TODO: move this into a separate pass */
 +                              draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT_NEW));
 +                      }
 +
 +                      glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
 +
 +                      if (ob->sculpt && (p = BKE_paint_get_active(scene, sl))) {
 +                              float planes[4][4];
 +                              float (*fpl)[4] = NULL;
 +                              const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
 +
 +                              if (ob->sculpt->partial_redraw) {
 +                                      if (ar->do_draw & RGN_DRAW_PARTIAL) {
 +                                              ED_sculpt_redraw_planes_get(planes, ar, ob);
 +                                              fpl = planes;
 +                                              ob->sculpt->partial_redraw = 0;
 +                                      }
 +                              }
 +
 +                              dm->drawFacesSolid(dm, fpl, fast, GPU_object_material_bind);
 +                      }
 +                      else
 +                              dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind);
 +
 +                      glFrontFace(GL_CCW);
 +
 +                      GPU_object_material_unbind();
 +
 +                      if (!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
 +                              if ((dflag & DRAW_CONSTCOLOR) == 0) {
 +                                      glColor3ubv(ob_wire_col);
 +                              }
 +                              glLineWidth(1.0f);
 +                              dm->drawLooseEdges(dm);
 +                      }
 +              }
 +      }
 +      else if (dt == OB_PAINT) {
 +              draw_mesh_paint(v3d, rv3d, ob, dm, draw_flags);
  
 -                                      glBegin(GL_LINE_LOOP);
 -                                      for (int nr = dl->nr; nr; nr--, data += 3)
 -                                              glVertex3fv(data);
 -                                      glEnd();
 +              /* since we already draw wire as wp guide, don't draw over the top */
 +              draw_wire = OBDRAW_WIRE_OFF;
 +      }
 +
 +      if ((draw_wire != OBDRAW_WIRE_OFF) &&  /* draw extra wire */
 +          /* when overriding with render only, don't bother */
 +          (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_SOLID) == 0)) // <-- is this "== 0" in the right spot???
 +      {
 +              /* When using wireframe object draw in particle edit mode
 +               * the mesh gets in the way of seeing the particles, fade the wire color
 +               * with the background. */
 +
 +              if ((dflag & DRAW_CONSTCOLOR) == 0) {
 +                      /* TODO:
 +                       * Batch_UniformColor4ubv(ob_wire_col);
 +                       */
 +              }
 +
 +              /* If drawing wire and drawtype is not OB_WIRE then we are
 +               * overlaying the wires.
 +               *
 +               * No need for polygon offset because new technique is AWESOME.
 +               */
 +#if 0
 +              glLineWidth(1.0f);
 +              dm->drawEdges(dm, ((dt == OB_WIRE) || no_faces), (ob->dtx & OB_DRAW_ALL_EDGES) != 0);
 +#else
 +              /* something */
 +#endif
 +      }
 +      
 +#if 0 // (merwin) what is this for?
 +      if (is_obact && BKE_paint_select_vert_test(ob)) {
 +              const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) != 0;
-               glColor3f(0.0f, 0.0f, 0.0f);
 +              glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
 +
 +              if (!use_depth) glDisable(GL_DEPTH_TEST);
 +              else            ED_view3d_polygon_offset(rv3d, 1.0);
 +              drawSelectedVertices(dm, ob->data);
 +              if (!use_depth) glEnable(GL_DEPTH_TEST);
 +              else            ED_view3d_polygon_offset(rv3d, 0.0);
 +      }
 +#endif
 +
 +      dm->release(dm);
 +}
 +
 +static bool draw_mesh_object_new(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
 +                                 const char dt, const unsigned char ob_wire_col[4], const short dflag)
 +{
 +      Object *ob = base->object;
 +      Object *obedit = scene->obedit;
 +      Mesh *me = ob->data;
 +      BMEditMesh *em = me->edit_btmesh;
 +      bool do_alpha_after = false, drawlinked = false, retval = false;
 +
 +      if (v3d->flag2 & V3D_RENDER_SHADOW) {
 +              /* TODO: handle shadow pass separately */
 +              return true;
 +      }
 +      
 +      if (obedit && ob != obedit && ob->data == obedit->data) {
 +              if (BKE_key_from_object(ob) || BKE_key_from_object(obedit)) {}
 +              else if (ob->modifiers.first || obedit->modifiers.first) {}
 +              else drawlinked = true;
 +      }
 +
 +      /* backface culling */
 +      const bool solid = dt > OB_WIRE;
 +      const bool cullBackface = solid && (v3d->flag2 & V3D_BACKFACE_CULLING);
 +      if (cullBackface) {
 +              glEnable(GL_CULL_FACE);
 +              glCullFace(GL_BACK);
 +      }
 +
 +      if (ob == obedit || drawlinked) {
 +              DerivedMesh *finalDM, *cageDM;
 +
 +              if (obedit != ob) {
 +                      /* linked to the edit object */
 +                      finalDM = cageDM = editbmesh_get_derived_base(
 +                              ob, em, scene->customdata_mask);
 +              }
 +              else {
 +                      cageDM = editbmesh_get_derived_cage_and_final(
 +                              scene, ob, em, scene->customdata_mask,
 +                              &finalDM);
 +              }
 +
 +              const bool use_material = solid && ((me->drawflag & ME_DRAWEIGHT) == 0);
 +
 +#if 0 // why update if not being used?
 +              DM_update_materials(finalDM, ob);
 +              if (cageDM != finalDM) {
 +                      DM_update_materials(cageDM, ob);
 +              }
 +#endif // moved to below
 +
 +              if (use_material) {
 +                      DM_update_materials(finalDM, ob);
 +                      if (cageDM != finalDM) {
 +                              DM_update_materials(cageDM, ob);
 +                      }
 +
 +                      const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt);
 +
 +                      GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL);
 +              }
 +
 +              draw_em_fancy_new(scene, ar, v3d, ob, me, em, cageDM, finalDM, dt);
 +
 +              if (use_material) {
 +                      GPU_end_object_materials();
 +              }
 +
 +              if (obedit != ob)
 +                      finalDM->release(finalDM);
 +      }
 +      else {
 +              /* ob->bb was set by derived mesh system, do NULL check just to be sure */
 +              if (me->totpoly <= 4 || (!ob->bb || ED_view3d_boundbox_clip(rv3d, ob->bb))) {
 +                      if (solid) {
 +                              const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt);
 +
 +                              if (dt == OB_SOLID || glsl) {
 +                                      const bool check_alpha = check_alpha_pass(base);
 +                                      GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl,
 +                                                                 (check_alpha) ? &do_alpha_after : NULL);
 +                              }
 +                      }
 +
 +                      const bool other_obedit = obedit && (obedit != ob);
 +
 +                      draw_mesh_fancy_new(scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag, other_obedit);
 +
 +                      GPU_end_object_materials();
 +
 +                      if (me->totvert == 0) retval = true;
 +              }
 +      }
 +
 +      if (cullBackface)
 +              glDisable(GL_CULL_FACE);
 +
 +      return retval;
 +}
 +
 +/* ************** DRAW DISPLIST ****************** */
 +
 +static void drawDispListVerts(PrimitiveType prim_type, const void *data, unsigned int vert_ct, const unsigned char wire_col[3])
 +{
 +      VertexFormat format = {0};
 +      unsigned int pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
 +
 +      VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
 +      VertexBuffer_allocate_data(vbo, vert_ct);
 +
 +      VertexBuffer_fill_attrib(vbo, pos_id, data);
 +
 +      Batch *batch = Batch_create(prim_type, vbo, NULL);
 +      Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR);
 +      if (wire_col) {
 +              Batch_Uniform4f(batch, "color", wire_col[0]/255.0f, wire_col[1]/255.0f, wire_col[2]/255.0f, 1.0f);
 +      }
 +      Batch_draw(batch);
 +      Batch_discard_all(batch);
 +}
 +
 +/* convert dispList with elem indices to batch, only support triangles and quads
 + * XXX : This is a huge perf issue. We should cache the resulting batches inside the object instead.
 + *       But new viewport will do it anyway
 + * TODO implement flat drawing */
 +static void drawDispListElem(bool quads, bool UNUSED(smooth), const float *data, const float *ndata, unsigned int vert_ct,
 +                             const int *elem, unsigned int elem_ct, const unsigned char wire_col[3])
 +{
 +      VertexFormat format = {0};
 +      int i;
 +      const int *idx = elem;
 +      unsigned int pos_id, nor_id;
 +
 +      pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
 +      if (ndata) {
 +              nor_id = VertexFormat_add_attrib(&format, "nor", COMP_F32, 3, KEEP_FLOAT);
 +      }
 +
 +      ElementListBuilder elb;
 +      ElementListBuilder_init(&elb, PRIM_TRIANGLES, (quads) ? elem_ct * 2 : elem_ct, 0xffffffff);
 +
 +      if (quads) {
 +              for (i = elem_ct; i; --i, idx += 4) {
 +                      add_triangle_vertices(&elb, idx[0], idx[1], idx[2]);
 +                      add_triangle_vertices(&elb, idx[0], idx[2], idx[3]);
 +              }
 +      }
 +      else {
 +              for (i = elem_ct; i; --i, idx += 3) {
 +                      add_triangle_vertices(&elb, idx[0], idx[1], idx[2]);
 +              }
 +      }
 +
 +      VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
 +      VertexBuffer_allocate_data(vbo, vert_ct);
 +
 +      VertexBuffer_fill_attrib(vbo, pos_id, data);
 +
 +      if (ndata) {
 +              VertexBuffer_fill_attrib(vbo, nor_id, ndata);
 +      }
 +
 +      Batch *batch = Batch_create(PRIM_TRIANGLES, vbo, ElementList_build(&elb));
 +      Batch_set_builtin_program(batch, GPU_SHADER_SIMPLE_LIGHTING);
 +      if (wire_col) {
 +              Batch_Uniform4f(batch, "color", wire_col[0]/255.0f, wire_col[1]/255.0f, wire_col[2]/255.0f, 1.0f);
 +      }
 +      Batch_Uniform4f(batch, "color", 0.8f, 0.8f, 0.8f, 1.0f);
 +      Batch_Uniform3f(batch, "light", 0.0f, 0.0f, 1.0f);
 +      Batch_draw(batch);
 +      Batch_discard_all(batch);
 +}
 +
 +/**
 + * \param dl_type_mask Only draw types matching this mask.
 + * \return true when nothing was drawn
 + */
 +static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask, const unsigned char wire_col[3])
 +{
 +      if (dlbase == NULL) return true;
 +      
 +      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 +
 +      for (DispList *dl = dlbase->first; dl; dl = dl->next) {
 +              if (dl->parts == 0 || dl->nr == 0) {
 +                      continue;
 +              }
 +
 +              if ((dl_type_mask & (1 << dl->type)) == 0) {
 +                      continue;
 +              }
 +
 +              const float *data = dl->verts;
 +              int parts;
 +
 +              switch (dl->type) {
 +                      case DL_SEGM:
 +                              for (parts = 0; parts < dl->parts; parts++)
 +                                      drawDispListVerts(PRIM_LINE_STRIP, data + (parts * dl->nr * 3), dl->nr, wire_col);
 +                              break;
 +
 +                      case DL_POLY:
 +                              for (parts = 0; parts < dl->parts; parts++)
 +                                      drawDispListVerts(PRIM_LINE_LOOP, data + (parts * dl->nr * 3), dl->nr, wire_col);
 +                              break;
 +
 +                      case DL_SURF:
 +                              for (parts = 0; parts < dl->parts; parts++) {
 +                                      if (dl->flag & DL_CYCL_U)
 +                                              drawDispListVerts(PRIM_LINE_LOOP, data + (parts * dl->nr * 3), dl->nr, wire_col);
 +                                      else
 +                                              drawDispListVerts(PRIM_LINE_STRIP, data + (parts * dl->nr * 3), dl->nr, wire_col);
 +                              }
 +
 +                              float *data_aligned = MEM_mallocN(sizeof(float) * 3 * dl->parts, "aligned data");
 +                              for (int nr = 0; nr < dl->nr; nr++) {
 +                                      int ofs = 3 * dl->nr;
 +                                      int idx = 0;
 +
 +                                      data = (dl->verts) + 3 * nr;
 +                                      parts = dl->parts;
 +
 +                                      while (parts--) {
 +                                              copy_v3_v3(data_aligned + idx, data);
 +                                              data += ofs;
 +                                              idx += 3;
 +                                      }
 +
 +                                      if (dl->flag & DL_CYCL_V)
 +                                              drawDispListVerts(PRIM_LINE_LOOP, data_aligned, dl->parts, wire_col);
 +                                      else
 +                                              drawDispListVerts(PRIM_LINE_STRIP, data_aligned, dl->parts, wire_col);
 +                              }
 +
 +                              if (data_aligned)
 +                                      MEM_freeN(data_aligned);
 +
 +                              break;
 +
 +                      case DL_INDEX3:
 +                              drawDispListElem(false, true, dl->verts, NULL, dl->nr, dl->index, dl->parts, wire_col);
 +                              break;
 +
 +                      case DL_INDEX4:
 +                              drawDispListElem(true, true, dl->verts, NULL, dl->nr, dl->index, dl->parts, wire_col);
 +                              break;
 +              }
 +      }
 +      
 +      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 +      
 +      return false;
 +}
 +
 +static bool drawDispListwire(ListBase *dlbase, const short ob_type, const unsigned char wire_col[3])
 +{
 +      unsigned int dl_mask = 0xffffffff;
 +
 +      /* skip fill-faces for curves & fonts */
 +      if (ELEM(ob_type, OB_FONT, OB_CURVE)) {
 +              dl_mask &= ~((1 << DL_INDEX3) | (1 << DL_INDEX4));
 +      }
 +
 +      return drawDispListwire_ex(dlbase, dl_mask, wire_col);
 +}
 +
 +static bool index3_nors_incr = true;
 +
 +static void drawDispListsolid(ListBase *lb, Object *ob, const short UNUSED(dflag),
 +                              const unsigned char ob_wire_col[4], const bool use_glsl)
 +{
 +      GPUVertexAttribs gattribs;
 +      
 +      if (lb == NULL) return;
 +
 +      /* track current material, -1 for none (needed for lines) */
 +      short col = -1;
 +      
 +      DispList *dl = lb->first;
 +      while (dl) {
 +              const float *data = dl->verts;
 +              //const float *ndata = dl->nors;
 +
 +              switch (dl->type) {
 +                      case DL_SEGM:
 +                              if (ob->type == OB_SURF) {
 +                                      if (col != -1) {
 +                                              GPU_object_material_unbind();
 +                                              col = -1;
 +                                      }
 +
 +                                      drawDispListVerts(PRIM_LINE_STRIP, data, dl->nr, ob_wire_col);
 +                              }
 +                              break;
 +                      case DL_POLY:
 +                              if (ob->type == OB_SURF) {
 +                                      if (col != -1) {
 +                                              GPU_object_material_unbind();
 +                                              col = -1;
 +                                      }
 +
 +                                      drawDispListVerts(PRIM_LINE_LOOP, data, dl->nr, ob_wire_col);
                                }
                                break;
                        case DL_SURF: