Blender V5.0
sequencer_preview_draw.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10#include <cmath>
11#include <cstring>
12
13#include "BLF_api.hh"
14
15#include "BLI_index_range.hh"
16#include "BLI_math_matrix.hh"
18#include "BLI_math_rotation.h"
20#include "BLI_rect.h"
21#include "BLI_string_utf8.h"
22#include "BLI_utildefines.h"
23#include "BLI_vector.hh"
24
25#include "DNA_scene_types.h"
26#include "DNA_screen_types.h"
27#include "DNA_sequence_types.h"
28#include "DNA_space_types.h"
29#include "DNA_view2d_types.h"
30
31#include "BKE_context.hh"
32#include "BKE_global.hh"
33#include "BKE_scene.hh"
34#include "BKE_screen.hh"
35
37#include "IMB_imbuf.hh"
38#include "IMB_imbuf_types.hh"
39
40#include "GPU_compute.hh"
41#include "GPU_debug.hh"
42#include "GPU_framebuffer.hh"
43#include "GPU_immediate.hh"
44#include "GPU_immediate_util.hh"
45#include "GPU_matrix.hh"
46#include "GPU_primitive.hh"
47#include "GPU_shader_shared.hh"
48#include "GPU_state.hh"
49#include "GPU_viewport.hh"
50
51#include "ED_gpencil_legacy.hh"
52#include "ED_screen.hh"
53#include "ED_sequencer.hh"
54#include "ED_space_api.hh"
55#include "ED_util.hh"
56#include "ED_view3d.hh"
57
58#include "BIF_glutil.hh"
59
60#include "SEQ_channels.hh"
61#include "SEQ_effects.hh"
62#include "SEQ_iterator.hh"
63#include "SEQ_prefetch.hh"
64#include "SEQ_preview_cache.hh"
65#include "SEQ_proxy.hh"
66#include "SEQ_render.hh"
67#include "SEQ_select.hh"
68#include "SEQ_sequencer.hh"
69#include "SEQ_time.hh"
70#include "SEQ_transform.hh"
71
72#include "UI_interface.hh"
73#include "UI_resources.hh"
74#include "UI_view2d.hh"
75
76#include "WM_api.hh"
77#include "WM_types.hh"
78
79#include "sequencer_intern.hh"
81#include "sequencer_scopes.hh"
82
83namespace blender::ed::vse {
84static Strip *special_seq_update = nullptr;
85
87{
88 special_seq_update = strip;
89}
90
95
96void special_preview_set(bContext *C, const int mval[2])
97{
99 if (!seq::editing_get(scene)) {
100 return;
101 }
102
103 ARegion *region = CTX_wm_region(C);
104 Strip *strip = strip_under_mouse_get(scene, &region->v2d, mval);
105 if (strip != nullptr && strip->type != STRIP_TYPE_SOUND_RAM) {
107 }
108}
109
114
115ImBuf *sequencer_ibuf_get(const bContext *C, const int timeline_frame, const char *viewname)
116{
117 Main *bmain = CTX_data_main(C);
118 ARegion *region = CTX_wm_region(C);
121 SpaceSeq *sseq = CTX_wm_space_seq(C);
122 bScreen *screen = CTX_wm_screen(C);
123
124 seq::RenderData context = {nullptr};
125 ImBuf *ibuf;
126 short is_break = G.is_break;
128 sseq->render_size);
129 if (render_size_mode == SEQ_RENDER_SIZE_NONE) {
130 return nullptr;
131 }
132
133 const float render_scale = seq::get_render_scale_factor(render_size_mode, scene->r.size);
134 int rectx = roundf(render_scale * scene->r.xsch);
135 int recty = roundf(render_scale * scene->r.ysch);
136
138 bmain, depsgraph, scene, rectx, recty, render_size_mode, nullptr, &context);
139 context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
140 context.use_proxies = (sseq->flag & SEQ_USE_PROXIES) != 0;
141 context.is_playing = screen->animtimer != nullptr;
142 context.is_scrubbing = screen->scrubbing;
143
144 /* Sequencer could start rendering, in this case we need to be sure it wouldn't be
145 * canceled by Escape pressed somewhere in the past. */
146 G.is_break = false;
147
150 if (viewport) {
151 /* Unbind viewport to release the DRW context. */
152 GPU_viewport_unbind(viewport);
153 }
154 else {
155 /* Rendering can change OGL context. Save & Restore frame-buffer. */
157 }
158
159 if (special_preview_get()) {
160 ibuf = seq::render_give_ibuf_direct(&context, timeline_frame, special_preview_get());
161 }
162 else {
163 ibuf = seq::render_give_ibuf(&context, timeline_frame, sseq->chanshown);
164 }
165
166 if (viewport) {
167 /* Follows same logic as wm_draw_window_offscreen to make sure to restore the same
168 * viewport. */
169 int view = (sseq->multiview_eye == STEREO_RIGHT_ID) ? 1 : 0;
170 GPU_viewport_bind(viewport, view, &region->winrct);
171 }
172 else if (fb) {
174 }
175
176 /* Restore state so real rendering would be canceled if needed. */
177 G.is_break = is_break;
178
179 return ibuf;
180}
181
182static void sequencer_display_size(const RenderData &render_data, float r_viewrect[2])
183{
184 r_viewrect[0] = float(render_data.xsch);
185 r_viewrect[1] = float(render_data.ysch);
186
187 r_viewrect[0] *= render_data.xasp / render_data.yasp;
188}
189
191{
192 /* Draw grease-pencil (image aligned). */
194
195 /* Orthographic at pixel level. */
197
198 /* Draw grease-pencil (screen aligned). */
200}
201
206 const View2D &v2d,
207 const Scene *scene)
208{
209 const float x1 = v2d.tot.xmin;
210 const float y1 = v2d.tot.ymin;
211 const float x2 = v2d.tot.xmax;
212 const float y2 = v2d.tot.ymax;
213
214 GPU_line_width(1.0f);
215
216 /* Draw border. */
217 const uint shdr_pos = GPU_vertformat_attr_add(
218 immVertexFormat(), "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
219
221
222 float viewport_size[4];
223 GPU_viewport_size_get_f(viewport_size);
224 immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC);
225
227 immUniform1i("colors_len", 0); /* Simple dashes. */
228 immUniform1f("dash_width", 6.0f);
229 immUniform1f("udash_factor", 0.5f);
230
231 imm_draw_box_wire_2d(shdr_pos, x1 - 0.5f, y1 - 0.5f, x2 + 0.5f, y2 + 0.5f);
232
233 /* Draw safety border. */
236 rctf rect;
237 rect.xmin = x1;
238 rect.xmax = x2;
239 rect.ymin = y1;
240 rect.ymax = y2;
241 UI_draw_safe_areas(shdr_pos, &rect, scene->safe_areas.title, scene->safe_areas.action);
242
244
246 shdr_pos, &rect, scene->safe_areas.title_center, scene->safe_areas.action_center);
247 }
248 }
249
251}
252
253#if 0
254void sequencer_draw_maskedit(const bContext *C, Scene *scene, ARegion *region, SpaceSeq *sseq)
255{
256 /* NOTE: sequencer mask editing isn't finished, the draw code is working but editing not.
257 * For now just disable drawing since the strip frame will likely be offset. */
258
259 // if (sc->mode == SC_MODE_MASKEDIT)
260 if (0 && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
261 Mask *mask = SEQ_active_mask_get(scene);
262
263 if (mask) {
264 int width, height;
265 float aspx = 1.0f, aspy = 1.0f;
266 // ED_mask_get_size(C, &width, &height);
267
268 // Scene *scene = CTX_data_sequencer_scene(C);
269 BKE_render_resolution(&scene->r, false, &width, &height);
270
272 region,
273 true,
274 0,
275 0,
276 0, /* TODO */
277 width,
278 height,
279 aspx,
280 aspy,
281 false,
282 true,
283 nullptr,
284 C);
285 }
286 }
287}
288#endif
289
290/* Force redraw, when prefetching and using cache view. */
291static void seq_prefetch_wm_notify(const bContext *C, Scene *scene)
292{
293 if (seq::prefetch_need_redraw(C, scene)) {
295 }
296}
297
298static void sequencer_stop_running_jobs(const bContext *C, Scene *scene)
299{
300 if (G.is_rendering == false && (scene->r.seq_prev_type) == OB_RENDER) {
301 /* Stop all running jobs, except screen one. Currently previews frustrate Render.
302 * Need to make so sequencers rendering doesn't conflict with compositor. */
304
305 /* In case of final rendering used for preview, kill all previews,
306 * otherwise threading conflict will happen in rendering module. */
308 }
309}
310
315
316/* Semantic utility to get a rectangle with positions that correspond to a full frame drawn in the
317 * preview region. */
319{
320 return region.v2d.tot;
321}
322
323/* Semantic utility to generate rectangle with UV coordinates that cover an entire 0 .. 1
324 * rectangle. */
326{
327 rctf texture_coord;
328 BLI_rctf_init(&texture_coord, 0.0f, 1.0f, 0.0f, 1.0f);
329 return texture_coord;
330}
331
332/* Get rectangle positions within preview region that are to be used to draw reference frame.
333 *
334 * If the frame overlay is set to RECTANGLE this function returns coordinates of the rectangle
335 * where partial reference frame is to be drawn.
336 *
337 * If the frame overlay is set to REFERENCE this function returns full-frame rectangle, same as
338 * preview_get_full_position().
339 *
340 * If the frame overlay is set to REFERENCE or is disabled the return value is valid but
341 * corresponds to an undefined state.
342 */
343static rctf preview_get_reference_position(const SpaceSeq &space_sequencer,
344 const Editing &editing,
345 const ARegion &region)
346{
347 const View2D &v2d = region.v2d;
348
349 BLI_assert(ELEM(space_sequencer.overlay_frame_type,
352
353 if (space_sequencer.overlay_frame_type == SEQ_OVERLAY_FRAME_TYPE_RECT) {
354 rctf position;
355 const float xmin = v2d.tot.xmin;
356 const float ymin = v2d.tot.ymin;
357
358 const float width = BLI_rctf_size_x(&v2d.tot);
359 const float height = BLI_rctf_size_y(&v2d.tot);
360
361 position.xmax = xmin + width * editing.overlay_frame_rect.xmax;
362 position.xmin = xmin + width * editing.overlay_frame_rect.xmin;
363 position.ymax = ymin + height * editing.overlay_frame_rect.ymax;
364 position.ymin = ymin + height * editing.overlay_frame_rect.ymin;
365
366 return position;
367 }
368
369 return v2d.tot;
370}
371
372/* Return rectangle with UV coordinates that are to be used to draw reference frame.
373 *
374 * If the frame overlay is set to rectangle the return value contains vUV coordinates of the
375 * rectangle within the reference frame.
376 *
377 * If the frame overlay is set to REFERENCE this function returns full-frame UV rectangle, same as
378 * preview_get_full_texture_coord().
379 *
380 * If the frame overlay is set to REFERENCE or is disabled the return value is valid but
381 * corresponds to an undefined state.
382 */
384 const Editing &editing)
385{
386 if (space_sequencer.overlay_frame_type == SEQ_OVERLAY_FRAME_TYPE_RECT) {
387 return editing.overlay_frame_rect;
388 }
389
390 rctf texture_coord;
391 BLI_rctf_init(&texture_coord, 0.0f, 1.0f, 0.0f, 1.0f);
392
393 return texture_coord;
394}
395
396static void add_vertical_line(const float val,
397 const uchar4 color,
398 View2D &v2d,
399 const float text_scale_x,
400 const float text_scale_y,
401 SeqQuadsBatch &quads,
402 const rctf &area)
403{
404 const float x = area.xmin + (area.xmax - area.xmin) * val;
405
406 char buf[20];
407 const size_t buf_len = SNPRINTF_UTF8_RLEN(buf, "%.2f", val);
408 float text_width, text_height;
409 BLF_width_and_height(BLF_default(), buf, buf_len, &text_width, &text_height);
410 text_width *= text_scale_x;
411 text_height *= text_scale_y;
413 &v2d, x - text_width / 2, area.ymax - text_height * 1.3f, buf, buf_len, color);
414
415 quads.add_line(x, area.ymin, x, area.ymax - text_height * 1.4f, color);
416}
417
418static void draw_histogram(ARegion &region,
419 const ScopeHistogram &hist,
420 SeqQuadsBatch &quads,
421 const rctf &area)
422{
423 if (hist.data.is_empty()) {
424 return;
425 }
426
427 /* Grid lines and labels. */
428 View2D &v2d = region.v2d;
429 float text_scale_x, text_scale_y;
430 UI_view2d_scale_get_inverse(&v2d, &text_scale_x, &text_scale_y);
431
432 const bool hdr = ScopeHistogram::bin_to_float(math::reduce_max(hist.max_bin)) > 1.001f;
433 const float max_val = hdr ? 12.0f : 1.0f;
434
435 /* Grid lines covering 0..1 range, with 0.25 steps. */
436 const uchar col_grid[4] = {128, 128, 128, 128};
437 for (float val = 0.0f; val <= 1.0f; val += 0.25f) {
438 add_vertical_line(val, col_grid, v2d, text_scale_x, text_scale_y, quads, area);
439 }
440 /* For HDR content, more lines every 1.0 step. */
441 if (hdr) {
442 for (float val = 2.0f; val <= max_val; val += 1.0f) {
443 add_vertical_line(val, col_grid, v2d, text_scale_x, text_scale_y, quads, area);
444 }
445 }
446 /* Lines for maximum values. */
447 const float max_val_r = ScopeHistogram::bin_to_float(hist.max_bin.x);
448 const float max_val_g = ScopeHistogram::bin_to_float(hist.max_bin.y);
449 const float max_val_b = ScopeHistogram::bin_to_float(hist.max_bin.z);
450 add_vertical_line(max_val_r, {128, 0, 0, 128}, v2d, text_scale_x, text_scale_y, quads, area);
451 add_vertical_line(max_val_g, {0, 128, 0, 128}, v2d, text_scale_x, text_scale_y, quads, area);
452 add_vertical_line(max_val_b, {0, 0, 128, 128}, v2d, text_scale_x, text_scale_y, quads, area);
453
454 /* Horizontal lines. */
455 const float x_val_min = area.xmin;
456 const float x_val_max = area.xmin + (area.xmax - area.xmin) * max_val;
457 quads.add_line(x_val_min, area.ymin, x_val_max, area.ymin, col_grid);
458 quads.add_line(x_val_min, area.ymax, x_val_max, area.ymax, col_grid);
459
460 /* Histogram area for each R/G/B channels, additively blended. */
461 quads.draw();
463 for (int ch = 0; ch < 3; ++ch) {
464 if (hist.max_value[ch] == 0) {
465 continue;
466 }
467 uchar col_line[4] = {32, 32, 32, 255};
468 uchar col_area[4] = {64, 64, 64, 128};
469 col_line[ch] = 224;
470 col_area[ch] = 224;
471 float y_scale = (area.ymax - area.ymin) / hist.max_value[ch] * 0.95f;
472 float x_scale = (area.xmax - area.xmin);
473 float yb = area.ymin;
474 for (int bin = 0; bin <= hist.max_bin[ch]; bin++) {
475 uint bin_val = hist.data[bin][ch];
476 if (bin_val == 0) {
477 continue;
478 }
479 float f0 = ScopeHistogram::bin_to_float(bin);
480 float f1 = ScopeHistogram::bin_to_float(bin + 1);
481 float x0 = area.xmin + f0 * x_scale;
482 float x1 = area.xmin + f1 * x_scale;
483
484 float y = area.ymin + bin_val * y_scale;
485 quads.add_quad(x0, yb, x0, y, x1, yb, x1, y, col_area);
486 quads.add_line(x0, y, x1, y, col_line);
487 }
488 }
489 quads.draw();
491
493}
494
496{
497 float y, u, v;
498 rgb_to_yuv(rgb.x, rgb.y, rgb.z, &y, &u, &v, BLI_YUV_ITU_BT709);
499 /* Scale to +-0.5 range. */
502 return blender::float2(u, v);
503}
504
505static void draw_waveform_graticule(ARegion *region, SeqQuadsBatch &quads, const rctf &area)
506{
507 /* Horizontal lines at 10%, 70%, 90%. */
508 const float lines[3] = {0.1f, 0.7f, 0.9f};
509 uchar col_grid[4] = {160, 64, 64, 128};
510 const float x0 = area.xmin;
511 const float x1 = area.xmax;
512
513 for (int i = 0; i < 3; i++) {
514 const float y = area.ymin + (area.ymax - area.ymin) * lines[i];
515 char buf[10];
516 const size_t buf_len = SNPRINTF_UTF8_RLEN(buf, "%.1f", lines[i]);
517 quads.add_line(x0, y, x1, y, col_grid);
518 UI_view2d_text_cache_add(&region->v2d, x0 + 8, y + 8, buf, buf_len, col_grid);
519 }
520 /* Border. */
521 uchar col_border[4] = {64, 64, 64, 128};
522 quads.add_wire_quad(x0, area.ymin, x1, area.ymax, col_border);
523
524 quads.draw();
526}
527
528static void draw_vectorscope_graticule(ARegion *region, SeqQuadsBatch &quads, const rctf &area)
529{
530 const float skin_rad = DEG2RADF(123.0f); /* angle in radians of the skin tone line */
531
532 const float w = BLI_rctf_size_x(&area);
533 const float h = BLI_rctf_size_y(&area);
534 const float2 center{BLI_rctf_cent_x(&area), BLI_rctf_cent_y(&area)};
535 const float radius = ((w < h) ? w : h) * 0.5f;
536
537 /* Precalculate circle points/colors. */
538 constexpr int circle_delta = 6;
539 constexpr int num_circle_points = 360 / circle_delta;
540 float2 circle_pos[num_circle_points];
541 float3 circle_col[num_circle_points];
542 for (int i = 0; i < num_circle_points; i++) {
543 float a = DEG2RADF(i * circle_delta);
544 float x = cosf(a);
545 float y = sinf(a);
546 circle_pos[i] = float2(x, y);
547 float u = x / SeqScopes::VECSCOPE_U_SCALE;
549
550 float3 col;
551 yuv_to_rgb(0.5f, u, v, &col.x, &col.y, &col.z, BLI_YUV_ITU_BT709);
552 circle_col[i] = col;
553 }
554
555 /* Draw colored background and outer ring, additively blended
556 * since vectorscope image is already drawn. */
558
559 constexpr float alpha_f = 0.8f;
560 constexpr uchar alpha_b = uchar(alpha_f * 255.0f);
561 const uchar4 col_center(50, 50, 50, alpha_b);
562
563 uchar4 col1(0, 0, 0, alpha_b);
564 uchar4 col2(0, 0, 0, alpha_b);
565 uchar4 col3(0, 0, 0, alpha_b);
566
567 /* Background: since the quads batch utility draws quads, draw two
568 * segments of the circle (two triangles) in one iteration. */
569 constexpr float mul_background = 0.2f;
570 for (int i = 0; i < num_circle_points; i += 2) {
571 int idx1 = i;
572 int idx2 = (i + 1) % num_circle_points;
573 int idx3 = (i + 2) % num_circle_points;
574 float2 pt1 = center + circle_pos[idx1] * radius;
575 float2 pt2 = center + circle_pos[idx2] * radius;
576 float2 pt3 = center + circle_pos[idx3] * radius;
577 float3 rgb1 = circle_col[idx1] * mul_background;
578 float3 rgb2 = circle_col[idx2] * mul_background;
579 float3 rgb3 = circle_col[idx3] * mul_background;
580 rgb_float_to_uchar(col1, rgb1);
581 rgb_float_to_uchar(col2, rgb2);
582 rgb_float_to_uchar(col3, rgb3);
583 quads.add_quad(pt1.x,
584 pt1.y,
585 pt2.x,
586 pt2.y,
587 center.x,
588 center.y,
589 pt3.x,
590 pt3.y,
591 col1,
592 col2,
593 col_center,
594 col3);
595 }
596
597 /* Outer ring. */
598 const float outer_radius = radius * 1.02f;
599 for (int i = 0; i < num_circle_points; i++) {
600 int idx1 = i;
601 int idx2 = (i + 1) % num_circle_points;
602 float2 pt1a = center + circle_pos[idx1] * radius;
603 float2 pt2a = center + circle_pos[idx2] * radius;
604 float2 pt1b = center + circle_pos[idx1] * outer_radius;
605 float2 pt2b = center + circle_pos[idx2] * outer_radius;
606 float3 rgb1 = circle_col[idx1];
607 float3 rgb2 = circle_col[idx2];
608 rgb_float_to_uchar(col1, rgb1);
609 rgb_float_to_uchar(col2, rgb2);
610 quads.add_quad(
611 pt1a.x, pt1a.y, pt1b.x, pt1b.y, pt2a.x, pt2a.y, pt2b.x, pt2b.y, col1, col1, col2, col2);
612 }
613
614 quads.draw();
615
616 /* Draw grid and other labels using regular alpha blending. */
618 const uchar4 col_grid(128, 128, 128, 128);
619
620 /* Cross. */
621 quads.add_line(center.x - radius, center.y, center.x + radius, center.y, col_grid);
622 quads.add_line(center.x, center.y - radius, center.x, center.y + radius, col_grid);
623
624 /* Inner circles. */
625 for (int j = 1; j < 5; j++) {
626 float r = radius * j * 0.2f;
627 for (int i = 0; i < num_circle_points; i++) {
628 int idx1 = i;
629 int idx2 = (i + 1) % num_circle_points;
630 float2 pt1 = center + circle_pos[idx1] * r;
631 float2 pt2 = center + circle_pos[idx2] * r;
632 quads.add_line(pt1.x, pt1.y, pt2.x, pt2.y, col_grid);
633 }
634 }
635
636 /* "Safe" (0.75 saturation) primary color locations and labels. */
637 const float3 primaries[6] = {
638 {1, 0, 0},
639 {1, 1, 0},
640 {0, 1, 0},
641 {0, 1, 1},
642 {0, 0, 1},
643 {1, 0, 1},
644 };
645 const char *names = "RYGCBM";
646
647 /* Calculate size of single text letter. */
648 char buf[2] = {'M', 0};
649 float text_scale_x, text_scale_y;
650 UI_view2d_scale_get_inverse(&region->v2d, &text_scale_x, &text_scale_y);
651 float text_width, text_height;
652 BLF_width_and_height(BLF_default(), buf, 1, &text_width, &text_height);
653 text_width *= text_scale_x;
654 text_height *= text_scale_y;
655
656 const uchar4 col_target(128, 128, 128, 192);
657 const float delta = radius * 0.01f;
658 for (int i = 0; i < 6; i++) {
659 float3 safe = primaries[i] * 0.75f;
660 float2 pos = center + rgb_to_uv_scaled(safe) * (radius * 2);
661 quads.add_wire_quad(pos.x - delta, pos.y - delta, pos.x + delta, pos.y + delta, col_target);
662
663 buf[0] = names[i];
665 pos.x + delta * 1.2f + text_width / 4,
666 pos.y - text_height / 2,
667 buf,
668 1,
669 col_target);
670 }
671
672 /* Skin tone line. */
673 const uchar4 col_tone(255, 102, 0, 128);
674 quads.add_line(center.x,
675 center.y,
676 center.x + cosf(skin_rad) * radius,
677 center.y + sinf(skin_rad) * radius,
678 col_tone);
679
680 quads.draw();
682}
683
685{
686 switch (type) {
688 return "VSE Vectorscope";
690 return "VSE Waveform";
692 return "VSE Parade";
694 return "VSE Histogram";
696 return "VSE Overexposed";
697 default:
698 return "VSE Scope";
699 }
700}
701
702static void sequencer_draw_scopes(Scene *scene,
703 const SpaceSeq &space_sequencer,
704 ARegion &region,
705 int timeline_frame,
706 int image_width,
707 int image_height,
708 bool premultiplied)
709{
711
713 scene, timeline_frame, 0);
714 if (input_texture == nullptr) {
716 scene, timeline_frame, space_sequencer.chanshown);
717 }
718
719 SeqQuadsBatch quads;
720 const SeqScopes *scopes = &space_sequencer.runtime->scopes;
721
722 bool use_blend = (space_sequencer.mainb == SEQ_DRAW_IMG_IMBUF &&
723 space_sequencer.flag & SEQ_USE_ALPHA) ||
724 (space_sequencer.mainb != SEQ_DRAW_IMG_IMBUF);
725
726 const rctf preview = preview_get_full_position(region);
727
728 /* Draw black rectangle over scopes area. */
729 if (space_sequencer.mainb != SEQ_DRAW_IMG_IMBUF) {
732 immVertexFormat(), "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
733 uchar black[4] = {0, 0, 0, 255};
735 immUniformColor4ubv(black);
736 immRectf(pos, preview.xmin, preview.ymin, preview.xmax, preview.ymax);
738 }
739
740 if (use_blend) {
742 }
743
744 if (input_texture) {
745 if (space_sequencer.mainb == SEQ_DRAW_IMG_IMBUF) {
746 /* Draw overexposed overlay. */
748 GPUVertFormat *imm_format = immVertexFormat();
750 imm_format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
752 imm_format, "texCoord", blender::gpu::VertAttrType::SFLOAT_32_32);
753
755 immUniform1i("img_premultiplied", premultiplied ? 1 : 0);
756 immUniform1f("zebra_limit", space_sequencer.zebra / 100.0f);
757 immUniformColor3f(1.0f, 1.0f, 1.0f);
758
759 GPU_texture_bind(input_texture, 0);
760 rctf uv;
761 BLI_rctf_init(&uv, 0.0f, 1.0f, 0.0f, 1.0f);
763 GPU_texture_unbind(input_texture);
765 }
766 else if (space_sequencer.mainb != SEQ_DRAW_IMG_HISTOGRAM) {
767 /* Draw point-based scopes using a compute shader based rasterizer (using
768 * regular GPU pipeline to draw many points, where thousands of them can
769 * hit the same pixels, is very inefficient, especially on tile-based GPUs).
770 *
771 * Compute shader rasterizer does atomic adds of fixed point colors into
772 * a screen size buffer, then a fragment shader resolve pass outputs the
773 * final colors. */
774 const float point_size = (BLI_rcti_size_x(&region.v2d.mask) + 1) /
775 BLI_rctf_size_x(&region.v2d.cur);
776 float3 coeffs;
778
779 int viewport_size_i[4];
780 GPU_viewport_size_get_i(viewport_size_i);
781 const int2 viewport_size = int2(viewport_size_i[2], viewport_size_i[3]);
782 const int2 image_size = int2(image_width, image_height);
783 gpu::StorageBuf *raster_ssbo = GPU_storagebuf_create_ex(viewport_size.x * viewport_size.y *
784 sizeof(SeqScopeRasterData),
785 nullptr,
787 "Scopes Raster");
788 GPU_storagebuf_clear_to_zero(raster_ssbo);
789 /* Compute shader rasterization. */
790 {
792 BLI_assert(shader);
793 GPU_shader_bind(shader);
794
795 const int raster_ssbo_location = GPU_shader_get_ssbo_binding(shader, "raster_buf");
796 GPU_storagebuf_bind(raster_ssbo, raster_ssbo_location);
797 const int image_location = GPU_shader_get_sampler_binding(shader, "image");
798 GPU_texture_bind(input_texture, image_location);
799
800 GPU_shader_uniform_1i(shader, "view_width", viewport_size.x);
801 GPU_shader_uniform_1i(shader, "view_height", viewport_size.y);
802 GPU_shader_uniform_3fv(shader, "luma_coeffs", coeffs);
803 GPU_shader_uniform_1f(shader, "scope_point_size", point_size);
804 GPU_shader_uniform_1b(shader, "img_premultiplied", premultiplied);
805 GPU_shader_uniform_1i(shader, "image_width", image_width);
806 GPU_shader_uniform_1i(shader, "image_height", image_height);
807 GPU_shader_uniform_1i(shader, "scope_mode", space_sequencer.mainb);
808
809 const int2 groups_to_dispatch = math::divide_ceil(image_size, int2(16));
810 GPU_compute_dispatch(shader, groups_to_dispatch.x, groups_to_dispatch.y, 1);
811
813 GPU_storagebuf_unbind(raster_ssbo);
814 /* Make computed results consistently visible in the following resolve pass. */
816 }
817
818 /* Resolve pass. */
819 {
820 if (use_blend) {
822 }
823
824 /* Depending on resolution of the image, different amounts of pixels are expected
825 * to hit the same locations of the scope. Adjust the scope transparency mapping
826 * exponent so that the scope has decent visibility without saturating or being too dark:
827 * 0.07 at height=2160 (4K) and up, 0.5 at height=360 and below, and interpolating between
828 * those. */
829 float alpha = math::clamp(ratiof(360.0f, 2160.0f, image_height), 0.0f, 1.0f);
830 float exponent = math::interpolate(0.5f, 0.07f, alpha);
831
833 BLI_assert(shader);
834
835 const int raster_ssbo_location = GPU_shader_get_ssbo_binding(shader, "raster_buf");
836 GPU_storagebuf_bind(raster_ssbo, raster_ssbo_location);
837
838 blender::gpu::Batch *batch = GPU_batch_create_procedural(GPU_PRIM_TRIS, 3);
839
841 GPU_batch_uniform_1i(batch, "view_width", viewport_size.x);
842 GPU_batch_uniform_1i(batch, "view_height", viewport_size.y);
843 GPU_batch_uniform_1f(batch, "alpha_exponent", exponent);
845
847 GPU_storagebuf_unbind(raster_ssbo);
848 }
849
850 GPU_storagebuf_free(raster_ssbo);
851 }
852 }
853
854 /* Draw scope graticules. */
855 if (use_blend) {
857 }
858
859 if (space_sequencer.mainb == SEQ_DRAW_IMG_HISTOGRAM) {
860 draw_histogram(region, scopes->histogram, quads, preview);
861 }
863 use_blend = true;
864 draw_waveform_graticule(&region, quads, preview);
865 }
866 if (space_sequencer.mainb == SEQ_DRAW_IMG_VECTORSCOPE) {
867 use_blend = true;
868 draw_vectorscope_graticule(&region, quads, preview);
869 }
870
871 quads.draw();
872
873 if (use_blend) {
875 }
877}
878
879static void update_gpu_scopes(const ImBuf *input_ibuf,
880 gpu::Texture *input_texture,
881 const ColorManagedViewSettings &view_settings,
882 const ColorManagedDisplaySettings &display_settings,
883 const SpaceSeq &space_sequencer,
884 Scene *scene,
885 int timeline_frame)
886{
887 BLI_assert(input_ibuf && input_texture);
888
889 /* No need for GPU texture transformed to display space: can use input texture as-is. */
890 if (!IMB_colormanagement_display_processor_needed(input_ibuf, &view_settings, &display_settings))
891 {
892 return;
893 }
894
895 /* Display space GPU texture is already calculated. */
897 scene, timeline_frame, space_sequencer.chanshown);
898 if (display_texture != nullptr) {
899 return;
900 }
901
902 /* Create GPU texture. */
903 const int width = GPU_texture_width(input_texture);
904 const int height = GPU_texture_height(input_texture);
906 const gpu::TextureFormat format = gpu::TextureFormat::SFLOAT_16_16_16_16;
907 display_texture = GPU_texture_create_2d(
908 "seq_scope_display_buf", width, height, 1, format, usage, nullptr);
909 if (display_texture == nullptr) {
910 return;
911 }
912 GPU_texture_filter_mode(display_texture, false);
913
916 GPU_matrix_ortho_set(0.0f, 1.0f, 0.0f, 1.0f, -1.0, 1.0f);
918
919 blender::gpu::FrameBuffer *fb = nullptr;
921 {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(display_texture)});
923
924 GPUVertFormat *imm_format = immVertexFormat();
926 imm_format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
928 imm_format, "texCoord", blender::gpu::VertAttrType::SFLOAT_32_32);
929
930 const ColorSpace *input_colorspace = input_ibuf->float_buffer.data ?
931 input_ibuf->float_buffer.colorspace :
932 input_ibuf->byte_buffer.colorspace;
933 const bool predivide = input_ibuf->float_buffer.data != nullptr;
935 &view_settings, &display_settings, input_colorspace, 0.0f, predivide, false))
936 {
937 GPU_texture_bind(input_texture, 0);
938 const rctf position{0.0f, 1.0f, 0.0f, 1.0f};
939 const rctf texture_coord{0.0f, 1.0f, 0.0f, 1.0f};
940 immRectf_with_texco(pos, tex_coord, position, texture_coord);
941 GPU_texture_unbind(input_texture);
943 }
944
946
949
951 scene, timeline_frame, space_sequencer.chanshown, display_texture);
952}
953
954static void update_cpu_scopes(const SpaceSeq &space_sequencer,
955 const ColorManagedViewSettings &view_settings,
956 const ColorManagedDisplaySettings &display_settings,
957 const ImBuf &ibuf,
958 const int timeline_frame)
959
960{
961 SeqScopes &scopes = space_sequencer.runtime->scopes;
962 if (scopes.last_ibuf == &ibuf && scopes.last_timeline_frame == timeline_frame) {
963 /* Nothing to do: scopes already calculated for this image/frame. */
964 return;
965 }
966
967 scopes.cleanup();
968 if (space_sequencer.mainb == SEQ_DRAW_IMG_HISTOGRAM) {
969 scopes.histogram.calc_from_ibuf(&ibuf, view_settings, display_settings);
970 }
971 scopes.last_ibuf = &ibuf;
972 scopes.last_timeline_frame = timeline_frame;
973}
974
975static bool sequencer_draw_get_transform_preview(const SpaceSeq &sseq, const Scene &scene)
976{
977 Strip *last_seq = seq::select_active_get(&scene);
978 if (last_seq == nullptr) {
979 return false;
980 }
981
982 return (G.moving & G_TRANSFORM_SEQ) && (last_seq->flag & SELECT) &&
983 ((last_seq->flag & SEQ_LEFTSEL) || (last_seq->flag & SEQ_RIGHTSEL)) &&
985}
986
988{
989 Strip *last_seq = seq::select_active_get(scene);
990 /* #sequencer_draw_get_transform_preview must already have been called. */
991 BLI_assert(last_seq != nullptr);
992 int preview_frame;
993
994 if (last_seq->flag & SEQ_RIGHTSEL) {
995 preview_frame = seq::time_right_handle_frame_get(scene, last_seq) - 1;
996 }
997 else {
998 preview_frame = seq::time_left_handle_frame_get(scene, last_seq);
999 }
1000
1001 return preview_frame;
1002}
1003
1005 Strip *strip,
1006 bool is_active_seq)
1007{
1008 SpaceSeq *sseq = CTX_wm_space_seq(C);
1009 const ARegion *region = CTX_wm_region(C);
1011 return;
1012 }
1013 if ((strip->flag & SELECT) == 0) {
1014 return;
1015 }
1017 return;
1018 }
1019 if ((sseq->flag & SEQ_SHOW_OVERLAY) == 0 ||
1021 {
1022 return;
1023 }
1024 if (ELEM(sseq->mainb,
1029 {
1030 return;
1031 }
1032
1034 CTX_data_sequencer_scene(C), strip);
1035
1036 /* Origin. */
1038 uint pos = GPU_vertformat_attr_add(format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
1040 immUniform1f("outlineWidth", 1.5f);
1041 immUniformColor3f(1.0f, 1.0f, 1.0f);
1042 immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 1.0f);
1043 immUniform1f("size", 15.0f * U.pixelsize);
1045 immVertex2f(pos, origin[0], origin[1]);
1046 immEnd();
1048
1049 /* Outline. */
1051 CTX_data_sequencer_scene(C), strip);
1052
1053 GPU_line_smooth(true);
1055 GPU_line_width(2);
1057
1058 float col[3];
1059 if (is_active_seq) {
1061 }
1062 else {
1064 }
1067 immVertex2f(pos, strip_image_quad[0].x, strip_image_quad[0].y);
1068 immVertex2f(pos, strip_image_quad[1].x, strip_image_quad[1].y);
1069 immVertex2f(pos, strip_image_quad[2].x, strip_image_quad[2].y);
1070 immVertex2f(pos, strip_image_quad[3].x, strip_image_quad[3].y);
1071 immEnd();
1073 GPU_line_width(1);
1075 GPU_line_smooth(false);
1076}
1077
1078static void text_selection_draw(const bContext *C, const Strip *strip, uint pos)
1079{
1080 const TextVars *data = static_cast<TextVars *>(strip->effectdata);
1081 const TextVarsRuntime *text = data->runtime;
1082 const Scene *scene = CTX_data_sequencer_scene(C);
1083
1084 if (data->selection_start_offset == -1 || strip_text_selection_range_get(data).is_empty()) {
1085 return;
1086 }
1087
1090 sel_range.first());
1091 const blender::int2 selection_end = strip_text_cursor_offset_to_position(text, sel_range.last());
1092 const int line_start = selection_start.y;
1093 const int line_end = selection_end.y;
1094
1095 for (int line_index = line_start; line_index <= line_end; line_index++) {
1096 const blender::seq::LineInfo line = text->lines[line_index];
1097 blender::seq::CharInfo character_start = line.characters.first();
1098 blender::seq::CharInfo character_end = line.characters.last();
1099
1100 if (line_index == selection_start.y) {
1101 character_start = line.characters[selection_start.x];
1102 }
1103 if (line_index == selection_end.y) {
1104 character_end = line.characters[selection_end.x];
1105 }
1106
1107 const float line_y = character_start.position.y + text->font_descender;
1108
1109 const blender::float2 view_offs{-scene->r.xsch / 2.0f, -scene->r.ysch / 2.0f};
1110 const float view_aspect = scene->r.xasp / scene->r.yasp;
1111 blender::float3x3 transform_mat = seq::image_transform_matrix_get(scene, strip);
1112 blender::float2 selection_quad[4] = {
1113 {character_start.position.x, line_y},
1114 {character_start.position.x, line_y + text->line_height},
1115 {character_end.position.x + character_end.advance_x, line_y + text->line_height},
1116 {character_end.position.x + character_end.advance_x, line_y},
1117 };
1118
1121
1122 for (int i : blender::IndexRange(0, 4)) {
1123 selection_quad[i] += view_offs;
1124 selection_quad[i] = blender::math::transform_point(transform_mat, selection_quad[i]);
1125 selection_quad[i].x *= view_aspect;
1126 }
1127 for (int i : blender::Vector<int>{0, 1, 2, 2, 3, 0}) {
1128 immVertex2f(pos, selection_quad[i][0], selection_quad[i][1]);
1129 }
1130
1131 immEnd();
1132 }
1133}
1134
1136{
1137 blender::int2 coords_view;
1138 UI_view2d_view_to_region(v2d, coords.x, coords.y, &coords_view.x, &coords_view.y);
1139 coords_view.x = std::round(coords_view.x);
1140 coords_view.y = std::round(coords_view.y);
1141 blender::float2 coords_region_aligned;
1143 v2d, coords_view.x, coords_view.y, &coords_region_aligned.x, &coords_region_aligned.y);
1144 return coords_region_aligned;
1145}
1146
1147static void text_edit_draw_cursor(const bContext *C, const Strip *strip, uint pos)
1148{
1149 const TextVars *data = static_cast<TextVars *>(strip->effectdata);
1150 const TextVarsRuntime *text = data->runtime;
1151 const Scene *scene = CTX_data_sequencer_scene(C);
1152
1153 const blender::float2 view_offs{-scene->r.xsch / 2.0f, -scene->r.ysch / 2.0f};
1154 const float view_aspect = scene->r.xasp / scene->r.yasp;
1155 blender::float3x3 transform_mat = seq::image_transform_matrix_get(scene, strip);
1157 data->cursor_offset);
1158 const float cursor_width = 10;
1159 blender::float2 cursor_coords =
1160 text->lines[cursor_position.y].characters[cursor_position.x].position;
1161 /* Clamp cursor coords to be inside of text boundbox. Compensate for cursor width, but also line
1162 * width hardcoded in shader. */
1163 const float bound_left = float(text->text_boundbox.xmin) + U.pixelsize;
1164 const float bound_right = float(text->text_boundbox.xmax) - (cursor_width + U.pixelsize);
1165 /* Note: do not use std::clamp since due to math above left can become larger than right. */
1166 cursor_coords.x = std::max(cursor_coords.x, bound_left);
1167 cursor_coords.x = std::min(cursor_coords.x, bound_right);
1168
1169 cursor_coords = coords_region_view_align(UI_view2d_fromcontext(C), cursor_coords);
1170
1171 blender::float2 cursor_quad[4] = {
1172 {cursor_coords.x, cursor_coords.y},
1173 {cursor_coords.x, cursor_coords.y + text->line_height},
1174 {cursor_coords.x + cursor_width, cursor_coords.y + text->line_height},
1175 {cursor_coords.x + cursor_width, cursor_coords.y},
1176 };
1177 const blender::float2 descender_offs{0.0f, float(text->font_descender)};
1178
1181
1182 for (int i : blender::IndexRange(0, 4)) {
1183 cursor_quad[i] += descender_offs + view_offs;
1184 cursor_quad[i] = blender::math::transform_point(transform_mat, cursor_quad[i]);
1185 cursor_quad[i].x *= view_aspect;
1186 }
1187 for (int i : blender::Vector<int>{0, 1, 2, 2, 3, 0}) {
1188 immVertex2f(pos, cursor_quad[i][0], cursor_quad[i][1]);
1189 }
1190
1191 immEnd();
1192}
1193
1194static void text_edit_draw(const bContext *C)
1195{
1196 if (!sequencer_text_editing_active_poll(const_cast<bContext *>(C))) {
1197 return;
1198 }
1200 if (!seq::effects_can_render_text(strip)) {
1201 return;
1202 }
1203
1206 format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
1207 GPU_line_smooth(true);
1210
1211 text_selection_draw(C, strip, pos);
1212 text_edit_draw_cursor(C, strip, pos);
1213
1216 GPU_line_smooth(false);
1217}
1218
1219/* Draw empty preview region.
1220 * The entire region is cleared with the TH_SEQ_PREVIEW color.
1221 *
1222 * Used in cases when there is no editing, or when the display is set to NONE. */
1224{
1226 BLI_assert(viewport);
1227
1229 GPU_framebuffer_bind_no_srgb(overlay_fb);
1230
1232}
1233
1234/* Begin drawing the sequence preview region.
1235 * Initializes the drawing state which is common for color render and overlay drawing.
1236 *
1237 * #preview_draw_end() is to be called after drawing is done. */
1238static void preview_draw_begin(const bContext *C,
1239 const RenderData &render_data,
1240 const ColorManagedViewSettings &view_settings,
1241 const ColorManagedDisplaySettings &display_settings,
1242 ARegion &region,
1243 eSpaceSeq_RegionType preview_type)
1244{
1246
1248 BLI_assert(viewport);
1249
1250 /* Configure color space used by the viewport.
1251 * This also checks for HDR support and enables it for the viewport when found and needed. */
1253 viewport, &view_settings, &display_settings, render_data.dither_intensity);
1254
1256
1257 /* Setup view. */
1258 View2D &v2d = region.v2d;
1259 float viewrect[2];
1260 /* For histogram and wave/parade scopes, allow arbitrary zoom. */
1263 }
1264 else {
1266 }
1267 sequencer_display_size(render_data, viewrect);
1268 UI_view2d_totRect_set(&v2d, roundf(viewrect[0]), roundf(viewrect[1]));
1271}
1272
1278
1279/* Configure current GPU state to draw on the color render frame-buffer of the viewport. */
1281{
1283 BLI_assert(viewport);
1284
1286 GPU_framebuffer_bind(render_fb);
1287
1288 float col[4] = {0, 0, 0, 0};
1289 GPU_framebuffer_clear_color(render_fb, col);
1290}
1291
1292/* Configure current GPU state to draw on the overlay frame-buffer of the viewport. */
1294{
1296 BLI_assert(viewport);
1297
1299 GPU_framebuffer_bind_no_srgb(overlay_fb);
1300
1302}
1303
1304/* Draw the given texture on the currently bound frame-buffer without any changes to its pixels
1305 * colors.
1306 *
1307 * The position denotes coordinates of a rectangle used to display the texture.
1308 * The texture_coord contains UV coordinates of the input texture which are mapped to the corners
1309 * of the rectangle. */
1311 const rctf &position,
1312 const rctf &texture_coord)
1313{
1314 GPUVertFormat *imm_format = immVertexFormat();
1316 imm_format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
1318 imm_format, "texCoord", blender::gpu::VertAttrType::SFLOAT_32_32);
1319
1321 immUniformColor3f(1.0f, 1.0f, 1.0f);
1322
1324
1325 immRectf_with_texco(pos, tex_coord, position, texture_coord);
1326
1329}
1330
1331/* Draw the given texture on the currently bound frame-buffer and convert its colors to linear
1332 * space in the fragment shader. This makes it suitable to be further processed by a GPUViewport
1333 *
1334 * The position denotes coordinates of a rectangle used to display the texture.
1335 * The texture_coord contains UV coordinates of the input texture which are mapped to the corners
1336 * of the rectangle. */
1338 const char *texture_colorspace_name,
1339 const bool predivide,
1340 const rctf &position,
1341 const rctf &texture_coord)
1342{
1343 GPUVertFormat *imm_format = immVertexFormat();
1345 imm_format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
1347 imm_format, "texCoord", blender::gpu::VertAttrType::SFLOAT_32_32);
1348
1349 if (!IMB_colormanagement_setup_glsl_draw_to_scene_linear(texture_colorspace_name, predivide)) {
1350 /* An error happened when configuring GPU side color space conversion. Return and allow the
1351 * view to be black, so that it is obvious something went wrong and that a bug report is to
1352 * be submitted.
1353 *
1354 * Note that fallback OCIO implementation is handled on a higher level. */
1355 return;
1356 }
1357
1359
1360 immRectf_with_texco(pos, tex_coord, position, texture_coord);
1361
1363
1365}
1366
1367/* Draw overlays for the currently displayed images in the preview. */
1369 const Scene *scene,
1370 const Editing &editing,
1371 const int timeline_frame)
1372{
1373 ListBase *channels = seq::channels_displayed_get(&editing);
1375 scene, channels, editing.current_strips(), timeline_frame, 0);
1376 Strip *active_seq = seq::select_active_get(scene);
1377 for (Strip *strip : strips) {
1378 /* TODO(sergey): Avoid having per-strip strip-independent checks. */
1379 strip_draw_image_origin_and_outline(C, strip, strip == active_seq);
1381 }
1382}
1383
1384static bool is_cursor_visible(const SpaceSeq &sseq)
1385{
1386 if (G.moving & G_TRANSFORM_CURSOR) {
1387 return true;
1388 }
1389
1390 if ((sseq.flag & SEQ_SHOW_OVERLAY) &&
1392 {
1393 return true;
1394 }
1395 return false;
1396}
1397
1401static void draw_cursor_2d(const ARegion *region, const blender::float2 &cursor)
1402{
1403 int co[2];
1404 UI_view2d_view_to_region(&region->v2d, cursor[0], cursor[1], &co[0], &co[1]);
1405
1406 /* Draw nice Anti Aliased cursor. */
1408
1409 /* Draw lines */
1410 float original_proj[4][4];
1411 GPU_matrix_projection_get(original_proj);
1413 ED_region_pixelspace(region);
1414 GPU_matrix_translate_2f(co[0] + 0.5f, co[1] + 0.5f);
1415 GPU_matrix_scale_2f(U.widget_unit, U.widget_unit);
1416
1417 float viewport[4];
1418 GPU_viewport_size_get_f(viewport);
1419
1421 struct {
1422 uint pos, col;
1423 } attr_id{};
1424 attr_id.pos = GPU_vertformat_attr_add(format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
1426 format, "color", blender::gpu::VertAttrType::SFLOAT_32_32_32);
1428 immUniform2fv("viewportSize", &viewport[2]);
1429 immUniform1f("lineWidth", U.pixelsize);
1430
1431 const float f5 = 0.25f;
1432 const float f10 = 0.5f;
1433 const float f20 = 1.0f;
1434
1435 const float red[3] = {1.0f, 0.0f, 0.0f};
1436 const float white[3] = {1.0f, 1.0f, 1.0f};
1437
1438 const int segments = 16;
1439 immBegin(GPU_PRIM_LINE_STRIP, segments + 1);
1440 for (int i = 0; i < segments + 1; i++) {
1441 float angle = float(2 * M_PI) * (float(i) / float(segments));
1442 float x = f10 * cosf(angle);
1443 float y = f10 * sinf(angle);
1444
1445 immAttr3fv(attr_id.col, (i % 2 == 0) ? red : white);
1446 immVertex2f(attr_id.pos, x, y);
1447 }
1448 immEnd();
1449
1450 float crosshair_color[3];
1451 UI_GetThemeColor3fv(TH_VIEW_OVERLAY, crosshair_color);
1452
1454 immAttr3fv(attr_id.col, crosshair_color);
1455 immVertex2f(attr_id.pos, -f20, 0);
1456 immAttr3fv(attr_id.col, crosshair_color);
1457 immVertex2f(attr_id.pos, -f5, 0);
1458
1459 immAttr3fv(attr_id.col, crosshair_color);
1460 immVertex2f(attr_id.pos, +f20, 0);
1461 immAttr3fv(attr_id.col, crosshair_color);
1462 immVertex2f(attr_id.pos, +f5, 0);
1463
1464 immAttr3fv(attr_id.col, crosshair_color);
1465 immVertex2f(attr_id.pos, 0, -f20);
1466 immAttr3fv(attr_id.col, crosshair_color);
1467 immVertex2f(attr_id.pos, 0, -f5);
1468
1469 immAttr3fv(attr_id.col, crosshair_color);
1470 immVertex2f(attr_id.pos, 0, +f20);
1471 immAttr3fv(attr_id.col, crosshair_color);
1472 immVertex2f(attr_id.pos, 0, +f5);
1473 immEnd();
1474
1476
1478
1480 GPU_matrix_projection_set(original_proj);
1481}
1482
1483/* Get offset in frame numbers of the reference frame relative to the current frame. */
1484static int get_reference_frame_offset(const Editing &editing, const RenderData &render_data)
1485{
1487 return editing.overlay_frame_abs - render_data.cfra;
1488 }
1489 return editing.overlay_frame_ofs;
1490}
1491
1492/* Create blender::gpu::Texture from the given image buffer for drawing rendered sequencer frame on
1493 * the color render frame buffer.
1494 *
1495 * The texture format and color space matches the CPU-side buffer.
1496 *
1497 * If both float and byte buffers are missing nullptr is returned.
1498 * If channel configuration is incompatible with the texture nullptr is returned. */
1500{
1501 const eGPUTextureUsage texture_usage = GPU_TEXTURE_USAGE_SHADER_READ |
1503
1504 blender::gpu::Texture *texture = nullptr;
1505
1506 if (ibuf.float_buffer.data) {
1507 blender::gpu::TextureFormat texture_format;
1508 switch (ibuf.channels) {
1509 case 1:
1510 texture_format = blender::gpu::TextureFormat::SFLOAT_32;
1511 break;
1512 case 3:
1513 texture_format = blender::gpu::TextureFormat::SFLOAT_32_32_32;
1514 break;
1515 case 4:
1516 texture_format = blender::gpu::TextureFormat::SFLOAT_32_32_32_32;
1517 break;
1518 default:
1519 BLI_assert_msg(0, "Incompatible number of channels for float buffer in sequencer");
1520 return nullptr;
1521 }
1522
1524 "seq_display_buf", ibuf.x, ibuf.y, 1, texture_format, texture_usage, nullptr);
1525 if (texture) {
1527 }
1528 }
1529 else if (ibuf.byte_buffer.data) {
1530 texture = GPU_texture_create_2d("seq_display_buf",
1531 ibuf.x,
1532 ibuf.y,
1533 1,
1534 blender::gpu::TextureFormat::UNORM_8_8_8_8,
1535 texture_usage,
1536 nullptr);
1537 if (texture) {
1539 }
1540 }
1541
1542 if (texture) {
1544 }
1545
1546 return texture;
1547}
1548
1549/* Get colorspace name of the image buffer used to create GPU texture.
1550 *
1551 * Needs to be kept in sync with create_texture() w.r.t which buffers are used to create the
1552 * texture. If the image buffer does not specify color space explicitly scene linear is returned if
1553 * there is a float buffer, and default byte space is returned if there is a byte buffer.
1554 *
1555 * If there are no buffers at all scene linear space is returned. */
1575
1576/* Part of the sequencer preview region drawing which renders images to the viewport's color render
1577 * frame-buffer. */
1578static void sequencer_preview_draw_color_render(const SpaceSeq &space_sequencer,
1579 const Editing &editing,
1580 ARegion &region,
1581 const ImBuf *current_ibuf,
1582 blender::gpu::Texture *current_texture,
1583 const ImBuf *reference_ibuf,
1584 blender::gpu::Texture *reference_texture)
1585{
1587
1588 if (current_texture) {
1589 BLI_assert(current_ibuf);
1590 const rctf position = preview_get_full_position(region);
1591 const rctf texture_coord = preview_get_full_texture_coord();
1592 const char *texture_colorspace = get_texture_colorspace_name(*current_ibuf);
1593 const bool predivide = (current_ibuf->float_buffer.data != nullptr);
1595 *current_texture, texture_colorspace, predivide, position, texture_coord);
1596 }
1597
1598 if (reference_texture) {
1599 BLI_assert(reference_ibuf);
1600 const rctf position = preview_get_reference_position(space_sequencer, editing, region);
1601 const rctf texture_coord = preview_get_reference_texture_coord(space_sequencer, editing);
1602 const char *texture_colorspace = get_texture_colorspace_name(*reference_ibuf);
1603 const bool predivide = (reference_ibuf->float_buffer.data != nullptr);
1605 *reference_texture, texture_colorspace, predivide, position, texture_coord);
1606 }
1607}
1608
1609static void draw_registered_callbacks(const bContext *C, ARegion &region)
1610{
1612 BLI_assert(viewport);
1613
1615
1616 GPU_framebuffer_bind(overlay_fb);
1618 GPU_framebuffer_bind_no_srgb(overlay_fb);
1619}
1620
1622{
1623 return (sseq.mainb != SEQ_DRAW_IMG_HISTOGRAM) &&
1625}
1626
1627/* Part of the sequencer preview region drawing which renders information overlays to the
1628 * viewport's overlay frame-buffer. */
1630 const wmWindowManager &wm,
1631 Scene *scene,
1632 const SpaceSeq &space_sequencer,
1633 const Editing &editing,
1634 const ColorManagedViewSettings &view_settings,
1635 const ColorManagedDisplaySettings &display_settings,
1636 ARegion &region,
1637 blender::gpu::Texture *current_texture,
1638 blender::gpu::Texture *reference_texture,
1639 const ImBuf *input_ibuf,
1640 const int timeline_frame)
1641{
1642 const bool is_playing = ED_screen_animation_playing(&wm);
1643 const bool show_preview_image = space_sequencer.mainb == SEQ_DRAW_IMG_IMBUF;
1644 const bool has_cpu_scope = input_ibuf && space_sequencer.mainb == SEQ_DRAW_IMG_HISTOGRAM;
1645 const bool has_gpu_scope = input_ibuf && current_texture &&
1646 ((space_sequencer.mainb == SEQ_DRAW_IMG_IMBUF &&
1647 space_sequencer.zebra != 0) ||
1648 ELEM(space_sequencer.mainb,
1652
1653 /* Update scopes before starting regular draw (GPU scopes update changes framebuffer, etc.). */
1654 space_sequencer.runtime->scopes.last_ibuf_float = input_ibuf &&
1655 input_ibuf->float_buffer.data != nullptr;
1656 if (has_cpu_scope) {
1658 space_sequencer, view_settings, display_settings, *input_ibuf, timeline_frame);
1659 }
1660 if (has_gpu_scope) {
1661 update_gpu_scopes(input_ibuf,
1662 current_texture,
1663 view_settings,
1664 display_settings,
1665 space_sequencer,
1666 scene,
1667 timeline_frame);
1668 }
1669
1671
1672 if (has_cpu_scope || has_gpu_scope) {
1673 /* Draw scope. */
1675 space_sequencer,
1676 region,
1677 timeline_frame,
1678 input_ibuf->x,
1679 input_ibuf->y,
1680 input_ibuf->float_buffer.data != nullptr);
1681 }
1682 else if (space_sequencer.flag & SEQ_USE_ALPHA) {
1683 /* Draw checked-board. */
1684 const View2D &v2d = region.v2d;
1685 imm_draw_box_checker_2d(v2d.tot.xmin, v2d.tot.ymin, v2d.tot.xmax, v2d.tot.ymax, true);
1686
1687 /* Draw current and preview textures in a special way to pierce a hole in the overlay to make
1688 * the actual image visible. */
1690 if (current_texture) {
1691 const rctf position = preview_get_full_position(region);
1692 const rctf texture_coord = preview_get_full_texture_coord();
1693 preview_draw_texture_simple(*current_texture, position, texture_coord);
1694 }
1695 if (reference_texture) {
1696 const rctf position = preview_get_reference_position(space_sequencer, editing, region);
1697 const rctf texture_coord = preview_get_reference_texture_coord(space_sequencer, editing);
1698 preview_draw_texture_simple(*reference_texture, position, texture_coord);
1699 }
1701 }
1702 else {
1703 /* The overlay framebuffer is fully cleared. Need to draw a full-frame transparent rectangle in
1704 * it to make sequencer result visible. */
1705
1706 const rctf position = preview_get_full_position(region);
1707
1708 GPUVertFormat *imm_format = immVertexFormat();
1710 imm_format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
1711
1713
1715 immUniformColor3f(1.0f, 1.0f, 1.0f);
1716 immRectf(pos, position.xmin, position.ymin, position.xmax, position.ymax);
1718
1720 }
1721
1722 /* Draw metadata. */
1723 if (show_preview_image && input_ibuf) {
1724 if ((space_sequencer.preview_overlay.flag & SEQ_PREVIEW_SHOW_METADATA) &&
1725 (space_sequencer.flag & SEQ_SHOW_OVERLAY))
1726 {
1727 const View2D &v2d = region.v2d;
1728 ED_region_image_metadata_draw(0.0, 0.0, input_ibuf, &v2d.tot, 1.0, 1.0);
1729 }
1730 }
1731
1732 if (show_preview_image && (space_sequencer.flag & SEQ_SHOW_OVERLAY)) {
1733 sequencer_draw_borders_overlay(space_sequencer, region.v2d, scene);
1734
1735 /* Various overlays like strip selection and text editing. */
1736 preview_draw_all_image_overlays(C, scene, editing, timeline_frame);
1737
1738 if ((space_sequencer.preview_overlay.flag & SEQ_PREVIEW_SHOW_GPENCIL) && space_sequencer.gpd) {
1740 }
1741 }
1742
1744
1746
1747 /* No need to show the cursor for scopes. */
1748 if ((is_playing == false) && show_preview_image && is_cursor_visible(space_sequencer)) {
1749 GPU_color_mask(true, true, true, true);
1750 GPU_depth_mask(false);
1752
1753 const float2 cursor_pixel = seq::image_preview_unit_to_px(scene, space_sequencer.cursor);
1754 draw_cursor_2d(&region, cursor_pixel);
1755 }
1756
1757 /* Gizmos. */
1758 if ((is_playing == false) && (space_sequencer.gizmo_flag & SEQ_GIZMO_HIDE) == 0) {
1760 }
1761
1762 /* FPS counter. */
1763 if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(&wm)) {
1764 const rcti *rect = ED_region_visible_rect(&region);
1765 int xoffset = rect->xmin + U.widget_unit;
1766 int yoffset = rect->ymax;
1767
1768 /* #ED_scene_draw_fps does not set text/shadow colors, except when frame-rate is too low, then
1769 * it sets text color to red. Make sure the "normal case" also has legible colors. */
1770 const int font_id = BLF_default();
1771 float text_color[4] = {1, 1, 1, 1}, shadow_color[4] = {0, 0, 0, 0.8f};
1772 BLF_color4fv(font_id, text_color);
1773 BLF_enable(font_id, BLF_SHADOW);
1774 BLF_shadow_offset(font_id, 0, 0);
1775 BLF_shadow(font_id, FontShadowType::Outline, shadow_color);
1776
1777 ED_scene_draw_fps(scene, xoffset, &yoffset);
1778
1779 BLF_disable(font_id, BLF_SHADOW);
1780 }
1781}
1782
1784{
1785 const ScrArea *area = CTX_wm_area(C);
1786 const SpaceSeq &space_sequencer = *static_cast<const SpaceSeq *>(area->spacedata.first);
1788
1789 /* Check if preview needs to be drawn at all. Note: do not draw preview region when
1790 * there is ongoing offline rendering, to avoid threading conflicts. */
1791 if (G.is_rendering || !scene || !scene->ed ||
1792 space_sequencer.render_size == SEQ_RENDER_SIZE_NONE)
1793 {
1795 return;
1796 }
1797
1798 const Editing &editing = *scene->ed;
1799 const RenderData &render_data = scene->r;
1800
1802 render_data,
1803 scene->view_settings,
1804 scene->display_settings,
1805 *region,
1806 eSpaceSeq_RegionType(space_sequencer.mainb));
1807
1808 const bool show_imbuf = check_show_imbuf(space_sequencer);
1809 const bool use_gpu_texture = show_imbuf || check_scope_needs_input_texture(space_sequencer);
1810
1811 const bool draw_overlay = (space_sequencer.flag & SEQ_SHOW_OVERLAY);
1812 const bool draw_frame_overlay = (editing.overlay_frame_flag & SEQ_EDIT_OVERLAY_FRAME_SHOW) &&
1813 draw_overlay;
1814 const bool need_current_frame = !(draw_frame_overlay && (space_sequencer.overlay_frame_type ==
1816 const bool need_reference_frame = show_imbuf && draw_frame_overlay &&
1817 space_sequencer.overlay_frame_type !=
1819
1820 int timeline_frame = render_data.cfra;
1821 if (sequencer_draw_get_transform_preview(space_sequencer, *scene)) {
1822 timeline_frame = sequencer_draw_get_transform_preview_frame(scene);
1823 }
1824
1825 /* GPU textures for the current and reference frames.
1826 *
1827 * When non-nullptr they are to be drawn (in other words, when they are non-nullptr the
1828 * corresponding draw_current_frame and draw_reference_frame is true). */
1829 blender::gpu::Texture *current_texture = nullptr;
1830 blender::gpu::Texture *reference_texture = nullptr;
1831
1832 /* Get image buffers before setting up GPU state for drawing. This is because
1833 * sequencer_ibuf_get() might not properly restore the state.
1834 * Additionally, some image buffers might be needed for both color render and overlay drawing. */
1835 ImBuf *current_ibuf = nullptr;
1836 ImBuf *reference_ibuf = nullptr;
1837 const char *view_names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
1838 if (need_reference_frame) {
1839 const int offset = get_reference_frame_offset(editing, render_data);
1840 reference_ibuf = sequencer_ibuf_get(
1841 C, timeline_frame + offset, view_names[space_sequencer.multiview_eye]);
1842 if (show_imbuf && reference_ibuf) {
1843 reference_texture = create_texture(*reference_ibuf);
1844 }
1845 }
1846 if (need_current_frame) {
1847 current_ibuf = sequencer_ibuf_get(
1848 C, timeline_frame, view_names[space_sequencer.multiview_eye]);
1849 if (use_gpu_texture && current_ibuf) {
1850 current_texture = seq::preview_cache_get_gpu_texture(
1851 scene, timeline_frame, space_sequencer.chanshown);
1852 if (current_texture == nullptr) {
1853 current_texture = create_texture(*current_ibuf);
1855 scene, timeline_frame, space_sequencer.chanshown, current_texture);
1856 }
1857 }
1858 }
1859
1860 /* Image buffer used for overlays: scopes, metadata etc. */
1861 ImBuf *overlay_ibuf = need_current_frame ? current_ibuf : reference_ibuf;
1862
1863 /* Draw parts of the preview region to the corresponding frame buffers. */
1865 editing,
1866 *region,
1867 current_ibuf,
1868 show_imbuf ? current_texture : nullptr,
1869 reference_ibuf,
1870 show_imbuf ? reference_texture : nullptr);
1872 *CTX_wm_manager(C),
1873 scene,
1874 space_sequencer,
1875 editing,
1876 scene->view_settings,
1877 scene->display_settings,
1878 *region,
1879 current_texture,
1880 reference_texture,
1881 overlay_ibuf,
1882 timeline_frame);
1883
1884#if 0
1885 sequencer_draw_maskedit(C, scene, region, sseq);
1886#endif
1887
1888 /* Free GPU textures. Note that the #current_texture is kept around via #preview_set_gpu_texture,
1889 * for other preview areas or frames if nothing changes between them. */
1890 if (reference_texture) {
1891 GPU_texture_free(reference_texture);
1892 }
1893
1894 /* Free CPU side resources. */
1895 IMB_freeImBuf(current_ibuf);
1896 IMB_freeImBuf(reference_ibuf);
1897
1899}
1900
1901} // namespace blender::ed::vse
Depsgraph * CTX_data_expect_evaluated_depsgraph(const bContext *C)
bScreen * CTX_wm_screen(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
SpaceSeq * CTX_wm_space_seq(const bContext *C)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
Scene * CTX_data_sequencer_scene(const bContext *C)
@ G_TRANSFORM_CURSOR
@ G_TRANSFORM_SEQ
void BKE_render_resolution(const RenderData *r, const bool use_crop, int *r_width, int *r_height)
Definition scene.cc:2915
int BKE_scene_multiview_view_id_get(const RenderData *rd, const char *viewname)
Definition scene.cc:3082
void BLF_enable(int fontid, FontFlags flag)
Definition blf.cc:320
void BLF_shadow(int fontid, FontShadowType type, const float rgba[4]=nullptr)
Definition blf.cc:934
void BLF_width_and_height(int fontid, const char *str, size_t str_len, float *r_width, float *r_height) ATTR_NONNULL()
Definition blf.cc:789
void BLF_color4fv(int fontid, const float rgba[4])
Definition blf.cc:505
void BLF_shadow_offset(int fontid, int x, int y)
Definition blf.cc:946
int BLF_default()
void BLF_disable(int fontid, FontFlags flag)
Definition blf.cc:329
blender::ocio::ColorSpace ColorSpace
Definition BLF_api.hh:38
@ BLF_SHADOW
Definition BLF_enums.hh:35
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
MINLINE float ratiof(float min, float max, float pos)
#define BLI_YUV_ITU_BT709
MINLINE void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3])
void rgb_to_yuv(float r, float g, float b, float *r_y, float *r_u, float *r_v, int colorspace)
Definition math_color.cc:67
void yuv_to_rgb(float y, float u, float v, float *r_r, float *r_g, float *r_b, int colorspace)
Definition math_color.cc:91
#define DEG2RADF(_deg)
#define M_PI
static constexpr int image_width
static constexpr int image_height
BLI_INLINE float BLI_rctf_cent_y(const struct rctf *rct)
Definition BLI_rect.h:189
BLI_INLINE float BLI_rctf_cent_x(const struct rctf *rct)
Definition BLI_rect.h:185
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition rct.cc:404
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition BLI_rect.h:202
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:206
#define SNPRINTF_UTF8_RLEN(dst, format,...)
unsigned char uchar
unsigned int uint
#define ELEM(...)
@ OB_RENDER
#define STEREO_LEFT_NAME
#define STEREO_RIGHT_NAME
@ STEREO_RIGHT_ID
@ RGN_TYPE_PREVIEW
struct TextVarsRuntime TextVarsRuntime
@ STRIP_TYPE_SOUND_RAM
@ SEQ_EDIT_OVERLAY_FRAME_ABS
@ SEQ_EDIT_OVERLAY_FRAME_SHOW
@ SEQ_RIGHTSEL
@ SEQ_LEFTSEL
eSpaceSeq_Proxy_RenderSize
@ SEQ_RENDER_SIZE_NONE
@ SEQ_VIEW_SEQUENCE_PREVIEW
@ SEQ_VIEW_PREVIEW
@ SEQ_PREVIEW_SHOW_METADATA
@ SEQ_PREVIEW_SHOW_GPENCIL
@ SEQ_PREVIEW_SHOW_SAFE_MARGINS
@ SEQ_PREVIEW_SHOW_OUTLINE_SELECTED
@ SEQ_PREVIEW_SHOW_SAFE_CENTER
@ SEQ_PREVIEW_SHOW_2D_CURSOR
@ SEQ_DRAW_TRANSFORM_PREVIEW
@ SEQ_OVERLAY_FRAME_TYPE_RECT
@ SEQ_OVERLAY_FRAME_TYPE_CURRENT
@ SEQ_OVERLAY_FRAME_TYPE_REFERENCE
eSpaceSeq_RegionType
@ SEQ_DRAW_IMG_VECTORSCOPE
@ SEQ_DRAW_IMG_RGBPARADE
@ SEQ_DRAW_IMG_HISTOGRAM
@ SEQ_DRAW_IMG_IMBUF
@ SEQ_DRAW_IMG_WAVEFORM
@ SEQ_USE_ALPHA
@ SEQ_USE_PROXIES
@ SEQ_SHOW_OVERLAY
@ SEQ_GIZMO_HIDE
#define UI_SCALE_FAC
@ USER_SHOW_FPS
@ V2D_KEEPZOOM
@ V2D_KEEPASPECT
void ED_mask_draw_region(Depsgraph *depsgraph, Mask *mask, ARegion *region, bool show_overlays, char draw_flag, char draw_type, eMaskOverlayMode overlay_mode, float blend_factor, int width_i, int height_i, float aspx, float aspy, bool do_scale_applied, bool do_draw_cb, float stabmat[4][4], const bContext *C)
Definition mask_draw.cc:641
const rcti * ED_region_visible_rect(ARegion *region)
Definition area.cc:4301
bScreen * ED_screen_animation_no_scrub(const wmWindowManager *wm)
void ED_region_pixelspace(const ARegion *region)
Definition area.cc:87
bScreen * ED_screen_animation_playing(const wmWindowManager *wm)
void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type)
#define REGION_DRAW_POST_VIEW
void ED_region_image_metadata_draw(int x, int y, const ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy)
Definition ed_draw.cc:1030
void ED_scene_draw_fps(const Scene *scene, int xoffset, int *yoffset)
static AppView * view
#define GPU_batch_uniform_1f(batch, name, x)
Definition GPU_batch.hh:271
void GPU_batch_discard(blender::gpu::Batch *batch)
void GPU_batch_draw(blender::gpu::Batch *batch)
blender::gpu::Batch * GPU_batch_create_procedural(GPUPrimType primitive_type, int32_t vertex_count)
Definition gpu_batch.cc:83
void GPU_batch_set_shader(blender::gpu::Batch *batch, blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
#define GPU_batch_uniform_1i(batch, name, x)
Definition GPU_batch.hh:269
void GPU_compute_dispatch(blender::gpu::Shader *shader, uint groups_x_len, uint groups_y_len, uint groups_z_len, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_debug_group_end()
Definition gpu_debug.cc:33
void GPU_debug_group_begin(const char *name)
Definition gpu_debug.cc:22
#define GPU_FRAMEBUFFER_FREE_SAFE(fb)
#define GPU_ATTACHMENT_TEXTURE(_texture)
void GPU_framebuffer_restore()
#define GPU_ATTACHMENT_NONE
void GPU_framebuffer_bind_no_srgb(blender::gpu::FrameBuffer *fb)
void GPU_framebuffer_clear_color(blender::gpu::FrameBuffer *fb, const float clear_col[4])
#define GPU_framebuffer_ensure_config(_fb,...)
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
blender::gpu::FrameBuffer * GPU_framebuffer_active_get()
void immUniformColor4ubv(const unsigned char rgba[4])
void immUniform4f(const char *name, float x, float y, float z, float w)
void immEnd()
void immUniform2fv(const char *name, const float data[2])
void immUnbindProgram()
void immBindBuiltinProgram(GPUBuiltinShader shader_id)
void immUniform2f(const char *name, float x, float y)
void immVertex2f(uint attr_id, float x, float y)
void immUniformThemeColor(int color_id)
void immUniform1i(const char *name, int x)
void immUniform1f(const char *name, float x)
GPUVertFormat * immVertexFormat()
void immUniformThemeColorBlend(int color_id1, int color_id2, float fac)
void immUniformColor3f(float r, float g, float b)
void immAttr3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void immUniformColor3fv(const float rgb[3])
void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2)
void immRectf_with_texco(uint pos, uint tex_coord, const rctf &p, const rctf &uv)
void immRectf(uint pos, float x1, float y1, float x2, float y2)
void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2, bool clear_alpha=false)
void GPU_matrix_ortho_set(float left, float right, float bottom, float top, float near, float far)
void GPU_matrix_identity_set()
void GPU_matrix_scale_2f(float x, float y)
void GPU_matrix_push()
void GPU_matrix_push_projection()
void GPU_matrix_pop_projection()
#define GPU_matrix_projection_get(x)
#define GPU_matrix_projection_set(x)
void GPU_matrix_pop()
void GPU_matrix_translate_2f(float x, float y)
@ GPU_PRIM_LINE_LOOP
@ GPU_PRIM_LINES
@ GPU_PRIM_POINTS
@ GPU_PRIM_LINE_STRIP
@ GPU_PRIM_TRIS
void GPU_shader_uniform_1b(blender::gpu::Shader *sh, const char *name, bool value)
void GPU_shader_uniform_1f(blender::gpu::Shader *sh, const char *name, float value)
int GPU_shader_get_sampler_binding(blender::gpu::Shader *shader, const char *name)
void GPU_shader_uniform_3fv(blender::gpu::Shader *sh, const char *name, const float data[3])
void GPU_shader_bind(blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
int GPU_shader_get_ssbo_binding(blender::gpu::Shader *shader, const char *name)
void GPU_shader_uniform_1i(blender::gpu::Shader *sh, const char *name, int value)
void GPU_shader_unbind()
blender::gpu::Shader * GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
@ GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_SHADER_SEQUENCER_SCOPE_RASTER
@ GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA
@ GPU_SHADER_3D_POLYLINE_FLAT_COLOR
@ GPU_SHADER_SEQUENCER_ZEBRA
@ GPU_SHADER_SEQUENCER_SCOPE_RESOLVE
@ GPU_SHADER_3D_IMAGE_COLOR
@ GPU_BARRIER_SHADER_STORAGE
Definition GPU_state.hh:48
@ GPU_DEPTH_NONE
Definition GPU_state.hh:111
void GPU_line_width(float width)
Definition gpu_state.cc:166
void GPU_line_smooth(bool enable)
Definition gpu_state.cc:78
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
@ GPU_BLEND_ADDITIVE
Definition GPU_state.hh:89
@ GPU_BLEND_OVERLAY_MASK_FROM_ALPHA
Definition GPU_state.hh:107
void GPU_depth_mask(bool depth)
Definition gpu_state.cc:110
void GPU_blend(GPUBlend blend)
Definition gpu_state.cc:42
void GPU_depth_test(GPUDepthTest test)
Definition gpu_state.cc:68
void GPU_color_mask(bool r, bool g, bool b, bool a)
Definition gpu_state.cc:98
void GPU_viewport_size_get_i(int coords[4])
Definition gpu_state.cc:282
void GPU_memory_barrier(GPUBarrier barrier)
Definition gpu_state.cc:326
void GPU_viewport_size_get_f(float coords[4])
Definition gpu_state.cc:273
void GPU_storagebuf_free(blender::gpu::StorageBuf *ssbo)
blender::gpu::StorageBuf * GPU_storagebuf_create_ex(size_t size, const void *data, GPUUsageType usage, const char *name)
void GPU_storagebuf_clear_to_zero(blender::gpu::StorageBuf *ssbo)
void GPU_storagebuf_bind(blender::gpu::StorageBuf *ssbo, int slot)
void GPU_storagebuf_unbind(blender::gpu::StorageBuf *ssbo)
int GPU_texture_height(const blender::gpu::Texture *texture)
void GPU_texture_unbind(blender::gpu::Texture *texture)
int GPU_texture_width(const blender::gpu::Texture *texture)
@ GPU_DATA_UBYTE
@ GPU_DATA_FLOAT
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
blender::gpu::Texture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_filter_mode(blender::gpu::Texture *texture, bool use_filter)
void GPU_texture_bind(blender::gpu::Texture *texture, int unit)
void GPU_texture_free(blender::gpu::Texture *texture)
void GPU_texture_update(blender::gpu::Texture *texture, eGPUDataFormat data_format, const void *data)
@ GPU_USAGE_DEVICE_ONLY
uint GPU_vertformat_attr_add(GPUVertFormat *format, blender::StringRef name, blender::gpu::VertAttrType type)
void GPU_viewport_bind(GPUViewport *viewport, int view, const rcti *rect)
blender::gpu::FrameBuffer * GPU_viewport_framebuffer_overlay_get(GPUViewport *viewport)
blender::gpu::FrameBuffer * GPU_viewport_framebuffer_render_get(GPUViewport *viewport)
void GPU_viewport_colorspace_set(GPUViewport *viewport, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, float dither)
void GPU_viewport_unbind(GPUViewport *viewport)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
@ COLOR_ROLE_DEFAULT_BYTE
@ COLOR_ROLE_SCENE_LINEAR
bool IMB_colormanagement_display_processor_needed(const ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings)
const char * IMB_colormanagement_colorspace_get_name(const ColorSpace *colorspace)
const char * IMB_colormanagement_role_colorspace_name_get(int role)
void IMB_colormanagement_finish_glsl_draw()
BLI_INLINE void IMB_colormanagement_get_luminance_coefficients(float r_rgb[3])
bool IMB_colormanagement_setup_glsl_draw_to_scene_linear(const char *from_colorspace_name, bool predivide)
bool IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, const ColorSpace *from_colorspace, float dither, bool predivide, bool do_overlay_merge)
void IMB_freeImBuf(ImBuf *ibuf)
#define C
Definition RandGen.cpp:29
void UI_draw_safe_areas(uint pos, const rctf *rect, const float title_aspect[2], const float action_aspect[2])
void UI_GetThemeColor3fv(int colorid, float col[3])
@ TH_SEQ_SELECTED
@ TH_BACK
@ TH_SEQ_SELECTED_TEXT
@ TH_SEQ_PREVIEW
@ TH_SEQ_TEXT_CURSOR
@ TH_VIEW_OVERLAY
@ TH_SEQ_ACTIVE
void UI_ThemeClearColor(int colorid)
void UI_view2d_curRect_validate(View2D *v2d)
Definition view2d.cc:828
void UI_view2d_scale_get_inverse(const View2D *v2d, float *r_x, float *r_y)
Definition view2d.cc:1929
char char char char void UI_view2d_text_cache_add(View2D *v2d, float x, float y, const char *str, size_t str_len, const unsigned char col[4])
Definition view2d.cc:2082
void UI_view2d_view_restore(const bContext *C)
Definition view2d.cc:1162
void UI_view2d_text_cache_draw(ARegion *region)
Definition view2d.cc:2142
void UI_view2d_totRect_set(View2D *v2d, int width, int height)
Definition view2d.cc:1036
void UI_view2d_view_ortho(const View2D *v2d)
Definition view2d.cc:1095
View2D * UI_view2d_fromcontext(const bContext *C)
Definition view2d.cc:1855
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
Definition view2d.cc:1668
void UI_view2d_view_to_region(const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL()
Definition view2d.cc:1723
@ WM_JOB_TYPE_COMPOSITE
Definition WM_api.hh:1777
@ WM_JOB_TYPE_RENDER_PREVIEW
Definition WM_api.hh:1779
@ WM_GIZMOMAP_DRAWSTEP_2D
#define ND_SEQUENCER
Definition WM_types.hh:437
#define NC_SCENE
Definition WM_types.hh:378
void ED_annotation_draw_2dimage(const bContext *C)
void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
#define U
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
constexpr int64_t first() const
constexpr int64_t last(const int64_t n=0) const
void add_quad(float x1, float y1, float x2, float y2, const uchar color[4])
void add_line(float x1, float y1, float x2, float y2, const uchar color[4])
void add_wire_quad(float x1, float y1, float x2, float y2, const uchar color[4])
nullptr float
#define SELECT
#define roundf(x)
struct @021025263243242147216143265077100330027142264337::@225245033123204053237120173316075113304004012000 batch
uint pos
uint col
struct @021025263243242147216143265077100330027142264337::@240232116316110053135047106323056371161236243121 attr_id
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
uint tex_coord
BLI_INLINE float fb(float length, float L)
format
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
#define G(x, y, z)
blender::IndexRange strip_text_selection_range_get(const TextVars *data)
static Strip * special_seq_update
static void sequencer_draw_scopes(Scene *scene, const SpaceSeq &space_sequencer, ARegion &region, int timeline_frame, int image_width, int image_height, bool premultiplied)
static int sequencer_draw_get_transform_preview_frame(const Scene *scene)
static void preview_draw_end(const bContext *C)
static void preview_draw_color_render_begin(ARegion &region)
static void text_selection_draw(const bContext *C, const Strip *strip, uint pos)
static void draw_cursor_2d(const ARegion *region, const blender::float2 &cursor)
static void sequencer_preview_clear()
bool sequencer_text_editing_active_poll(bContext *C)
static void preview_draw_overlay_begin(ARegion &region)
static bool sequencer_draw_get_transform_preview(const SpaceSeq &sseq, const Scene &scene)
static rctf preview_get_reference_position(const SpaceSeq &space_sequencer, const Editing &editing, const ARegion &region)
static void text_edit_draw(const bContext *C)
static void draw_registered_callbacks(const bContext *C, ARegion &region)
static rctf preview_get_full_position(const ARegion &region)
static void sequencer_preview_draw_empty(ARegion &region)
static const char * get_scope_debug_name(eSpaceSeq_RegionType type)
static bool check_scope_needs_input_texture(const SpaceSeq &sseq)
static rctf preview_get_full_texture_coord()
void sequencer_preview_region_draw(const bContext *C, ARegion *region)
static void draw_histogram(ARegion &region, const ScopeHistogram &hist, SeqQuadsBatch &quads, const rctf &area)
static void update_cpu_scopes(const SpaceSeq &space_sequencer, const ColorManagedViewSettings &view_settings, const ColorManagedDisplaySettings &display_settings, const ImBuf &ibuf, const int timeline_frame)
static void draw_waveform_graticule(ARegion *region, SeqQuadsBatch &quads, const rctf &area)
static void sequencer_stop_running_jobs(const bContext *C, Scene *scene)
static void preview_draw_all_image_overlays(const bContext *C, const Scene *scene, const Editing &editing, const int timeline_frame)
static void draw_vectorscope_graticule(ARegion *region, SeqQuadsBatch &quads, const rctf &area)
static blender::gpu::Texture * create_texture(const ImBuf &ibuf)
static rctf preview_get_reference_texture_coord(const SpaceSeq &space_sequencer, const Editing &editing)
static void text_edit_draw_cursor(const bContext *C, const Strip *strip, uint pos)
Strip * strip_under_mouse_get(const Scene *scene, const View2D *v2d, const int mval[2])
static void add_vertical_line(const float val, const uchar4 color, View2D &v2d, const float text_scale_x, const float text_scale_y, SeqQuadsBatch &quads, const rctf &area)
bool sequencer_view_preview_only_poll(const bContext *C)
void sequencer_special_update_set(Strip *strip)
void special_preview_set(bContext *C, const int mval[2])
static void sequencer_draw_borders_overlay(const SpaceSeq &sseq, const View2D &v2d, const Scene *scene)
static void seq_prefetch_wm_notify(const bContext *C, Scene *scene)
bool check_show_imbuf(const SpaceSeq &sseq)
static void sequencer_draw_gpencil_overlay(const bContext *C)
blender::int2 strip_text_cursor_offset_to_position(const TextVarsRuntime *text, int cursor_offset)
static void sequencer_preview_draw_color_render(const SpaceSeq &space_sequencer, const Editing &editing, ARegion &region, const ImBuf *current_ibuf, blender::gpu::Texture *current_texture, const ImBuf *reference_ibuf, blender::gpu::Texture *reference_texture)
static blender::float2 coords_region_view_align(const View2D *v2d, const blender::float2 coords)
static int get_reference_frame_offset(const Editing &editing, const RenderData &render_data)
static void sequencer_preview_draw_overlays(const bContext *C, const wmWindowManager &wm, Scene *scene, const SpaceSeq &space_sequencer, const Editing &editing, const ColorManagedViewSettings &view_settings, const ColorManagedDisplaySettings &display_settings, ARegion &region, blender::gpu::Texture *current_texture, blender::gpu::Texture *reference_texture, const ImBuf *input_ibuf, const int timeline_frame)
ImBuf * sequencer_ibuf_get(const bContext *C, int timeline_frame, const char *viewname)
static blender::float2 rgb_to_uv_scaled(const blender::float3 &rgb)
static void preview_draw_texture_simple(blender::gpu::Texture &texture, const rctf &position, const rctf &texture_coord)
static void strip_draw_image_origin_and_outline(const bContext *C, Strip *strip, bool is_active_seq)
static void update_gpu_scopes(const ImBuf *input_ibuf, gpu::Texture *input_texture, const ColorManagedViewSettings &view_settings, const ColorManagedDisplaySettings &display_settings, const SpaceSeq &space_sequencer, Scene *scene, int timeline_frame)
static const char * get_texture_colorspace_name(const ImBuf &ibuf)
static void sequencer_display_size(const RenderData &render_data, float r_viewrect[2])
static void preview_draw_texture_to_linear(blender::gpu::Texture &texture, const char *texture_colorspace_name, const bool predivide, const rctf &position, const rctf &texture_coord)
static void preview_draw_begin(const bContext *C, const RenderData &render_data, const ColorManagedViewSettings &view_settings, const ColorManagedDisplaySettings &display_settings, ARegion &region, eSpaceSeq_RegionType preview_type)
static bool is_cursor_visible(const SpaceSeq &sseq)
T clamp(const T &a, const T &min, const T &max)
T reduce_max(const VecBase< T, Size > &a)
VecBase< T, Size > divide_ceil(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
T interpolate(const T &a, const T &b, const FactorT &t)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
int time_right_handle_frame_get(const Scene *scene, const Strip *strip)
Array< float2 > image_transform_final_quad_get(const Scene *scene, const Strip *strip)
ImBuf * render_give_ibuf(const RenderData *context, float timeline_frame, int chanshown)
Definition render.cc:2028
ListBase * channels_displayed_get(const Editing *ed)
Definition channels.cc:28
bool prefetch_need_redraw(const bContext *C, Scene *scene)
Definition prefetch.cc:644
float3x3 image_transform_matrix_get(const Scene *scene, const Strip *strip)
Editing * editing_get(const Scene *scene)
Definition sequencer.cc:286
float get_render_scale_factor(eSpaceSeq_Proxy_RenderSize render_size, short scene_render_scale)
Definition render.cc:2118
int time_left_handle_frame_get(const Scene *, const Strip *strip)
void preview_cache_set_gpu_display_texture(Scene *scene, int timeline_frame, int display_channel, gpu::Texture *texture)
Strip * select_active_get(const Scene *scene)
void render_new_render_data(Main *bmain, Depsgraph *depsgraph, Scene *scene, int rectx, int recty, eSpaceSeq_Proxy_RenderSize preview_render_size, Render *render, RenderData *r_context)
Definition render.cc:210
gpu::Texture * preview_cache_get_gpu_texture(Scene *scene, int timeline_frame, int display_channel)
void preview_cache_set_gpu_texture(Scene *scene, int timeline_frame, int display_channel, gpu::Texture *texture)
bool effects_can_render_text(const Strip *strip)
float2 image_transform_origin_offset_pixelspace_get(const Scene *scene, const Strip *strip)
VectorSet< Strip * > query_rendered_strips(const Scene *scene, ListBase *channels, ListBase *seqbase, const int timeline_frame, const int displayed_channel)
Definition iterator.cc:228
float2 image_preview_unit_to_px(const Scene *scene, const float2 co_src)
ImBuf * render_give_ibuf_direct(const RenderData *context, float timeline_frame, Strip *strip)
Definition render.cc:2100
gpu::Texture * preview_cache_get_gpu_display_texture(Scene *scene, int timeline_frame, int display_channel)
blender::VecBase< uint8_t, 4 > uchar4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
#define sinf
#define cosf
ARegionRuntimeHandle * runtime
rctf overlay_frame_rect
const ColorSpace * colorspace
const ColorSpace * colorspace
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
void * first
float dither_intensity
ColorManagedViewSettings view_settings
struct Editing * ed
struct RenderData r
struct DisplaySafeAreas safe_areas
ColorManagedDisplaySettings display_settings
ListBase spacedata
char overlay_frame_type
float cursor[2]
struct bGPdata * gpd
short render_size
SpaceSeq_Runtime * runtime
struct SequencerPreviewOverlay preview_overlay
void * effectdata
short keepzoom
struct wmTimer * animtimer
void calc_from_ibuf(const ImBuf *ibuf, const ColorManagedViewSettings &view_settings, const ColorManagedDisplaySettings &display_settings)
static constexpr float VECSCOPE_V_SCALE
static constexpr float VECSCOPE_U_SCALE
Vector< CharInfo > characters
float xmax
float xmin
float ymax
float ymin
int ymax
int xmin
i
Definition text_draw.cc:230
GPUViewport * WM_draw_region_get_bound_viewport(ARegion *region)
Definition wm_draw.cc:950
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_gizmomap_draw(wmGizmoMap *gzmap, const bContext *C, const eWM_GizmoFlagMapDrawStep drawstep)
void WM_jobs_kill_type(wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:623