Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / uvedit / uvedit_draw.c
index 79dcfb3..e467c61 100644 (file)
@@ -33,6 +33,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "MEM_guardedalloc.h"
+
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_editmesh.h"
 #include "BKE_material.h"
+#include "BKE_layer.h"
 
 #include "BKE_scene.h"
 
-#include "BIF_gl.h"
 #include "BIF_glutil.h"
 
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "GPU_batch.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+
 #include "ED_image.h"
 #include "ED_mesh.h"
 #include "ED_uvedit.h"
 
 #include "uvedit_intern.h"
 
-#include "GPU_basic_shader.h"
-
-/* use editmesh tessface */
-#define USE_EDBM_LOOPTRIS
-
-static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset);
+static void draw_uvs_lineloop_bmfaces(BMesh *bm, const int cd_loop_uv_offset, const uint shdr_pos);
 
 void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
 {
@@ -82,37 +87,58 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
        x_fac = zoom[0];
        y_fac = zoom[1];
 
-       cpack(0xFFFFFF);
-       glTranslate2fv(cursor);
-       fdrawline(-0.05f * x_fac, 0, 0, 0.05f * y_fac);
-       fdrawline(0, 0.05f * y_fac, 0.05f * x_fac, 0.0f);
-       fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac);
-       fdrawline(0.0f, -0.05f * y_fac, -0.05f * x_fac, 0.0f);
-
-       setlinestyle(4);
-       cpack(0xFF);
-       fdrawline(-0.05f * x_fac, 0.0f, 0.0f, 0.05f * y_fac);
-       fdrawline(0.0f, 0.05f * y_fac, 0.05f * x_fac, 0.0f);
-       fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac);
-       fdrawline(0.0f, -0.05f * y_fac, -0.05f * x_fac, 0.0f);
-
-
-       setlinestyle(0.0f);
-       cpack(0x0);
-       fdrawline(-0.020f * x_fac, 0.0f, -0.1f * x_fac, 0.0f);
-       fdrawline(0.1f * x_fac, 0.0f, 0.020f * x_fac, 0.0f);
-       fdrawline(0.0f, -0.020f * y_fac, 0.0f, -0.1f * y_fac);
-       fdrawline(0.0f, 0.1f * y_fac, 0.0f, 0.020f * y_fac);
-
-       setlinestyle(1);
-       cpack(0xFFFFFF);
-       fdrawline(-0.020f * x_fac, 0.0f, -0.1f * x_fac, 0.0f);
-       fdrawline(0.1f * x_fac, 0.0f, 0.020f * x_fac, 0.0f);
-       fdrawline(0.0f, -0.020f * y_fac, 0.0f, -0.1f * y_fac);
-       fdrawline(0.0f, 0.1f * y_fac, 0.0f, 0.020f * y_fac);
-
-       glTranslatef(-cursor[0], -cursor[1], 0.0);
-       setlinestyle(0);
+       gpuTranslate2fv(cursor);
+
+       const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+       immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+       float viewport_size[4];
+       glGetFloatv(GL_VIEWPORT, viewport_size);
+       immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+       immUniform1i("num_colors", 2);  /* "advanced" mode */
+       immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2);
+       immUniform1f("dash_width", 8.0f);
+
+       immBegin(GWN_PRIM_LINES, 8);
+
+       immVertex2f(shdr_pos, -0.05f * x_fac, 0.0f);
+       immVertex2f(shdr_pos, 0.0f, 0.05f * y_fac);
+
+       immVertex2f(shdr_pos, 0.0f, 0.05f * y_fac);
+       immVertex2f(shdr_pos, 0.05f * x_fac, 0.0f);
+
+       immVertex2f(shdr_pos, 0.05f * x_fac, 0.0f);
+       immVertex2f(shdr_pos, 0.0f, -0.05f * y_fac);
+
+       immVertex2f(shdr_pos, 0.0f, -0.05f * y_fac);
+       immVertex2f(shdr_pos, -0.05f * x_fac, 0.0f);
+
+       immEnd();
+
+       immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
+       immUniform1f("dash_width", 2.0f);
+
+       immBegin(GWN_PRIM_LINES, 8);
+
+       immVertex2f(shdr_pos, -0.020f * x_fac, 0.0f);
+       immVertex2f(shdr_pos, -0.1f * x_fac, 0.0f);
+
+       immVertex2f(shdr_pos, 0.1f * x_fac, 0.0f);
+       immVertex2f(shdr_pos, 0.020f * x_fac, 0.0f);
+
+       immVertex2f(shdr_pos, 0.0f, -0.020f * y_fac);
+       immVertex2f(shdr_pos, 0.0f, -0.1f * y_fac);
+
+       immVertex2f(shdr_pos, 0.0f, 0.1f * y_fac);
+       immVertex2f(shdr_pos, 0.0f, 0.020f * y_fac);
+
+       immEnd();
+
+       immUnbindProgram();
+
+       gpuTranslate2f(-cursor[0], -cursor[1]);
 }
 
 static int draw_uvs_face_check(Scene *scene)
@@ -136,46 +162,33 @@ static void draw_uvs_shadow(Object *obedit)
 {
        BMEditMesh *em = BKE_editmesh_from_object(obedit);
        BMesh *bm = em->bm;
-       BMFace *efa;
-       BMIter iter;
 
        const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
 
-       /* draws the mesh when painting */
-       UI_ThemeColor(TH_UV_SHADOW);
+       unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 
-       BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
-               draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
-       }
-}
+       immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 
-static int draw_uvs_dm_shadow(DerivedMesh *dm)
-{
-       /* draw shadow mesh - this is the mesh with the modifier applied */
+       /* draws the mesh when painting */
+       immUniformThemeColor(TH_UV_SHADOW);
 
-       if (dm && dm->drawUVEdges && CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
-               UI_ThemeColor(TH_UV_SHADOW);
-               dm->drawUVEdges(dm);
-               return 1;
-       }
+       draw_uvs_lineloop_bmfaces(bm, cd_loop_uv_offset, pos);
 
-       return 0;
+       immUnbindProgram();
 }
 
-static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTexPoly *activetf)
+static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, Object *obedit, BMEditMesh *em, const BMFace *efa_act)
 {
        BMesh *bm = em->bm;
        BMFace *efa;
        BMLoop *l;
        BMIter iter, liter;
-       MTexPoly *tf;
        MLoopUV *luv;
        Image *ima = sima->image;
        float aspx, aspy, col[4];
        int i;
 
        const int cd_loop_uv_offset  = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-       const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
 
        BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
        BLI_buffer_declare_static(vec2f, tf_uvorig_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
@@ -191,7 +204,6 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
                                const int efa_len = efa->len;
                                float (*tf_uv)[2]     = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf,     vec2f, efa_len);
                                float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uvorig_buf, vec2f, efa_len);
-                               tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
 
                                BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
                                        luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -203,28 +215,37 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
                                totarea += BM_face_calc_area(efa);
                                totuvarea += area_poly_v2(tf_uv, efa->len);
 
-                               if (uvedit_face_visible_test(scene, ima, efa, tf)) {
+                               if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
                                        BM_elem_flag_enable(efa, BM_ELEM_TAG);
                                }
                                else {
-                                       if (tf == activetf)
-                                               activetf = NULL;
+                                       if (efa == efa_act) {
+                                               efa_act = NULL;
+                                       }
                                        BM_elem_flag_disable(efa, BM_ELEM_TAG);
                                }
                        }
 
+                       unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+                       immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
                        if (totarea < FLT_EPSILON || totuvarea < FLT_EPSILON) {
                                col[0] = 1.0;
                                col[1] = col[2] = 0.0;
-                               glColor3fv(col);
+
+                               immUniformColor3fv(col);
+
                                BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
                                        if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
-                                               glBegin(GL_POLYGON);
+                                               immBegin(GWN_PRIM_TRI_FAN, efa->len);
+
                                                BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
                                                        luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-                                                       glVertex2fv(luv->uv);
+                                                       immVertex2fv(pos, luv->uv);
                                                }
-                                               glEnd();
+
+                                               immEnd();
                                        }
                                }
                        }
@@ -254,18 +275,23 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
                                                        areadiff = 1.0f - (area / uvarea);
 
                                                weight_to_rgb(col, areadiff);
-                                               glColor3fv(col);
+                                               immUniformColor3fv(col);
+
+                                               /* TODO: use editmesh tessface */
+                                               immBegin(GWN_PRIM_TRI_FAN, efa->len);
 
-                                               /* TODO: USE_EDBM_LOOPTRIS */
-                                               glBegin(GL_POLYGON);
                                                BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
                                                        luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-                                                       glVertex2fv(luv->uv);
+                                                       immVertex2fv(pos, luv->uv);
                                                }
-                                               glEnd();
+
+                                               immEnd();
                                        }
                                }
                        }
+
+                       immUnbindProgram();
+
                        break;
                }
                case SI_UVDT_STRETCH_ANGLE:
@@ -279,10 +305,14 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
 
                        col[3] = 0.5f; /* hard coded alpha, not that nice */
 
-                       BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
-                               tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
+                       Gwn_VertFormat *format = immVertexFormat();
+                       unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+                       unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
 
-                               if (uvedit_face_visible_test(scene, ima, efa, tf)) {
+                       immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+                       BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+                               if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
                                        const int efa_len = efa->len;
                                        float (*tf_uv)[2]     = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf,     vec2f, efa_len);
                                        float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uvorig_buf, vec2f, efa_len);
@@ -319,24 +349,26 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
                                                ang[i] = angle_normalized_v3v3(av[i], av[(i + 1) % efa_len]);
                                        }
 
-                                       /* TODO: USE_EDBM_LOOPTRIS */
-                                       glBegin(GL_POLYGON);
+                                       /* TODO: use editmesh tessface */
+                                       immBegin(GWN_PRIM_TRI_FAN, efa->len);
                                        BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
                                                luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
                                                a = fabsf(uvang[i] - ang[i]) / (float)M_PI;
                                                weight_to_rgb(col, 1.0f - pow2f(1.0f - a));
-                                               glColor3fv(col);
-                                               glVertex2fv(luv->uv);
+                                               immAttrib3fv(color, col);
+                                               immVertex2fv(pos, luv->uv);
                                        }
-                                       glEnd();
+                                       immEnd();
                                }
                                else {
-                                       if (tf == activetf)
-                                               activetf = NULL;
+                                       if (efa == efa_act)
+                                               efa_act = NULL;
                                        BM_elem_flag_disable(efa, BM_ELEM_TAG);
                                }
                        }
 
+                       immUnbindProgram();
+
                        BLI_buffer_free(&uvang_buf);
                        BLI_buffer_free(&ang_buf);
                        BLI_buffer_free(&av_buf);
@@ -350,58 +382,58 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
        BLI_buffer_free(&tf_uvorig_buf);
 }
 
-static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset)
+static void draw_uvs_lineloop_bmfaces(BMesh *bm, const int cd_loop_uv_offset, const uint shdr_pos)
 {
-       BMIter liter;
+       BMIter iter, liter;
+       BMFace *efa;
        BMLoop *l;
        MLoopUV *luv;
 
-       glBegin(GL_LINE_LOOP);
-       BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
-               luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-               glVertex2fv(luv->uv);
+       /* For more efficiency first transfer the entire buffer to vram. */
+       Gwn_Batch *loop_batch = immBeginBatchAtMost(GWN_PRIM_LINE_LOOP, bm->totloop);
+
+       BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+               if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+                       continue;
+
+               BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
+                       luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+                       immVertex2fv(shdr_pos, luv->uv);
+               }
+       }
+       immEnd();
+
+       /* Then draw each face contour separately. */
+       GWN_batch_program_use_begin(loop_batch);
+       unsigned int index = 0;
+       BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+               if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+                       continue;
+
+               GWN_batch_draw_range_ex(loop_batch, index, efa->len, false);
+               index += efa->len;
        }
-       glEnd();
+       GWN_batch_program_use_end(loop_batch);
+       GWN_batch_discard(loop_batch);
 }
 
-static void draw_uvs_lineloop_mpoly(Mesh *me, MPoly *mpoly)
+static void draw_uvs_lineloop_mpoly(Mesh *me, MPoly *mpoly, unsigned int pos)
 {
        MLoopUV *mloopuv;
        int i;
 
-       glBegin(GL_LINE_LOOP);
+       immBegin(GWN_PRIM_LINE_LOOP, mpoly->totloop);
+
        mloopuv = &me->mloopuv[mpoly->loopstart];
        for (i = mpoly->totloop; i != 0; i--, mloopuv++) {
-               glVertex2fv(mloopuv->uv);
-       }
-       glEnd();
-}
-
-static void draw_uvs_other_mesh_texface(Object *ob, const Image *curimage, const int other_uv_filter)
-{
-       Mesh *me = ob->data;
-       MPoly *mpoly = me->mpoly;
-       MTexPoly *mtpoly = me->mtpoly;
-       int a;
-
-       if (me->mloopuv == NULL) {
-               return;
+               immVertex2fv(pos, mloopuv->uv);
        }
 
-       for (a = me->totpoly; a != 0; a--, mpoly++, mtpoly++) {
-               if (other_uv_filter == SI_FILTER_ALL) {
-                       /* Nothing to compare, all UV faces are visible. */
-               }
-               else if (other_uv_filter == SI_FILTER_SAME_IMAGE) {
-                       if (mtpoly->tpage != curimage) {
-                               continue;
-                       }
-               }
-
-               draw_uvs_lineloop_mpoly(me, mpoly);
-       }
+       immEnd();
 }
-static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage, const int other_uv_filter)
+
+static void draw_uvs_other_mesh(Object *ob, const Image *curimage,
+                                const int other_uv_filter, unsigned int pos)
 {
        Mesh *me = ob->data;
        MPoly *mpoly = me->mpoly;
@@ -453,53 +485,42 @@ static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage, c
                        }
                }
 
-               draw_uvs_lineloop_mpoly(me, mpoly);
-       }
-}
-static void draw_uvs_other_mesh(Object *ob, const Image *curimage, const bool new_shading_nodes,
-                                const int other_uv_filter)
-{
-       if (new_shading_nodes) {
-               draw_uvs_other_mesh_new_shading(ob, curimage, other_uv_filter);
-       }
-       else {
-               draw_uvs_other_mesh_texface(ob, curimage, other_uv_filter);
+               draw_uvs_lineloop_mpoly(me, mpoly, pos);
        }
 }
 
-static void draw_uvs_other(Scene *scene, Object *obedit, const Image *curimage, const bool new_shading_nodes,
+static void draw_uvs_other(ViewLayer *view_layer, Object *obedit, const Image *curimage,
                            const int other_uv_filter)
 {
-       Base *base;
-
-       UI_ThemeColor(TH_UV_OTHERS);
+       unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 
-       for (base = scene->base.first; base; base = base->next) {
-               Object *ob = base->object;
+       immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 
-               if (!(base->flag & SELECT)) continue;
-               if (!(base->lay & scene->lay)) continue;
-               if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
+       immUniformThemeColor(TH_UV_OTHERS);
 
-               if ((ob->type == OB_MESH) && (ob != obedit) && ((Mesh *)ob->data)->mloopuv) {
-                       draw_uvs_other_mesh(ob, curimage, new_shading_nodes, other_uv_filter);
+       for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+               if (((base->flag & BASE_SELECTED) != 0) &&
+                   ((base->flag & BASE_VISIBLED) != 0))
+               {
+                       Object *ob = base->object;
+                       if ((ob->type == OB_MESH) && (ob != obedit) && ((Mesh *)ob->data)->mloopuv) {
+                               draw_uvs_other_mesh(ob, curimage, other_uv_filter, pos);
+                       }
                }
        }
+       immUnbindProgram();
 }
 
-static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
+static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Object *ob)
 {
-       const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
        Image *curimage = ED_space_image(sima);
        Mesh *me = ob->data;
        Material *ma;
 
        if (sima->flag & SI_DRAW_OTHER) {
-               draw_uvs_other(scene, ob, curimage, new_shading_nodes, sima->other_uv_filter);
+               draw_uvs_other(view_layer, ob, curimage, sima->other_uv_filter);
        }
 
-       UI_ThemeColor(TH_UV_SHADOW);
-
        ma = give_current_material(ob, ob->actcol);
 
        if (me->mloopuv) {
@@ -512,24 +533,33 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
                        mloopuv = me->mloopuv;
                }
 
+               unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+               immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+               immUniformThemeColor(TH_UV_SHADOW);
+
                mloopuv_base = mloopuv;
 
                for (a = me->totpoly; a > 0; a--, mpoly++) {
                        if ((scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE) && mpoly->mat_nr != ob->actcol - 1)
                                continue;
-                       glBegin(GL_LINE_LOOP);
+
+                       immBegin(GWN_PRIM_LINE_LOOP, mpoly->totloop);
 
                        mloopuv = mloopuv_base + mpoly->loopstart;
                        for (b = 0; b < mpoly->totloop; b++, mloopuv++) {
-                               glVertex2fv(mloopuv->uv);
+                               immVertex2fv(pos, mloopuv->uv);
                        }
-                       glEnd();
+
+                       immEnd();
                }
+
+               immUnbindProgram();
        }
 }
 
-#ifdef USE_EDBM_LOOPTRIS
-static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const int cd_loop_uv_offset)
+static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const int cd_loop_uv_offset, unsigned int pos)
 {
        unsigned int i = *r_loop_index;
        BMFace *f = em->looptris[i][0]->f;
@@ -537,43 +567,34 @@ static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const i
                unsigned int j;
                for (j = 0; j < 3; j++) {
                        MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(em->looptris[i][j], cd_loop_uv_offset);
-                       glVertex2fv(luv->uv);
+                       immVertex2fv(pos, luv->uv);
                }
                i++;
        } while (i != em->tottri && (f == em->looptris[i][0]->f));
        *r_loop_index = i - 1;
 }
-#endif
 
 /* draws uv's in the image space */
-static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
+static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Object *obedit, Depsgraph *depsgraph)
 {
-       const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
        ToolSettings *ts;
        Mesh *me = obedit->data;
        BMEditMesh *em = me->edit_btmesh;
        BMesh *bm = em->bm;
        BMFace *efa, *efa_act;
-#ifndef USE_EDBM_LOOPTRIS
-       BMFace *activef;
-#endif
        BMLoop *l;
        BMIter iter, liter;
-       MTexPoly *tf, *activetf = NULL;
        MLoopUV *luv;
-       DerivedMesh *finaldm, *cagedm;
-       unsigned char col1[4], col2[4];
+       float col1[4], col2[4];
        float pointsize;
        int drawfaces, interpedges;
        Image *ima = sima->image;
 
        const int cd_loop_uv_offset  = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-       const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
 
-       efa_act = EDBM_uv_active_face_get(em, false, false, &activetf); /* will be set to NULL if hidden */
-#ifndef USE_EDBM_LOOPTRIS
-       activef = BM_mesh_active_face_get(bm, false, false);
-#endif
+       unsigned int pos, color;
+
+       efa_act = EDBM_uv_active_face_get(em, false, false); /* will be set to NULL if hidden */
        ts = scene->toolsettings;
 
        drawfaces = draw_uvs_face_check(scene);
@@ -586,272 +607,279 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
        if (sima->flag & SI_DRAW_OTHER) {
                Image *curimage;
 
-               if (new_shading_nodes) {
-                       if (efa_act) {
-                               ED_object_get_active_image(obedit, efa_act->mat_nr + 1, &curimage, NULL, NULL, NULL);
-                       }
-                       else {
-                               curimage = ima;
-                       }
+               if (efa_act) {
+                       ED_object_get_active_image(obedit, efa_act->mat_nr + 1, &curimage, NULL, NULL, NULL);
                }
                else {
-                       curimage = (activetf) ? activetf->tpage : ima;
+                       curimage = ima;
                }
 
-               draw_uvs_other(scene, obedit, curimage, new_shading_nodes, sima->other_uv_filter);
+               draw_uvs_other(view_layer, obedit, curimage, sima->other_uv_filter);
        }
 
        /* 1. draw shadow mesh */
 
        if (sima->flag & SI_DRAWSHADOW) {
-               DM_update_materials(em->derivedFinal, obedit);
-               /* first try existing derivedmesh */
-               if (!draw_uvs_dm_shadow(em->derivedFinal)) {
-                       /* create one if it does not exist */
-                       cagedm = editbmesh_get_derived_cage_and_final(
-                               scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH | CD_MASK_MTFACE,
-                               &finaldm);
-
-                       /* when sync selection is enabled, all faces are drawn (except for hidden)
-                        * so if cage is the same as the final, theres no point in drawing this */
-                       if (!((ts->uv_flag & UV_SYNC_SELECTION) && (cagedm == finaldm)))
-                               draw_uvs_dm_shadow(finaldm);
-
-                       /* release derivedmesh again */
-                       if (cagedm != finaldm) cagedm->release(cagedm);
-                       finaldm->release(finaldm);
+               Object *ob_cage_eval = DEG_get_evaluated_object(depsgraph, obedit);
+               /* XXX TODO: Need to check if shadow mesh is different than original mesh. */
+               bool is_cage_like_final_meshes = (ob_cage_eval == obedit);
+
+               /* When sync selection is enabled, all faces are drawn (except for hidden)
+                * so if cage is the same as the final, there is no point in drawing this. */
+               if (((ts->uv_flag & UV_SYNC_SELECTION) == 0) || is_cage_like_final_meshes) {
+                       draw_uvs_shadow(ob_cage_eval);
                }
        }
 
        /* 2. draw colored faces */
 
        if (sima->flag & SI_DRAW_STRETCH) {
-               draw_uvs_stretch(sima, scene, em, activetf);
+               draw_uvs_stretch(sima, scene, obedit, em, efa_act);
        }
-       else if (!(sima->flag & SI_NO_DRAWFACES)) {
-               /* draw transparent faces */
-               UI_GetThemeColor4ubv(TH_FACE, col1);
-               UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
-               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-               glEnable(GL_BLEND);
+       else {
+               unsigned int tri_count = 0;
+               BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+                       if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
+                               BM_elem_flag_enable(efa, BM_ELEM_TAG);
+                               tri_count += efa->len - 2;
+                       }
+                       else {
+                               BM_elem_flag_disable(efa, BM_ELEM_TAG);
+                       }
+               }
 
-#ifdef USE_EDBM_LOOPTRIS
-               {
-                       unsigned int i;
-                       for (i = 0; i < em->tottri; i++) {
+               if (tri_count && !(sima->flag & SI_NO_DRAWFACES)) {
+                       /* draw transparent faces */
+                       UI_GetThemeColor4fv(TH_FACE, col1);
+                       UI_GetThemeColor4fv(TH_FACE_SELECT, col2);
+                       glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+                       glEnable(GL_BLEND);
+
+                       Gwn_VertFormat *format = immVertexFormat();
+                       pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+                       color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+
+                       immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+                       Gwn_Batch *face_batch = immBeginBatch(GWN_PRIM_TRIS, tri_count * 3);
+                       for (unsigned int i = 0; i < em->tottri; i++) {
                                efa = em->looptris[i][0]->f;
-                               tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-                               if (uvedit_face_visible_test(scene, ima, efa, tf)) {
+                               if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
                                        const bool is_select = uvedit_face_select_test(scene, efa, cd_loop_uv_offset);
-                                       BM_elem_flag_enable(efa, BM_ELEM_TAG);
 
-                                       if (tf == activetf) {
+                                       if (efa == efa_act) {
                                                /* only once */
-                                               GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
-                                               GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE);
-                                               UI_ThemeColor4(TH_EDITMESH_ACTIVE);
+                                               float tmp_col[4];
+                                               UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, tmp_col);
+                                               immAttrib4fv(color, tmp_col);
                                        }
                                        else {
-                                               glColor4ubv((GLubyte *)(is_select ? col2 : col1));
+                                               immAttrib4fv(color, is_select ? col2 : col1);
                                        }
 
-                                       glBegin(GL_TRIANGLES);
-                                       draw_uvs_looptri(em, &i, cd_loop_uv_offset);
-                                       glEnd();
-
-                                       if (tf == activetf) {
-                                               GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-                                       }
-                               }
-                               else {
-                                       BM_elem_flag_disable(efa, BM_ELEM_TAG);
+                                       draw_uvs_looptri(em, &i, cd_loop_uv_offset, pos);
                                }
                        }
-               }
-#else
-               BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
-                       tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-                       if (uvedit_face_visible_test(scene, ima, efa, tf)) {
-                               BM_elem_flag_enable(efa, BM_ELEM_TAG);
-                               if (tf == activetf) continue;  /* important the temp boolean is set above */
+                       immEnd();
 
-                               if (uvedit_face_select_test(scene, efa, cd_loop_uv_offset))
-                                       glColor4ubv((GLubyte *)col2);
-                               else
-                                       glColor4ubv((GLubyte *)col1);
+                       /* XXX performance: we should not create and throw away result. */
+                       GWN_batch_draw(face_batch);
+                       GWN_batch_program_use_end(face_batch);
+                       GWN_batch_discard(face_batch);
 
-                               glBegin(GL_POLYGON);
-                               BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
-                                       luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-                                       glVertex2fv(luv->uv);
-                               }
-                               glEnd();
-                       }
-                       else {
-                               if (tf == activetf)
-                                       activetf = NULL;
-                               BM_elem_flag_disable(efa, BM_ELEM_TAG);
-                       }
-               }
-#endif
-               glDisable(GL_BLEND);
-       }
-       else {
-               /* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */
-
-               BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
-                       tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
+                       immUnbindProgram();
 
-                       if (uvedit_face_visible_test(scene, ima, efa, tf)) {
-                               BM_elem_flag_enable(efa, BM_ELEM_TAG);
-                       }
-                       else {
-                               if (tf == activetf)
-                                       activetf = NULL;
-                               BM_elem_flag_disable(efa, BM_ELEM_TAG);
+                       glDisable(GL_BLEND);
+               }
+               else {
+                       if (efa_act && !uvedit_face_visible_test(scene, obedit, ima, efa_act)) {
+                               efa_act = NULL;
                        }
                }
-
        }
 
        /* 3. draw active face stippled */
-#ifndef USE_EDBM_LOOPTRIS
-       if (activef) {
-               tf = BM_ELEM_CD_GET_VOID_P(activef, cd_poly_tex_offset);
-               if (uvedit_face_visible_test(scene, ima, activef, tf)) {
-                       glEnable(GL_BLEND);
-                       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-                       UI_ThemeColor4(TH_EDITMESH_ACTIVE);
-
-                       GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
-                       GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE);
-
-                       glBegin(GL_POLYGON);
-                       BM_ITER_ELEM (l, &liter, activef, BM_LOOPS_OF_FACE) {
-                               luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-                               glVertex2fv(luv->uv);
-                       }
-                       glEnd();
-
-                       GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-                       glDisable(GL_BLEND);
-               }
-       }
-#endif
+       /* (removed during OpenGL upgrade, reimplement if needed) */
 
        /* 4. draw edges */
 
        if (sima->flag & SI_SMOOTH_UV) {
                glEnable(GL_LINE_SMOOTH);
                glEnable(GL_BLEND);
-               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
        }
 
-       glLineWidth(1);
+       pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 
        switch (sima->dt_uv) {
                case SI_UVDT_DASH:
-                       BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
-                               if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
-                                       continue;
-                               tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
-                               if (tf) {
-                                       cpack(0x111111);
-
-                                       draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
+               {
+                       immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
 
-                                       setlinestyle(2);
-                                       cpack(0x909090);
+                       float viewport_size[4];
+                       glGetFloatv(GL_VIEWPORT, viewport_size);
+                       immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
 
-                                       draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
+                       immUniform1i("num_colors", 2);  /* "advanced" mode */
+                       immUniformArray4fv("colors", (float *)(float[][4]){{0.56f, 0.56f, 0.56f, 1.0f}, {0.07f, 0.07f, 0.07f, 1.0f}}, 2);
+                       immUniform1f("dash_width", 4.0f);
+                       glLineWidth(1.0f);
 
-                                       setlinestyle(0);
-                               }
-                       }
                        break;
+               }
                case SI_UVDT_BLACK: /* black/white */
                case SI_UVDT_WHITE:
-                       if (sima->dt_uv == SI_UVDT_WHITE) glColor3f(1.0f, 1.0f, 1.0f);
-                       else glColor3f(0.0f, 0.0f, 0.0f);
-
-                       BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
-                               if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
-                                       continue;
-
-                               draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
+                       immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+                       if (sima->dt_uv == SI_UVDT_WHITE) {
+                               immUniformColor3f(1.0f, 1.0f, 1.0f);
                        }
+                       else {
+                               immUniformColor3f(0.0f, 0.0f, 0.0f);
+                       }
+                       glLineWidth(1.0f);
+
                        break;
                case SI_UVDT_OUTLINE:
-                       glLineWidth(3);
-                       cpack(0x0);
+                       immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+                       imm_cpack(0x0);
+                       glLineWidth(3.0f);
 
-                       BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
-                               if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
-                                       continue;
+                       break;
+       }
 
-                               draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
-                       }
+       /* For more efficiency first transfer the entire buffer to vram. */
+       Gwn_Batch *loop_batch = immBeginBatchAtMost(GWN_PRIM_LINE_LOOP, bm->totloop);
+       Gwn_VertBuf *loop_vbo = loop_batch->verts[0];
+       BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+               if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+                       continue;
 
-                       glLineWidth(1);
-                       UI_GetThemeColor4ubv(TH_WIRE_EDIT, col2);
-                       glColor4ubv((unsigned char *)col2);
+               BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
+                       luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+                       immVertex2fv(pos, luv->uv);
+               }
+       }
+       immEnd();
+
+       /* Then draw each face contour separately. */
+       if (loop_vbo->vertex_ct != 0) {
+               GWN_batch_program_use_begin(loop_batch);
+               unsigned int index = 0, loop_vbo_count;
+               BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+                       if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+                               continue;
+
+                       GWN_batch_draw_range_ex(loop_batch, index, efa->len, false);
+                       index += efa->len;
+               }
+               loop_vbo_count = index;
+               GWN_batch_program_use_end(loop_batch);
+               immUnbindProgram();
+
+
+               if (sima->dt_uv == SI_UVDT_OUTLINE) {
+                       glLineWidth(1.0f);
+                       UI_GetThemeColor4fv(TH_WIRE_EDIT, col2);
 
                        if (me->drawflag & ME_DRAWEDGES) {
-                               int sel, lastsel = -1;
-                               UI_GetThemeColor4ubv(TH_EDGE_SELECT, col1);
+                               int sel;
+                               UI_GetThemeColor4fv(TH_EDGE_SELECT, col1);
 
                                if (interpedges) {
-                                       GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-                                       BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+                                       /* Create a color buffer. */
+                                       static Gwn_VertFormat format = { 0 };
+                                       static uint shdr_col;
+                                       if (format.attrib_ct == 0) {
+                                               shdr_col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+                                       }
+
+                                       Gwn_VertBuf *vbo_col = GWN_vertbuf_create_with_format(&format);
+                                       GWN_vertbuf_data_alloc(vbo_col, loop_vbo_count);
+
+                                       index = 0;
+                                       BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
                                                if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
                                                        continue;
 
-                                               glBegin(GL_LINE_LOOP);
-                                               BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+                                               BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
                                                        sel = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
-                                                       glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2);
-
-                                                       luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-                                                       glVertex2fv(luv->uv);
+                                                       GWN_vertbuf_attr_set(vbo_col, shdr_col, index++, sel ? col1 : col2);
                                                }
-                                               glEnd();
                                        }
+                                       /* Reuse the UV buffer and add the color buffer. */
+                                       GWN_batch_vertbuf_add_ex(loop_batch, vbo_col, true);
+
+                                       /* Now draw each face contour separately with another builtin program. */
+                                       GWN_batch_program_set_builtin(loop_batch, GPU_SHADER_2D_SMOOTH_COLOR);
+                                       gpuBindMatrices(loop_batch->interface);
+
+                                       GWN_batch_program_use_begin(loop_batch);
+                                       index = 0;
+                                       BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+                                               if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
+                                                       continue;
+
+                                               GWN_batch_draw_range_ex(loop_batch, index, efa->len, false);
+                                               index += efa->len;
+                                       }
+                                       GWN_batch_program_use_end(loop_batch);
                                }
                                else {
-                                       BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+                                       Gwn_VertFormat *format = immVertexFormat();
+                                       pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+                                       color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+
+                                       immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+                                       /* Use batch here to avoid problems with `IMM_BUFFER_SIZE`. */
+                                       Gwn_Batch *flat_edges_batch = immBeginBatchAtMost(GWN_PRIM_LINES, loop_vbo_count * 2);
+                                       BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
                                                if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
                                                        continue;
 
-                                               glBegin(GL_LINES);
-                                               BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+                                               BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
                                                        sel = uvedit_edge_select_test(scene, l, cd_loop_uv_offset);
-                                                       if (sel != lastsel) {
-                                                               glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2);
-                                                               lastsel = sel;
-                                                       }
+                                                       immAttrib4fv(color, sel ? col1 : col2);
+
                                                        luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-                                                       glVertex2fv(luv->uv);
+                                                       immVertex2fv(pos, luv->uv);
                                                        luv = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
-                                                       glVertex2fv(luv->uv);
+                                                       immVertex2fv(pos, luv->uv);
                                                }
-                                               glEnd();
                                        }
+                                       immEnd();
+
+                                       GWN_batch_draw(flat_edges_batch);
+                                       GWN_batch_discard(flat_edges_batch);
+
+                                       immUnbindProgram();
                                }
                        }
                        else {
+                               GWN_batch_uniform_4fv(loop_batch, "color", col2);
+                               immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
                                /* no nice edges */
-                               BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+                               GWN_batch_program_use_begin(loop_batch);
+                               index = 0;
+                               BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
                                        if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
                                                continue;
 
-                                       draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
+                                       GWN_batch_draw_range_ex(loop_batch, index, efa->len, false);
+                                       index += efa->len;
                                }
+                               GWN_batch_program_use_end(loop_batch);
+                               immUnbindProgram();
                        }
-
-                       break;
+               }
+       }
+       else {
+               immUnbindProgram();
        }
 
+       GWN_batch_discard(loop_batch);
+
        if (sima->flag & SI_SMOOTH_UV) {
                glDisable(GL_LINE_SMOOTH);
                glDisable(GL_BLEND);
@@ -861,50 +889,80 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
 
        if (drawfaces) {
                float cent[2];
+               bool col_set = false;
+
+               Gwn_VertFormat *format = immVertexFormat();
+               pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+               color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+               immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
 
                pointsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
                glPointSize(pointsize);
 
-               glBegin(GL_POINTS);
+               immBeginAtMost(GWN_PRIM_POINTS, bm->totface);
 
                /* unselected faces */
-               UI_ThemeColor(TH_WIRE);
 
                BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
                        if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
                                continue;
 
                        if (!uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
+                               /* Only set color for the first face */
+                               if (!col_set) {
+                                       UI_GetThemeColor3fv(TH_WIRE, col1);
+                                       immAttrib3fv(color, col1);
+
+                                       col_set = true;
+                               }
+
                                uv_poly_center(efa, cent, cd_loop_uv_offset);
-                               glVertex2fv(cent);
+                               immVertex2fv(pos, cent);
                        }
                }
 
+               col_set = false;
+
                /* selected faces */
-               UI_ThemeColor(TH_FACE_DOT);
 
                BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
                        if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
                                continue;
 
                        if (uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
+                               /* Only set color for the first face */
+                               if (!col_set) {
+                                       UI_GetThemeColor3fv(TH_FACE_DOT, col1);
+                                       immAttrib3fv(color, col1);
+
+                                       col_set = true;
+                               }
+
                                uv_poly_center(efa, cent, cd_loop_uv_offset);
-                               glVertex2fv(cent);
+                               immVertex2fv(pos, cent);
                        }
                }
 
-               glEnd();
+               immEnd();
+
+               immUnbindProgram();
        }
 
        /* 6. draw uv vertices */
 
        if (drawfaces != 2) { /* 2 means Mesh Face Mode */
+               pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+               immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
                /* unselected uvs */
-               UI_ThemeColor(TH_VERTEX);
+               immUniformThemeColor(TH_VERTEX);
                pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
                glPointSize(pointsize);
 
-               glBegin(GL_POINTS);
+               immBeginAtMost(GWN_PRIM_POINTS, bm->totloop);
+
                BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
                        if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
                                continue;
@@ -912,17 +970,19 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
                        BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
                                luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
                                if (!uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
-                                       glVertex2fv(luv->uv);
+                                       immVertex2fv(pos, luv->uv);
                        }
                }
-               glEnd();
+
+               immEnd();
 
                /* pinned uvs */
                /* give odd pointsizes odd pin pointsizes */
                glPointSize(pointsize * 2 + (((int)pointsize % 2) ? (-1) : 0));
-               cpack(0xFF);
+               imm_cpack(0xFF);
+
+               immBeginAtMost(GWN_PRIM_POINTS, bm->totloop);
 
-               glBegin(GL_POINTS);
                BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
                        if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
                                continue;
@@ -931,16 +991,18 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
                                luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
 
                                if (luv->flag & MLOOPUV_PINNED)
-                                       glVertex2fv(luv->uv);
+                                       immVertex2fv(pos, luv->uv);
                        }
                }
-               glEnd();
+
+               immEnd();
 
                /* selected uvs */
-               UI_ThemeColor(TH_VERTEX_SELECT);
+               immUniformThemeColor(TH_VERTEX_SELECT);
                glPointSize(pointsize);
 
-               glBegin(GL_POINTS);
+               immBeginAtMost(GWN_PRIM_POINTS, bm->totloop);
+
                BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
                        if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
                                continue;
@@ -949,15 +1011,20 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
                                luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
 
                                if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
-                                       glVertex2fv(luv->uv);
+                                       immVertex2fv(pos, luv->uv);
                        }
                }
-               glEnd();
+
+               immEnd();
+
+               immUnbindProgram();
        }
 }
 
 
-static void draw_uv_shadows_get(SpaceImage *sima, Object *ob, Object *obedit, bool *show_shadow, bool *show_texpaint)
+static void draw_uv_shadows_get(
+        SpaceImage *sima, Object *ob, Object *obedit,
+        bool *show_shadow, bool *show_texpaint)
 {
        *show_shadow = *show_texpaint = false;
 
@@ -973,7 +1040,9 @@ static void draw_uv_shadows_get(SpaceImage *sima, Object *ob, Object *obedit, bo
        *show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT);
 }
 
-void ED_uvedit_draw_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit, Object *obact)
+void ED_uvedit_draw_main(
+        SpaceImage *sima,
+        ARegion *ar, Scene *scene, ViewLayer *view_layer, Object *obedit, Object *obact, Depsgraph *depsgraph)
 {
        ToolSettings *toolsettings = scene->toolsettings;
        bool show_uvedit, show_uvshadow, show_texpaint_uvshadow;
@@ -982,12 +1051,21 @@ void ED_uvedit_draw_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *ob
        draw_uv_shadows_get(sima, obact, obedit, &show_uvshadow, &show_texpaint_uvshadow);
 
        if (show_uvedit || show_uvshadow || show_texpaint_uvshadow) {
-               if (show_uvshadow)
+               if (show_uvshadow) {
                        draw_uvs_shadow(obedit);
-               else if (show_uvedit)
-                       draw_uvs(sima, scene, obedit);
-               else
-                       draw_uvs_texpaint(sima, scene, obact);
+               }
+               else if (show_uvedit) {
+                       uint objects_len = 0;
+                       Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(view_layer, &objects_len);
+                       for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+                               Object *ob_iter = objects[ob_index];
+                               draw_uvs(sima, scene, view_layer, ob_iter, depsgraph);
+                       }
+                       MEM_freeN(objects);
+               }
+               else {
+                       draw_uvs_texpaint(sima, scene, view_layer, obact);
+               }
 
                if (show_uvedit && !(toolsettings->use_uv_sculpt))
                        ED_image_draw_cursor(ar, sima->cursor);