VSE: speedup timeline drawing, and improve waveform display #115311
|
@ -32,6 +32,7 @@ set(SRC
|
|||
sequencer_preview.cc
|
||||
sequencer_preview_draw.cc
|
||||
sequencer_proxy.cc
|
||||
sequencer_quads_batch.cc
|
||||
sequencer_retiming.cc
|
||||
sequencer_retiming_draw.cc
|
||||
sequencer_scopes.cc
|
||||
|
@ -42,6 +43,7 @@ set(SRC
|
|||
space_sequencer.cc
|
||||
|
||||
sequencer_intern.hh
|
||||
sequencer_quads_batch.hh
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
/* Internal exports only. */
|
||||
|
||||
class SeqQuadsBatch;
|
||||
struct ARegion;
|
||||
struct ARegionType;
|
||||
struct Depsgraph;
|
||||
|
@ -317,7 +318,7 @@ int sequencer_retiming_select_all_exec(bContext *C, wmOperator *op);
|
|||
int sequencer_retiming_box_select_exec(bContext *C, wmOperator *op);
|
||||
|
||||
/* `sequencer_retiming_draw.cc` */
|
||||
void sequencer_draw_retiming(const bContext *C);
|
||||
void sequencer_draw_retiming(const bContext *C, SeqQuadsBatch *quads);
|
||||
blender::Vector<Sequence *> sequencer_visible_strips_get(const bContext *C);
|
||||
SeqRetimingKey *try_to_realize_virtual_key(const bContext *C, Sequence *seq, const int mval[2]);
|
||||
SeqRetimingKey *retiming_mousover_key_get(const bContext *C, const int mval[2], Sequence **r_seq);
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spseq
|
||||
*/
|
||||
|
||||
#include "sequencer_quads_batch.hh"
|
||||
|
||||
#include "BLI_color.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
#include "GPU_batch.h"
|
||||
#include "GPU_index_buffer.h"
|
||||
#include "GPU_vertex_buffer.h"
|
||||
|
||||
struct ColorVertex {
|
||||
blender::float2 pos;
|
||||
blender::ColorTheme4b color;
|
||||
};
|
||||
static_assert(sizeof(ColorVertex) == 12);
|
||||
|
||||
static GPUIndexBuf *create_quads_index_buffer(int quads_count)
|
||||
{
|
||||
GPUIndexBufBuilder elb;
|
||||
GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, quads_count * 2, quads_count * 4);
|
||||
for (int i = 0; i < quads_count; i++) {
|
||||
const uint i0 = i * 4 + 0;
|
||||
const uint i1 = i * 4 + 1;
|
||||
const uint i2 = i * 4 + 2;
|
||||
const uint i3 = i * 4 + 3;
|
||||
GPU_indexbuf_add_tri_verts(&elb, i0, i1, i2);
|
||||
GPU_indexbuf_add_tri_verts(&elb, i2, i1, i3);
|
||||
}
|
||||
return GPU_indexbuf_build(&elb);
|
||||
}
|
||||
|
||||
SeqQuadsBatch::SeqQuadsBatch()
|
||||
{
|
||||
ibo_quads = create_quads_index_buffer(MAX_QUADS);
|
||||
|
||||
GPUVertFormat format;
|
||||
GPU_vertformat_clear(&format);
|
||||
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
GPU_vertformat_attr_add(&format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
|
||||
vbo_quads = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STREAM);
|
||||
GPU_vertbuf_data_alloc(vbo_quads, MAX_QUADS * 4);
|
||||
|
||||
vbo_lines = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STREAM);
|
||||
GPU_vertbuf_data_alloc(vbo_lines, MAX_LINES * 2);
|
||||
|
||||
batch_quads = GPU_batch_create_ex(
|
||||
GPU_PRIM_TRIS, vbo_quads, ibo_quads, GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
|
||||
GPU_batch_program_set_builtin(batch_quads, GPU_SHADER_3D_FLAT_COLOR);
|
||||
|
||||
batch_lines = GPU_batch_create_ex(GPU_PRIM_LINES, vbo_lines, nullptr, GPU_BATCH_OWNS_VBO);
|
||||
GPU_batch_program_set_builtin(batch_lines, GPU_SHADER_3D_FLAT_COLOR);
|
||||
}
|
||||
|
||||
SeqQuadsBatch::~SeqQuadsBatch()
|
||||
{
|
||||
BLI_assert_msg(quads_num == 0 && lines_num == 0,
|
||||
"SeqQuadsBatch is being destroyed without drawing quads/lines it contains");
|
||||
GPU_batch_discard(batch_quads);
|
||||
GPU_batch_discard(batch_lines);
|
||||
}
|
||||
|
||||
void SeqQuadsBatch::draw()
|
||||
{
|
||||
if (quads_num > 0) {
|
||||
GPU_vertbuf_tag_dirty(vbo_quads);
|
||||
GPU_vertbuf_use(vbo_quads);
|
||||
GPU_batch_draw_range(batch_quads, 0, quads_num * 6);
|
||||
quads_num = 0;
|
||||
verts_quads = nullptr;
|
||||
}
|
||||
if (lines_num > 0) {
|
||||
GPU_vertbuf_tag_dirty(vbo_lines);
|
||||
GPU_vertbuf_use(vbo_lines);
|
||||
GPU_batch_draw_range(batch_lines, 0, lines_num * 2);
|
||||
lines_num = 0;
|
||||
verts_lines = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SeqQuadsBatch::add_quad(float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
float x3,
|
||||
float y3,
|
||||
float x4,
|
||||
float y4,
|
||||
const uchar color[4])
|
||||
{
|
||||
if (quads_num >= MAX_QUADS) {
|
||||
draw();
|
||||
}
|
||||
if (quads_num == 0) {
|
||||
verts_quads = static_cast<ColorVertex *>(GPU_vertbuf_get_data(vbo_quads));
|
||||
BLI_assert(verts_quads != nullptr);
|
||||
}
|
||||
aras_p marked this conversation as resolved
|
||||
|
||||
ColorVertex v0 = {blender::float2(x1, y1), color};
|
||||
ColorVertex v1 = {blender::float2(x2, y2), color};
|
||||
ColorVertex v2 = {blender::float2(x3, y3), color};
|
||||
aras_p marked this conversation as resolved
Outdated
Richard Antalik
commented
Use Use `static_cast` for casting types, see https://wiki.blender.org/wiki/Style_Guide/C_Cpp#C.2B.2B_Type_Cast
|
||||
ColorVertex v3 = {blender::float2(x4, y4), color};
|
||||
|
||||
*verts_quads++ = v0;
|
||||
*verts_quads++ = v1;
|
||||
*verts_quads++ = v2;
|
||||
*verts_quads++ = v3;
|
||||
|
||||
quads_num++;
|
||||
}
|
||||
|
||||
void SeqQuadsBatch::add_wire_quad(float x1, float y1, float x2, float y2, const uchar color[4])
|
||||
{
|
||||
if (lines_num + 4 > MAX_LINES) {
|
||||
draw();
|
||||
}
|
||||
if (lines_num == 0) {
|
||||
verts_lines = static_cast<ColorVertex *>(GPU_vertbuf_get_data(vbo_lines));
|
||||
BLI_assert(verts_lines != nullptr);
|
||||
}
|
||||
|
||||
ColorVertex v0 = {blender::float2(x1, y1), color};
|
||||
ColorVertex v1 = {blender::float2(x1, y2), color};
|
||||
ColorVertex v2 = {blender::float2(x2, y1), color};
|
||||
ColorVertex v3 = {blender::float2(x2, y2), color};
|
||||
|
||||
/* Left */
|
||||
*verts_lines++ = v0;
|
||||
*verts_lines++ = v1;
|
||||
/* Right */
|
||||
*verts_lines++ = v2;
|
||||
*verts_lines++ = v3;
|
||||
/* Bottom */
|
||||
*verts_lines++ = v0;
|
||||
*verts_lines++ = v2;
|
||||
/* Top */
|
||||
*verts_lines++ = v1;
|
||||
*verts_lines++ = v3;
|
||||
|
||||
lines_num += 4;
|
||||
}
|
||||
|
||||
void SeqQuadsBatch::add_line(float x1, float y1, float x2, float y2, const uchar color[4])
|
||||
{
|
||||
if (lines_num + 1 > MAX_LINES) {
|
||||
draw();
|
||||
}
|
||||
if (lines_num == 0) {
|
||||
verts_lines = static_cast<ColorVertex *>(GPU_vertbuf_get_data(vbo_lines));
|
||||
BLI_assert(verts_lines != nullptr);
|
||||
}
|
||||
|
||||
ColorVertex v0 = {blender::float2(x1, y1), color};
|
||||
ColorVertex v1 = {blender::float2(x2, y2), color};
|
||||
|
||||
*verts_lines++ = v0;
|
||||
*verts_lines++ = v1;
|
||||
|
||||
lines_num++;
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spseq
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
struct GPUVertBuf;
|
||||
struct GPUIndexBuf;
|
||||
struct GPUBatch;
|
||||
struct ColorVertex;
|
||||
|
||||
/**
|
||||
* Flat-colored 2D geometry draw batching utility.
|
||||
*
|
||||
* Internally uses #GPU_SHADER_3D_FLAT_COLOR to draw single-colored rectangles, quads
|
||||
* or lines. After adding a number of primitives with #add_quad, #add_wire_quad, #add_line,
|
||||
* draw them using #draw. Note that #draw can be called behind the scenes if number of primitives
|
||||
* is larger than the internal batch buffer size.
|
||||
*/
|
||||
class SeqQuadsBatch {
|
||||
public:
|
||||
SeqQuadsBatch();
|
||||
~SeqQuadsBatch();
|
||||
|
||||
/** Draw all the previously added primitives. */
|
||||
void draw();
|
||||
/** Add an axis-aligned quad. */
|
||||
void add_quad(float x1, float y1, float x2, float y2, const uchar color[4])
|
||||
{
|
||||
add_quad(x1, y1, x1, y2, x2, y1, x2, y2, color);
|
||||
}
|
||||
/** Add a quad. */
|
||||
void add_quad(float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
float x3,
|
||||
float y3,
|
||||
float x4,
|
||||
float y4,
|
||||
const uchar color[4]);
|
||||
/** Add four lines of an axis-aligned quad edges. */
|
||||
void add_wire_quad(float x1, float y1, float x2, float y2, const uchar color[4]);
|
||||
/** Add a line. */
|
||||
void add_line(float x1, float y1, float x2, float y2, const uchar color[4]);
|
||||
|
||||
private:
|
||||
static constexpr int MAX_QUADS = 1024;
|
||||
static constexpr int MAX_LINES = 4096;
|
||||
|
||||
GPUVertBuf *vbo_quads = nullptr;
|
||||
GPUIndexBuf *ibo_quads = nullptr;
|
||||
GPUBatch *batch_quads = nullptr;
|
||||
ColorVertex *verts_quads = nullptr;
|
||||
int quads_num = 0;
|
||||
|
||||
GPUVertBuf *vbo_lines = nullptr;
|
||||
GPUBatch *batch_lines = nullptr;
|
||||
ColorVertex *verts_lines = nullptr;
|
||||
int lines_num = 0;
|
||||
};
|
|
@ -53,6 +53,7 @@
|
|||
|
||||
/* Own include. */
|
||||
#include "sequencer_intern.hh"
|
||||
#include "sequencer_quads_batch.hh"
|
||||
|
||||
#define KEY_SIZE (10 * U.pixelsize)
|
||||
#define KEY_CENTER (UI_view2d_view_to_region_y(v2d, strip_y_rescale(seq, 0.0f)) + 4 + KEY_SIZE / 2)
|
||||
|
@ -261,7 +262,11 @@ SeqRetimingKey *retiming_mousover_key_get(const bContext *C, const int mval[2],
|
|||
/** \name Retiming Key
|
||||
* \{ */
|
||||
|
||||
static void retime_key_draw(const bContext *C, const Sequence *seq, const SeqRetimingKey *key)
|
||||
static void retime_key_draw(const bContext *C,
|
||||
const Sequence *seq,
|
||||
const SeqRetimingKey *key,
|
||||
const KeyframeShaderBindings &sh_bindings,
|
||||
const blender::Map<SeqRetimingKey *, Sequence *> &selection)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
const float key_x = key_x_get(scene, seq, key);
|
||||
|
@ -272,24 +277,6 @@ static void retime_key_draw(const bContext *C, const Sequence *seq, const SeqRet
|
|||
return; /* Key out of the strip bounds. */
|
||||
}
|
||||
|
||||
GPUVertFormat *format = immVertexFormat();
|
||||
KeyframeShaderBindings sh_bindings;
|
||||
|
||||
sh_bindings.pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
sh_bindings.size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
sh_bindings.color_id = GPU_vertformat_attr_add(
|
||||
format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
sh_bindings.outline_color_id = GPU_vertformat_attr_add(
|
||||
format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
sh_bindings.flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
|
||||
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
GPU_program_point_size(true);
|
||||
immBindBuiltinProgram(GPU_SHADER_KEYFRAME_SHAPE);
|
||||
immUniform1f("outline_scale", 1.0f);
|
||||
immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
|
||||
immBegin(GPU_PRIM_POINTS, 1);
|
||||
|
||||
eBezTriple_KeyframeType key_type = BEZT_KEYTYPE_KEYFRAME;
|
||||
if (SEQ_retiming_key_is_freeze_frame(key)) {
|
||||
key_type = BEZT_KEYTYPE_BREAKDOWN;
|
||||
|
@ -298,7 +285,7 @@ static void retime_key_draw(const bContext *C, const Sequence *seq, const SeqRet
|
|||
key_type = BEZT_KEYTYPE_MOVEHOLD;
|
||||
}
|
||||
|
||||
const bool is_selected = SEQ_retiming_selection_contains(SEQ_editing_get(scene), key);
|
||||
const bool is_selected = selection.contains(const_cast<SeqRetimingKey *>(key));
|
||||
const int size = KEY_SIZE;
|
||||
const float bottom = KEY_CENTER;
|
||||
|
||||
|
@ -323,17 +310,16 @@ static void retime_key_draw(const bContext *C, const Sequence *seq, const SeqRet
|
|||
&sh_bindings,
|
||||
0,
|
||||
0);
|
||||
immEnd();
|
||||
GPU_program_point_size(false);
|
||||
immUnbindProgram();
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
static void draw_continuity(const bContext *C, const Sequence *seq, const SeqRetimingKey *key)
|
||||
static void draw_continuity(const bContext *C,
|
||||
const Sequence *seq,
|
||||
const SeqRetimingKey *key,
|
||||
const blender::Map<SeqRetimingKey *, Sequence *> &selection,
|
||||
aras_p marked this conversation as resolved
Outdated
Richard Antalik
commented
Sorry, I have noticed this only now, you should avoid passing pointers to objects, pass reference instead. So argument would be Sorry, I have noticed this only now, you should avoid passing pointers to objects, pass reference instead.
So argument would be `const blender::Set<const SeqRetimingKey *> &selection`
|
||||
SeqQuadsBatch *quads)
|
||||
{
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
const Editing *ed = SEQ_editing_get(scene);
|
||||
|
||||
if (key_x_get(scene, seq, key) == SEQ_time_left_handle_frame_get(scene, seq) ||
|
||||
key->strip_frame_index == 0)
|
||||
|
@ -358,29 +344,34 @@ static void draw_continuity(const bContext *C, const Sequence *seq, const SeqRet
|
|||
const float bottom = y_center - size * width_fac;
|
||||
const float top = y_center + size * width_fac;
|
||||
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
|
||||
uchar color[4];
|
||||
if (SEQ_retiming_data_is_editable(seq) &&
|
||||
(SEQ_retiming_selection_contains(ed, key) || SEQ_retiming_selection_contains(ed, key - 1)))
|
||||
(selection.contains(const_cast<SeqRetimingKey *>(key)) ||
|
||||
selection.contains(const_cast<SeqRetimingKey *>(key - 1))))
|
||||
{
|
||||
immUniform4f("color", 0.65f, 0.5f, 0.2f, 1.0f);
|
||||
color[0] = 166;
|
||||
color[1] = 127;
|
||||
color[2] = 51;
|
||||
color[3] = 255;
|
||||
}
|
||||
else {
|
||||
immUniform4f("color", 0.0f, 0.0f, 0.0f, 0.1f);
|
||||
color[0] = 0;
|
||||
color[1] = 0;
|
||||
color[2] = 0;
|
||||
color[3] = 25;
|
||||
}
|
||||
immRectf(pos, prev_key_position, bottom, key_position, top);
|
||||
immUnbindProgram();
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
quads->add_quad(prev_key_position, bottom, key_position, top, color);
|
||||
}
|
||||
|
||||
/* If there are no keys, draw fake keys and create real key when they are selected. */
|
||||
/* TODO: would be nice to draw continuity between fake keys. */
|
||||
static void fake_keys_draw(const bContext *C, Sequence *seq)
|
||||
static bool fake_keys_draw(const bContext *C,
|
||||
Sequence *seq,
|
||||
const KeyframeShaderBindings &sh_bindings,
|
||||
const blender::Map<SeqRetimingKey *, Sequence *> &selection)
|
||||
{
|
||||
if (!SEQ_retiming_is_active(seq) && !SEQ_retiming_data_is_editable(seq)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
|
@ -391,18 +382,19 @@ static void fake_keys_draw(const bContext *C, Sequence *seq)
|
|||
SeqRetimingKey fake_key;
|
||||
fake_key.strip_frame_index = left_key_frame - SEQ_time_start_frame_get(seq);
|
||||
fake_key.flag = 0;
|
||||
retime_key_draw(C, seq, &fake_key);
|
||||
retime_key_draw(C, seq, &fake_key, sh_bindings, selection);
|
||||
}
|
||||
|
||||
if (SEQ_retiming_key_get_by_timeline_frame(scene, seq, right_key_frame) == nullptr) {
|
||||
SeqRetimingKey fake_key;
|
||||
fake_key.strip_frame_index = right_key_frame - SEQ_time_start_frame_get(seq);
|
||||
fake_key.flag = 0;
|
||||
retime_key_draw(C, seq, &fake_key);
|
||||
retime_key_draw(C, seq, &fake_key, sh_bindings, selection);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void retime_keys_draw(const bContext *C)
|
||||
static void retime_keys_draw(const bContext *C, SeqQuadsBatch *quads)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
if (scene->ed == nullptr) {
|
||||
|
@ -413,22 +405,75 @@ static void retime_keys_draw(const bContext *C)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Get the selection here once, for faster "is key selected?" lookups later. */
|
||||
blender::Map<SeqRetimingKey *, Sequence *> selection = SEQ_retiming_selection_get(scene->ed);
|
||||
|
||||
wmOrtho2_region_pixelspace(CTX_wm_region(C));
|
||||
|
||||
for (Sequence *seq : sequencer_visible_strips_get(C)) {
|
||||
blender::Vector<Sequence *> strips = sequencer_visible_strips_get(C);
|
||||
|
||||
/* Draw all continuity sections. */
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
for (Sequence *seq : strips) {
|
||||
if (!SEQ_retiming_is_allowed(seq)) {
|
||||
aras_p marked this conversation as resolved
Outdated
Richard Antalik
commented
Can't you just pass map returnd by Can't you just pass map returnd by `SEQ_retiming_selection_get()` and use `contains()` method? This seems like unnecessary code duplication.
Aras Pranckevicius
commented
That's what I tried initially, but SEQ_retiming_selection_get returns non-const Sequence pointers as map keys, and my C++-fu is not strong enough to find the magic incantation, how to use That's what I tried initially, but SEQ_retiming_selection_get returns non-const Sequence pointers as map keys, and my C++-fu is not strong enough to find the magic incantation, how to use `contains()` when I have a const-Sequence pointer. `contains_as()` with const pointer does not compile, at least on visual studio.
Richard Antalik
commented
I am not great with C++ either, but you can use non-const There is also I am not great with C++ either, but you can use non-const `SeqRetimingKey` for iteration.
There is also `const_cast` which seems to work, but not sure if it is good idea to use it in this case.
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const SeqRetimingKey &key : SEQ_retiming_keys_get(seq)) {
|
||||
draw_continuity(C, seq, &key);
|
||||
}
|
||||
|
||||
fake_keys_draw(C, seq);
|
||||
for (const SeqRetimingKey &key : SEQ_retiming_keys_get(seq)) {
|
||||
retime_key_draw(C, seq, &key);
|
||||
draw_continuity(C, seq, &key, selection, quads);
|
||||
}
|
||||
}
|
||||
quads->draw();
|
||||
|
||||
/* Draw all keys. */
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
|
||||
GPUVertFormat *format = immVertexFormat();
|
||||
KeyframeShaderBindings sh_bindings;
|
||||
|
||||
sh_bindings.pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
sh_bindings.size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
sh_bindings.color_id = GPU_vertformat_attr_add(
|
||||
format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
sh_bindings.outline_color_id = GPU_vertformat_attr_add(
|
||||
format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
sh_bindings.flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
|
||||
|
||||
GPU_program_point_size(true);
|
||||
immBindBuiltinProgram(GPU_SHADER_KEYFRAME_SHAPE);
|
||||
immUniform1f("outline_scale", 1.0f);
|
||||
immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
|
||||
|
||||
constexpr int MAX_KEYS_IN_BATCH = 1024;
|
||||
int point_counter = 0;
|
||||
immBeginAtMost(GPU_PRIM_POINTS, MAX_KEYS_IN_BATCH);
|
||||
|
||||
for (Sequence *seq : strips) {
|
||||
if (!SEQ_retiming_is_allowed(seq)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fake_keys_draw(C, seq, sh_bindings, selection)) {
|
||||
point_counter += 2;
|
||||
}
|
||||
|
||||
for (const SeqRetimingKey &key : SEQ_retiming_keys_get(seq)) {
|
||||
retime_key_draw(C, seq, &key, sh_bindings, selection);
|
||||
point_counter++;
|
||||
|
||||
aras_p marked this conversation as resolved
Outdated
Richard Antalik
commented
I could have specified this a bit more, you can have just 1 condition This way batch should never be overfilled, and from what I read, with I could have specified this a bit more, you can have just 1 condition
`if (point_counter + 3 > MAX_KEYS_IN_BATCH) {` after `retime_key_draw()`
This way batch should never be overfilled, and from what I read, with `immBeginAtMost()` you can always draw less vertices.
|
||||
/* Next key plus possible two fake keys for next sequence would need at
|
||||
* most 3 points, so restart the batch if we're close to that. */
|
||||
if (point_counter + 3 >= MAX_KEYS_IN_BATCH) {
|
||||
immEnd();
|
||||
immBeginAtMost(GPU_PRIM_POINTS, MAX_KEYS_IN_BATCH);
|
||||
point_counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
immEnd();
|
||||
GPU_program_point_size(false);
|
||||
immUnbindProgram();
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -550,8 +595,8 @@ static void retime_speed_draw(const bContext *C)
|
|||
|
||||
/** \} */
|
||||
|
||||
void sequencer_draw_retiming(const bContext *C)
|
||||
void sequencer_draw_retiming(const bContext *C, SeqQuadsBatch *quads)
|
||||
{
|
||||
retime_keys_draw(C);
|
||||
retime_keys_draw(C, quads);
|
||||
retime_speed_draw(C);
|
||||
}
|
||||
|
|
|
@ -1517,13 +1517,10 @@ static void rna_Sequence_separate(ID *id, Sequence *seqm, Main *bmain)
|
|||
/* Find channel owner. If nullptr, owner is `Editing`, otherwise it's `Sequence`. */
|
||||
static Sequence *rna_SeqTimelineChannel_owner_get(Editing *ed, SeqTimelineChannel *channel)
|
||||
{
|
||||
blender::VectorSet strips = SEQ_query_all_strips_recursive(&ed->seqbase);
|
||||
blender::VectorSet strips = SEQ_query_all_meta_strips_recursive(&ed->seqbase);
|
||||
|
||||
Sequence *channel_owner = nullptr;
|
||||
for (Sequence *seq : strips) {
|
||||
if (seq->type != SEQ_TYPE_META) {
|
||||
continue;
|
||||
}
|
||||
if (BLI_findindex(&seq->channels, channel) != -1) {
|
||||
channel_owner = seq;
|
||||
break;
|
||||
|
|
|
@ -87,6 +87,13 @@ blender::VectorSet<Sequence *> SEQ_query_all_strips(ListBase *seqbase);
|
|||
* \return set of strips
|
||||
*/
|
||||
blender::VectorSet<Sequence *> SEQ_query_all_strips_recursive(ListBase *seqbase);
|
||||
/**
|
||||
* Query all meta strips in seqbase and nested meta strips.
|
||||
*
|
||||
* \param seqbase: ListBase in which strips are queried
|
||||
* \return set of meta strips
|
||||
*/
|
||||
blender::VectorSet<Sequence *> SEQ_query_all_meta_strips_recursive(ListBase *seqbase);
|
||||
|
||||
/**
|
||||
* Query all effect strips that are directly or indirectly connected to seq_reference.
|
||||
|
|
|
@ -92,6 +92,16 @@ static void query_all_strips_recursive(ListBase *seqbase, VectorSet<Sequence *>
|
|||
}
|
||||
}
|
||||
|
||||
static void query_all_meta_strips_recursive(ListBase *seqbase, VectorSet<Sequence *> &strips)
|
||||
{
|
||||
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
|
||||
if (seq->type == SEQ_TYPE_META) {
|
||||
query_all_meta_strips_recursive(&seq->seqbase, strips);
|
||||
strips.add(seq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VectorSet<Sequence *> SEQ_query_all_strips_recursive(ListBase *seqbase)
|
||||
{
|
||||
VectorSet<Sequence *> strips;
|
||||
|
@ -99,6 +109,13 @@ VectorSet<Sequence *> SEQ_query_all_strips_recursive(ListBase *seqbase)
|
|||
return strips;
|
||||
}
|
||||
|
||||
VectorSet<Sequence *> SEQ_query_all_meta_strips_recursive(ListBase *seqbase)
|
||||
{
|
||||
VectorSet<Sequence *> strips;
|
||||
query_all_meta_strips_recursive(seqbase, strips);
|
||||
return strips;
|
||||
}
|
||||
|
||||
VectorSet<Sequence *> SEQ_query_all_strips(ListBase *seqbase)
|
||||
{
|
||||
VectorSet<Sequence *> strips;
|
||||
|
|
|
@ -387,10 +387,10 @@ ListBase *SEQ_get_seqbase_by_seq(const Scene *scene, Sequence *seq)
|
|||
|
||||
Sequence *SEQ_get_meta_by_seqbase(ListBase *seqbase_main, ListBase *meta_seqbase)
|
||||
{
|
||||
blender::VectorSet strips = SEQ_query_all_strips_recursive(seqbase_main);
|
||||
blender::VectorSet strips = SEQ_query_all_meta_strips_recursive(seqbase_main);
|
||||
|
||||
for (Sequence *seq : strips) {
|
||||
if (seq->type == SEQ_TYPE_META && &seq->seqbase == meta_seqbase) {
|
||||
if (&seq->seqbase == meta_seqbase) {
|
||||
return seq;
|
||||
}
|
||||
}
|
||||
|
|
Do you need to clear the flag, because you are reusing the buffer? I would expect that there is some function to handle this.
Here it seems to work when I remove call to
GPU_vertbuf_attr_get_raw_data()
. Would have to look how exactly this flag is used.