Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / animation / keyframes_draw.c
index 6e78687..d137770 100644 (file)
@@ -52,7 +52,8 @@
 
 #include "BKE_fcurve.h"
 
-#include "BIF_gl.h"
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
 
 #include "UI_resources.h"
 #include "UI_view2d.h"
@@ -463,47 +464,13 @@ bool actkeyblock_is_valid(ActKeyBlock *ab, DLRBT_Tree *keys)
 
 /* *************************** Keyframe Drawing *************************** */
 
-/* coordinates for diamond shape */
-static const float _unit_diamond_shape[4][2] = {
-       {0.0f, 1.0f},   /* top vert */
-       {1.0f, 0.0f},   /* mid-right */
-       {0.0f, -1.0f},  /* bottom vert */
-       {-1.0f, 0.0f}   /* mid-left */
-};
-
-/* draw a simple diamond shape with OpenGL */
-void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha)
+void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type, short mode, float alpha,
+                         unsigned int pos_id, unsigned int size_id, unsigned int color_id, unsigned int outline_color_id)
 {
-       static GLuint displist1 = 0;
-       static GLuint displist2 = 0;
-
-       /* initialize 2 display lists for diamond shape - one empty, one filled */
-       if (displist1 == 0) {
-               displist1 = glGenLists(1);
-               glNewList(displist1, GL_COMPILE);
-
-               glBegin(GL_LINE_LOOP);
-               glVertex2fv(_unit_diamond_shape[0]);
-               glVertex2fv(_unit_diamond_shape[1]);
-               glVertex2fv(_unit_diamond_shape[2]);
-               glVertex2fv(_unit_diamond_shape[3]);
-               glEnd();
-
-               glEndList();
-       }
-       if (displist2 == 0) {
-               displist2 = glGenLists(1);
-               glNewList(displist2, GL_COMPILE);
-
-               glBegin(GL_QUADS);
-               glVertex2fv(_unit_diamond_shape[0]);
-               glVertex2fv(_unit_diamond_shape[1]);
-               glVertex2fv(_unit_diamond_shape[2]);
-               glVertex2fv(_unit_diamond_shape[3]);
-               glEnd();
-
-               glEndList();
-       }
+       bool draw_fill = ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH);
+       bool draw_outline = ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH);
+
+       BLI_assert(draw_fill || draw_outline);
 
        /* tweak size of keyframe shape according to type of keyframe
         * - 'proper' keyframes have key_type = 0, so get drawn at full size
@@ -513,120 +480,92 @@ void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel,
                        break;
 
                case BEZT_KEYTYPE_BREAKDOWN: /* slightly smaller than normal keyframe */
-                       hsize *= 0.85f;
+                       size *= 0.85f;
                        break;
 
                case BEZT_KEYTYPE_MOVEHOLD:  /* slightly smaller than normal keyframes (but by less than for breakdowns) */
-                       //hsize *= 0.72f;
-                       hsize *= 0.95f;
+                       size *= 0.925f;
                        break;
 
                case BEZT_KEYTYPE_EXTREME:   /* slightly larger */
-                       hsize *= 1.2f;
+                       size *= 1.2f;
                        break;
 
                default:
-                       hsize -= 0.5f * key_type;
-                       break;
+                       size -= 0.8f * key_type;
        }
 
-       /* adjust view transform before starting */
-       glTranslatef(x, y, 0.0f);
-       glScalef(1.0f / xscale * hsize, hsize, 1.0f);
-
-       /* anti-aliased lines for more consistent appearance */
-       glEnable(GL_LINE_SMOOTH);
+       unsigned char fill_col[4];
+       unsigned char outline_col[4];
 
        /* draw! */
-       if (ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH)) {
-               float inner_col[4];
-
+       if (draw_fill) {
                /* get interior colors from theme (for selected and unselected only) */
                switch (key_type) {
                        case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames (default theme) */
-                       {
-                               if (sel)  UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN_SELECT, inner_col);
-                               else UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN, inner_col);
+                               UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_BREAKDOWN_SELECT : TH_KEYTYPE_BREAKDOWN, fill_col);
                                break;
-                       }
                        case BEZT_KEYTYPE_EXTREME: /* reddish frames (default theme) */
-                       {
-                               if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME_SELECT, inner_col);
-                               else UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME, inner_col);
+                               UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_EXTREME_SELECT : TH_KEYTYPE_EXTREME, fill_col);
                                break;
-                       }
                        case BEZT_KEYTYPE_JITTER: /* greenish frames (default theme) */
-                       {
-                               if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_JITTER_SELECT, inner_col);
-                               else UI_GetThemeColor4fv(TH_KEYTYPE_JITTER, inner_col);
+                               UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_JITTER_SELECT : TH_KEYTYPE_JITTER, fill_col);
                                break;
-                       }
                        case BEZT_KEYTYPE_MOVEHOLD: /* similar to traditional keyframes, but different... */
-                       {
                                /* XXX: Should these get their own theme options instead? */
-                               if (sel) UI_GetThemeColorShade4fv(TH_STRIP_SELECT, 35, inner_col);
-                               else UI_GetThemeColorShade4fv(TH_STRIP, 50, inner_col);
-
-                               inner_col[3] = 1.0f; /* full opacity, to avoid problems with visual glitches */
+                               if (sel) UI_GetThemeColorShade3ubv(TH_STRIP_SELECT, 35, fill_col);
+                               else UI_GetThemeColorShade3ubv(TH_STRIP, 50, fill_col);
+                               fill_col[3] = 255; /* full opacity, to avoid problems with visual glitches */
                                break;
-                       }
                        case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames (default theme) */
                        default:
-                       {
-                               if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME_SELECT, inner_col);
-                               else UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME, inner_col);
-                               break;
-                       }
+                               UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_KEYFRAME_SELECT : TH_KEYTYPE_KEYFRAME, fill_col);
                }
 
                /* NOTE: we don't use the straight alpha from the theme, or else effects such as
                 * graying out protected/muted channels doesn't work correctly!
                 */
-               inner_col[3] *= alpha;
-               glColor4fv(inner_col);
-
-               /* draw the "filled in" interior poly now */
-               glCallList(displist2);
+               fill_col[3] *= alpha;
+
+               if (!draw_outline) {
+                       /* force outline color to match */
+                       outline_col[0] = fill_col[0];
+                       outline_col[1] = fill_col[1];
+                       outline_col[2] = fill_col[2];
+                       outline_col[3] = fill_col[3];
+               }
        }
 
-       if (ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH)) {
-               float border_col[4];
-
+       if (draw_outline) {
                /* exterior - black frame */
-               if (sel)  UI_GetThemeColor4fv(TH_KEYBORDER_SELECT, border_col);
-               else  UI_GetThemeColor4fv(TH_KEYBORDER, border_col);
-
-               border_col[3] *= alpha;
-               glColor4fv(border_col);
-
-               glCallList(displist1);
+               UI_GetThemeColor4ubv(sel ? TH_KEYBORDER_SELECT : TH_KEYBORDER, outline_col);
+               outline_col[3] *= alpha;
+
+               if (!draw_fill) {
+                       /* fill color needs to be (outline.rgb, 0) */
+                       fill_col[0] = outline_col[0];
+                       fill_col[1] = outline_col[1];
+                       fill_col[2] = outline_col[2];
+                       fill_col[3] = 0;
+               }
        }
 
-       glDisable(GL_LINE_SMOOTH);
-
-       /* restore view transform */
-       glScalef(xscale / hsize, 1.0f / hsize, 1.0f);
-       glTranslatef(-x, -y, 0.0f);
+       immAttrib1f(size_id, size);
+       immAttrib4ubv(color_id, fill_col);
+       immAttrib4ubv(outline_color_id, outline_col);
+       immVertex2f(pos_id, x, y);
 }
 
 static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, float yscale_fac, bool channelLocked)
 {
-       ActKeyColumn *ak;
-       ActKeyBlock *ab;
-       float alpha;
-       float xscale;
-
-       const float iconsize = (U.widget_unit / 4.0f) * yscale_fac;
-       const float mhsize   = iconsize * 0.7f;
+       const float icon_sz = U.widget_unit * 0.5f * yscale_fac;
+       const float half_icon_sz = 0.5f * icon_sz;
 
        glEnable(GL_BLEND);
 
-       /* get View2D scaling factor */
-       UI_view2d_scale_get(v2d, &xscale, NULL);
-
        /* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */
        /* TODO: allow this opacity factor to be themed? */
-       alpha = (channelLocked) ? 0.25f : 1.0f;
+       float alpha = channelLocked ? 0.25f : 1.0f;
 
        /* draw keyblocks */
        if (blocks) {
@@ -645,44 +584,73 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
                copy_v4_v4(unsel_mhcol, unsel_color);
                unsel_mhcol[3] *= 0.8f;
 
-               /* NOTE: the tradeoff for changing colors between each draw is dwarfed by the cost of checking validity */
-               for (ab = blocks->first; ab; ab = ab->next) {
+               unsigned int block_ct = 0;
+               for (ActKeyBlock *ab = blocks->first; ab; ab = ab->next) {
                        if (actkeyblock_is_valid(ab, keys)) {
-                               if (ab->flag & ACTKEYBLOCK_FLAG_MOVING_HOLD) {
-                                       /* draw "moving hold" long-keyframe block - slightly smaller */
-                                       if (ab->sel)
-                                               glColor4fv(sel_mhcol);
-                                       else
-                                               glColor4fv(unsel_mhcol);
-
-                                       glRectf(ab->start, ypos - mhsize, ab->end, ypos + mhsize);
-                               }
-                               else {
-                                       /* draw standard long-keyframe block */
-                                       if (ab->sel)
-                                               glColor4fv(sel_color);
-                                       else
-                                               glColor4fv(unsel_color);
-
-                                       glRectf(ab->start, ypos - iconsize, ab->end, ypos + iconsize);
+                               block_ct++;
+                       }
+               }
+
+               if (block_ct > 0) {
+                       Gwn_VertFormat *format = immVertexFormat();
+                       unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+                       unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+                       immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+                       immBegin(GWN_PRIM_TRIS, 6 * block_ct);
+                       for (ActKeyBlock *ab = blocks->first; ab; ab = ab->next) {
+                               if (actkeyblock_is_valid(ab, keys)) {
+                                       if (ab->flag & ACTKEYBLOCK_FLAG_MOVING_HOLD) {
+                                               /* draw "moving hold" long-keyframe block - slightly smaller */
+                                               immRectf_fast_with_color(pos_id, color_id,
+                                                                        ab->start, ypos - half_icon_sz, ab->end, ypos + half_icon_sz,
+                                                                        (ab->sel) ? sel_mhcol : unsel_mhcol);
+                                       }
+                                       else {
+                                               /* draw standard long-keyframe block */
+                                               immRectf_fast_with_color(pos_id, color_id,
+                                                                        ab->start, ypos - half_icon_sz, ab->end, ypos + half_icon_sz,
+                                                                        (ab->sel) ? sel_color : unsel_color);
+                                       }
                                }
                        }
+                       immEnd();
+                       immUnbindProgram();
                }
        }
 
-       /* draw keys */
        if (keys) {
-               for (ak = keys->first; ak; ak = ak->next) {
+               /* count keys */
+               unsigned int key_ct = 0;
+               for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
                        /* optimization: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw
                         *      - this might give some improvements, since we current have to flip between view/region matrices
                         */
-                       if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax) == 0)
-                               continue;
+                       if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax))
+                               key_ct++;
+               }
+
+               if (key_ct > 0) {
+                       /* draw keys */
+                       Gwn_VertFormat *format = immVertexFormat();
+                       unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+                       unsigned int size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+                       unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+                       unsigned int outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+                       immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+                       GPU_enable_program_point_size();
+                       immBegin(GWN_PRIM_POINTS, key_ct);
+
+                       for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
+                               if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) {
+                                       draw_keyframe_shape(ak->cfra, ypos, icon_sz, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha,
+                                                           pos_id, size_id, color_id, outline_color_id);
+                               }
+                       }
 
-                       /* draw using OpenGL - uglier but faster */
-                       /* NOTE1: a previous version of this didn't work nice for some intel cards
-                        * NOTE2: if we wanted to go back to icons, these are  icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; */
-                       draw_keyframe_shape(ak->cfra, ypos, xscale, iconsize, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha);
+                       immEnd();
+                       GPU_disable_program_point_size();
+                       immUnbindProgram();
                }
        }