GPU: Rename GPU_shader_get_uniform to GPU_shader_get_uniform_ensure
[blender.git] / source / blender / editors / mask / mask_draw.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2012 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation,
23  *                 Campbell Barton,
24  *                 Sergey Sharybin
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/editors/mask/mask_draw.c
30  *  \ingroup edmask
31  */
32
33 #include "MEM_guardedalloc.h"
34
35 #include "BLI_utildefines.h"
36 #include "BLI_math.h"
37 #include "BLI_rect.h"
38 #include "BLI_task.h"
39 #include "BLI_listbase.h"
40
41 #include "BKE_context.h"
42 #include "BKE_mask.h"
43
44 #include "DNA_mask_types.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_object_types.h"   /* SELECT */
47 #include "DNA_space_types.h"
48
49 #include "ED_clip.h"
50 #include "ED_mask.h"  /* own include */
51 #include "ED_space_api.h"
52
53 #include "BIF_glutil.h"
54
55 #include "GPU_immediate.h"
56 #include "GPU_draw.h"
57 #include "GPU_shader.h"
58 #include "GPU_matrix.h"
59 #include "GPU_state.h"
60
61 #include "UI_interface.h"
62 #include "UI_resources.h"
63 #include "UI_view2d.h"
64
65 #include "mask_intern.h"  /* own include */
66
67 static void mask_spline_color_get(MaskLayer *masklay, MaskSpline *spline, const bool is_sel,
68                                   unsigned char r_rgb[4])
69 {
70         if (is_sel) {
71                 if (masklay->act_spline == spline) {
72                         r_rgb[0] = r_rgb[1] = r_rgb[2] = 255;
73                 }
74                 else {
75                         r_rgb[0] = 255;
76                         r_rgb[1] = r_rgb[2] = 0;
77                 }
78         }
79         else {
80                 r_rgb[0] = 128;
81                 r_rgb[1] = r_rgb[2] = 0;
82         }
83
84         r_rgb[3] = 255;
85 }
86
87 static void mask_spline_feather_color_get(MaskLayer *UNUSED(masklay), MaskSpline *UNUSED(spline), const bool is_sel,
88                                           unsigned char r_rgb[4])
89 {
90         if (is_sel) {
91                 r_rgb[1] = 255;
92                 r_rgb[0] = r_rgb[2] = 0;
93         }
94         else {
95                 r_rgb[1] = 128;
96                 r_rgb[0] = r_rgb[2] = 0;
97         }
98
99         r_rgb[3] = 255;
100 }
101
102 static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float co[2])
103 {
104         BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co);
105         ED_clip_point_undistorted_pos(sc, r_co, r_co);
106         BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co);
107 }
108
109 static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoint *point,
110                                const eMaskWhichHandle which_handle, const int draw_type,
111                                const float handle_size,
112                                const float point_pos[2], const float handle_pos[2])
113 {
114         const BezTriple *bezt = &point->bezt;
115         char handle_type;
116
117         if (which_handle == MASK_WHICH_HANDLE_STICK || which_handle == MASK_WHICH_HANDLE_LEFT) {
118                 handle_type = bezt->h1;
119         }
120         else {
121                 handle_type = bezt->h2;
122         }
123
124         if (handle_type == HD_VECT) {
125                 return;
126         }
127
128         GPUVertFormat *format = immVertexFormat();
129         uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
130         const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
131
132         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
133         immUniformColor3ubv(rgb_gray);
134
135         /* this could be split into its own loop */
136         if (draw_type == MASK_DT_OUTLINE) {
137                 GPU_line_width(3.0f);
138                 immBegin(GPU_PRIM_LINES, 2);
139                 immVertex2fv(pos, point_pos);
140                 immVertex2fv(pos, handle_pos);
141                 immEnd();
142         }
143
144         switch (handle_type) {
145                 case HD_FREE:
146                         immUniformThemeColor(TH_HANDLE_FREE);
147                         break;
148                 case HD_AUTO:
149                         immUniformThemeColor(TH_HANDLE_AUTO);
150                         break;
151                 case HD_ALIGN:
152                 case HD_ALIGN_DOUBLESIDE:
153                         immUniformThemeColor(TH_HANDLE_ALIGN);
154                         break;
155         }
156
157         GPU_line_width(1.0f);
158         immBegin(GPU_PRIM_LINES, 2);
159         immVertex2fv(pos, point_pos);
160         immVertex2fv(pos, handle_pos);
161         immEnd();
162         immUnbindProgram();
163
164         /* draw handle points */
165         immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
166         immUniform1f("size", handle_size);
167         immUniform1f("outlineWidth", 1.5f);
168
169         float point_color[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; /* active color by default */
170         if (MASKPOINT_ISSEL_HANDLE(point, which_handle)) {
171                 if (point != mask_layer->act_point) {
172                         UI_GetThemeColor3fv(TH_HANDLE_VERTEX_SELECT, point_color);
173                 }
174         }
175         else {
176                 UI_GetThemeColor3fv(TH_HANDLE_VERTEX, point_color);
177         }
178
179         immUniform4fv("outlineColor", point_color);
180         immUniformColor3fvAlpha(point_color, 0.25f);
181
182         immBegin(GPU_PRIM_POINTS, 1);
183         immVertex2fv(pos, handle_pos);
184         immEnd();
185
186         immUnbindProgram();
187 }
188
189 /* return non-zero if spline is selected */
190 static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline *spline,
191                                const char draw_flag, const char draw_type)
192 {
193         const bool is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
194         const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0;
195
196         unsigned char rgb_spline[4];
197         MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
198         SpaceClip *sc = CTX_wm_space_clip(C);
199         bool undistort = false;
200
201         int tot_feather_point;
202         float (*feather_points)[2], (*fp)[2];
203         float min[2], max[2];
204
205         if (!spline->tot_point)
206                 return;
207
208         if (sc)
209                 undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
210
211         /* TODO, add this to sequence editor */
212         float handle_size = 2.0f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
213
214         mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline);
215
216         GPUVertFormat *format = immVertexFormat();
217         uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
218
219         immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
220         immUniform1f("size", 0.7f * handle_size);
221
222         /* feather points */
223         feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
224         for (int i = 0; i < spline->tot_point; i++) {
225
226                 /* watch it! this is intentionally not the deform array, only check for sel */
227                 MaskSplinePoint *point = &spline->points[i];
228
229                 for (int j = 0; j <= point->tot_uw; j++) {
230                         float feather_point[2];
231                         bool sel = false;
232
233                         copy_v2_v2(feather_point, *fp);
234
235                         if (undistort)
236                                 mask_point_undistort_pos(sc, feather_point, feather_point);
237
238                         if (j == 0) {
239                                 sel = MASKPOINT_ISSEL_ANY(point);
240                         }
241                         else {
242                                 sel = (point->uw[j - 1].flag & SELECT) != 0;
243                         }
244
245                         if (sel) {
246                                 if (point == masklay->act_point)
247                                         immUniformColor3f(1.0f, 1.0f, 1.0f);
248                                 else
249                                         immUniformThemeColor(TH_HANDLE_VERTEX_SELECT);
250                         }
251                         else {
252                                 immUniformThemeColor(TH_HANDLE_VERTEX);
253                         }
254
255                         immBegin(GPU_PRIM_POINTS, 1);
256                         immVertex2fv(pos, feather_point);
257                         immEnd();
258
259                         fp++;
260                 }
261         }
262         MEM_freeN(feather_points);
263
264         immUnbindProgram();
265
266         if (is_smooth) {
267                 GPU_line_smooth(true);
268         }
269
270         /* control points */
271         INIT_MINMAX2(min, max);
272         for (int i = 0; i < spline->tot_point; i++) {
273
274                 /* watch it! this is intentionally not the deform array, only check for sel */
275                 MaskSplinePoint *point = &spline->points[i];
276                 MaskSplinePoint *point_deform = &points_array[i];
277                 BezTriple *bezt = &point_deform->bezt;
278
279                 float vert[2];
280
281                 copy_v2_v2(vert, bezt->vec[1]);
282
283                 if (undistort) {
284                         mask_point_undistort_pos(sc, vert, vert);
285                 }
286
287                 /* draw handle segment */
288                 if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
289                         float handle[2];
290                         BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_STICK, handle);
291                         if (undistort) {
292                                 mask_point_undistort_pos(sc, handle, handle);
293                         }
294                         draw_single_handle(masklay, point, MASK_WHICH_HANDLE_STICK,
295                                            draw_type, handle_size, vert, handle);
296                 }
297                 else {
298                         float handle_left[2], handle_right[2];
299                         BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_LEFT, handle_left);
300                         BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_RIGHT, handle_right);
301                         if (undistort) {
302                                 mask_point_undistort_pos(sc, handle_left, handle_left);
303                                 mask_point_undistort_pos(sc, handle_left, handle_left);
304                         }
305                         draw_single_handle(masklay, point, MASK_WHICH_HANDLE_LEFT,
306                                            draw_type, handle_size, vert, handle_left);
307                         draw_single_handle(masklay, point, MASK_WHICH_HANDLE_RIGHT,
308                                            draw_type, handle_size, vert, handle_right);
309                 }
310
311                 /* bind program in loop so it does not interfere with draw_single_handle */
312                 immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
313
314                 /* draw CV point */
315                 if (MASKPOINT_ISSEL_KNOT(point)) {
316                         if (point == masklay->act_point)
317                                 immUniformColor3f(1.0f, 1.0f, 1.0f);
318                         else
319                                 immUniformThemeColor(TH_HANDLE_VERTEX_SELECT);
320                 }
321                 else
322                         immUniformThemeColor(TH_HANDLE_VERTEX);
323
324                 immBegin(GPU_PRIM_POINTS, 1);
325                 immVertex2fv(pos, vert);
326                 immEnd();
327
328                 immUnbindProgram();
329
330                 minmax_v2v2_v2(min, max, vert);
331         }
332
333         if (is_smooth) {
334                 GPU_line_smooth(false);
335         }
336
337         if (is_spline_sel) {
338                 float x = (min[0] + max[0]) * 0.5f;
339                 float y = (min[1] + max[1]) * 0.5f;
340
341                 immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
342                 immUniform1f("outlineWidth", 1.5f);
343
344                 if (masklay->act_spline == spline) {
345                         immUniformColor3f(1.0f, 1.0f, 1.0f);
346                 }
347                 else {
348                         immUniformColor3f(1.0f, 1.0f, 0.0f);
349                 }
350
351                 immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 1.0f);
352                 immUniform1f("size", 12.0f);
353
354                 immBegin(GPU_PRIM_POINTS, 1);
355                 immVertex2f(pos, x, y);
356                 immEnd();
357
358                 immUnbindProgram();
359         }
360 }
361
362 static void mask_color_active_tint(unsigned char r_rgb[4], const unsigned char rgb[4], const bool is_active)
363 {
364         if (!is_active) {
365                 r_rgb[0] = (unsigned char)((((int)(rgb[0])) + 128) / 2);
366                 r_rgb[1] = (unsigned char)((((int)(rgb[1])) + 128) / 2);
367                 r_rgb[2] = (unsigned char)((((int)(rgb[2])) + 128) / 2);
368                 r_rgb[3] = rgb[3];
369         }
370         else {
371                 *(unsigned int *)r_rgb = *(const unsigned int *)rgb;
372         }
373 }
374
375 static void mask_draw_array(unsigned int pos, GPUPrimType prim_type, const float (*points)[2], unsigned int vertex_len)
376 {
377         immBegin(prim_type, vertex_len);
378         for (unsigned int i = 0; i < vertex_len; ++i) {
379                 immVertex2fv(pos, points[i]);
380         }
381         immEnd();
382 }
383
384 static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*orig_points)[2], int tot_point,
385                                  const bool is_feather, const bool is_active,
386                                  const unsigned char rgb_spline[4], const char draw_type)
387 {
388         const GPUPrimType draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GPU_PRIM_LINE_LOOP : GPU_PRIM_LINE_STRIP;
389         const unsigned char rgb_black[4] = {0x00, 0x00, 0x00, 0xff};
390         unsigned char rgb_tmp[4];
391         SpaceClip *sc = CTX_wm_space_clip(C);
392         float (*points)[2] = orig_points;
393
394         if (sc) {
395                 const bool undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
396
397                 if (undistort) {
398                         points = MEM_callocN(2 * tot_point * sizeof(float), "undistorthed mask curve");
399
400                         for (int i = 0; i < tot_point; i++) {
401                                 mask_point_undistort_pos(sc, points[i], orig_points[i]);
402                         }
403                 }
404         }
405
406         GPUVertFormat *format = immVertexFormat();
407         uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
408
409         switch (draw_type) {
410
411                 case MASK_DT_OUTLINE:
412                         /* TODO(merwin): use fancy line shader here
413                          * probably better with geometry shader (after core profile switch)
414                          */
415                         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
416
417                         GPU_line_width(3.0f);
418
419                         mask_color_active_tint(rgb_tmp, rgb_black, is_active);
420                         immUniformColor4ubv(rgb_tmp);
421                         mask_draw_array(pos, draw_method, points, tot_point);
422
423                         GPU_line_width(1.0f);
424
425                         mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
426                         immUniformColor4ubv(rgb_tmp);
427                         mask_draw_array(pos, draw_method, points, tot_point);
428
429                         immUnbindProgram();
430                         break;
431
432                 case MASK_DT_BLACK:
433                 case MASK_DT_WHITE:
434                         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
435                         GPU_line_width(1.0f);
436
437                         if (draw_type == MASK_DT_BLACK) { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 0;   }
438                         else                            { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 255; }
439                         /* alpha values seem too low but gl draws many points that compensate for it */
440                         if (is_feather) { rgb_tmp[3] = 64; }
441                         else            { rgb_tmp[3] = 128; }
442
443                         if (is_feather) {
444                                 rgb_tmp[0] = (unsigned char)(((short)rgb_tmp[0] + (short)rgb_spline[0]) / 2);
445                                 rgb_tmp[1] = (unsigned char)(((short)rgb_tmp[1] + (short)rgb_spline[1]) / 2);
446                                 rgb_tmp[2] = (unsigned char)(((short)rgb_tmp[2] + (short)rgb_spline[2]) / 2);
447                         }
448
449                         mask_color_active_tint(rgb_tmp, rgb_tmp, is_active);
450                         immUniformColor4ubv(rgb_tmp);
451                         mask_draw_array(pos, draw_method, points, tot_point);
452
453                         immUnbindProgram();
454                         break;
455
456                 case MASK_DT_DASH:
457                 {
458                         float colors[8];
459
460                         mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
461                         rgba_uchar_to_float(colors, rgb_tmp);
462                         mask_color_active_tint(rgb_tmp, rgb_black, is_active);
463                         rgba_uchar_to_float(colors + 4, rgb_tmp);
464
465                         immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
466
467                         float viewport_size[4];
468                         GPU_viewport_size_get_f(viewport_size);
469                         immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
470
471                         immUniform1i("colors_len", 2);  /* "advanced" mode */
472                         immUniformArray4fv("colors", colors, 2);
473                         immUniform1f("dash_width", 4.0f);
474                         GPU_line_width(1.0f);
475
476                         mask_draw_array(pos, draw_method, points, tot_point);
477
478                         immUnbindProgram();
479                         break;
480                 }
481
482                 default:
483                         BLI_assert(false);
484         }
485
486         if (points != orig_points)
487                 MEM_freeN(points);
488 }
489
490 static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline *spline,
491                               const char draw_flag, const char draw_type,
492                               const bool is_active,
493                               const int width, const int height)
494 {
495         const unsigned int resol = max_ii(BKE_mask_spline_feather_resolution(spline, width, height),
496                                           BKE_mask_spline_resolution(spline, width, height));
497
498         unsigned char rgb_tmp[4];
499
500         const bool is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
501         const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0;
502         const bool is_fill = (spline->flag & MASK_SPLINE_NOFILL) == 0;
503
504         unsigned int tot_diff_point;
505         float (*diff_points)[2];
506
507         unsigned int tot_feather_point;
508         float (*feather_points)[2];
509
510         diff_points = BKE_mask_spline_differentiate_with_resolution(spline, &tot_diff_point, resol);
511
512         if (!diff_points)
513                 return;
514
515         if (is_smooth) {
516                 GPU_line_smooth(true);
517         }
518
519         feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution(spline, &tot_feather_point, resol, (is_fill != false));
520
521         /* draw feather */
522         mask_spline_feather_color_get(masklay, spline, is_spline_sel, rgb_tmp);
523         mask_draw_curve_type(C, spline, feather_points, tot_feather_point,
524                              true, is_active,
525                              rgb_tmp, draw_type);
526
527         if (!is_fill) {
528                 const float *fp   = &diff_points[0][0];
529                 float *fp_feather = &feather_points[0][0];
530
531                 BLI_assert(tot_diff_point == tot_feather_point);
532
533                 for (int i = 0; i < tot_diff_point; i++, fp += 2, fp_feather += 2) {
534                         float tvec[2];
535                         sub_v2_v2v2(tvec, fp, fp_feather);
536                         add_v2_v2v2(fp_feather, fp, tvec);
537                 }
538
539                 /* same as above */
540                 mask_draw_curve_type(C, spline, feather_points, tot_feather_point,
541                                      true, is_active,
542                                      rgb_tmp, draw_type);
543         }
544
545         MEM_freeN(feather_points);
546
547         /* draw main curve */
548         mask_spline_color_get(masklay, spline, is_spline_sel, rgb_tmp);
549         mask_draw_curve_type(C, spline, diff_points, tot_diff_point,
550                              false, is_active,
551                              rgb_tmp, draw_type);
552         MEM_freeN(diff_points);
553
554         if (is_smooth) {
555                 GPU_line_smooth(false);
556         }
557 }
558
559 static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, const char draw_type,
560                           const int width, const int height)
561 {
562         GPU_blend(true);
563         GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
564         GPU_enable_program_point_size();
565
566         MaskLayer *masklay;
567         int i;
568
569         for (masklay = mask->masklayers.first, i = 0; masklay; masklay = masklay->next, i++) {
570                 MaskSpline *spline;
571                 const bool is_active = (i == mask->masklay_act);
572
573                 if (masklay->restrictflag & MASK_RESTRICT_VIEW) {
574                         continue;
575                 }
576
577                 for (spline = masklay->splines.first; spline; spline = spline->next) {
578
579                         /* draw curve itself first... */
580                         draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height);
581
582                         if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) {
583                                 /* ...and then handles over the curve so they're nicely visible */
584                                 draw_spline_points(C, masklay, spline, draw_flag, draw_type);
585                         }
586
587                         /* show undeform for testing */
588                         if (0) {
589                                 void *back = spline->points_deform;
590
591                                 spline->points_deform = NULL;
592                                 draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height);
593                                 draw_spline_points(C, masklay, spline, draw_flag, draw_type);
594                                 spline->points_deform = back;
595                         }
596                 }
597         }
598
599         GPU_disable_program_point_size();
600         GPU_blend(false);
601 }
602
603 void ED_mask_draw(const bContext *C,
604                   const char draw_flag, const char draw_type)
605 {
606         ScrArea *sa = CTX_wm_area(C);
607         Mask *mask = CTX_data_edit_mask(C);
608         int width, height;
609
610         if (!mask)
611                 return;
612
613         ED_mask_get_size(sa, &width, &height);
614
615         draw_masklays(C, mask, draw_flag, draw_type, width, height);
616 }
617
618 static float *mask_rasterize(Mask *mask, const int width, const int height)
619 {
620         MaskRasterHandle *handle;
621         float *buffer = MEM_mallocN(sizeof(float) * height * width, "rasterized mask buffer");
622
623         /* Initialize rasterization handle. */
624         handle = BKE_maskrasterize_handle_new();
625         BKE_maskrasterize_handle_init(handle, mask, width, height, true, true, true);
626
627         BKE_maskrasterize_buffer(handle, width, height, buffer);
628
629         /* Free memory. */
630         BKE_maskrasterize_handle_free(handle);
631
632         return buffer;
633 }
634
635 /* sets up the opengl context.
636  * width, height are to match the values from ED_mask_get_size() */
637 void ED_mask_draw_region(
638         Mask *mask, ARegion *ar,
639         const char draw_flag, const char draw_type, const char overlay_mode,
640         /* convert directly into aspect corrected vars */
641         const int width_i, const int height_i,
642         const float aspx, const float aspy,
643         const bool do_scale_applied, const bool do_draw_cb,
644         /* optional - only used by clip */
645         float stabmat[4][4],
646         /* optional - only used when do_post_draw is set or called from clip editor */
647         const bContext *C)
648 {
649         struct View2D *v2d = &ar->v2d;
650
651         /* aspect always scales vertically in movie and image spaces */
652         const float width = width_i, height = (float)height_i * (aspy / aspx);
653
654         int x, y;
655         /* int w, h; */
656         float zoomx, zoomy;
657
658         /* frame image */
659         float maxdim;
660         float xofs, yofs;
661
662         /* find window pixel coordinates of origin */
663         UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
664
665
666         /* w = BLI_rctf_size_x(&v2d->tot); */
667         /* h = BLI_rctf_size_y(&v2d->tot); */
668
669
670         zoomx = (float)(BLI_rcti_size_x(&ar->winrct) + 1) / BLI_rctf_size_x(&ar->v2d.cur);
671         zoomy = (float)(BLI_rcti_size_y(&ar->winrct) + 1) / BLI_rctf_size_y(&ar->v2d.cur);
672
673         if (do_scale_applied) {
674                 zoomx /= width;
675                 zoomy /= height;
676         }
677
678         x += v2d->tot.xmin * zoomx;
679         y += v2d->tot.ymin * zoomy;
680
681         /* frame the image */
682         maxdim = max_ff(width, height);
683         if (width == height) {
684                 xofs = yofs = 0;
685         }
686         else if (width < height) {
687                 xofs = ((height - width) / -2.0f) * zoomx;
688                 yofs = 0.0f;
689         }
690         else { /* (width > height) */
691                 xofs = 0.0f;
692                 yofs = ((width - height) / -2.0f) * zoomy;
693         }
694
695         if (draw_flag & MASK_DRAWFLAG_OVERLAY) {
696                 float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
697                 float *buffer = mask_rasterize(mask, width, height);
698
699                 if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
700                         /* More blending types could be supported in the future. */
701                         GPU_blend(true);
702                         GPU_blend_set_func(GPU_DST_COLOR, GPU_ZERO);
703                 }
704
705                 GPU_matrix_push();
706                 GPU_matrix_translate_2f(x, y);
707                 GPU_matrix_scale_2f(zoomx, zoomy);
708                 if (stabmat) {
709                         GPU_matrix_mul(stabmat);
710                 }
711                 IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
712                 GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
713                 immDrawPixelsTex(&state, 0.0f, 0.0f, width, height, GL_RED, GL_FLOAT, GL_NEAREST, buffer, 1.0f, 1.0f, NULL);
714
715                 GPU_matrix_pop();
716
717                 if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
718                         GPU_blend(false);
719                 }
720
721                 MEM_freeN(buffer);
722         }
723
724         /* apply transformation so mask editing tools will assume drawing from the
725          * origin in normalized space */
726         GPU_matrix_push();
727         GPU_matrix_translate_2f(x + xofs, y + yofs);
728         GPU_matrix_scale_2f(zoomx, zoomy);
729         if (stabmat) {
730                 GPU_matrix_mul(stabmat);
731         }
732         GPU_matrix_scale_2f(maxdim, maxdim);
733
734         if (do_draw_cb) {
735                 ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
736         }
737
738         /* draw! */
739         draw_masklays(C, mask, draw_flag, draw_type, width, height);
740
741         if (do_draw_cb) {
742                 ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
743         }
744
745         GPU_matrix_pop();
746 }
747
748 void ED_mask_draw_frames(Mask *mask, ARegion *ar, const int cfra, const int sfra, const int efra)
749 {
750         const float framelen = ar->winx / (float)(efra - sfra + 1);
751
752         MaskLayer *masklay = BKE_mask_layer_active(mask);
753
754         if (masklay) {
755                 unsigned int num_lines = BLI_listbase_count(&masklay->splines_shapes);
756
757                 if (num_lines > 0) {
758                         uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
759
760                         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
761                         immUniformColor4ub(255, 175, 0, 255);
762
763                         immBegin(GPU_PRIM_LINES, 2 * num_lines);
764
765                         for (MaskLayerShape *masklay_shape = masklay->splines_shapes.first;
766                              masklay_shape;
767                              masklay_shape = masklay_shape->next)
768                         {
769                                 int frame = masklay_shape->frame;
770
771                                 /* draw_keyframe(i, CFRA, sfra, framelen, 1); */
772                                 int height = (frame == cfra) ? 22 : 10;
773                                 int x = (frame - sfra) * framelen;
774                                 immVertex2i(pos, x, 0);
775                                 immVertex2i(pos, x, height);
776                         }
777                         immEnd();
778                         immUnbindProgram();
779                 }
780         }
781 }